2012/12/4 forrest <forrestl@xxxxxxxxxxxx>: > This problem is easily to reproduce > > Create a file with size larger than 1GB. > > dd if=/dev/zero of=/test_file bs=1M count=1024 > > Punch every even block in test_file, and then use debugfs to dump > extents, followings is dumped result > > 2/ 2 339/340 231197 - 231197 3917597 - 3917597 1 > 2/ 2 340/340 231199 - 231199 3917599 - 3917599 1 > 0/ 2 2/ 2 231201 - 262143 3901486 30943 > 1/ 2 1/ 46 231201 - 231880 3901488 680 > 2/ 2 1/340 231201 - 231201 3917601 - 3917601 1 > 2/ 2 2/340 231203 - 231203 3917603 - 3917603 1 > > Punch blocks #231779 ~#231201 , to remove extent index, and then use > debugfs to dump extents, followings is dumped result > > 2/ 2 340/340 231199 - 231199 3917599 - 3917599 1 > 0/ 2 2/ 2 231201 - 262143 3901486 30943 > -------> logical block index didn't update when remove extent index > 1/ 2 1/ 45 231881 - 232560 3901490 680 > 2/ 2 1/340 231881 - 231881 3918281 - 3918281 1 > 2/ 2 2/340 231883 - 231883 3918283 - 3918283 1 After blocks #231202~#231880 had been punch out, theses blocks can't map again. If we do map a block in #231202~#231880, we will get error messages like followings. EXT4-fs error (device md2): ext4_ext_search_left:1239: inode #13: comm flush-9:2: ix (231201) != EXT_FIRST_INDEX (1) (depth 0)! EXT4-fs (md2): delayed block allocation failed for inode 13 at logical offset 231203 with max blocks 1 with error -5 EXT4-fs (md2): This should not happen!! Data will be lost Regards, Forrest > > 2012/12/4 Forrest Liu <forrestl@xxxxxxxxxxxx>: >> Extent indexes didn't update correctly in ext4_ext_rm_idx, when depth >> of extent tree is greater than 1. >> >> Signed-off-by: Forrest Liu <forrestl@xxxxxxxxxxxx> >> --- >> fs/ext4/extents.c | 24 ++++++++++++++++++++---- >> 1 files changed, 20 insertions(+), 4 deletions(-) >> >> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c >> index d3dd618..b10b8c0 100644 >> --- a/fs/ext4/extents.c >> +++ b/fs/ext4/extents.c >> @@ -2190,13 +2190,15 @@ errout: >> * removes index from the index block. >> */ >> static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, >> - struct ext4_ext_path *path) >> + struct ext4_ext_path *path, int depth) >> { >> int err; >> ext4_fsblk_t leaf; >> + __le32 border; >> >> /* free index block */ >> - path--; >> + depth--; >> + path = path + depth; >> leaf = ext4_idx_pblock(path->p_idx); >> if (unlikely(path->p_hdr->eh_entries == 0)) { >> EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0"); >> @@ -2221,6 +2223,20 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, >> >> ext4_free_blocks(handle, inode, NULL, leaf, 1, >> EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); >> + >> + border = path->p_idx->ei_block; >> + while (--depth >= 0) { >> + if (path->p_idx != EXT_FIRST_INDEX(path->p_hdr)) >> + break; >> + path--; >> + err = ext4_ext_get_access(handle, inode, path); >> + if (err) >> + break; >> + path->p_idx->ei_block = border; >> + err = ext4_ext_dirty(handle, inode, path); >> + if (err) >> + break; >> + } >> return err; >> } >> >> @@ -2557,7 +2573,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, >> /* if this leaf is free, then we should >> * remove it from index block above */ >> if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL) >> - err = ext4_ext_rm_idx(handle, inode, path + depth); >> + err = ext4_ext_rm_idx(handle, inode, path, depth); >> >> out: >> return err; >> @@ -2760,7 +2776,7 @@ again: >> /* index is empty, remove it; >> * handle must be already prepared by the >> * truncatei_leaf() */ >> - err = ext4_ext_rm_idx(handle, inode, path + i); >> + err = ext4_ext_rm_idx(handle, inode, path, i); >> } >> /* root level has p_bh == NULL, brelse() eats this */ >> brelse(path[i].p_bh); >> -- >> 1.7.5.4 >> -- 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