tunefs.c revision 109597
11558Srgrimes/*
21558Srgrimes * Copyright (c) 1983, 1993
31558Srgrimes *	The Regents of the University of California.  All rights reserved.
41558Srgrimes *
51558Srgrimes * Redistribution and use in source and binary forms, with or without
61558Srgrimes * modification, are permitted provided that the following conditions
71558Srgrimes * are met:
81558Srgrimes * 1. Redistributions of source code must retain the above copyright
91558Srgrimes *    notice, this list of conditions and the following disclaimer.
101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111558Srgrimes *    notice, this list of conditions and the following disclaimer in the
121558Srgrimes *    documentation and/or other materials provided with the distribution.
131558Srgrimes * 3. All advertising materials mentioning features or use of this software
141558Srgrimes *    must display the following acknowledgement:
151558Srgrimes *	This product includes software developed by the University of
161558Srgrimes *	California, Berkeley and its contributors.
171558Srgrimes * 4. Neither the name of the University nor the names of its contributors
181558Srgrimes *    may be used to endorse or promote products derived from this software
191558Srgrimes *    without specific prior written permission.
201558Srgrimes *
211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311558Srgrimes * SUCH DAMAGE.
321558Srgrimes */
331558Srgrimes
341558Srgrimes#ifndef lint
3538040Scharnierstatic const char copyright[] =
361558Srgrimes"@(#) Copyright (c) 1983, 1993\n\
371558Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381558Srgrimes#endif /* not lint */
391558Srgrimes
401558Srgrimes#ifndef lint
4138040Scharnier#if 0
421558Srgrimesstatic char sccsid[] = "@(#)tunefs.c	8.2 (Berkeley) 4/19/94";
4338040Scharnier#endif
4438040Scharnierstatic const char rcsid[] =
4550476Speter  "$FreeBSD: head/sbin/tunefs/tunefs.c 109597 2003-01-20 21:15:02Z jmallett $";
461558Srgrimes#endif /* not lint */
471558Srgrimes
481558Srgrimes/*
49102231Strhodes * tunefs: change layout parameters to an existing file system.
501558Srgrimes */
511558Srgrimes#include <sys/param.h>
5242873Sluoqi#include <sys/mount.h>
5396478Sphk#include <sys/disklabel.h>
541558Srgrimes#include <sys/stat.h>
551558Srgrimes
5698542Smckusick#include <ufs/ufs/ufsmount.h>
5798542Smckusick#include <ufs/ufs/dinode.h>
581558Srgrimes#include <ufs/ffs/fs.h>
591558Srgrimes
601558Srgrimes#include <err.h>
611558Srgrimes#include <fcntl.h>
621558Srgrimes#include <fstab.h>
63109597Sjmallett#include <libufs.h>
6438040Scharnier#include <paths.h>
651558Srgrimes#include <stdio.h>
661558Srgrimes#include <stdlib.h>
6758047Ssheldonh#include <string.h>
681558Srgrimes#include <unistd.h>
691558Srgrimes
701558Srgrimes/* the optimization warning string template */
711558Srgrimes#define	OPTWARN	"should optimize for %s with minfree %s %d%%"
721558Srgrimes
73109597Sjmallettstruct uufsd disk;
74109597Sjmallett#define	sblock disk.d_fs
751558Srgrimes
7692883Simpvoid usage(void);
7792883Simpvoid printfs(void);
781558Srgrimes
791558Srgrimesint
80109597Sjmallettmain(int argc, char *argv[])
811558Srgrimes{
8279750Sdd	char *special;
8379750Sdd	const char *name;
841558Srgrimes	struct stat st;
85105120Srwatson	int Aflag = 0, active = 0, aflag = 0;
86105120Srwatson	int eflag = 0, fflag = 0, lflag = 0, mflag = 0;
8775377Smckusick	int nflag = 0, oflag = 0, pflag = 0, sflag = 0;
88103005Sphk	int evalue = 0, fvalue = 0;
8975377Smckusick	int mvalue = 0, ovalue = 0, svalue = 0;
90105120Srwatson	char *avalue = NULL, *lvalue = NULL, *nvalue = NULL;
911558Srgrimes	struct fstab *fs;
9279750Sdd	const char *chg[2];
9379750Sdd	char device[MAXPATHLEN];
9442873Sluoqi	struct ufs_args args;
9542873Sluoqi	struct statfs stfs;
9669314Scharnier	int found_arg, ch;
971558Srgrimes
9869314Scharnier        if (argc < 3)
9969314Scharnier                usage();
10069314Scharnier	found_arg = 0; /* at least one arg is required */
101105156Srwatson	while ((ch = getopt(argc, argv, "Aa:e:f:l:m:n:o:ps:")) != -1)
10269314Scharnier	  switch (ch) {
103105156Srwatson	  case 'A':
104105156Srwatson		found_arg = 1;
105105156Srwatson		Aflag++;
106105156Srwatson		break;
107105120Srwatson	  case 'a':
108105120Srwatson		found_arg = 1;
109105120Srwatson		name = "ACLs";
110105120Srwatson		avalue = optarg;
111105120Srwatson		if (strcmp(avalue, "enable") && strcmp(avalue, "disable")) {
112105120Srwatson			errx(10, "bad %s (options are %s)", name,
113105120Srwatson			    "`enable' or `disable'");
114105120Srwatson		}
115105120Srwatson		aflag = 1;
116105120Srwatson		break;
11769314Scharnier	  case 'e':
11869314Scharnier		found_arg = 1;
11969314Scharnier		name = "maximum blocks per file in a cylinder group";
12069829Scharnier		evalue = atoi(optarg);
12169829Scharnier		if (evalue < 1)
12269314Scharnier			errx(10, "%s must be >= 1 (was %s)", name, optarg);
12369829Scharnier		eflag = 1;
12469314Scharnier		break;
12575377Smckusick	  case 'f':
12675377Smckusick		found_arg = 1;
12775377Smckusick		name = "average file size";
12875377Smckusick		fvalue = atoi(optarg);
12975377Smckusick		if (fvalue < 1)
13075377Smckusick			errx(10, "%s must be >= 1 (was %s)", name, optarg);
13175377Smckusick		fflag = 1;
13275377Smckusick		break;
133105120Srwatson	  case 'l':
134105120Srwatson		found_arg = 1;
135105120Srwatson		name = "multilabel MAC file system";
136105120Srwatson		lvalue = optarg;
137105120Srwatson		if (strcmp(lvalue, "enable") && strcmp(lvalue, "disable")) {
138105120Srwatson			errx(10, "bad %s (options are %s)", name,
139105120Srwatson			    "`enable' or `disable'");
140105120Srwatson		}
141105120Srwatson		lflag = 1;
142105120Srwatson		break;
14369314Scharnier	  case 'm':
14469314Scharnier		found_arg = 1;
14569314Scharnier		name = "minimum percentage of free space";
14669829Scharnier		mvalue = atoi(optarg);
14769829Scharnier		if (mvalue < 0 || mvalue > 99)
14869314Scharnier			errx(10, "bad %s (%s)", name, optarg);
14969829Scharnier		mflag = 1;
15069314Scharnier		break;
15169314Scharnier	  case 'n':
15269314Scharnier		found_arg = 1;
15369314Scharnier 		name = "soft updates";
15469829Scharnier 		nvalue = optarg;
15569829Scharnier                if (strcmp(nvalue, "enable") && strcmp(nvalue, "disable")) {
15669314Scharnier 			errx(10, "bad %s (options are %s)",
15769314Scharnier 			    name, "`enable' or `disable'");
15869314Scharnier 		}
15969829Scharnier		nflag = 1;
16069314Scharnier 		break;
16169314Scharnier	  case 'o':
16269314Scharnier		found_arg = 1;
16369314Scharnier		name = "optimization preference";
16469314Scharnier		chg[FS_OPTSPACE] = "space";
16569314Scharnier		chg[FS_OPTTIME] = "time";
16669314Scharnier		if (strcmp(optarg, chg[FS_OPTSPACE]) == 0)
16769829Scharnier			ovalue = FS_OPTSPACE;
16869314Scharnier		else if (strcmp(optarg, chg[FS_OPTTIME]) == 0)
16969829Scharnier			ovalue = FS_OPTTIME;
17069314Scharnier		else
17169314Scharnier			errx(10, "bad %s (options are `space' or `time')",
1721558Srgrimes					    name);
17369829Scharnier		oflag = 1;
17469314Scharnier		break;
17569314Scharnier	  case 'p':
17671790Sben		found_arg = 1;
17769829Scharnier		pflag = 1;
17869829Scharnier		break;
17975377Smckusick	  case 's':
18075377Smckusick		found_arg = 1;
18175377Smckusick		name = "expected number of files per directory";
18275377Smckusick		svalue = atoi(optarg);
18375377Smckusick		if (svalue < 1)
18475377Smckusick			errx(10, "%s must be >= 1 (was %s)", name, optarg);
18575377Smckusick		sflag = 1;
18675377Smckusick		break;
18769314Scharnier	  default:
18869314Scharnier		usage();
18969314Scharnier	  }
19069314Scharnier	argc -= optind;
19169314Scharnier	argv += optind;
1921558Srgrimes
19369314Scharnier	if (found_arg == 0 || argc != 1)
19469314Scharnier	  usage();
19569314Scharnier
19669829Scharnier	special = argv[0];
19769829Scharnier	fs = getfsfile(special);
19869829Scharnier	if (fs) {
19969829Scharnier		if (statfs(special, &stfs) == 0 &&
20069829Scharnier		    strcmp(special, stfs.f_mntonname) == 0) {
20169829Scharnier			active = 1;
20269829Scharnier		}
20369829Scharnier		special = fs->fs_spec;
20469829Scharnier	}
20569829Scharnieragain:
20669829Scharnier	if (stat(special, &st) < 0) {
20769829Scharnier		if (*special != '/') {
20869829Scharnier			if (*special == 'r')
20969829Scharnier				special++;
21084166Siedowse			(void)snprintf(device, sizeof(device), "%s%s",
21180277Skris				       _PATH_DEV, special);
21269829Scharnier			special = device;
21369829Scharnier			goto again;
21469829Scharnier		}
21569829Scharnier		err(1, "%s", special);
21669829Scharnier	}
21784166Siedowse	if (fs == NULL && (st.st_mode & S_IFMT) == S_IFDIR)
218102231Strhodes		errx(10, "%s: unknown file system", special);
219109597Sjmallett	if (ufs_disk_fillout(&disk, special) == -1) {
220109597Sjmallett		if (disk.d_error != NULL)
221109597Sjmallett			errx(11, "%s: %s", special, disk.d_error);
222109597Sjmallett		else
223109597Sjmallett			err(12, "%s", special);
224109597Sjmallett	}
22569829Scharnier
22669829Scharnier	if (pflag) {
22769829Scharnier		printfs();
22869829Scharnier		exit(0);
22969829Scharnier	}
230105120Srwatson	if (aflag) {
231105120Srwatson		name = "ACLs";
232105120Srwatson		if (strcmp(avalue, "enable") == 0) {
233105120Srwatson			if (sblock.fs_flags & FS_ACLS) {
234105120Srwatson				warnx("%s remains unchanged as enabled", name);
235105120Srwatson			} else {
236105120Srwatson				sblock.fs_flags |= FS_ACLS;
237105120Srwatson				warnx("%s set", name);
238105120Srwatson			}
239105120Srwatson		} else if (strcmp(avalue, "disable") == 0) {
240105120Srwatson			if ((~sblock.fs_flags & FS_ACLS) ==
241105120Srwatson			    FS_ACLS) {
242105120Srwatson				warnx("%s remains unchanged as disabled",
243105120Srwatson				    name);
244105120Srwatson			} else {
245105120Srwatson				sblock.fs_flags &= ~FS_ACLS;
246105206Srwatson				warnx("%s cleared", name);
247105120Srwatson			}
248105120Srwatson		}
249105120Srwatson	}
25069829Scharnier	if (eflag) {
25169829Scharnier		name = "maximum blocks per file in a cylinder group";
25269829Scharnier		if (sblock.fs_maxbpg == evalue) {
25369829Scharnier			warnx("%s remains unchanged as %d", name, evalue);
25469829Scharnier		}
25569829Scharnier		else {
25669829Scharnier			warnx("%s changes from %d to %d",
25769829Scharnier					name, sblock.fs_maxbpg, evalue);
25869829Scharnier			sblock.fs_maxbpg = evalue;
25969829Scharnier		}
26069829Scharnier	}
26175377Smckusick	if (fflag) {
26275377Smckusick		name = "average file size";
26375377Smckusick		if (sblock.fs_avgfilesize == fvalue) {
26475377Smckusick			warnx("%s remains unchanged as %d", name, fvalue);
26575377Smckusick		}
26675377Smckusick		else {
26775377Smckusick			warnx("%s changes from %d to %d",
26875377Smckusick					name, sblock.fs_avgfilesize, fvalue);
26975377Smckusick			sblock.fs_avgfilesize = fvalue;
27075377Smckusick		}
27175377Smckusick	}
272105120Srwatson	if (lflag) {
273105120Srwatson		name = "multilabel";
274105120Srwatson		if (strcmp(lvalue, "enable") == 0) {
275105120Srwatson			if (sblock.fs_flags & FS_MULTILABEL) {
276105120Srwatson				warnx("%s remains unchanged as enabled", name);
277105120Srwatson			} else {
278105120Srwatson				sblock.fs_flags |= FS_MULTILABEL;
279105120Srwatson				warnx("%s set", name);
280105120Srwatson			}
281105120Srwatson		} else if (strcmp(lvalue, "disable") == 0) {
282105120Srwatson			if ((~sblock.fs_flags & FS_MULTILABEL) ==
283105120Srwatson			    FS_MULTILABEL) {
284105120Srwatson				warnx("%s remains unchanged as disabled",
285105120Srwatson				    name);
286105120Srwatson			} else {
287105120Srwatson				sblock.fs_flags &= ~FS_MULTILABEL;
288105206Srwatson				warnx("%s cleared", name);
289105120Srwatson			}
290105120Srwatson		}
291105120Srwatson	}
29269829Scharnier	if (mflag) {
29369829Scharnier		name = "minimum percentage of free space";
29469829Scharnier		if (sblock.fs_minfree == mvalue) {
29569829Scharnier			warnx("%s remains unchanged as %d%%", name, mvalue);
29669829Scharnier		}
29769829Scharnier		else {
29869829Scharnier			warnx("%s changes from %d%% to %d%%",
29969829Scharnier				    name, sblock.fs_minfree, mvalue);
30069829Scharnier			sblock.fs_minfree = mvalue;
30169829Scharnier			if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE)
30269829Scharnier				warnx(OPTWARN, "time", ">=", MINFREE);
30369829Scharnier			if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME)
30469829Scharnier				warnx(OPTWARN, "space", "<", MINFREE);
30569829Scharnier		}
30669829Scharnier	}
30769829Scharnier	if (nflag) {
30869829Scharnier 		name = "soft updates";
30969829Scharnier 		if (strcmp(nvalue, "enable") == 0) {
31075498Smckusick			if (sblock.fs_flags & FS_DOSOFTDEP) {
31169829Scharnier				warnx("%s remains unchanged as enabled", name);
31275498Smckusick			} else if (sblock.fs_clean == 0) {
31375498Smckusick				warnx("%s cannot be enabled until fsck is run",
31475498Smckusick				    name);
31569829Scharnier			} else {
31669829Scharnier 				sblock.fs_flags |= FS_DOSOFTDEP;
31769829Scharnier 				warnx("%s set", name);
31869829Scharnier			}
31969829Scharnier 		} else if (strcmp(nvalue, "disable") == 0) {
32069829Scharnier			if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP) {
32169829Scharnier				warnx("%s remains unchanged as disabled", name);
32269829Scharnier			} else {
32369829Scharnier 				sblock.fs_flags &= ~FS_DOSOFTDEP;
32469829Scharnier 				warnx("%s cleared", name);
32569829Scharnier			}
32669829Scharnier 		}
32769829Scharnier	}
32869829Scharnier	if (oflag) {
32969829Scharnier		name = "optimization preference";
33069829Scharnier		chg[FS_OPTSPACE] = "space";
33169829Scharnier		chg[FS_OPTTIME] = "time";
33269829Scharnier		if (sblock.fs_optim == ovalue) {
33369829Scharnier			warnx("%s remains unchanged as %s", name, chg[ovalue]);
33469829Scharnier		}
33569829Scharnier		else {
33669829Scharnier			warnx("%s changes from %s to %s",
33769829Scharnier				    name, chg[sblock.fs_optim], chg[ovalue]);
33869829Scharnier			sblock.fs_optim = ovalue;
33969829Scharnier			if (sblock.fs_minfree >= MINFREE &&
34069829Scharnier					ovalue == FS_OPTSPACE)
34169829Scharnier				warnx(OPTWARN, "time", ">=", MINFREE);
34269829Scharnier			if (sblock.fs_minfree < MINFREE &&
34369829Scharnier					ovalue == FS_OPTTIME)
34469829Scharnier				warnx(OPTWARN, "space", "<", MINFREE);
34569829Scharnier		}
34669829Scharnier	}
34775377Smckusick	if (sflag) {
34875377Smckusick		name = "expected number of files per directory";
34975377Smckusick		if (sblock.fs_avgfpdir == svalue) {
35075377Smckusick			warnx("%s remains unchanged as %d", name, svalue);
35175377Smckusick		}
35275377Smckusick		else {
35375377Smckusick			warnx("%s changes from %d to %d",
35475377Smckusick					name, sblock.fs_avgfpdir, svalue);
35575377Smckusick			sblock.fs_avgfpdir = svalue;
35675377Smckusick		}
35775377Smckusick	}
35869829Scharnier
359109597Sjmallett	sbwrite(&disk, Aflag);
36042873Sluoqi	if (active) {
36142873Sluoqi		bzero(&args, sizeof(args));
36242873Sluoqi		if (mount("ufs", fs->fs_file,
36342873Sluoqi		    stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0)
36442873Sluoqi			err(9, "%s: reload", special);
365102231Strhodes		warnx("file system reloaded");
36642873Sluoqi	}
3671558Srgrimes	exit(0);
3681558Srgrimes}
3691558Srgrimes
3701558Srgrimesvoid
371109597Sjmallettusage(void)
3721558Srgrimes{
37338040Scharnier	fprintf(stderr, "%s\n%s\n%s\n",
374105156Srwatson"usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]",
375105120Srwatson"              [-l enable | disable] [-m minfree] [-n enable | disable]",
376105120Srwatson"              [-o space | time] [-p] [-s avgfpdir] special | filesystem");
3771558Srgrimes	exit(2);
3781558Srgrimes}
3791558Srgrimes
3801558Srgrimesvoid
381109597Sjmallettprintfs(void)
3821558Srgrimes{
383105162Srwatson	warnx("ACLs: (-a)                                         %s",
384105162Srwatson		(sblock.fs_flags & FS_ACLS)? "enabled" : "disabled");
385105162Srwatson	warnx("MAC multilabel: (-l)                               %s",
386105162Srwatson		(sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled");
387109468Sjmallett	warnx("soft updates: (-n)                                 %s",
38834266Sjulian		(sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled");
3899315Sjoerg	warnx("maximum blocks per file in a cylinder group: (-e)  %d",
3909315Sjoerg	      sblock.fs_maxbpg);
39175377Smckusick	warnx("average file size: (-f)                            %d",
39275377Smckusick	      sblock.fs_avgfilesize);
39375377Smckusick	warnx("average number of files in a directory: (-s)       %d",
39475377Smckusick	      sblock.fs_avgfpdir);
3959315Sjoerg	warnx("minimum percentage of free space: (-m)             %d%%",
3969315Sjoerg	      sblock.fs_minfree);
3979315Sjoerg	warnx("optimization preference: (-o)                      %s",
3989315Sjoerg	      sblock.fs_optim == FS_OPTSPACE ? "space" : "time");
3999315Sjoerg	if (sblock.fs_minfree >= MINFREE &&
4009315Sjoerg	    sblock.fs_optim == FS_OPTSPACE)
4019315Sjoerg		warnx(OPTWARN, "time", ">=", MINFREE);
4029315Sjoerg	if (sblock.fs_minfree < MINFREE &&
4039315Sjoerg	    sblock.fs_optim == FS_OPTTIME)
4049315Sjoerg		warnx(OPTWARN, "space", "<", MINFREE);
4059315Sjoerg}
406