From: Andreas Dilger Date: Wed, 5 Feb 2020 03:54:03 +0000 (-0700) Subject: LU-13197 misc: handle large files with filefrag X-Git-Tag: v1.45.2.wc2~2 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=bd3c5a11044c9427066a0b2a3122787a269ddeb0;p=tools%2Fe2fsprogs.git LU-13197 misc: handle large files with filefrag Avoid overflowing the column-width calc when printing files over 4B blocks. Document the availability of [KMG] suffixes for the "-b " option. The blocksize is limited to at most 1GiB blocksize to avoid shifting all of the extents down to zero GB in size. Even the use of 1GB blocksize is a bit tenuous, but some filesystems may multi-GB extents beyond ext4. Change-Id: I003a721a3d199b1cb8b3912236328eb80b34f0fe Signed-off-by: Andreas Dilger Reviewed-on: https://review.whamcloud.com/37439 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Wang Shilong Reviewed-by: Andreas Dilger --- diff --git a/misc/filefrag.8.in b/misc/filefrag.8.in index 797c763..69e9953 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 ef1864e..52fb65d 100644 --- a/misc/filefrag.c +++ b/misc/filefrag.c @@ -53,7 +53,7 @@ extern int optind; #include 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 */ @@ -75,7 +75,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; @@ -87,7 +87,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; @@ -490,17 +490,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) @@ -555,7 +555,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); } @@ -574,7 +574,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 @@ -583,15 +585,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; @@ -600,6 +602,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 "