aboutsummaryrefslogtreecommitdiff
path: root/lib/ext2fs/punch.c
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2014-03-15 11:36:34 -0400
committerTheodore Ts'o <tytso@mit.edu>2015-11-16 06:08:17 -0500
commit7dce0c06e56d0f661126bd1ee1e5d70c174c2500 (patch)
tree95496d24aaa4a8ae95a288a11a8aa530c333b62b /lib/ext2fs/punch.c
parentb9ba837dc1847f76dbbdf7762651aaf6182a8766 (diff)
downloade2fsprogs-7dce0c06e56d0f661126bd1ee1e5d70c174c2500.tar.gz
libext2fs: fix parents when modifying extents
In ext2fs_extent_set_bmap() and ext2fs_punch_extent(), fix the parents when altering either end of an extent so that the parent nodes reflect the added mapping. There's a slight complication to using fix_parents: if there are two mappings to an lblk in the tree, the value of handle->path->curr can point to either extent afterwards), which is documented in a comment. Some additional color commentary from Darrick: In the _set_bmap() case, I noticed that the "remapping last block in extent" case would produce symptoms if we are trying to remap a block from "extent" to "next_extent", and the two extents are pointed to by different index nodes. _extent_replace(..., next_extent) updates e_lblk in the leaf extent, but because there's no _extent_fix_parents() call, the index nodes never get updated. In the _punch_extent() case, we conclude that we need to split an extent into two pieces since we're punching out the middle. If the extent is the last extent in the block, the second extent will be inserted into a new leaf node block. Without _fix_parents(), the index node doesn't seem to get updated. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'lib/ext2fs/punch.c')
-rw-r--r--lib/ext2fs/punch.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/lib/ext2fs/punch.c b/lib/ext2fs/punch.c
index a3d020ec..2a2cf102 100644
--- a/lib/ext2fs/punch.c
+++ b/lib/ext2fs/punch.c
@@ -343,10 +343,16 @@ static errcode_t ext2fs_punch_extent(ext2_filsys fs, ext2_ino_t ino,
EXT2_EXTENT_INSERT_AFTER, &newex);
if (retval)
goto errout;
- /* Now pointing at inserted extent; so go back */
- retval = ext2fs_extent_get(handle,
- EXT2_EXTENT_PREV_LEAF,
- &newex);
+ retval = ext2fs_extent_fix_parents(handle);
+ if (retval)
+ goto errout;
+ /*
+ * Now pointing at inserted extent; so go back.
+ *
+ * We cannot use EXT2_EXTENT_PREV to go back; note the
+ * subtlety in the comment for fix_parents().
+ */
+ retval = ext2fs_extent_goto(handle, extent.e_lblk);
if (retval)
goto errout;
}