From 35956d32df499515f036a81f8a38bfbb11808037 Mon Sep 17 00:00:00 2001 From: Yaroslav Tykhiy Date: Wed, 28 Nov 2007 07:29:10 +0000 Subject: [PATCH] MFp4: Add a new option to newfs(8), -r, to specify reserved space at the end of the device. It can be useful, e.g., when the device is to become a member of a gmirror array later w/o losing the file system on it. Document the new option in the manpage. While I'm here, improve error handling for -s option, which is syntactically similar to -r; and document the fact that -s0 selects the default fs size explicitly, which can be useful, e.g., in a menu-based wrapper around newfs(8) requiring some value be entered for the fs size. Also fix a small typo in the help line for -s (missing space). Idea and initial implementation by: marck Discussed on: -fs Critical review by: bde Tested with: cmp(1) --- sbin/newfs/newfs.8 | 24 +++++++++++++++++--- sbin/newfs/newfs.c | 55 +++++++++++++++++++++++++++++++--------------- sbin/newfs/newfs.h | 2 +- 3 files changed, 59 insertions(+), 22 deletions(-) diff --git a/sbin/newfs/newfs.8 b/sbin/newfs/newfs.8 index 8be6d3521485..875f915c0db1 100644 --- a/sbin/newfs/newfs.8 +++ b/sbin/newfs/newfs.8 @@ -52,6 +52,7 @@ .Op Fl i Ar bytes .Op Fl m Ar free-space .Op Fl o Ar optimization +.Op Fl r Ar reserved .Op Fl s Ar size .Ar special .Sh DESCRIPTION @@ -196,14 +197,30 @@ the default is to optimize for See .Xr tunefs 8 for more details on how to set this option. +.It Fl r Ar reserved +The size, in sectors, of reserved space +at the end of the partition specified in +.Ar special . +This space will not be occupied by the file system; +it can be used by other consumers such as +.Xr geom 4 . +Defaults to 0. .It Fl s Ar size The size of the file system in sectors. This value defaults to the size of the raw partition specified in .Ar special -(in other words, -.Nm -will use the entire partition for the file system). +less the +.Ar reserved +space at its end (see +.Fl r ) . +A +.Ar size +of 0 can also be used to choose the default value. +A valid +.Ar size +value cannot be larger than the default one, +which means that the file system cannot extend into the reserved space. .El .Pp The following options override the standard sizes for the disk geometry. @@ -237,6 +254,7 @@ This large fragment size may lead to much wasted space on file systems that contain many small files. .Sh SEE ALSO .Xr fdformat 1 , +.Xr geom 4 , .Xr disktab 5 , .Xr fs 5 , .Xr bsdlabel 8 , diff --git a/sbin/newfs/newfs.c b/sbin/newfs/newfs.c index 41823cb42e9d..532e066a5238 100644 --- a/sbin/newfs/newfs.c +++ b/sbin/newfs/newfs.c @@ -120,7 +120,7 @@ int Eflag = 0; /* exit in middle of newfs for testing */ int Jflag; /* enable gjournal for file system */ int lflag; /* enable multilabel for file system */ int nflag; /* do not create .snap directory */ -quad_t fssize; /* file system size */ +intmax_t fssize; /* file system size */ int sectorsize; /* bytes/sector */ int realsectorsize; /* bytes/sector in hardware */ int fsize = 0; /* fragment size */ @@ -141,6 +141,7 @@ static char device[MAXPATHLEN]; static char *disktype; static int unlabeled; +static void getfssize(intmax_t *, const char *p, intmax_t, intmax_t); static struct disklabel *getdisklabel(char *s); static void rewritelabel(char *s, struct disklabel *lp); static void usage(void); @@ -153,11 +154,13 @@ main(int argc, char *argv[]) struct partition oldpartition; struct stat st; char *cp, *special; + intmax_t reserved; int ch, i; off_t mediasize; + reserved = 0; while ((ch = getopt(argc, argv, - "EJL:NO:RS:T:Ua:b:c:d:e:f:g:h:i:lm:no:s:")) != -1) + "EJL:NO:RS:T:Ua:b:c:d:e:f:g:h:i:lm:no:r:s:")) != -1) switch (ch) { case 'E': Eflag++; @@ -262,11 +265,19 @@ main(int argc, char *argv[]) "%s: unknown optimization preference: use `space' or `time'", optarg); break; + case 'r': + errno = 0; + reserved = strtoimax(optarg, &cp, 0); + if (errno != 0 || cp == optarg || + *cp != '\0' || reserved < 0) + errx(1, "%s: bad reserved size", optarg); + break; case 's': errno = 0; - fssize = strtoimax(optarg, NULL, 0); - if (errno != 0) - err(1, "%s: bad file system size", optarg); + fssize = strtoimax(optarg, &cp, 0); + if (errno != 0 || cp == optarg || + *cp != '\0' || fssize < 0) + errx(1, "%s: bad file system size", optarg); break; case '?': default: @@ -302,13 +313,8 @@ main(int argc, char *argv[]) if (sectorsize == 0) ioctl(disk.d_fd, DIOCGSECTORSIZE, §orsize); - if (sectorsize && !ioctl(disk.d_fd, DIOCGMEDIASIZE, &mediasize)) { - if (fssize == 0) - fssize = mediasize / sectorsize; - else if (fssize > mediasize / sectorsize) - errx(1, "%s: maximum file system size is %jd", - special, (intmax_t)(mediasize / sectorsize)); - } + if (sectorsize && !ioctl(disk.d_fd, DIOCGMEDIASIZE, &mediasize)) + getfssize(&fssize, special, mediasize / sectorsize, reserved); pp = NULL; lp = getdisklabel(special); if (lp != NULL) { @@ -328,11 +334,7 @@ main(int argc, char *argv[]) if (pp->p_fstype == FS_BOOT) errx(1, "%s: `%c' partition overlaps boot program", special, *cp); - if (fssize == 0) - fssize = pp->p_size; - if (fssize > pp->p_size) - errx(1, - "%s: maximum file system size %d", special, pp->p_size); + getfssize(&fssize, special, pp->p_size, reserved); if (sectorsize == 0) sectorsize = lp->d_secsize; if (fsize == 0) @@ -385,6 +387,22 @@ main(int argc, char *argv[]) exit(0); } +void +getfssize(intmax_t *fsz, const char *s, intmax_t disksize, intmax_t reserved) +{ + intmax_t available; + + available = disksize - reserved; + if (available <= 0) + errx(1, "%s: reserved not less than device size %jd", + s, disksize); + if (*fsz == 0) + *fsz = available; + else if (*fsz > available) + errx(1, "%s: maximum file system size is %jd", + s, available); +} + struct disklabel * getdisklabel(char *s) { @@ -443,6 +461,7 @@ usage() fprintf(stderr, "\t-n do not create .snap directory\n"); fprintf(stderr, "\t-m minimum free space %%\n"); fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); - fprintf(stderr, "\t-s file systemsize (sectors)\n"); + fprintf(stderr, "\t-r reserved sectors at the end of device\n"); + fprintf(stderr, "\t-s file system size (sectors)\n"); exit(1); } diff --git a/sbin/newfs/newfs.h b/sbin/newfs/newfs.h index 55f920f02925..19e383acc809 100644 --- a/sbin/newfs/newfs.h +++ b/sbin/newfs/newfs.h @@ -52,7 +52,7 @@ extern int Eflag; /* exit as if error, for testing */ extern int Jflag; /* enable gjournal for file system */ extern int lflag; /* enable multilabel MAC for file system */ extern int nflag; /* do not create .snap directory */ -extern quad_t fssize; /* file system size */ +extern intmax_t fssize; /* file system size */ extern int sectorsize; /* bytes/sector */ extern int realsectorsize; /* bytes/sector in hardware*/ extern int fsize; /* fragment size */