[PATCH 1/2] growfs: support unit postfixes when specifying sizes
Christoph Hellwig <[email protected]> Thu, 30 Jul 2026 14:25:13 +0200
| Newsgroups | org.kernel.vger.linux-xfs |
|---|---|
| Message-ID | <[email protected]> |
Try using cvtnum to parse the sizes for the -D, -L and -R arguments, and only fall back to plain integer parsing and interpreting it as blocks when that fails. This matches the mkfs UI and makes specifying a size significantly easier. Signed-off-by: Christoph Hellwig <[email protected]> --- growfs/xfs_growfs.c | 32 ++++++++++++++++++++++++++++---- man/man8/xfs_growfs.8 | 39 +++++++++++++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/growfs/xfs_growfs.c b/growfs/xfs_growfs.c index 0d0b2ae3e739..184631b1735b 100644 --- a/growfs/xfs_growfs.c +++ b/growfs/xfs_growfs.c @@ -5,6 +5,7 @@ */ #include "libxfs.h" +#include "libfrog/convert.h" #include "libfrog/paths.h" #include "libfrog/fsgeom.h" @@ -31,6 +32,19 @@ Options:\n\ exit(2); } +static long long +parse_size( + struct xfs_fsop_geom *geo, + const char *size_str) +{ + long long size; + + size = cvtnum(geo->blocksize, geo->sectsize, size_str); + if (size == -1) + return strtoll(size_str, NULL, 10); + return size / geo->blocksize; +} + int main(int argc, char **argv) { @@ -55,6 +69,9 @@ main(int argc, char **argv) struct xfs_fsop_geom ngeo; /* new fs geometry */ int rflag; /* -r flag */ long long rsize; /* new rt size in fs blocks */ + const char *dsize_str = NULL; + const char *lsize_str = NULL; + const char *rsize_str = NULL; int xflag; /* -x flag */ char *fname; /* mount point name */ char *datadev; /* data device name */ @@ -77,7 +94,7 @@ main(int argc, char **argv) while ((c = getopt(argc, argv, "dD:e:ilL:m:np:rR:t:xV")) != EOF) { switch (c) { case 'D': - dsize = strtoll(optarg, NULL, 10); + dsize_str = strdup(optarg); fallthrough; case 'd': dflag = 1; @@ -90,7 +107,7 @@ main(int argc, char **argv) lflag = iflag = 1; break; case 'L': - lsize = strtoll(optarg, NULL, 10); + lsize_str = strdup(optarg); fallthrough; case 'l': lflag = 1; @@ -106,7 +123,7 @@ main(int argc, char **argv) progname = optarg; break; case 'R': - rsize = strtoll(optarg, NULL, 10); + rsize_str = strdup(optarg); fallthrough; case 'r': rflag = 1; @@ -202,7 +219,7 @@ main(int argc, char **argv) progname, fname); exit(1); } - if (rflag && (!xi.rt.dev && !geo.rtstart)) { + if (rflag && (!xi.rt.dev && !xi.nr_raid_devices & !geo.rtstart)) { fprintf(stderr, _("%s: failed to access realtime device for %s\n"), progname, fname); @@ -211,6 +228,13 @@ main(int argc, char **argv) xfs_report_geom(&geo, datadev, logdev, rtdev); + if (dsize_str) + dsize = parse_size(&geo, dsize_str); + if (lsize_str) + lsize = parse_size(&geo, lsize_str); + if (rsize_str) + rsize = parse_size(&geo, rsize_str); + if (geo.rtstart) { xfs_daddr_t rtstart = geo.rtstart * (geo.blocksize / BBSIZE); diff --git a/man/man8/xfs_growfs.8 b/man/man8/xfs_growfs.8 index 2e329fa61758..d6e5fe13e943 100644 --- a/man/man8/xfs_growfs.8 +++ b/man/man8/xfs_growfs.8 @@ -57,6 +57,32 @@ The filesystem must be mounted to be grown (see .BR mount (8)). The existing contents of the filesystem are undisturbed, and the added space becomes available for additional file storage. +The following lists possible multiplication suffixes for any argument specifying +sizes. +.RS +.PD 0 +.HP +.BR s "\ \-\ multiply by sector size (default = 512, see " \-s +option below). +.HP +.BR b "\ \-\ multiply by filesystem block size (default = 4K, see " \-b +option below). +.HP +.BR k "\ \-\ multiply by one kilobyte (1,024 bytes)." +.HP +.BR m "\ \-\ multiply by one megabyte (1,048,576 bytes)." +.HP +.BR g "\ \-\ multiply by one gigabyte (1,073,741,824 bytes)." +.HP +.BR t "\ \-\ multiply by one terabyte (1,099,511,627,776 bytes)." +.HP +.BR p "\ \-\ multiply by one petabyte (1,024 terabytes)." +.HP +.BR e "\ \-\ multiply by one exabyte (1,048,576 terabytes)." +.PD +.RE +If no suffix is specified, the sizes are in file system blocks. +.RE .SH OPTIONS .TP .BI "\-d | \-D " size @@ -67,9 +93,8 @@ option is given, the data section is changed to that .IR size , otherwise the data section is grown to the largest size possible with the .B \-d -option. The size is expressed in filesystem blocks. A filesystem with only -1 AG cannot be shrunk further, and a filesystem cannot be shrunk to the point -where it would only have 1 AG. +option. A filesystem with only 1 AG cannot be shrunk further, and a +filesystem cannot be shrunk to the point where it would only have 1 AG. .B [NOTE: Only shrinking the last AG without removing it is implemented] .TP .B \-e @@ -90,8 +115,7 @@ shrunk, or moved. If the .I size option is given, the log section is changed to be that .IR size , -if possible. The size is expressed in filesystem blocks. -The size of an internal log must be smaller than the size +if possible. The size of an internal log must be smaller than the size of an allocation group (this value is printed at .BR mkfs (8) time). If neither @@ -124,9 +148,8 @@ Specifies that the real-time section of the filesystem should be grown. If the option is given, the real-time section is grown to that size, otherwise the real-time section is grown to the largest size possible with the .B \-r -option. The size is expressed in filesystem blocks. -The filesystem does not need to have contained a real-time section before -the +option. The filesystem does not need to have contained a real-time section +before the .B xfs_growfs operation. .TP -- 2.53.0