On Mon, Jan 20, 2014 at 10:22:17PM -0800, Darrick J. Wong wrote: > If a client asks us to remap a block in the middle of an extent, we > potentially have to allocate a fair number of blocks to handle extent > tree splits. A failure in either of the ext2fs_extent_insert calls > leaves us with an extent tree that no longer maps the logical block in > question and everything that came after it! Therefore, try to roll > back the extent tree changes before returning an error code. > > Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> Reviewed-by: Zheng Liu <wenqing.lz@xxxxxxxxxx> - Zheng > --- > lib/ext2fs/extent.c | 25 ++++++++++++++++++++++--- > 1 file changed, 22 insertions(+), 3 deletions(-) > > > diff --git a/lib/ext2fs/extent.c b/lib/ext2fs/extent.c > index 2928695..87921e6 100644 > --- a/lib/ext2fs/extent.c > +++ b/lib/ext2fs/extent.c > @@ -1438,13 +1438,17 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle, > goto done; > } else { > __u32 orig_length; > + blk64_t orig_lblk; > + struct ext2fs_extent orig_extent; > + errcode_t r2; > > #ifdef DEBUG > printf("(re/un)mapping in middle of extent\n"); > #endif > /* need to split this extent; later */ > - > + orig_lblk = extent.e_lblk; > orig_length = extent.e_len; > + orig_extent = extent; > > /* shorten pre-split extent */ > extent.e_len = (logical - extent.e_lblk); > @@ -1456,8 +1460,13 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle, > /* insert new extent after current */ > retval = ext2fs_extent_insert(handle, > EXT2_EXTENT_INSERT_AFTER, &newextent); > - if (retval) > + if (retval) { > + r2 = ext2fs_extent_goto(handle, orig_lblk); > + if (r2 == 0) > + ext2fs_extent_replace(handle, 0, > + &orig_extent); > goto done; > + } > } > /* add post-split extent */ > extent.e_pblk += extent.e_len + 1; > @@ -1465,8 +1474,18 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle, > extent.e_len = orig_length - extent.e_len - 1; > retval = ext2fs_extent_insert(handle, > EXT2_EXTENT_INSERT_AFTER, &extent); > - if (retval) > + if (retval) { > + if (physical) { > + r2 = ext2fs_extent_goto(handle, > + newextent.e_lblk); > + if (r2 == 0) > + ext2fs_extent_delete(handle, 0); > + } > + r2 = ext2fs_extent_goto(handle, orig_lblk); > + if (r2 == 0) > + ext2fs_extent_replace(handle, 0, &orig_extent); > goto done; > + } > } > > done: > > -- > 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 -- 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