Avoid overflowing the column-width calc printing files over 4B blocks. Document the [KMG] suffixes for the "-b <blocksize>" option. The blocksize is limited to at most 1GiB blocksize to avoid shifting all extents down to zero GB in size. Even the use of 1GB blocksize is unlikely, but non-ext4 filesystems may use multi-GB extents. Signed-off-by: Andreas Dilger <adilger@xxxxxxxxx> Lustre-bug-id: https://jira.whamcloud.com/browse/LU-13197 --- misc/filefrag.8.in | 4 ++-- misc/filefrag.c | 36 ++++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/misc/filefrag.8.in b/misc/filefrag.8.in index 5292672..4b89e72 100644 --- a/misc/filefrag.8.in +++ b/misc/filefrag.8.in @@ -33,8 +33,8 @@ testing purposes. .BI \-b blocksize Use .I blocksize -in bytes for output instead of the filesystem blocksize. -For compatibility with earlier versions of +in bytes, or with [KMG] suffix, up to 1GB for output instead of the +filesystem blocksize. For compatibility with earlier versions of .BR filefrag , if .I blocksize diff --git a/misc/filefrag.c b/misc/filefrag.c index 1eec146..032535f 100644 --- a/misc/filefrag.c +++ b/misc/filefrag.c @@ -53,7 +53,7 @@ extern int optind; #include <ext2fs/fiemap.h> int verbose = 0; -int blocksize; /* Use specified blocksize (default 1kB) */ +unsigned int blocksize; /* Use specified blocksize (default 1kB) */ int sync_file = 0; /* fsync file before getting the mapping */ int xattr_map = 0; /* get xattr mapping */ int force_bmap; /* force use of FIBMAP instead of FIEMAP */ @@ -73,7 +73,7 @@ const char *hex_fmt = "%4d: %*llx..%*llx: %*llx..%*llx: %6llx: %s\n"; #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ #define EXT3_IOC_GETFLAGS _IOR('f', 1, long) -static int int_log2(int arg) +static int ulong_log2(unsigned long arg) { int l = 0; @@ -85,7 +85,7 @@ static int int_log2(int arg) return l; } -static int int_log10(unsigned long long arg) +static int ulong_log10(unsigned long long arg) { int l = 0; @@ -452,17 +452,17 @@ static int frag_report(const char *filename) } last_device = st.st_dev; - width = int_log10(fsinfo.f_blocks); + width = ulong_log10(fsinfo.f_blocks); if (width > physical_width) physical_width = width; numblocks = (st.st_size + blksize - 1) / blksize; if (blocksize != 0) - blk_shift = int_log2(blocksize); + blk_shift = ulong_log2(blocksize); else - blk_shift = int_log2(blksize); + blk_shift = ulong_log2(blksize); - width = int_log10(numblocks); + width = ulong_log10(numblocks); if (width > logical_width) logical_width = width; if (verbose) @@ -517,7 +517,7 @@ out_close: static void usage(const char *progname) { - fprintf(stderr, "Usage: %s [-b{blocksize}] [-BeksvxX] file ...\n", + fprintf(stderr, "Usage: %s [-b{blocksize}[KMG]] [-BeksvxX] file ...\n", progname); exit(1); } @@ -535,7 +535,9 @@ int main(int argc, char**argv) case 'b': if (optarg) { char *end; - blocksize = strtoul(optarg, &end, 0); + unsigned long val; + + val = strtoul(optarg, &end, 0); if (end) { #if __GNUC_PREREQ (7, 0) #pragma GCC diagnostic push @@ -544,15 +546,15 @@ int main(int argc, char**argv) switch (end[0]) { case 'g': case 'G': - blocksize *= 1024; + val *= 1024; /* fall through */ case 'm': case 'M': - blocksize *= 1024; + val *= 1024; /* fall through */ case 'k': case 'K': - blocksize *= 1024; + val *= 1024; break; default: break; @@ -561,6 +563,16 @@ int main(int argc, char**argv) #pragma GCC diagnostic pop #endif } + /* Specifying too large a blocksize will just + * shift all extents down to zero length. Even + * 1GB is questionable, but caveat emptor. */ + if (val > 1024 * 1024 * 1024) { + fprintf(stderr, + "%s: blocksize %lu over 1GB\n", + argv[0], val); + usage(argv[0]); + } + blocksize = val; } else { /* Allow -b without argument for compat. Remove * this eventually so "-b {blocksize}" works */ fprintf(stderr, "%s: -b needs a blocksize " -- 1.8.0