Bugzilla – Attachment 330750 Details for
Bug 133718
memory allocation hangs during DVD-RAM writing
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
IDP Log In
|
Forgot Password
[patch]
Patch making UDF avoid IO in udf_clear_inode
0001-udf-Avoid-IO-in-udf_clear_inode.patch (text/plain), 6.41 KB, created by
Jan Kara
on 2009-12-03 13:11:58 UTC
(
hide
)
Description:
Patch making UDF avoid IO in udf_clear_inode
Filename:
MIME Type:
Creator:
Jan Kara
Created:
2009-12-03 13:11:58 UTC
Size:
6.41 KB
patch
obsolete
>From ca1eef023e383907c3e635948a9a8629a1974dff Mon Sep 17 00:00:00 2001 >From: Jan Kara <jack@suse.cz> >Date: Thu, 3 Dec 2009 13:39:28 +0100 >Subject: [PATCH] udf: Avoid IO in udf_clear_inode > >It is not very good to do IO in udf_clear_inode. First, VFS does not really >expect inode to become dirty there and thus we have to write it ourselves, >second, memory reclaim gets blocked waiting for IO when it does not really >expect it, third, the IO pattern (e.g. on umount) resulting from writes in >udf_clear_inode is bad and it slows down writing a lot. > >The reason why UDF needed to do IO in udf_clear_inode is that UDF standard >mandates extent length to exactly match inode size. But when we allocate >extents to a file or directory, we don't really know what exactly the final >file size will be and thus temporarily set it to block boundary and later >truncate it to exact length in udf_clear_inode. Now, this is changed to >truncate to final file size in udf_release_file for regular files. For >directories and symlinks, we do the truncation at the moment when learn >what the final file size will be. > >Signed-off-by: Jan Kara <jack@suse.cz> >--- > fs/udf/file.c | 1 + > fs/udf/inode.c | 24 ++++++++++++------------ > fs/udf/namei.c | 37 +++++++++++++++++++++++++++---------- > 3 files changed, 40 insertions(+), 22 deletions(-) > >diff --git a/fs/udf/file.c b/fs/udf/file.c >index b80cbd7..f311d50 100644 >--- a/fs/udf/file.c >+++ b/fs/udf/file.c >@@ -196,6 +196,7 @@ static int udf_release_file(struct inode *inode, struct file *filp) > mutex_lock(&inode->i_mutex); > lock_kernel(); > udf_discard_prealloc(inode); >+ udf_truncate_tail_extent(inode); > unlock_kernel(); > mutex_unlock(&inode->i_mutex); > } >diff --git a/fs/udf/inode.c b/fs/udf/inode.c >index 6d24c2c..f90231e 100644 >--- a/fs/udf/inode.c >+++ b/fs/udf/inode.c >@@ -97,15 +97,17 @@ no_delete: > */ > void udf_clear_inode(struct inode *inode) > { >- struct udf_inode_info *iinfo; >- if (!(inode->i_sb->s_flags & MS_RDONLY)) { >- lock_kernel(); >- udf_truncate_tail_extent(inode); >- unlock_kernel(); >- write_inode_now(inode, 0); >- invalidate_inode_buffers(inode); >+ struct udf_inode_info *iinfo = UDF_I(inode); >+ >+ if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && >+ inode->i_size != iinfo->i_lenExtents) { >+ printk(KERN_WARNING "UDF-fs (%s): Inode %lu (mode %o) has " >+ "inode size %llu different from extent lenght %llu. " >+ "Filesystem need not be standards compliant.\n", >+ inode->i_sb->s_id, inode->i_ino, inode->i_mode, >+ (unsigned long long)inode->i_size, >+ (unsigned long long)iinfo->i_lenExtents); > } >- iinfo = UDF_I(inode); > kfree(iinfo->i_ext.i_data); > iinfo->i_ext.i_data = NULL; > } >@@ -198,7 +200,6 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, > int newblock; > struct buffer_head *dbh = NULL; > struct kernel_lb_addr eloc; >- uint32_t elen; > uint8_t alloctype; > struct extent_position epos; > >@@ -273,12 +274,11 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, > eloc.logicalBlockNum = *block; > eloc.partitionReferenceNum = > iinfo->i_location.partitionReferenceNum; >- elen = inode->i_sb->s_blocksize; >- iinfo->i_lenExtents = elen; >+ iinfo->i_lenExtents = inode->i_size; > epos.bh = NULL; > epos.block = iinfo->i_location; > epos.offset = udf_file_entry_alloc_offset(inode); >- udf_add_aext(inode, &epos, &eloc, elen, 0); >+ udf_add_aext(inode, &epos, &eloc, inode->i_size, 0); > /* UniqueID stuff */ > > brelse(epos.bh); >diff --git a/fs/udf/namei.c b/fs/udf/namei.c >index 21dad8c..ba2d643 100644 >--- a/fs/udf/namei.c >+++ b/fs/udf/namei.c >@@ -408,15 +408,6 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, > } > > add: >- /* Is there any extent whose size we need to round up? */ >- if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && elen) { >- elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1); >- if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) >- epos.offset -= sizeof(struct short_ad); >- else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) >- epos.offset -= sizeof(struct long_ad); >- udf_write_aext(dir, &epos, &eloc, elen, 1); >- } > f_pos += nfidlen; > > if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB && >@@ -439,6 +430,7 @@ add: > udf_current_aext(dir, &epos, &eloc, &elen, 1); > } > >+ /* Entry fits into current block? */ > if (sb->s_blocksize - fibh->eoffset >= nfidlen) { > fibh->soffset = fibh->eoffset; > fibh->eoffset += nfidlen; >@@ -462,6 +454,16 @@ add: > (fibh->sbh->b_data + fibh->soffset); > } > } else { >+ /* Round up last extent in the file */ >+ elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1); >+ if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) >+ epos.offset -= sizeof(struct short_ad); >+ else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) >+ epos.offset -= sizeof(struct long_ad); >+ udf_write_aext(dir, &epos, &eloc, elen, 1); >+ dinfo->i_lenExtents = (dinfo->i_lenExtents + sb->s_blocksize >+ - 1) & ~(sb->s_blocksize - 1); >+ > fibh->soffset = fibh->eoffset - sb->s_blocksize; > fibh->eoffset += nfidlen - sb->s_blocksize; > if (fibh->sbh != fibh->ebh) { >@@ -508,6 +510,19 @@ add: > dir->i_size += nfidlen; > if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) > dinfo->i_lenAlloc += nfidlen; >+ else { >+ /* Find the last extent and truncate it to proper size */ >+ while (udf_next_aext(dir, &epos, &eloc, &elen, 1) == >+ (EXT_RECORDED_ALLOCATED >> 30)); >+ elen -= dinfo->i_lenExtents - dir->i_size; >+ if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) >+ epos.offset -= sizeof(struct short_ad); >+ else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) >+ epos.offset -= sizeof(struct long_ad); >+ udf_write_aext(dir, &epos, &eloc, elen, 1); >+ dinfo->i_lenExtents = dir->i_size; >+ } >+ > mark_inode_dirty(dir); > goto out_ok; > } else { >@@ -922,7 +937,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, > block = udf_get_pblock(inode->i_sb, block, > iinfo->i_location.partitionReferenceNum, > 0); >- epos.bh = udf_tread(inode->i_sb, block); >+ epos.bh = udf_tgetblk(inode->i_sb, block); > lock_buffer(epos.bh); > memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize); > set_buffer_uptodate(epos.bh); >@@ -999,6 +1014,8 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, > inode->i_size = elen; > if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) > iinfo->i_lenAlloc = inode->i_size; >+ else >+ udf_truncate_tail_extent(inode); > mark_inode_dirty(inode); > > fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); >-- >1.6.4.2 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
Actions:
View
|
Diff
Attachments on
bug 133718
:
224038
|
224046
|
304763
| 330750