aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/inode.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2009-12-03 07:39:28 -0500
committerJan Kara <jack@suse.cz>2009-12-14 15:40:04 -0500
commit2c948b3f86e5f0327e2e57858600af6e6f0ae29a (patch)
treea40d5fd7a5757d26fc41829e5620b4685bac44e2 /fs/udf/inode.c
parente971b0b9e0dd50d9ceecb67a6a6ab80a80906033 (diff)
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>
Diffstat (limited to 'fs/udf/inode.c')
-rw-r--r--fs/udf/inode.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 6d24c2c63f93..f90231eb2916 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -97,15 +97,17 @@ no_delete:
97 */ 97 */
98void udf_clear_inode(struct inode *inode) 98void udf_clear_inode(struct inode *inode)
99{ 99{
100 struct udf_inode_info *iinfo; 100 struct udf_inode_info *iinfo = UDF_I(inode);
101 if (!(inode->i_sb->s_flags & MS_RDONLY)) { 101
102 lock_kernel(); 102 if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
103 udf_truncate_tail_extent(inode); 103 inode->i_size != iinfo->i_lenExtents) {
104 unlock_kernel(); 104 printk(KERN_WARNING "UDF-fs (%s): Inode %lu (mode %o) has "
105 write_inode_now(inode, 0); 105 "inode size %llu different from extent lenght %llu. "
106 invalidate_inode_buffers(inode); 106 "Filesystem need not be standards compliant.\n",
107 inode->i_sb->s_id, inode->i_ino, inode->i_mode,
108 (unsigned long long)inode->i_size,
109 (unsigned long long)iinfo->i_lenExtents);
107 } 110 }
108 iinfo = UDF_I(inode);
109 kfree(iinfo->i_ext.i_data); 111 kfree(iinfo->i_ext.i_data);
110 iinfo->i_ext.i_data = NULL; 112 iinfo->i_ext.i_data = NULL;
111} 113}
@@ -198,7 +200,6 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block,
198 int newblock; 200 int newblock;
199 struct buffer_head *dbh = NULL; 201 struct buffer_head *dbh = NULL;
200 struct kernel_lb_addr eloc; 202 struct kernel_lb_addr eloc;
201 uint32_t elen;
202 uint8_t alloctype; 203 uint8_t alloctype;
203 struct extent_position epos; 204 struct extent_position epos;
204 205
@@ -273,12 +274,11 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block,
273 eloc.logicalBlockNum = *block; 274 eloc.logicalBlockNum = *block;
274 eloc.partitionReferenceNum = 275 eloc.partitionReferenceNum =
275 iinfo->i_location.partitionReferenceNum; 276 iinfo->i_location.partitionReferenceNum;
276 elen = inode->i_sb->s_blocksize; 277 iinfo->i_lenExtents = inode->i_size;
277 iinfo->i_lenExtents = elen;
278 epos.bh = NULL; 278 epos.bh = NULL;
279 epos.block = iinfo->i_location; 279 epos.block = iinfo->i_location;
280 epos.offset = udf_file_entry_alloc_offset(inode); 280 epos.offset = udf_file_entry_alloc_offset(inode);
281 udf_add_aext(inode, &epos, &eloc, elen, 0); 281 udf_add_aext(inode, &epos, &eloc, inode->i_size, 0);
282 /* UniqueID stuff */ 282 /* UniqueID stuff */
283 283
284 brelse(epos.bh); 284 brelse(epos.bh);