Theodore Ts'o wrote: > In the case where we ext2fs_extent_set_bmap() is replacing the block > mapping at the beginning of an already-existing extent, insert a new > extent if necessary before shrinking an existing extent, to avoid data > loss if the disk is full. > > This mostly addresses the problem described in Red Hat Bugzilla's > statistics are still wrong, but at least the files on the filesystem > are not corrupted. If there is a failure during the > inode_scan_and_fix pass, the simplest thing to do may be to tell the > user to run e2fsck -fy. > > Addresses-Red-Hat-Bug: #510379 Thanks Ted, looks reasonable at first glance. I'll review more in depth tomorrow, but I think you can also remove the again: target, since nobody's going there anymore w/ this patch. -Eric > Signed-off-by: "Theodore Ts'o" <tytso@xxxxxxx> > --- > lib/ext2fs/extent.c | 44 ++++++++++++++++++++++++++++++++------------ > 1 files changed, 32 insertions(+), 12 deletions(-) > > diff --git a/lib/ext2fs/extent.c b/lib/ext2fs/extent.c > index 4a4fd2c..2f280ea 100644 > --- a/lib/ext2fs/extent.c > +++ b/lib/ext2fs/extent.c > @@ -1270,24 +1270,44 @@ again: > #ifdef DEBUG > printf("(re/un)mapping first block in extent\n"); > #endif > + if (physical) { > + retval = ext2fs_extent_get(handle, > + EXT2_EXTENT_PREV_LEAF, > + &extent); > + if (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) > + extent_uninit = 1; > + if (retval == EXT2_ET_EXTENT_NO_PREV) { > + retval = ext2fs_extent_insert(handle, > + 0, &newextent); > + } else if (retval) > + goto done; > + else if ((logical == extent.e_lblk + extent.e_len) && > + (physical == extent.e_pblk + extent.e_len) && > + (new_uninit == extent_uninit) && > + ((int) extent.e_len < max_len-1)) { > + extent.e_len++; > + retval = ext2fs_extent_replace(handle, 0, > + &extent); > + } else { > + retval = ext2fs_extent_insert(handle, > + EXT2_EXTENT_INSERT_AFTER, &newextent); > + } > + if (retval) > + goto done; > + } > + retval = ext2fs_extent_fix_parents(handle); > + if (retval) > + goto done; > + retval = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_LEAF, > + &extent); > + if (retval) > + goto done; > extent.e_pblk++; > extent.e_lblk++; > extent.e_len--; > retval = ext2fs_extent_replace(handle, 0, &extent); > if (retval) > goto done; > - if (physical) { > - /* > - * We've removed the old block, now rely on > - * the optimized hueristics for adding a new > - * mapping with appropriate merging if necessary. > - */ > - goto again; > - } else { > - retval = ext2fs_extent_fix_parents(handle); > - if (retval) > - goto done; > - } > } else { > __u32 orig_length; > -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html