]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
udf: Fix directory corruption after extent merging
authorJan Kara <jack@suse.cz>
Thu, 25 Nov 2010 02:56:24 +0000 (03:56 +0100)
committerJan Kara <jack@suse.cz>
Thu, 6 Jan 2011 16:03:57 +0000 (17:03 +0100)
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>
fs/udf/namei.c

index 26815a25379d6d41251506a18efc6b61b3c049bd..a2974f7563a283c391a0ba6fc504c9da8528e439 100644 (file)
@@ -471,15 +471,19 @@ add:
                                f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
                if (!fibh->ebh)
                        goto out_err;
+               /* Extents could have been merged, invalidate our position */
+               brelse(epos.bh);
+               epos.bh = NULL;
+               epos.block = dinfo->i_location;
+               epos.offset = udf_file_entry_alloc_offset(dir);
 
                if (!fibh->soffset) {
-                       if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
-                           (EXT_RECORDED_ALLOCATED >> 30)) {
-                               block = eloc.logicalBlockNum + ((elen - 1) >>
+                       /* Find the freshly allocated block */
+                       while (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
+                               (EXT_RECORDED_ALLOCATED >> 30))
+                               ;
+                       block = eloc.logicalBlockNum + ((elen - 1) >>
                                        dir->i_sb->s_blocksize_bits);
-                       } else
-                               block++;
-
                        brelse(fibh->sbh);
                        fibh->sbh = fibh->ebh;
                        fi = (struct fileIdentDesc *)(fibh->sbh->b_data);