tunefs.c revision 110174
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 110174 2003-02-01 04:17:10Z gordon $";
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
60110174Sgordon#include <ctype.h>
611558Srgrimes#include <err.h>
621558Srgrimes#include <fcntl.h>
631558Srgrimes#include <fstab.h>
64109597Sjmallett#include <libufs.h>
6538040Scharnier#include <paths.h>
661558Srgrimes#include <stdio.h>
671558Srgrimes#include <stdlib.h>
6858047Ssheldonh#include <string.h>
691558Srgrimes#include <unistd.h>
701558Srgrimes
711558Srgrimes/* the optimization warning string template */
721558Srgrimes#define	OPTWARN	"should optimize for %s with minfree %s %d%%"
731558Srgrimes
74109597Sjmallettstruct uufsd disk;
75109597Sjmallett#define	sblock disk.d_fs
761558Srgrimes
7792883Simpvoid usage(void);
7892883Simpvoid printfs(void);
791558Srgrimes
801558Srgrimesint
81109597Sjmallettmain(int argc, char *argv[])
821558Srgrimes{
83109963Sjmallett	const char *special, *on;
8479750Sdd	const char *name;
85110174Sgordon	int Aflag = 0, Lflag = 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;
90110174Sgordon	char *Lvalue = NULL, *avalue = NULL, *lvalue = NULL, *nvalue = NULL;
9179750Sdd	const char *chg[2];
9242873Sluoqi	struct ufs_args args;
9342873Sluoqi	struct statfs stfs;
94110174Sgordon	int found_arg, ch, i;
951558Srgrimes
9669314Scharnier        if (argc < 3)
9769314Scharnier                usage();
9869314Scharnier	found_arg = 0; /* at least one arg is required */
99110174Sgordon	while ((ch = getopt(argc, argv, "AL:a:e:f:l:m:n:o:ps:")) != -1)
10069314Scharnier	  switch (ch) {
101105156Srwatson	  case 'A':
102105156Srwatson		found_arg = 1;
103105156Srwatson		Aflag++;
104105156Srwatson		break;
105110174Sgordon	  case 'L':
106110174Sgordon		found_arg = 1;
107110174Sgordon		name = "volume label";
108110174Sgordon		Lvalue = optarg;
109110174Sgordon		i = -1;
110110174Sgordon		while (isalnum(Lvalue[++i]));
111110174Sgordon		if (Lvalue[i] != '\0') {
112110174Sgordon			errx(10, "bad %s. Valid characters are alphanumerics.",
113110174Sgordon			    name);
114110174Sgordon		}
115110174Sgordon		if (strlen(Lvalue) >= MAXVOLLEN) {
116110174Sgordon			errx(10, "bad %s. Length is longer than %d.",
117110174Sgordon			    name, MAXVOLLEN - 1);
118110174Sgordon		}
119110174Sgordon		Lflag = 1;
120110174Sgordon		break;
121105120Srwatson	  case 'a':
122105120Srwatson		found_arg = 1;
123105120Srwatson		name = "ACLs";
124105120Srwatson		avalue = optarg;
125105120Srwatson		if (strcmp(avalue, "enable") && strcmp(avalue, "disable")) {
126105120Srwatson			errx(10, "bad %s (options are %s)", name,
127105120Srwatson			    "`enable' or `disable'");
128105120Srwatson		}
129105120Srwatson		aflag = 1;
130105120Srwatson		break;
13169314Scharnier	  case 'e':
13269314Scharnier		found_arg = 1;
13369314Scharnier		name = "maximum blocks per file in a cylinder group";
13469829Scharnier		evalue = atoi(optarg);
13569829Scharnier		if (evalue < 1)
13669314Scharnier			errx(10, "%s must be >= 1 (was %s)", name, optarg);
13769829Scharnier		eflag = 1;
13869314Scharnier		break;
13975377Smckusick	  case 'f':
14075377Smckusick		found_arg = 1;
14175377Smckusick		name = "average file size";
14275377Smckusick		fvalue = atoi(optarg);
14375377Smckusick		if (fvalue < 1)
14475377Smckusick			errx(10, "%s must be >= 1 (was %s)", name, optarg);
14575377Smckusick		fflag = 1;
14675377Smckusick		break;
147105120Srwatson	  case 'l':
148105120Srwatson		found_arg = 1;
149105120Srwatson		name = "multilabel MAC file system";
150105120Srwatson		lvalue = optarg;
151105120Srwatson		if (strcmp(lvalue, "enable") && strcmp(lvalue, "disable")) {
152105120Srwatson			errx(10, "bad %s (options are %s)", name,
153105120Srwatson			    "`enable' or `disable'");
154105120Srwatson		}
155105120Srwatson		lflag = 1;
156105120Srwatson		break;
15769314Scharnier	  case 'm':
15869314Scharnier		found_arg = 1;
15969314Scharnier		name = "minimum percentage of free space";
16069829Scharnier		mvalue = atoi(optarg);
16169829Scharnier		if (mvalue < 0 || mvalue > 99)
16269314Scharnier			errx(10, "bad %s (%s)", name, optarg);
16369829Scharnier		mflag = 1;
16469314Scharnier		break;
16569314Scharnier	  case 'n':
16669314Scharnier		found_arg = 1;
16769314Scharnier 		name = "soft updates";
16869829Scharnier 		nvalue = optarg;
16969829Scharnier                if (strcmp(nvalue, "enable") && strcmp(nvalue, "disable")) {
17069314Scharnier 			errx(10, "bad %s (options are %s)",
17169314Scharnier 			    name, "`enable' or `disable'");
17269314Scharnier 		}
17369829Scharnier		nflag = 1;
17469314Scharnier 		break;
17569314Scharnier	  case 'o':
17669314Scharnier		found_arg = 1;
17769314Scharnier		name = "optimization preference";
17869314Scharnier		chg[FS_OPTSPACE] = "space";
17969314Scharnier		chg[FS_OPTTIME] = "time";
18069314Scharnier		if (strcmp(optarg, chg[FS_OPTSPACE]) == 0)
18169829Scharnier			ovalue = FS_OPTSPACE;
18269314Scharnier		else if (strcmp(optarg, chg[FS_OPTTIME]) == 0)
18369829Scharnier			ovalue = FS_OPTTIME;
18469314Scharnier		else
18569314Scharnier			errx(10, "bad %s (options are `space' or `time')",
1861558Srgrimes					    name);
18769829Scharnier		oflag = 1;
18869314Scharnier		break;
18969314Scharnier	  case 'p':
19071790Sben		found_arg = 1;
19169829Scharnier		pflag = 1;
19269829Scharnier		break;
19375377Smckusick	  case 's':
19475377Smckusick		found_arg = 1;
19575377Smckusick		name = "expected number of files per directory";
19675377Smckusick		svalue = atoi(optarg);
19775377Smckusick		if (svalue < 1)
19875377Smckusick			errx(10, "%s must be >= 1 (was %s)", name, optarg);
19975377Smckusick		sflag = 1;
20075377Smckusick		break;
20169314Scharnier	  default:
20269314Scharnier		usage();
20369314Scharnier	  }
20469314Scharnier	argc -= optind;
20569314Scharnier	argv += optind;
2061558Srgrimes
20769314Scharnier	if (found_arg == 0 || argc != 1)
20869314Scharnier	  usage();
20969314Scharnier
210109963Sjmallett	on = special = argv[0];
211109963Sjmallett	if (ufs_disk_fillout(&disk, special) == -1)
212109963Sjmallett		goto err;
213109963Sjmallett	if (disk.d_name != special) {
214109963Sjmallett		special = disk.d_name;
21569829Scharnier		if (statfs(special, &stfs) == 0 &&
216109963Sjmallett		    strcmp(special, stfs.f_mntonname) == 0)
21769829Scharnier			active = 1;
21869829Scharnier	}
21969829Scharnier
22069829Scharnier	if (pflag) {
22169829Scharnier		printfs();
22269829Scharnier		exit(0);
22369829Scharnier	}
224110174Sgordon	if (Lflag) {
225110174Sgordon		name = "volume label";
226110174Sgordon		strlcpy(sblock.fs_volname, Lvalue, MAXVOLLEN);
227110174Sgordon	}
228105120Srwatson	if (aflag) {
229105120Srwatson		name = "ACLs";
230105120Srwatson		if (strcmp(avalue, "enable") == 0) {
231105120Srwatson			if (sblock.fs_flags & FS_ACLS) {
232105120Srwatson				warnx("%s remains unchanged as enabled", name);
233105120Srwatson			} else {
234105120Srwatson				sblock.fs_flags |= FS_ACLS;
235105120Srwatson				warnx("%s set", name);
236105120Srwatson			}
237105120Srwatson		} else if (strcmp(avalue, "disable") == 0) {
238105120Srwatson			if ((~sblock.fs_flags & FS_ACLS) ==
239105120Srwatson			    FS_ACLS) {
240105120Srwatson				warnx("%s remains unchanged as disabled",
241105120Srwatson				    name);
242105120Srwatson			} else {
243105120Srwatson				sblock.fs_flags &= ~FS_ACLS;
244105206Srwatson				warnx("%s cleared", name);
245105120Srwatson			}
246105120Srwatson		}
247105120Srwatson	}
24869829Scharnier	if (eflag) {
24969829Scharnier		name = "maximum blocks per file in a cylinder group";
25069829Scharnier		if (sblock.fs_maxbpg == evalue) {
25169829Scharnier			warnx("%s remains unchanged as %d", name, evalue);
25269829Scharnier		}
25369829Scharnier		else {
25469829Scharnier			warnx("%s changes from %d to %d",
25569829Scharnier					name, sblock.fs_maxbpg, evalue);
25669829Scharnier			sblock.fs_maxbpg = evalue;
25769829Scharnier		}
25869829Scharnier	}
25975377Smckusick	if (fflag) {
26075377Smckusick		name = "average file size";
26175377Smckusick		if (sblock.fs_avgfilesize == fvalue) {
26275377Smckusick			warnx("%s remains unchanged as %d", name, fvalue);
26375377Smckusick		}
26475377Smckusick		else {
26575377Smckusick			warnx("%s changes from %d to %d",
26675377Smckusick					name, sblock.fs_avgfilesize, fvalue);
26775377Smckusick			sblock.fs_avgfilesize = fvalue;
26875377Smckusick		}
26975377Smckusick	}
270105120Srwatson	if (lflag) {
271105120Srwatson		name = "multilabel";
272105120Srwatson		if (strcmp(lvalue, "enable") == 0) {
273105120Srwatson			if (sblock.fs_flags & FS_MULTILABEL) {
274105120Srwatson				warnx("%s remains unchanged as enabled", name);
275105120Srwatson			} else {
276105120Srwatson				sblock.fs_flags |= FS_MULTILABEL;
277105120Srwatson				warnx("%s set", name);
278105120Srwatson			}
279105120Srwatson		} else if (strcmp(lvalue, "disable") == 0) {
280105120Srwatson			if ((~sblock.fs_flags & FS_MULTILABEL) ==
281105120Srwatson			    FS_MULTILABEL) {
282105120Srwatson				warnx("%s remains unchanged as disabled",
283105120Srwatson				    name);
284105120Srwatson			} else {
285105120Srwatson				sblock.fs_flags &= ~FS_MULTILABEL;
286105206Srwatson				warnx("%s cleared", name);
287105120Srwatson			}
288105120Srwatson		}
289105120Srwatson	}
29069829Scharnier	if (mflag) {
29169829Scharnier		name = "minimum percentage of free space";
29269829Scharnier		if (sblock.fs_minfree == mvalue) {
29369829Scharnier			warnx("%s remains unchanged as %d%%", name, mvalue);
29469829Scharnier		}
29569829Scharnier		else {
29669829Scharnier			warnx("%s changes from %d%% to %d%%",
29769829Scharnier				    name, sblock.fs_minfree, mvalue);
29869829Scharnier			sblock.fs_minfree = mvalue;
29969829Scharnier			if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE)
30069829Scharnier				warnx(OPTWARN, "time", ">=", MINFREE);
30169829Scharnier			if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME)
30269829Scharnier				warnx(OPTWARN, "space", "<", MINFREE);
30369829Scharnier		}
30469829Scharnier	}
30569829Scharnier	if (nflag) {
30669829Scharnier 		name = "soft updates";
30769829Scharnier 		if (strcmp(nvalue, "enable") == 0) {
30875498Smckusick			if (sblock.fs_flags & FS_DOSOFTDEP) {
30969829Scharnier				warnx("%s remains unchanged as enabled", name);
31075498Smckusick			} else if (sblock.fs_clean == 0) {
31175498Smckusick				warnx("%s cannot be enabled until fsck is run",
31275498Smckusick				    name);
31369829Scharnier			} else {
31469829Scharnier 				sblock.fs_flags |= FS_DOSOFTDEP;
31569829Scharnier 				warnx("%s set", name);
31669829Scharnier			}
31769829Scharnier 		} else if (strcmp(nvalue, "disable") == 0) {
31869829Scharnier			if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP) {
31969829Scharnier				warnx("%s remains unchanged as disabled", name);
32069829Scharnier			} else {
32169829Scharnier 				sblock.fs_flags &= ~FS_DOSOFTDEP;
32269829Scharnier 				warnx("%s cleared", name);
32369829Scharnier			}
32469829Scharnier 		}
32569829Scharnier	}
32669829Scharnier	if (oflag) {
32769829Scharnier		name = "optimization preference";
32869829Scharnier		chg[FS_OPTSPACE] = "space";
32969829Scharnier		chg[FS_OPTTIME] = "time";
33069829Scharnier		if (sblock.fs_optim == ovalue) {
33169829Scharnier			warnx("%s remains unchanged as %s", name, chg[ovalue]);
33269829Scharnier		}
33369829Scharnier		else {
33469829Scharnier			warnx("%s changes from %s to %s",
33569829Scharnier				    name, chg[sblock.fs_optim], chg[ovalue]);
33669829Scharnier			sblock.fs_optim = ovalue;
33769829Scharnier			if (sblock.fs_minfree >= MINFREE &&
33869829Scharnier					ovalue == FS_OPTSPACE)
33969829Scharnier				warnx(OPTWARN, "time", ">=", MINFREE);
34069829Scharnier			if (sblock.fs_minfree < MINFREE &&
34169829Scharnier					ovalue == FS_OPTTIME)
34269829Scharnier				warnx(OPTWARN, "space", "<", MINFREE);
34369829Scharnier		}
34469829Scharnier	}
34575377Smckusick	if (sflag) {
34675377Smckusick		name = "expected number of files per directory";
34775377Smckusick		if (sblock.fs_avgfpdir == svalue) {
34875377Smckusick			warnx("%s remains unchanged as %d", name, svalue);
34975377Smckusick		}
35075377Smckusick		else {
35175377Smckusick			warnx("%s changes from %d to %d",
35275377Smckusick					name, sblock.fs_avgfpdir, svalue);
35375377Smckusick			sblock.fs_avgfpdir = svalue;
35475377Smckusick		}
35575377Smckusick	}
35669829Scharnier
357109963Sjmallett	if (sbwrite(&disk, Aflag) == -1)
358109963Sjmallett		goto err;
359109963Sjmallett	ufs_disk_close(&disk);
36042873Sluoqi	if (active) {
36142873Sluoqi		bzero(&args, sizeof(args));
362109963Sjmallett		if (mount("ufs", on,
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);
368109963Sjmalletterr:
369109963Sjmallett	if (disk.d_error != NULL)
370109963Sjmallett		errx(11, "%s: %s", special, disk.d_error);
371109963Sjmallett	else
372109963Sjmallett		err(12, "%s", special);
3731558Srgrimes}
3741558Srgrimes
3751558Srgrimesvoid
376109597Sjmallettusage(void)
3771558Srgrimes{
378110174Sgordon	fprintf(stderr, "%s\n%s\n%s\n%s\n",
379110174Sgordon"usage: tunefs [-A] [-L volname] [-a enable | disable] [-e maxbpg]",
380110174Sgordon"              [-f avgfilesize] [-l enable | disable] [-m minfree]",
381110174Sgordon"              [-n enable | disable] [-o space | time] [-p]",
382110174Sgordon"              [-s avgfpdir] special | filesystem");
3831558Srgrimes	exit(2);
3841558Srgrimes}
3851558Srgrimes
3861558Srgrimesvoid
387109597Sjmallettprintfs(void)
3881558Srgrimes{
389105162Srwatson	warnx("ACLs: (-a)                                         %s",
390105162Srwatson		(sblock.fs_flags & FS_ACLS)? "enabled" : "disabled");
391105162Srwatson	warnx("MAC multilabel: (-l)                               %s",
392105162Srwatson		(sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled");
393109468Sjmallett	warnx("soft updates: (-n)                                 %s",
39434266Sjulian		(sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled");
3959315Sjoerg	warnx("maximum blocks per file in a cylinder group: (-e)  %d",
3969315Sjoerg	      sblock.fs_maxbpg);
39775377Smckusick	warnx("average file size: (-f)                            %d",
39875377Smckusick	      sblock.fs_avgfilesize);
39975377Smckusick	warnx("average number of files in a directory: (-s)       %d",
40075377Smckusick	      sblock.fs_avgfpdir);
4019315Sjoerg	warnx("minimum percentage of free space: (-m)             %d%%",
4029315Sjoerg	      sblock.fs_minfree);
4039315Sjoerg	warnx("optimization preference: (-o)                      %s",
4049315Sjoerg	      sblock.fs_optim == FS_OPTSPACE ? "space" : "time");
4059315Sjoerg	if (sblock.fs_minfree >= MINFREE &&
4069315Sjoerg	    sblock.fs_optim == FS_OPTSPACE)
4079315Sjoerg		warnx(OPTWARN, "time", ">=", MINFREE);
4089315Sjoerg	if (sblock.fs_minfree < MINFREE &&
4099315Sjoerg	    sblock.fs_optim == FS_OPTTIME)
4109315Sjoerg		warnx(OPTWARN, "space", "<", MINFREE);
411110174Sgordon	warnx("volume label: (-L)                                 %s",
412110174Sgordon		sblock.fs_volname);
4139315Sjoerg}
414