aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2010-11-24 21:56:24 -0500
committerJan Kara <jack@suse.cz>2011-01-06 11:03:57 -0500
commit4651c5900e7a3c84d4b70412f8bbc40c1bcb50cf (patch)
treebba6310572481952bb03079909712bf664a054fc /fs/udf
parent8754a3f718f08dc21b3c5eccd044f612d4bc1ab1 (diff)
udf: Fix directory corruption after extent merging
If udf_bread() called from udf_add_entry() managed to merge created extent to an already existing one (or if previous extents could be merged), the code truncating the last extent to proper size would just overwrite the freshly allocated extent with an extent that used to be in that place. This obviously results in a directory corruption. Fix the problem by properly reloading the last extent. Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf')
-rw-r--r--fs/udf/namei.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 26815a25379..a2974f7563a 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -471,15 +471,19 @@ add:
471 f_pos >> dir->i_sb->s_blocksize_bits, 1, err); 471 f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
472 if (!fibh->ebh) 472 if (!fibh->ebh)
473 goto out_err; 473 goto out_err;
474 /* Extents could have been merged, invalidate our position */
475 brelse(epos.bh);
476 epos.bh = NULL;
477 epos.block = dinfo->i_location;
478 epos.offset = udf_file_entry_alloc_offset(dir);
474 479
475 if (!fibh->soffset) { 480 if (!fibh->soffset) {
476 if (udf_next_aext(dir, &epos, &eloc, &elen, 1) == 481 /* Find the freshly allocated block */
477 (EXT_RECORDED_ALLOCATED >> 30)) { 482 while (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
478 block = eloc.logicalBlockNum + ((elen - 1) >> 483 (EXT_RECORDED_ALLOCATED >> 30))
484 ;
485 block = eloc.logicalBlockNum + ((elen - 1) >>
479 dir->i_sb->s_blocksize_bits); 486 dir->i_sb->s_blocksize_bits);
480 } else
481 block++;
482
483 brelse(fibh->sbh); 487 brelse(fibh->sbh);
484 fibh->sbh = fibh->ebh; 488 fibh->sbh = fibh->ebh;
485 fi = (struct fileIdentDesc *)(fibh->sbh->b_data); 489 fi = (struct fileIdentDesc *)(fibh->sbh->b_data);