From: Zheng Liu <wenqing.lz@xxxxxxxxxx> This commit fixes a bug in filefrag that filefrag miss calculates contiguous extent when physical blocks are contiguous but logical blocks aren't. This case can be created by xfstests #218 or the following script. for I in `seq 0 2 31`; do dd if=/dev/zero of=$testfile bs=4k count=1 conv=notrunc \ seek=$I oflag=sync &>/dev/null done Meanwhile this commit prints expected logical block. Signed-off-by: Zheng Liu <wenqing.lz@xxxxxxxxxx> --- misc/filefrag.c | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/misc/filefrag.c b/misc/filefrag.c index ee03a07..3af938f 100644 --- a/misc/filefrag.c +++ b/misc/filefrag.c @@ -116,16 +116,17 @@ static int get_bmap(int fd, unsigned long block, unsigned long *phy_blk) static void print_extent_header(void) { - printf(" ext: %*s %*s length: %*s flags:\n", + printf(" ext: %*s %*s length: %*s %*s flags:\n", logical_width * 2 + 3, "logical_offset:", physical_width * 2 + 3, "physical_offset:", - physical_width + 1, - "expected:"); + physical_width + 1, "log_expected:", + physical_width + 1, "phy_expected:"); } static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex, - unsigned long long expected, int blk_shift, + unsigned long long lexpected, + unsigned long long pexpected, int blk_shift, ext2fs_struct_stat *st) { unsigned long long physical_blk; @@ -133,6 +134,8 @@ static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex, unsigned long long ext_len; unsigned long long ext_blks; char flags[256] = ""; + char logex_flags[32] = ""; + char phyex_flags[32] = ""; /* For inline data all offsets should be in bytes, not blocks */ if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_INLINE) @@ -143,11 +146,20 @@ static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex, logical_blk = fm_extent->fe_logical >> blk_shift; physical_blk = fm_extent->fe_physical >> blk_shift; - if (expected) - sprintf(flags, ext_fmt == hex_fmt ? "%*llx: " : "%*llu: ", - physical_width, expected >> blk_shift); + if (lexpected) + sprintf(logex_flags, ext_fmt == hex_fmt ? "%*llx: " : "%*llu: ", + physical_width, lexpected >> blk_shift); else - sprintf(flags, "%.*s ", physical_width, " "); + sprintf(logex_flags, "%.*s ", physical_width, " "); + + if (pexpected) + sprintf(phyex_flags, ext_fmt == hex_fmt ? "%*llx: " : "%*llu: ", + physical_width, pexpected >> blk_shift); + else + sprintf(phyex_flags, "%.*s ", physical_width, " "); + + strcat(flags, logex_flags); + strcat(flags, phyex_flags); if (fm_extent->fe_flags & FIEMAP_EXTENT_UNKNOWN) strcat(flags, "unknown,"); @@ -188,7 +200,7 @@ static int filefrag_fiemap(int fd, int blk_shift, int *num_extents, struct fiemap_extent *fm_ext = &fiemap->fm_extents[0]; int count = (sizeof(buf) - sizeof(*fiemap)) / sizeof(struct fiemap_extent); - unsigned long long expected = 0; + unsigned long long lexpected = 0, pexpected = 0; unsigned long flags = 0; unsigned int i; static int fiemap_incompat_printed; @@ -230,18 +242,21 @@ static int filefrag_fiemap(int fd, int blk_shift, int *num_extents, for (i = 0; i < fiemap->fm_mapped_extents; i++) { if (fm_ext[i].fe_logical != 0 && - fm_ext[i].fe_physical != expected) { + (fm_ext[i].fe_logical != lexpected || + fm_ext[i].fe_physical != pexpected)) { tot_extents++; } else { - expected = 0; + lexpected = 0; + pexpected = 0; if (!tot_extents) tot_extents = 1; } if (verbose) - print_extent_info(&fm_ext[i], n, expected, - blk_shift, st); + print_extent_info(&fm_ext[i], n, lexpected, + pexpected, blk_shift, st); - expected = fm_ext[i].fe_physical + fm_ext[i].fe_length; + lexpected = fm_ext[i].fe_logical + fm_ext[i].fe_length; + pexpected = fm_ext[i].fe_physical + fm_ext[i].fe_length; if (fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST) last = 1; n++; @@ -308,7 +323,7 @@ static int filefrag_fibmap(int fd, int blk_shift, int *num_extents, if (force_extent && last_block != 0 && (block != last_block + 1 || fm_ext.fe_logical + fm_ext.fe_length != logical)) { - print_extent_info(&fm_ext, *num_extents - 1, + print_extent_info(&fm_ext, *num_extents - 1, logical, (last_block + 1) * st->st_blksize, blk_shift, st); fm_ext.fe_logical = logical; @@ -325,7 +340,7 @@ static int filefrag_fibmap(int fd, int blk_shift, int *num_extents, } if (force_extent) - print_extent_info(&fm_ext, *num_extents - 1, + print_extent_info(&fm_ext, *num_extents - 1, logical, last_block * st->st_blksize, blk_shift, st); return count; @@ -339,7 +354,7 @@ static void frag_report(const char *filename) long fd; unsigned long numblocks; int data_blocks_per_cyl = 1; - int num_extents = 1, expected = ~0; + int num_extents = 1, expected = 0; int is_ext2 = 0; static dev_t last_device; unsigned int flags; -- 1.7.12.rc2.18.g61b472e -- 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