Index: stable/11/sbin/newfs/newfs.8 =================================================================== --- stable/11/sbin/newfs/newfs.8 (revision 343537) +++ stable/11/sbin/newfs/newfs.8 (revision 343538) @@ -1,333 +1,334 @@ .\" Copyright (c) 1983, 1987, 1991, 1993, 1994 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)newfs.8 8.6 (Berkeley) 5/3/95 .\" $FreeBSD$ .\" .Dd July 15, 2015 .Dt NEWFS 8 .Os .Sh NAME .Nm newfs .Nd construct a new UFS1/UFS2 file system .Sh SYNOPSIS .Nm .Op Fl EJNUjlnt .Op Fl L Ar volname .Op Fl O Ar filesystem-type .Op Fl S Ar sector-size .Op Fl T Ar disktype .Op Fl a Ar maxcontig .Op Fl b Ar block-size .Op Fl c Ar blocks-per-cylinder-group .Op Fl d Ar max-extent-size .Op Fl e Ar maxbpg .Op Fl f Ar frag-size .Op Fl g Ar avgfilesize .Op Fl h Ar avgfpdir .Op Fl i Ar bytes .Op Fl k Ar held-for-metadata-blocks .Op Fl m Ar free-space .Op Fl o Ar optimization .Op Fl p Ar partition .Op Fl r Ar reserved .Op Fl s Ar size .Ar special .Sh DESCRIPTION The .Nm utility is used to initialize and clear file systems before first use. The .Nm utility builds a file system on the specified special file. (We often refer to the .Dq special file as the .Dq disk , although the special file need not be a physical disk. In fact, it need not even be special.) Typically the defaults are reasonable, however .Nm has numerous options to allow the defaults to be selectively overridden. .Pp The following options define the general layout policies: .Bl -tag -width indent .It Fl E Erase the content of the disk before making the filesystem. The reserved area in front of the superblock (for bootcode) will not be erased. .Pp This option is only relevant for flash based storage devices that use wear-leveling algorithms. .Pp Erasing may take a long time as it writes to every sector on the disk. .It Fl J Enable journaling on the new file system via gjournal. See .Xr gjournal 8 for details. .It Fl L Ar volname Add a volume label to the new file system. +Legal characters are alphanumerics and underscores. .It Fl N Cause the file system parameters to be printed out without really creating the file system. .It Fl O Ar filesystem-type Use 1 to specify that a UFS1 format file system be built; use 2 to specify that a UFS2 format file system be built. The default format is UFS2. .It Fl T Ar disktype For backward compatibility. .It Fl U Enable soft updates on the new file system. .It Fl a Ar maxcontig Specify the maximum number of contiguous blocks that will be laid out before forcing a rotational delay. The default value is 16. See .Xr tunefs 8 for more details on how to set this option. .It Fl b Ar block-size The block size of the file system, in bytes. It must be a power of 2. The default size is 32768 bytes, and the smallest allowable size is 4096 bytes. The optimal block:fragment ratio is 8:1. Other ratios are possible, but are not recommended, and may produce poor results. .It Fl c Ar blocks-per-cylinder-group The number of blocks per cylinder group in a file system. The default is to compute the maximum allowed by the other parameters. This value is dependent on a number of other parameters, in particular the block size and the number of bytes per inode. .It Fl d Ar max-extent-size The file system may choose to store large files using extents. This parameter specifies the largest extent size that may be used. The default value is the file system blocksize. It is presently limited to a maximum value of 16 times the file system blocksize and a minimum value of the file system blocksize. .It Fl e Ar maxbpg Indicate the maximum number of blocks any single file can allocate out of a cylinder group before it is forced to begin allocating blocks from another cylinder group. The default is about one quarter of the total blocks in a cylinder group. See .Xr tunefs 8 for more details on how to set this option. .It Fl f Ar frag-size The fragment size of the file system in bytes. It must be a power of two ranging in value between .Ar blocksize Ns /8 and .Ar blocksize . The default is 4096 bytes. .It Fl g Ar avgfilesize The expected average file size for the file system. .It Fl h Ar avgfpdir The expected average number of files per directory on the file system. .It Fl i Ar bytes Specify the density of inodes in the file system. The default is to create an inode for every .Pq 2 * Ar frag-size bytes of data space. If fewer inodes are desired, a larger number should be used; to create more inodes a smaller number should be given. One inode is required for each distinct file, so this value effectively specifies the average file size on the file system. .It Fl j Enable soft updates journaling on the new file system. This flag is implemented by running the .Xr tunefs 8 utility found in the user's .Dv $PATH . .It Fl k Ar held-for-metadata-blocks Set the amount of space to be held for metadata blocks in each cylinder group. When set, the file system preference routines will try to save the specified amount of space immediately following the inode blocks in each cylinder group for use by metadata blocks. Clustering the metadata blocks speeds up random file access and decreases the running time of .Xr fsck 8 . By default .Nm sets it to half of the space reserved to minfree. .It Fl l Enable multilabel MAC on the new file system. .It Fl m Ar free-space The percentage of space reserved from normal users; the minimum free space threshold. The default value used is defined by .Dv MINFREE from .In ufs/ffs/fs.h , currently 8%. See .Xr tunefs 8 for more details on how to set this option. .It Fl n Do not create a .Pa .snap directory on the new file system. The resulting file system will not support snapshot generation, so .Xr dump 8 in live mode and background .Xr fsck 8 will not function properly. The traditional .Xr fsck 8 and offline .Xr dump 8 will work on the file system. This option is intended primarily for memory or vnode-backed file systems that do not require .Xr dump 8 or .Xr fsck 8 support. .It Fl o Ar optimization .Cm ( space or .Cm time ) . The file system can either be instructed to try to minimize the time spent allocating blocks, or to try to minimize the space fragmentation on the disk. If the value of minfree (see above) is less than 8%, the default is to optimize for .Cm space ; if the value of minfree is greater than or equal to 8%, the default is to optimize for .Cm time . See .Xr tunefs 8 for more details on how to set this option. .It Fl p Ar partition The partition name (a..h) you want to use in case the underlying image is a file, so you do not have access to individual partitions through the filesystem. Can also be used with a device, e.g., .Nm .Fl p Ar f .Ar /dev/da1s3 is equivalent to .Nm .Ar /dev/da1s3f . .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 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. .It Fl t Turn on the TRIM enable flag. If enabled, and if the underlying device supports the BIO_DELETE command, the file system will send a delete request to the underlying device for each freed block. The trim enable flag is typically set when the underlying device uses flash-memory as the device can use the delete command to pre-zero or at least avoid copying blocks that have been deleted. .El .Pp The following options override the standard sizes for the disk geometry. Their default values are taken from the disk label. Changing these defaults is useful only when using .Nm to build a file system whose raw image will eventually be used on a different type of disk than the one on which it is initially created (for example on a write-once disk). Note that changing any of these values from their defaults will make it impossible for .Xr fsck 8 to find the alternate superblocks if the standard superblock is lost. .Bl -tag -width indent .It Fl S Ar sector-size The size of a sector in bytes (almost never anything but 512). .El .Sh EXAMPLES .Dl newfs /dev/ada3s1a .Pp Creates a new ufs file system on .Pa ada3s1a . The .Nm utility will use a block size of 32768 bytes, a fragment size of 4096 bytes and the largest possible number of blocks per cylinders group. These values tend to produce better performance for most applications than the historical defaults (8192 byte block size and 1024 byte fragment size). 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 camcontrol 8 , .Xr dump 8 , .Xr dumpfs 8 , .Xr fsck 8 , .Xr gpart 8 , .Xr gjournal 8 , .Xr growfs 8 , .Xr gvinum 8 , .Xr makefs 8 , .Xr mount 8 , .Xr tunefs 8 .Rs .%A M. McKusick .%A W. Joy .%A S. Leffler .%A R. Fabry .%T A Fast File System for UNIX .%J ACM Transactions on Computer Systems 2 .%V 3 .%P pp 181-197 .%D August 1984 .%O (reprinted in the BSD System Manager's Manual) .Re .Sh HISTORY The .Nm utility appeared in .Bx 4.2 . Index: stable/11/sbin/newfs/newfs.c =================================================================== --- stable/11/sbin/newfs/newfs.c (revision 343537) +++ stable/11/sbin/newfs/newfs.c (revision 343538) @@ -1,508 +1,509 @@ /* * Copyright (c) 2002 Networks Associates Technology, Inc. * All rights reserved. * * This software was developed for the FreeBSD Project by Marshall * Kirk McKusick and Network Associates Laboratories, the Security * Research Division of Network Associates, Inc. under DARPA/SPAWAR * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS * research program. * * Copyright (c) 1983, 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1983, 1989, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)newfs.c 8.13 (Berkeley) 5/1/95"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); /* * newfs: friendly front end to mkfs */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "newfs.h" int Eflag; /* Erase previous disk contents */ int Lflag; /* add a volume label */ int Nflag; /* run without writing file system */ int Oflag = 2; /* file system format (1 => UFS1, 2 => UFS2) */ int Rflag; /* regression test */ int Uflag; /* enable soft updates for file system */ int jflag; /* enable soft updates journaling for filesys */ int Xflag = 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 */ int tflag; /* enable TRIM */ intmax_t fssize; /* file system size */ off_t mediasize; /* device size */ int sectorsize; /* bytes/sector */ int realsectorsize; /* bytes/sector in hardware */ int fsize = 0; /* fragment size */ int bsize = 0; /* block size */ int maxbsize = 0; /* maximum clustering */ int maxblkspercg = MAXBLKSPERCG; /* maximum blocks per cylinder group */ int minfree = MINFREE; /* free space threshold */ int metaspace; /* space held for metadata blocks */ int opt = DEFAULTOPT; /* optimization preference (space or time) */ int density; /* number of bytes per inode */ int maxcontig = 0; /* max contiguous blocks to allocate */ int maxbpg; /* maximum blocks per file in a cyl group */ int avgfilesize = AVFILESIZ;/* expected average file size */ int avgfilesperdir = AFPDIR;/* expected number of files per directory */ u_char *volumelabel = NULL; /* volume label for filesystem */ struct uufsd disk; /* libufs disk structure */ static char device[MAXPATHLEN]; static u_char bootarea[BBSIZE]; static int is_file; /* work on a file, not a device */ static char *dkname; static char *disktype; static void getfssize(intmax_t *, const char *p, intmax_t, intmax_t); static struct disklabel *getdisklabel(char *s); static void usage(void); static int expand_number_int(const char *buf, int *num); ufs2_daddr_t part_ofs; /* partition offset in blocks, used with files */ int main(int argc, char *argv[]) { struct partition *pp; struct disklabel *lp; struct stat st; char *cp, *special; intmax_t reserved; int ch, i, rval; char part_name; /* partition name, default to full disk */ part_name = 'c'; reserved = 0; while ((ch = getopt(argc, argv, "EJL:NO:RS:T:UXa:b:c:d:e:f:g:h:i:jk:lm:no:p:r:s:t")) != -1) switch (ch) { case 'E': Eflag = 1; break; case 'J': Jflag = 1; break; case 'L': volumelabel = optarg; i = -1; while (isalnum(volumelabel[++i]) || volumelabel[i] == '_'); if (volumelabel[i] != '\0') { - errx(1, "bad volume label. Valid characters are alphanumerics."); + errx(1, "bad volume label. Valid characters " + "are alphanumerics and underscores."); } if (strlen(volumelabel) >= MAXVOLLEN) { errx(1, "bad volume label. Length is longer than %d.", MAXVOLLEN); } Lflag = 1; break; case 'N': Nflag = 1; break; case 'O': if ((Oflag = atoi(optarg)) < 1 || Oflag > 2) errx(1, "%s: bad file system format value", optarg); break; case 'R': Rflag = 1; break; case 'S': rval = expand_number_int(optarg, §orsize); if (rval < 0 || sectorsize <= 0) errx(1, "%s: bad sector size", optarg); break; case 'T': disktype = optarg; break; case 'j': jflag = 1; /* fall through to enable soft updates */ case 'U': Uflag = 1; break; case 'X': Xflag++; break; case 'a': rval = expand_number_int(optarg, &maxcontig); if (rval < 0 || maxcontig <= 0) errx(1, "%s: bad maximum contiguous blocks", optarg); break; case 'b': rval = expand_number_int(optarg, &bsize); if (rval < 0) errx(1, "%s: bad block size", optarg); if (bsize < MINBSIZE) errx(1, "%s: block size too small, min is %d", optarg, MINBSIZE); if (bsize > MAXBSIZE) errx(1, "%s: block size too large, max is %d", optarg, MAXBSIZE); break; case 'c': rval = expand_number_int(optarg, &maxblkspercg); if (rval < 0 || maxblkspercg <= 0) errx(1, "%s: bad blocks per cylinder group", optarg); break; case 'd': rval = expand_number_int(optarg, &maxbsize); if (rval < 0 || maxbsize < MINBSIZE) errx(1, "%s: bad extent block size", optarg); break; case 'e': rval = expand_number_int(optarg, &maxbpg); if (rval < 0 || maxbpg <= 0) errx(1, "%s: bad blocks per file in a cylinder group", optarg); break; case 'f': rval = expand_number_int(optarg, &fsize); if (rval < 0 || fsize <= 0) errx(1, "%s: bad fragment size", optarg); break; case 'g': rval = expand_number_int(optarg, &avgfilesize); if (rval < 0 || avgfilesize <= 0) errx(1, "%s: bad average file size", optarg); break; case 'h': rval = expand_number_int(optarg, &avgfilesperdir); if (rval < 0 || avgfilesperdir <= 0) errx(1, "%s: bad average files per dir", optarg); break; case 'i': rval = expand_number_int(optarg, &density); if (rval < 0 || density <= 0) errx(1, "%s: bad bytes per inode", optarg); break; case 'l': lflag = 1; break; case 'k': if ((metaspace = atoi(optarg)) < 0) errx(1, "%s: bad metadata space %%", optarg); if (metaspace == 0) /* force to stay zero in mkfs */ metaspace = -1; break; case 'm': if ((minfree = atoi(optarg)) < 0 || minfree > 99) errx(1, "%s: bad free space %%", optarg); break; case 'n': nflag = 1; break; case 'o': if (strcmp(optarg, "space") == 0) opt = FS_OPTSPACE; else if (strcmp(optarg, "time") == 0) opt = FS_OPTTIME; else errx(1, "%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 'p': is_file = 1; part_name = optarg[0]; break; case 's': errno = 0; fssize = strtoimax(optarg, &cp, 0); if (errno != 0 || cp == optarg || *cp != '\0' || fssize < 0) errx(1, "%s: bad file system size", optarg); break; case 't': tflag = 1; break; case '?': default: usage(); } argc -= optind; argv += optind; if (argc != 1) usage(); special = argv[0]; if (!special[0]) err(1, "empty file/special name"); cp = strrchr(special, '/'); if (cp == NULL) { /* * No path prefix; try prefixing _PATH_DEV. */ snprintf(device, sizeof(device), "%s%s", _PATH_DEV, special); special = device; } if (is_file) { /* bypass ufs_disk_fillout_blank */ bzero( &disk, sizeof(disk)); disk.d_bsize = 1; disk.d_name = special; disk.d_fd = open(special, O_RDONLY); if (disk.d_fd < 0 || (!Nflag && ufs_disk_write(&disk) == -1)) errx(1, "%s: ", special); } else if (ufs_disk_fillout_blank(&disk, special) == -1 || (!Nflag && ufs_disk_write(&disk) == -1)) { if (disk.d_error != NULL) errx(1, "%s: %s", special, disk.d_error); else err(1, "%s", special); } if (fstat(disk.d_fd, &st) < 0) err(1, "%s", special); if ((st.st_mode & S_IFMT) != S_IFCHR) { warn("%s: not a character-special device", special); is_file = 1; /* assume it is a file */ dkname = special; if (sectorsize == 0) sectorsize = 512; mediasize = st.st_size; /* set fssize from the partition */ } else { if (sectorsize == 0) if (ioctl(disk.d_fd, DIOCGSECTORSIZE, §orsize) == -1) sectorsize = 0; /* back out on error for safety */ if (sectorsize && ioctl(disk.d_fd, DIOCGMEDIASIZE, &mediasize) != -1) getfssize(&fssize, special, mediasize / sectorsize, reserved); } pp = NULL; lp = getdisklabel(special); if (lp != NULL) { if (!is_file) /* already set for files */ part_name = special[strlen(special) - 1]; if ((part_name < 'a' || part_name - 'a' >= MAXPARTITIONS) && !isdigit(part_name)) errx(1, "%s: can't figure out file system partition", special); cp = &part_name; if (isdigit(*cp)) pp = &lp->d_partitions[RAW_PART]; else pp = &lp->d_partitions[*cp - 'a']; if (pp->p_size == 0) errx(1, "%s: `%c' partition is unavailable", special, *cp); if (pp->p_fstype == FS_BOOT) errx(1, "%s: `%c' partition overlaps boot program", special, *cp); getfssize(&fssize, special, pp->p_size, reserved); if (sectorsize == 0) sectorsize = lp->d_secsize; if (fsize == 0) fsize = pp->p_fsize; if (bsize == 0) bsize = pp->p_frag * pp->p_fsize; if (is_file) part_ofs = pp->p_offset; } if (sectorsize <= 0) errx(1, "%s: no default sector size", special); if (fsize <= 0) fsize = MAX(DFL_FRAGSIZE, sectorsize); if (bsize <= 0) bsize = MIN(DFL_BLKSIZE, 8 * fsize); if (minfree < MINFREE && opt != FS_OPTSPACE) { fprintf(stderr, "Warning: changing optimization to space "); fprintf(stderr, "because minfree is less than %d%%\n", MINFREE); opt = FS_OPTSPACE; } realsectorsize = sectorsize; if (sectorsize != DEV_BSIZE) { /* XXX */ int secperblk = sectorsize / DEV_BSIZE; sectorsize = DEV_BSIZE; fssize *= secperblk; if (pp != NULL) pp->p_size *= secperblk; } mkfs(pp, special); ufs_disk_close(&disk); if (!jflag) exit(0); if (execlp("tunefs", "newfs", "-j", "enable", special, NULL) < 0) err(1, "Cannot enable soft updates journaling, tunefs"); /* NOT REACHED */ } 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) { static struct disklabel lab; struct disklabel *lp; if (is_file) { if (read(disk.d_fd, bootarea, BBSIZE) != BBSIZE) err(4, "cannot read bootarea"); if (bsd_disklabel_le_dec( bootarea + (0 /* labeloffset */ + 1 /* labelsoffset */ * sectorsize), &lab, MAXPARTITIONS)) errx(1, "no valid label found"); lp = &lab; return &lab; } if (disktype) { lp = getdiskbyname(disktype); if (lp != NULL) return (lp); } return (NULL); } static void usage() { fprintf(stderr, "usage: %s [ -fsoptions ] special-device%s\n", getprogname(), " [device-type]"); fprintf(stderr, "where fsoptions are:\n"); fprintf(stderr, "\t-E Erase previous disk content\n"); fprintf(stderr, "\t-J Enable journaling via gjournal\n"); fprintf(stderr, "\t-L volume label to add to superblock\n"); fprintf(stderr, "\t-N do not create file system, just print out parameters\n"); fprintf(stderr, "\t-O file system format: 1 => UFS1, 2 => UFS2\n"); fprintf(stderr, "\t-R regression test, suppress random factors\n"); fprintf(stderr, "\t-S sector size\n"); fprintf(stderr, "\t-T disktype\n"); fprintf(stderr, "\t-U enable soft updates\n"); fprintf(stderr, "\t-a maximum contiguous blocks\n"); fprintf(stderr, "\t-b block size\n"); fprintf(stderr, "\t-c blocks per cylinders group\n"); fprintf(stderr, "\t-d maximum extent size\n"); fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); fprintf(stderr, "\t-f frag size\n"); fprintf(stderr, "\t-g average file size\n"); fprintf(stderr, "\t-h average files per directory\n"); fprintf(stderr, "\t-i number of bytes per inode\n"); fprintf(stderr, "\t-j enable soft updates journaling\n"); fprintf(stderr, "\t-k space to hold for metadata blocks\n"); fprintf(stderr, "\t-l enable multilabel MAC\n"); 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-p partition name (a..h)\n"); fprintf(stderr, "\t-r reserved sectors at the end of device\n"); fprintf(stderr, "\t-s file system size (sectors)\n"); fprintf(stderr, "\t-t enable TRIM\n"); exit(1); } static int expand_number_int(const char *buf, int *num) { int64_t num64; int rval; rval = expand_number(buf, &num64); if (rval < 0) return (rval); if (num64 > INT_MAX || num64 < INT_MIN) { errno = ERANGE; return (-1); } *num = (int)num64; return (0); } Index: stable/11/sbin/tunefs/tunefs.8 =================================================================== --- stable/11/sbin/tunefs/tunefs.8 (revision 343537) +++ stable/11/sbin/tunefs/tunefs.8 (revision 343538) @@ -1,214 +1,215 @@ .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)tunefs.8 8.2 (Berkeley) 12/11/93 .\" $FreeBSD$ .\" .Dd April 19, 2016 .Dt TUNEFS 8 .Os .Sh NAME .Nm tunefs .Nd tune up an existing UFS file system .Sh SYNOPSIS .Nm .Op Fl A .Op Fl a Cm enable | disable .Op Fl e Ar maxbpg .Op Fl f Ar avgfilesize .Op Fl j Cm enable | disable .Op Fl J Cm enable | disable .Op Fl k Ar held-for-metadata-blocks .Op Fl L Ar volname .Op Fl l Cm enable | disable .Op Fl m Ar minfree .Op Fl N Cm enable | disable .Op Fl n Cm enable | disable .Op Fl o Cm space | time .Op Fl p .Op Fl s Ar avgfpdir .Op Fl S Ar size .Op Fl t Cm enable | disable .Ar special | filesystem .Sh DESCRIPTION The .Nm utility is designed to change the dynamic parameters of a UFS file system which affect the layout policies. The .Nm utility cannot be run on an active file system. To change an active file system, it must be downgraded to read-only or unmounted. .Pp The parameters which are to be changed are indicated by the flags given below: .Bl -tag -width indent .It Fl A The file system has several backups of the super-block. Specifying this option will cause all backups to be modified as well as the primary super-block. This is potentially dangerous - use with caution. .It Fl a Cm enable | disable Turn on/off the administrative POSIX.1e ACL enable flag. .It Fl e Ar maxbpg Indicate the maximum number of blocks any single file can allocate out of a cylinder group before it is forced to begin allocating blocks from another cylinder group. Typically this value is set to about one quarter of the total blocks in a cylinder group. The intent is to prevent any single file from using up all the blocks in a single cylinder group, thus degrading access times for all files subsequently allocated in that cylinder group. The effect of this limit is to cause big files to do long seeks more frequently than if they were allowed to allocate all the blocks in a cylinder group before seeking elsewhere. For file systems with exclusively large files, this parameter should be set higher. .It Fl f Ar avgfilesize Specify the expected average file size. .It Fl j Cm enable | disable Turn on/off soft updates journaling. .It Fl J Cm enable | disable Turn on/off gjournal flag. .It Fl k Ar held-for-metadata-blocks Set the amount of space to be held for metadata blocks. When set, the file system preference routines will try to save the specified amount of space immediately following the inode blocks in each cylinder group for use by metadata blocks. Clustering the metadata blocks speeds up random file access and decreases the running time of .Xr fsck 8 . While this option can be set at any time, it is most effective if set before any data is loaded into the file system. By default .Xr newfs 8 sets it to half of the space reserved to minfree. .It Fl L Ar volname Add/modify an optional file system volume label. +Legal characters are alphanumerics and underscores. .It Fl l Cm enable | disable Turn on/off MAC multilabel flag. .It Fl m Ar minfree Specify the percentage of space held back from normal users; the minimum free space threshold. The default value used is 8%. Note that lowering the threshold can adversely affect performance: .Bl -bullet .It Settings of 5% and less force space optimization to always be used which will greatly increase the overhead for file writes. .It The file system's ability to avoid fragmentation will be reduced when the total free space, including the reserve, drops below 15%. As free space approaches zero, throughput can degrade by up to a factor of three over the performance obtained at a 10% threshold. .El .Pp If the value is raised above the current usage level, users will be unable to allocate files until enough files have been deleted to get under the higher threshold. .It Fl N Cm enable | disable Turn on/off the administrative NFSv4 ACL enable flag. .It Fl n Cm enable | disable Turn on/off soft updates. .It Fl o Cm space | time The file system can either try to minimize the time spent allocating blocks, or it can attempt to minimize the space fragmentation on the disk. Optimization for space has much higher overhead for file writes. The kernel normally changes the preference automatically as the percent fragmentation changes on the file system. .It Fl p Show a summary of what the current tunable settings are on the selected file system. More detailed information can be obtained from the .Xr dumpfs 8 utility. .It Fl s Ar avgfpdir Specify the expected number of files per directory. .It Fl S Ar size Specify the softdep journal size in bytes. The minimum is 4M. .It Fl t Cm enable | disable Turn on/off the TRIM enable flag. If enabled, and if the underlying device supports the BIO_DELETE command, the file system will send a delete request to the underlying device for each freed block. The trim enable flag is typically set when the underlying device uses flash-memory as the device can use the delete command to pre-zero or at least avoid copying blocks that have been deleted. .Pp Note that this does not trim blocks that are already free. See the .Xr fsck_ffs 8 .Fl E flag. .El .Pp At least one of these flags is required. .Sh FILES .Bl -tag -width ".Pa /etc/fstab" .It Pa /etc/fstab read this to determine the device file for a specified mount point. .El .Sh SEE ALSO .Xr fs 5 , .Xr dumpfs 8 , .Xr gjournal 8 , .Xr growfs 8 , .Xr newfs 8 .Rs .%A M. McKusick .%A W. Joy .%A S. Leffler .%A R. Fabry .%T "A Fast File System for UNIX" .%J "ACM Transactions on Computer Systems 2" .%N 3 .%P pp 181-197 .%D August 1984 .%O "(reprinted in the BSD System Manager's Manual, SMM:5)" .Re .Sh HISTORY The .Nm utility appeared in .Bx 4.2 . .Sh BUGS This utility does not work on active file systems. To change the root file system, the system must be rebooted after the file system is tuned. .\" Take this out and a Unix Daemon will dog your steps from now until .\" the time_t's wrap around. .Pp You can tune a file system, but you cannot tune a fish. Index: stable/11/sbin/tunefs/tunefs.c =================================================================== --- stable/11/sbin/tunefs/tunefs.c (revision 343537) +++ stable/11/sbin/tunefs/tunefs.c (revision 343538) @@ -1,1135 +1,1134 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)tunefs.c 8.2 (Berkeley) 4/19/94"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); /* * tunefs: change layout parameters to an existing file system. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* the optimization warning string template */ #define OPTWARN "should optimize for %s with minfree %s %d%%" static int blocks; static char clrbuf[MAXBSIZE]; static struct uufsd disk; #define sblock disk.d_fs static void usage(void); static void printfs(void); static int journal_alloc(int64_t size); static void journal_clear(void); static void sbdirty(void); int main(int argc, char *argv[]) { const char *avalue, *jvalue, *Jvalue, *Lvalue, *lvalue, *Nvalue, *nvalue; const char *tvalue; const char *special, *on; const char *name; int active; int Aflag, aflag, eflag, evalue, fflag, fvalue, jflag, Jflag, kflag; int kvalue, Lflag, lflag, mflag, mvalue, Nflag, nflag, oflag, ovalue; int pflag, sflag, svalue, Svalue, tflag; int ch, found_arg, i; const char *chg[2]; struct ufs_args args; struct statfs stfs; if (argc < 3) usage(); Aflag = aflag = eflag = fflag = jflag = Jflag = kflag = Lflag = 0; lflag = mflag = Nflag = nflag = oflag = pflag = sflag = tflag = 0; avalue = jvalue = Jvalue = Lvalue = lvalue = Nvalue = nvalue = NULL; evalue = fvalue = mvalue = ovalue = svalue = Svalue = 0; active = 0; found_arg = 0; /* At least one arg is required. */ while ((ch = getopt(argc, argv, "Aa:e:f:j:J:k:L:l:m:N:n:o:ps:S:t:")) != -1) switch (ch) { case 'A': found_arg = 1; Aflag++; break; case 'a': found_arg = 1; name = "POSIX.1e ACLs"; avalue = optarg; if (strcmp(avalue, "enable") && strcmp(avalue, "disable")) { errx(10, "bad %s (options are %s)", name, "`enable' or `disable'"); } aflag = 1; break; case 'e': found_arg = 1; name = "maximum blocks per file in a cylinder group"; evalue = atoi(optarg); if (evalue < 1) errx(10, "%s must be >= 1 (was %s)", name, optarg); eflag = 1; break; case 'f': found_arg = 1; name = "average file size"; fvalue = atoi(optarg); if (fvalue < 1) errx(10, "%s must be >= 1 (was %s)", name, optarg); fflag = 1; break; case 'j': found_arg = 1; name = "softdep journaled file system"; jvalue = optarg; if (strcmp(jvalue, "enable") && strcmp(jvalue, "disable")) { errx(10, "bad %s (options are %s)", name, "`enable' or `disable'"); } jflag = 1; break; case 'J': found_arg = 1; name = "gjournaled file system"; Jvalue = optarg; if (strcmp(Jvalue, "enable") && strcmp(Jvalue, "disable")) { errx(10, "bad %s (options are %s)", name, "`enable' or `disable'"); } Jflag = 1; break; case 'k': found_arg = 1; name = "space to hold for metadata blocks"; kvalue = atoi(optarg); if (kvalue < 0) errx(10, "bad %s (%s)", name, optarg); kflag = 1; break; case 'L': found_arg = 1; name = "volume label"; Lvalue = optarg; i = -1; - while (isalnum(Lvalue[++i])); + while (isalnum(Lvalue[++i]) || Lvalue[i] == '_'); if (Lvalue[i] != '\0') { - errx(10, - "bad %s. Valid characters are alphanumerics.", - name); + errx(10, "bad %s. Valid characters are " + "alphanumerics and underscores.", name); } if (strlen(Lvalue) >= MAXVOLLEN) { errx(10, "bad %s. Length is longer than %d.", name, MAXVOLLEN - 1); } Lflag = 1; break; case 'l': found_arg = 1; name = "multilabel MAC file system"; lvalue = optarg; if (strcmp(lvalue, "enable") && strcmp(lvalue, "disable")) { errx(10, "bad %s (options are %s)", name, "`enable' or `disable'"); } lflag = 1; break; case 'm': found_arg = 1; name = "minimum percentage of free space"; mvalue = atoi(optarg); if (mvalue < 0 || mvalue > 99) errx(10, "bad %s (%s)", name, optarg); mflag = 1; break; case 'N': found_arg = 1; name = "NFSv4 ACLs"; Nvalue = optarg; if (strcmp(Nvalue, "enable") && strcmp(Nvalue, "disable")) { errx(10, "bad %s (options are %s)", name, "`enable' or `disable'"); } Nflag = 1; break; case 'n': found_arg = 1; name = "soft updates"; nvalue = optarg; if (strcmp(nvalue, "enable") != 0 && strcmp(nvalue, "disable") != 0) { errx(10, "bad %s (options are %s)", name, "`enable' or `disable'"); } nflag = 1; break; case 'o': found_arg = 1; name = "optimization preference"; if (strcmp(optarg, "space") == 0) ovalue = FS_OPTSPACE; else if (strcmp(optarg, "time") == 0) ovalue = FS_OPTTIME; else errx(10, "bad %s (options are `space' or `time')", name); oflag = 1; break; case 'p': found_arg = 1; pflag = 1; break; case 's': found_arg = 1; name = "expected number of files per directory"; svalue = atoi(optarg); if (svalue < 1) errx(10, "%s must be >= 1 (was %s)", name, optarg); sflag = 1; break; case 'S': found_arg = 1; name = "Softdep Journal Size"; Svalue = atoi(optarg); if (Svalue < SUJ_MIN) errx(10, "%s must be >= %d (was %s)", name, SUJ_MIN, optarg); break; case 't': found_arg = 1; name = "trim"; tvalue = optarg; if (strcmp(tvalue, "enable") != 0 && strcmp(tvalue, "disable") != 0) { errx(10, "bad %s (options are %s)", name, "`enable' or `disable'"); } tflag = 1; break; default: usage(); } argc -= optind; argv += optind; if (found_arg == 0 || argc != 1) usage(); on = special = argv[0]; if (ufs_disk_fillout(&disk, special) == -1) goto err; if (disk.d_name != special) { if (statfs(special, &stfs) != 0) warn("Can't stat %s", special); if (strcmp(special, stfs.f_mntonname) == 0) active = 1; } if (pflag) { printfs(); exit(0); } if (Lflag) { name = "volume label"; strncpy(sblock.fs_volname, Lvalue, MAXVOLLEN); } if (aflag) { name = "POSIX.1e ACLs"; if (strcmp(avalue, "enable") == 0) { if (sblock.fs_flags & FS_ACLS) { warnx("%s remains unchanged as enabled", name); } else if (sblock.fs_flags & FS_NFS4ACLS) { warnx("%s and NFSv4 ACLs are mutually " "exclusive", name); } else { sblock.fs_flags |= FS_ACLS; warnx("%s set", name); } } else if (strcmp(avalue, "disable") == 0) { if ((~sblock.fs_flags & FS_ACLS) == FS_ACLS) { warnx("%s remains unchanged as disabled", name); } else { sblock.fs_flags &= ~FS_ACLS; warnx("%s cleared", name); } } } if (eflag) { name = "maximum blocks per file in a cylinder group"; if (sblock.fs_maxbpg == evalue) warnx("%s remains unchanged as %d", name, evalue); else { warnx("%s changes from %d to %d", name, sblock.fs_maxbpg, evalue); sblock.fs_maxbpg = evalue; } } if (fflag) { name = "average file size"; if (sblock.fs_avgfilesize == (unsigned)fvalue) { warnx("%s remains unchanged as %d", name, fvalue); } else { warnx("%s changes from %d to %d", name, sblock.fs_avgfilesize, fvalue); sblock.fs_avgfilesize = fvalue; } } if (jflag) { name = "soft updates journaling"; if (strcmp(jvalue, "enable") == 0) { if ((sblock.fs_flags & (FS_DOSOFTDEP | FS_SUJ)) == (FS_DOSOFTDEP | FS_SUJ)) { warnx("%s remains unchanged as enabled", name); } else if (sblock.fs_clean == 0) { warnx("%s cannot be enabled until fsck is run", name); } else if (journal_alloc(Svalue) != 0) { warnx("%s can not be enabled", name); } else { sblock.fs_flags |= FS_DOSOFTDEP | FS_SUJ; warnx("%s set", name); } } else if (strcmp(jvalue, "disable") == 0) { if ((~sblock.fs_flags & FS_SUJ) == FS_SUJ) { warnx("%s remains unchanged as disabled", name); } else { journal_clear(); sblock.fs_flags &= ~FS_SUJ; sblock.fs_sujfree = 0; warnx("%s cleared but soft updates still set.", name); warnx("remove .sujournal to reclaim space"); } } } if (Jflag) { name = "gjournal"; if (strcmp(Jvalue, "enable") == 0) { if (sblock.fs_flags & FS_GJOURNAL) { warnx("%s remains unchanged as enabled", name); } else { sblock.fs_flags |= FS_GJOURNAL; warnx("%s set", name); } } else if (strcmp(Jvalue, "disable") == 0) { if ((~sblock.fs_flags & FS_GJOURNAL) == FS_GJOURNAL) { warnx("%s remains unchanged as disabled", name); } else { sblock.fs_flags &= ~FS_GJOURNAL; warnx("%s cleared", name); } } } if (kflag) { name = "space to hold for metadata blocks"; if (sblock.fs_metaspace == kvalue) warnx("%s remains unchanged as %d", name, kvalue); else { kvalue = blknum(&sblock, kvalue); if (kvalue > sblock.fs_fpg / 2) { kvalue = blknum(&sblock, sblock.fs_fpg / 2); warnx("%s cannot exceed half the file system " "space", name); } warnx("%s changes from %jd to %d", name, sblock.fs_metaspace, kvalue); sblock.fs_metaspace = kvalue; } } if (lflag) { name = "multilabel"; if (strcmp(lvalue, "enable") == 0) { if (sblock.fs_flags & FS_MULTILABEL) { warnx("%s remains unchanged as enabled", name); } else { sblock.fs_flags |= FS_MULTILABEL; warnx("%s set", name); } } else if (strcmp(lvalue, "disable") == 0) { if ((~sblock.fs_flags & FS_MULTILABEL) == FS_MULTILABEL) { warnx("%s remains unchanged as disabled", name); } else { sblock.fs_flags &= ~FS_MULTILABEL; warnx("%s cleared", name); } } } if (mflag) { name = "minimum percentage of free space"; if (sblock.fs_minfree == mvalue) warnx("%s remains unchanged as %d%%", name, mvalue); else { warnx("%s changes from %d%% to %d%%", name, sblock.fs_minfree, mvalue); sblock.fs_minfree = mvalue; if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE) warnx(OPTWARN, "time", ">=", MINFREE); if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME) warnx(OPTWARN, "space", "<", MINFREE); } } if (Nflag) { name = "NFSv4 ACLs"; if (strcmp(Nvalue, "enable") == 0) { if (sblock.fs_flags & FS_NFS4ACLS) { warnx("%s remains unchanged as enabled", name); } else if (sblock.fs_flags & FS_ACLS) { warnx("%s and POSIX.1e ACLs are mutually " "exclusive", name); } else { sblock.fs_flags |= FS_NFS4ACLS; warnx("%s set", name); } } else if (strcmp(Nvalue, "disable") == 0) { if ((~sblock.fs_flags & FS_NFS4ACLS) == FS_NFS4ACLS) { warnx("%s remains unchanged as disabled", name); } else { sblock.fs_flags &= ~FS_NFS4ACLS; warnx("%s cleared", name); } } } if (nflag) { name = "soft updates"; if (strcmp(nvalue, "enable") == 0) { if (sblock.fs_flags & FS_DOSOFTDEP) warnx("%s remains unchanged as enabled", name); else if (sblock.fs_clean == 0) { warnx("%s cannot be enabled until fsck is run", name); } else { sblock.fs_flags |= FS_DOSOFTDEP; warnx("%s set", name); } } else if (strcmp(nvalue, "disable") == 0) { if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP) warnx("%s remains unchanged as disabled", name); else { sblock.fs_flags &= ~FS_DOSOFTDEP; warnx("%s cleared", name); } } } if (oflag) { name = "optimization preference"; chg[FS_OPTSPACE] = "space"; chg[FS_OPTTIME] = "time"; if (sblock.fs_optim == ovalue) warnx("%s remains unchanged as %s", name, chg[ovalue]); else { warnx("%s changes from %s to %s", name, chg[sblock.fs_optim], chg[ovalue]); sblock.fs_optim = ovalue; if (sblock.fs_minfree >= MINFREE && ovalue == FS_OPTSPACE) warnx(OPTWARN, "time", ">=", MINFREE); if (sblock.fs_minfree < MINFREE && ovalue == FS_OPTTIME) warnx(OPTWARN, "space", "<", MINFREE); } } if (sflag) { name = "expected number of files per directory"; if (sblock.fs_avgfpdir == (unsigned)svalue) { warnx("%s remains unchanged as %d", name, svalue); } else { warnx("%s changes from %d to %d", name, sblock.fs_avgfpdir, svalue); sblock.fs_avgfpdir = svalue; } } if (tflag) { name = "issue TRIM to the disk"; if (strcmp(tvalue, "enable") == 0) { if (sblock.fs_flags & FS_TRIM) warnx("%s remains unchanged as enabled", name); else { sblock.fs_flags |= FS_TRIM; warnx("%s set", name); } } else if (strcmp(tvalue, "disable") == 0) { if ((~sblock.fs_flags & FS_TRIM) == FS_TRIM) warnx("%s remains unchanged as disabled", name); else { sblock.fs_flags &= ~FS_TRIM; warnx("%s cleared", name); } } } if (sbwrite(&disk, Aflag) == -1) goto err; ufs_disk_close(&disk); if (active) { bzero(&args, sizeof(args)); if (mount("ufs", on, stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0) err(9, "%s: reload", special); warnx("file system reloaded"); } exit(0); err: if (disk.d_error != NULL) errx(11, "%s: %s", special, disk.d_error); else err(12, "%s", special); } static void sbdirty(void) { disk.d_fs.fs_flags |= FS_UNCLEAN | FS_NEEDSFSCK; disk.d_fs.fs_clean = 0; } static ufs2_daddr_t journal_balloc(void) { ufs2_daddr_t blk; struct cg *cgp; int valid; static int contig = 1; cgp = &disk.d_cg; for (;;) { blk = cgballoc(&disk); if (blk > 0) break; /* * If we failed to allocate a block from this cg, move to * the next. */ if (cgwrite(&disk) < 0) { warn("Failed to write updated cg"); return (-1); } while ((valid = cgread(&disk)) == 1) { /* * Try to minimize fragmentation by requiring a minimum * number of blocks present. */ if (cgp->cg_cs.cs_nbfree > 256 * 1024) break; if (contig == 0 && cgp->cg_cs.cs_nbfree) break; } if (valid) continue; /* * Try once through looking only for large contiguous regions * and again taking any space we can find. */ if (contig) { contig = 0; disk.d_ccg = 0; warnx("Journal file fragmented."); continue; } warnx("Failed to find sufficient free blocks for the journal"); return -1; } if (bwrite(&disk, fsbtodb(&sblock, blk), clrbuf, sblock.fs_bsize) <= 0) { warn("Failed to initialize new block"); return -1; } return (blk); } /* * Search a directory block for the SUJ_FILE. */ static ino_t dir_search(ufs2_daddr_t blk, int bytes) { char block[MAXBSIZE]; struct direct *dp; int off; if (bread(&disk, fsbtodb(&sblock, blk), block, bytes) <= 0) { warn("Failed to read dir block"); return (-1); } for (off = 0; off < bytes; off += dp->d_reclen) { dp = (struct direct *)&block[off]; if (dp->d_reclen == 0) break; if (dp->d_ino == 0) continue; if (dp->d_namlen != strlen(SUJ_FILE)) continue; if (bcmp(dp->d_name, SUJ_FILE, dp->d_namlen) != 0) continue; return (dp->d_ino); } return (0); } /* * Search in the ROOTINO for the SUJ_FILE. If it exists we can not enable * journaling. */ static ino_t journal_findfile(void) { struct ufs1_dinode *dp1; struct ufs2_dinode *dp2; ino_t ino; int mode; void *ip; int i; if (getino(&disk, &ip, ROOTINO, &mode) != 0) { warn("Failed to get root inode"); return (-1); } dp2 = ip; dp1 = ip; if (sblock.fs_magic == FS_UFS1_MAGIC) { if ((off_t)dp1->di_size >= lblktosize(&sblock, NDADDR)) { warnx("ROOTINO extends beyond direct blocks."); return (-1); } for (i = 0; i < NDADDR; i++) { if (dp1->di_db[i] == 0) break; if ((ino = dir_search(dp1->di_db[i], sblksize(&sblock, (off_t)dp1->di_size, i))) != 0) return (ino); } } else { if ((off_t)dp2->di_size >= lblktosize(&sblock, NDADDR)) { warnx("ROOTINO extends beyond direct blocks."); return (-1); } for (i = 0; i < NDADDR; i++) { if (dp2->di_db[i] == 0) break; if ((ino = dir_search(dp2->di_db[i], sblksize(&sblock, (off_t)dp2->di_size, i))) != 0) return (ino); } } return (0); } static void dir_clear_block(const char *block, off_t off) { struct direct *dp; for (; off < sblock.fs_bsize; off += DIRBLKSIZ) { dp = (struct direct *)&block[off]; dp->d_ino = 0; dp->d_reclen = DIRBLKSIZ; dp->d_type = DT_UNKNOWN; } } /* * Insert the journal at inode 'ino' into directory blk 'blk' at the first * free offset of 'off'. DIRBLKSIZ blocks after off are initialized as * empty. */ static int dir_insert(ufs2_daddr_t blk, off_t off, ino_t ino) { struct direct *dp; char block[MAXBSIZE]; if (bread(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) { warn("Failed to read dir block"); return (-1); } bzero(&block[off], sblock.fs_bsize - off); dp = (struct direct *)&block[off]; dp->d_ino = ino; dp->d_reclen = DIRBLKSIZ; dp->d_type = DT_REG; dp->d_namlen = strlen(SUJ_FILE); bcopy(SUJ_FILE, &dp->d_name, strlen(SUJ_FILE)); dir_clear_block(block, off + DIRBLKSIZ); if (bwrite(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) { warn("Failed to write dir block"); return (-1); } return (0); } /* * Extend a directory block in 'blk' by copying it to a full size block * and inserting the new journal inode into .sujournal. */ static int dir_extend(ufs2_daddr_t blk, ufs2_daddr_t nblk, off_t size, ino_t ino) { char block[MAXBSIZE]; if (bread(&disk, fsbtodb(&sblock, blk), block, roundup(size, sblock.fs_fsize)) <= 0) { warn("Failed to read dir block"); return (-1); } dir_clear_block(block, size); if (bwrite(&disk, fsbtodb(&sblock, nblk), block, sblock.fs_bsize) <= 0) { warn("Failed to write dir block"); return (-1); } return (dir_insert(nblk, size, ino)); } /* * Insert the journal file into the ROOTINO directory. We always extend the * last frag */ static int journal_insertfile(ino_t ino) { struct ufs1_dinode *dp1; struct ufs2_dinode *dp2; void *ip; ufs2_daddr_t nblk; ufs2_daddr_t blk; ufs_lbn_t lbn; int size; int mode; int off; if (getino(&disk, &ip, ROOTINO, &mode) != 0) { warn("Failed to get root inode"); sbdirty(); return (-1); } dp2 = ip; dp1 = ip; blk = 0; size = 0; nblk = journal_balloc(); if (nblk <= 0) return (-1); /* * For simplicity sake we aways extend the ROOTINO into a new * directory block rather than searching for space and inserting * into an existing block. However, if the rootino has frags * have to free them and extend the block. */ if (sblock.fs_magic == FS_UFS1_MAGIC) { lbn = lblkno(&sblock, dp1->di_size); off = blkoff(&sblock, dp1->di_size); blk = dp1->di_db[lbn]; size = sblksize(&sblock, (off_t)dp1->di_size, lbn); } else { lbn = lblkno(&sblock, dp2->di_size); off = blkoff(&sblock, dp2->di_size); blk = dp2->di_db[lbn]; size = sblksize(&sblock, (off_t)dp2->di_size, lbn); } if (off != 0) { if (dir_extend(blk, nblk, off, ino) == -1) return (-1); } else { blk = 0; if (dir_insert(nblk, 0, ino) == -1) return (-1); } if (sblock.fs_magic == FS_UFS1_MAGIC) { dp1->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE; dp1->di_db[lbn] = nblk; dp1->di_size = lblktosize(&sblock, lbn+1); } else { dp2->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE; dp2->di_db[lbn] = nblk; dp2->di_size = lblktosize(&sblock, lbn+1); } if (putino(&disk) < 0) { warn("Failed to write root inode"); return (-1); } if (cgwrite(&disk) < 0) { warn("Failed to write updated cg"); sbdirty(); return (-1); } if (blk) { if (cgbfree(&disk, blk, size) < 0) { warn("Failed to write cg"); return (-1); } } return (0); } static int indir_fill(ufs2_daddr_t blk, int level, int *resid) { char indirbuf[MAXBSIZE]; ufs1_daddr_t *bap1; ufs2_daddr_t *bap2; ufs2_daddr_t nblk; int ncnt; int cnt; int i; bzero(indirbuf, sizeof(indirbuf)); bap1 = (ufs1_daddr_t *)indirbuf; bap2 = (void *)bap1; cnt = 0; for (i = 0; i < NINDIR(&sblock) && *resid != 0; i++) { nblk = journal_balloc(); if (nblk <= 0) return (-1); cnt++; if (sblock.fs_magic == FS_UFS1_MAGIC) *bap1++ = nblk; else *bap2++ = nblk; if (level != 0) { ncnt = indir_fill(nblk, level - 1, resid); if (ncnt <= 0) return (-1); cnt += ncnt; } else (*resid)--; } if (bwrite(&disk, fsbtodb(&sblock, blk), indirbuf, sblock.fs_bsize) <= 0) { warn("Failed to write indirect"); return (-1); } return (cnt); } /* * Clear the flag bits so the journal can be removed. */ static void journal_clear(void) { struct ufs1_dinode *dp1; struct ufs2_dinode *dp2; ino_t ino; int mode; void *ip; ino = journal_findfile(); if (ino == (ino_t)-1 || ino == 0) { warnx("Journal file does not exist"); return; } printf("Clearing journal flags from inode %ju\n", (uintmax_t)ino); if (getino(&disk, &ip, ino, &mode) != 0) { warn("Failed to get journal inode"); return; } dp2 = ip; dp1 = ip; if (sblock.fs_magic == FS_UFS1_MAGIC) dp1->di_flags = 0; else dp2->di_flags = 0; if (putino(&disk) < 0) { warn("Failed to write journal inode"); return; } } static int journal_alloc(int64_t size) { struct ufs1_dinode *dp1; struct ufs2_dinode *dp2; ufs2_daddr_t blk; void *ip; struct cg *cgp; int resid; ino_t ino; int blks; int mode; time_t utime; int i; cgp = &disk.d_cg; ino = 0; /* * If the journal file exists we can't allocate it. */ ino = journal_findfile(); if (ino == (ino_t)-1) return (-1); if (ino > 0) { warnx("Journal file %s already exists, please remove.", SUJ_FILE); return (-1); } /* * If the user didn't supply a size pick one based on the filesystem * size constrained with hardcoded MIN and MAX values. We opt for * 1/1024th of the filesystem up to MAX but not exceeding one CG and * not less than the MIN. */ if (size == 0) { size = (sblock.fs_size * sblock.fs_bsize) / 1024; size = MIN(SUJ_MAX, size); if (size / sblock.fs_fsize > sblock.fs_fpg) size = sblock.fs_fpg * sblock.fs_fsize; size = MAX(SUJ_MIN, size); /* fsck does not support fragments in journal files. */ size = roundup(size, sblock.fs_bsize); } resid = blocks = size / sblock.fs_bsize; if (sblock.fs_cstotal.cs_nbfree < blocks) { warn("Insufficient free space for %jd byte journal", size); return (-1); } /* * Find a cg with enough blocks to satisfy the journal * size. Presently the journal does not span cgs. */ while (cgread(&disk) == 1) { if (cgp->cg_cs.cs_nifree == 0) continue; ino = cgialloc(&disk); if (ino <= 0) break; printf("Using inode %ju in cg %d for %jd byte journal\n", (uintmax_t)ino, cgp->cg_cgx, size); if (getino(&disk, &ip, ino, &mode) != 0) { warn("Failed to get allocated inode"); sbdirty(); goto out; } /* * We leave fields unrelated to the number of allocated * blocks and size uninitialized. This causes legacy * fsck implementations to clear the inode. */ dp2 = ip; dp1 = ip; time(&utime); if (sblock.fs_magic == FS_UFS1_MAGIC) { bzero(dp1, sizeof(*dp1)); dp1->di_size = size; dp1->di_mode = IFREG | IREAD; dp1->di_nlink = 1; dp1->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP; dp1->di_atime = utime; dp1->di_mtime = utime; dp1->di_ctime = utime; } else { bzero(dp2, sizeof(*dp2)); dp2->di_size = size; dp2->di_mode = IFREG | IREAD; dp2->di_nlink = 1; dp2->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP; dp2->di_atime = utime; dp2->di_mtime = utime; dp2->di_ctime = utime; dp2->di_birthtime = utime; } for (i = 0; i < NDADDR && resid; i++, resid--) { blk = journal_balloc(); if (blk <= 0) goto out; if (sblock.fs_magic == FS_UFS1_MAGIC) { dp1->di_db[i] = blk; dp1->di_blocks++; } else { dp2->di_db[i] = blk; dp2->di_blocks++; } } for (i = 0; i < NIADDR && resid; i++) { blk = journal_balloc(); if (blk <= 0) goto out; blks = indir_fill(blk, i, &resid) + 1; if (blks <= 0) { sbdirty(); goto out; } if (sblock.fs_magic == FS_UFS1_MAGIC) { dp1->di_ib[i] = blk; dp1->di_blocks += blks; } else { dp2->di_ib[i] = blk; dp2->di_blocks += blks; } } if (sblock.fs_magic == FS_UFS1_MAGIC) dp1->di_blocks *= sblock.fs_bsize / disk.d_bsize; else dp2->di_blocks *= sblock.fs_bsize / disk.d_bsize; if (putino(&disk) < 0) { warn("Failed to write inode"); sbdirty(); return (-1); } if (cgwrite(&disk) < 0) { warn("Failed to write updated cg"); sbdirty(); return (-1); } if (journal_insertfile(ino) < 0) { sbdirty(); return (-1); } sblock.fs_sujfree = 0; return (0); } warnx("Insufficient free space for the journal."); out: return (-1); } static void usage(void) { fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n", "usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]", " [-J enable | disable] [-j enable | disable] [-k metaspace]", " [-L volname] [-l enable | disable] [-m minfree]", " [-N enable | disable] [-n enable | disable]", " [-o space | time] [-p] [-s avgfpdir] [-t enable | disable]", " special | filesystem"); exit(2); } static void printfs(void) { warnx("POSIX.1e ACLs: (-a) %s", (sblock.fs_flags & FS_ACLS)? "enabled" : "disabled"); warnx("NFSv4 ACLs: (-N) %s", (sblock.fs_flags & FS_NFS4ACLS)? "enabled" : "disabled"); warnx("MAC multilabel: (-l) %s", (sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled"); warnx("soft updates: (-n) %s", (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled"); warnx("soft update journaling: (-j) %s", (sblock.fs_flags & FS_SUJ)? "enabled" : "disabled"); warnx("gjournal: (-J) %s", (sblock.fs_flags & FS_GJOURNAL)? "enabled" : "disabled"); warnx("trim: (-t) %s", (sblock.fs_flags & FS_TRIM)? "enabled" : "disabled"); warnx("maximum blocks per file in a cylinder group: (-e) %d", sblock.fs_maxbpg); warnx("average file size: (-f) %d", sblock.fs_avgfilesize); warnx("average number of files in a directory: (-s) %d", sblock.fs_avgfpdir); warnx("minimum percentage of free space: (-m) %d%%", sblock.fs_minfree); warnx("space to hold for metadata blocks: (-k) %jd", sblock.fs_metaspace); warnx("optimization preference: (-o) %s", sblock.fs_optim == FS_OPTSPACE ? "space" : "time"); if (sblock.fs_minfree >= MINFREE && sblock.fs_optim == FS_OPTSPACE) warnx(OPTWARN, "time", ">=", MINFREE); if (sblock.fs_minfree < MINFREE && sblock.fs_optim == FS_OPTTIME) warnx(OPTWARN, "space", "<", MINFREE); warnx("volume label: (-L) %s", sblock.fs_volname); } Index: stable/11 =================================================================== --- stable/11 (revision 343537) +++ stable/11 (revision 343538) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r343449,343483