tunefs.c revision 42873
125184Sjkh/*
225184Sjkh * Copyright (c) 1983, 1993
350472Speter *	The Regents of the University of California.  All rights reserved.
425184Sjkh *
525184Sjkh * Redistribution and use in source and binary forms, with or without
651231Ssheldonh * modification, are permitted provided that the following conditions
751231Ssheldonh * are met:
825184Sjkh * 1. Redistributions of source code must retain the above copyright
925184Sjkh *    notice, this list of conditions and the following disclaimer.
1025184Sjkh * 2. Redistributions in binary form must reproduce the above copyright
1125184Sjkh *    notice, this list of conditions and the following disclaimer in the
1251231Ssheldonh *    documentation and/or other materials provided with the distribution.
1325184Sjkh * 3. All advertising materials mentioning features or use of this software
1451231Ssheldonh *    must display the following acknowledgement:
1525184Sjkh *	This product includes software developed by the University of
1651231Ssheldonh *	California, Berkeley and its contributors.
1751231Ssheldonh * 4. Neither the name of the University nor the names of its contributors
1851231Ssheldonh *    may be used to endorse or promote products derived from this software
1951231Ssheldonh *    without specific prior written permission.
2051231Ssheldonh *
2151231Ssheldonh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2225184Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2351231Ssheldonh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2451231Ssheldonh * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2551231Ssheldonh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2651231Ssheldonh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2751231Ssheldonh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2851231Ssheldonh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2951231Ssheldonh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3051231Ssheldonh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3151231Ssheldonh * SUCH DAMAGE.
3251231Ssheldonh */
3340006Sphk
3451231Ssheldonh#ifndef lint
3542621Shmstatic const char copyright[] =
3651231Ssheldonh"@(#) Copyright (c) 1983, 1993\n\
3751231Ssheldonh	The Regents of the University of California.  All rights reserved.\n";
3851231Ssheldonh#endif /* not lint */
3951231Ssheldonh
4051231Ssheldonh#ifndef lint
4151231Ssheldonh#if 0
4251231Ssheldonhstatic char sccsid[] = "@(#)tunefs.c	8.2 (Berkeley) 4/19/94";
4351231Ssheldonh#endif
4451231Ssheldonhstatic const char rcsid[] =
4551231Ssheldonh	"$Id: tunefs.c,v 1.6 1998/08/03 06:41:20 charnier Exp $";
4642627Sjoerg#endif /* not lint */
4751231Ssheldonh
4851231Ssheldonh/*
4951231Ssheldonh * tunefs: change layout parameters to an existing file system.
5051231Ssheldonh */
5151231Ssheldonh#include <sys/param.h>
5251231Ssheldonh#include <sys/mount.h>
5351231Ssheldonh#include <sys/stat.h>
5451231Ssheldonh
5551231Ssheldonh#include <ufs/ffs/fs.h>
5651231Ssheldonh#include <ufs/ufs/ufsmount.h>
5751231Ssheldonh
5851231Ssheldonh#include <err.h>
5951231Ssheldonh#include <fcntl.h>
6051231Ssheldonh#include <fstab.h>
6149122Sbrian#include <paths.h>
6251231Ssheldonh#include <stdio.h>
6351231Ssheldonh#include <stdlib.h>
6451231Ssheldonh#include <string.h>
6551231Ssheldonh#include <unistd.h>
6651231Ssheldonh
6751231Ssheldonh/* the optimization warning string template */
6851231Ssheldonh#define	OPTWARN	"should optimize for %s with minfree %s %d%%"
6949122Sbrian
7054458Sobrienunion {
7151231Ssheldonh	struct	fs sb;
7251231Ssheldonh	char pad[MAXBSIZE];
7351231Ssheldonh} sbun;
7454458Sobrien#define	sblock sbun.sb
7551231Ssheldonh
7649122Sbrianint fi;
7751231Ssheldonhlong dev_bsize = 1;
7851231Ssheldonh
7951231Ssheldonhvoid bwrite(daddr_t, char *, int);
8029300Sdannyint bread(daddr_t, char *, int);
8151231Ssheldonhvoid getsb(struct fs *, char *);
8251231Ssheldonhvoid usage __P((void));
8351231Ssheldonhvoid printfs __P((void));
8451231Ssheldonhchar *rawname __P((char *, char *));
8554458Sobrien
8654458Sobrienint
8754458Sobrienmain(argc, argv)
8851231Ssheldonh	int argc;
8951231Ssheldonh	char *argv[];
9051231Ssheldonh{
9154458Sobrien	char *cp, *special, *name, *action;
9251231Ssheldonh	struct stat st;
9351231Ssheldonh	int i;
9454458Sobrien	int Aflag = 0, active = 0;
9551231Ssheldonh	struct fstab *fs;
9654458Sobrien	char *chg[2], device[MAXPATHLEN];
9754458Sobrien	struct ufs_args args;
9854458Sobrien	struct statfs stfs;
9954458Sobrien
10054458Sobrien	argc--, argv++;
10151231Ssheldonh	if (argc < 2)
10251231Ssheldonh		usage();
10351231Ssheldonh	special = argv[argc - 1];
10451231Ssheldonh	fs = getfsfile(special);
10551231Ssheldonh	if (fs) {
10651231Ssheldonh		if (statfs(special, &stfs) == 0) {
10751231Ssheldonh		    	if ((stfs.f_flags & MNT_RDONLY) == 0) {
10854458Sobrien				errx(1, "cannot work on read-write mounted file system");
10951231Ssheldonh			}
11051231Ssheldonh			active = 1;
11151231Ssheldonh			special = rawname(fs->fs_spec, device);
11251231Ssheldonh		} else
11351231Ssheldonh			special = fs->fs_spec;
11451231Ssheldonh	}
11551231Ssheldonhagain:
11651231Ssheldonh	if (stat(special, &st) < 0) {
11751231Ssheldonh		if (*special != '/') {
11851231Ssheldonh			if (*special == 'r')
11951231Ssheldonh				special++;
12054458Sobrien			(void)sprintf(device, "%s/%s", _PATH_DEV, special);
12151231Ssheldonh			special = device;
12254458Sobrien			goto again;
12351231Ssheldonh		}
12454458Sobrien		err(1, "%s", special);
12554458Sobrien	}
12654458Sobrien	if ((st.st_mode & S_IFMT) != S_IFBLK &&
12751231Ssheldonh	    (st.st_mode & S_IFMT) != S_IFCHR)
12854458Sobrien		errx(10, "%s: not a block or character device", special);
12951231Ssheldonh	getsb(&sblock, special);
13051231Ssheldonh	for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
13157012Shm		for (cp = &argv[0][1]; *cp; cp++)
13257012Shm			switch (*cp) {
13357012Shm
13457012Shm			case 'A':
13557012Shm				Aflag++;
13657012Shm				continue;
13757012Shm
13857012Shm			case 'p':
13957012Shm				printfs();
14057012Shm				exit(0);
14151231Ssheldonh
14251231Ssheldonh			case 'a':
14351231Ssheldonh				name = "maximum contiguous block count";
14451231Ssheldonh				if (argc < 1)
14551231Ssheldonh					errx(10, "-a: missing %s", name);
14651231Ssheldonh				argc--, argv++;
14751231Ssheldonh				i = atoi(*argv);
14851231Ssheldonh				if (i < 1)
14951231Ssheldonh					errx(10, "%s must be >= 1 (was %s)",
15051231Ssheldonh					    name, *argv);
15151231Ssheldonh				warnx("%s changes from %d to %d",
15251231Ssheldonh				    name, sblock.fs_maxcontig, i);
15351231Ssheldonh				sblock.fs_maxcontig = i;
15451231Ssheldonh				continue;
15551231Ssheldonh
15651231Ssheldonh			case 'd':
15751231Ssheldonh				name =
15851231Ssheldonh				   "rotational delay between contiguous blocks";
15951231Ssheldonh				if (argc < 1)
16051231Ssheldonh					errx(10, "-d: missing %s", name);
16151231Ssheldonh				argc--, argv++;
16251231Ssheldonh				i = atoi(*argv);
16351231Ssheldonh				warnx("%s changes from %dms to %dms",
16451231Ssheldonh				    name, sblock.fs_rotdelay, i);
16551231Ssheldonh				sblock.fs_rotdelay = i;
16651231Ssheldonh				continue;
16751231Ssheldonh
16851231Ssheldonh			case 'e':
16951231Ssheldonh				name =
17051231Ssheldonh				  "maximum blocks per file in a cylinder group";
17151231Ssheldonh				if (argc < 1)
17251231Ssheldonh					errx(10, "-e: missing %s", name);
17329300Sdanny				argc--, argv++;
17451231Ssheldonh				i = atoi(*argv);
17529300Sdanny				if (i < 1)
17629300Sdanny					errx(10, "%s must be >= 1 (was %s)",
17751231Ssheldonh					    name, *argv);
17851231Ssheldonh				warnx("%s changes from %d to %d",
17951231Ssheldonh				    name, sblock.fs_maxbpg, i);
18051231Ssheldonh				sblock.fs_maxbpg = i;
18151231Ssheldonh				continue;
18251231Ssheldonh
18351231Ssheldonh			case 'm':
18451231Ssheldonh				name = "minimum percentage of free space";
18551231Ssheldonh				if (argc < 1)
18651231Ssheldonh					errx(10, "-m: missing %s", name);
18744992Sbrian				argc--, argv++;
18851231Ssheldonh				i = atoi(*argv);
18951231Ssheldonh				if (i < 0 || i > 99)
19051231Ssheldonh					errx(10, "bad %s (%s)", name, *argv);
19151231Ssheldonh				warnx("%s changes from %d%% to %d%%",
19251231Ssheldonh				    name, sblock.fs_minfree, i);
19351231Ssheldonh				sblock.fs_minfree = i;
19444992Sbrian				if (i >= MINFREE &&
19551231Ssheldonh				    sblock.fs_optim == FS_OPTSPACE)
19651231Ssheldonh					warnx(OPTWARN, "time", ">=", MINFREE);
19751231Ssheldonh				if (i < MINFREE &&
19851426Sgreen				    sblock.fs_optim == FS_OPTTIME)
19951426Sgreen					warnx(OPTWARN, "space", "<", MINFREE);
20051231Ssheldonh				continue;
20151231Ssheldonh
20251231Ssheldonh			case 'n':
20351231Ssheldonh 				name = "soft updates";
20451231Ssheldonh 				if (argc < 1)
20551231Ssheldonh 					errx(10, "-s: missing %s", name);
20651231Ssheldonh 				argc--, argv++;
20751231Ssheldonh 				if (strcmp(*argv, "enable") == 0) {
20851231Ssheldonh 					sblock.fs_flags |= FS_DOSOFTDEP;
20951231Ssheldonh 					action = "set";
21051231Ssheldonh 				} else if (strcmp(*argv, "disable") == 0) {
21151231Ssheldonh 					sblock.fs_flags &= ~FS_DOSOFTDEP;
21251231Ssheldonh 					action = "cleared";
21351231Ssheldonh 				} else {
21451231Ssheldonh 					errx(10, "bad %s (options are %s)",
21551231Ssheldonh 					    name, "`enable' or `disable'");
21651231Ssheldonh 				}
21751231Ssheldonh 				warnx("%s %s", name, action);
21851231Ssheldonh 				continue;
21951231Ssheldonh
22051231Ssheldonh			case 'o':
22151231Ssheldonh				name = "optimization preference";
22251231Ssheldonh				if (argc < 1)
22351231Ssheldonh					errx(10, "-o: missing %s", name);
22451231Ssheldonh				argc--, argv++;
22551231Ssheldonh				chg[FS_OPTSPACE] = "space";
22651231Ssheldonh				chg[FS_OPTTIME] = "time";
22751231Ssheldonh				if (strcmp(*argv, chg[FS_OPTSPACE]) == 0)
22851231Ssheldonh					i = FS_OPTSPACE;
22951231Ssheldonh				else if (strcmp(*argv, chg[FS_OPTTIME]) == 0)
23051231Ssheldonh					i = FS_OPTTIME;
23151231Ssheldonh				else
23251231Ssheldonh					errx(10, "bad %s (options are `space' or `time')",
23351231Ssheldonh					    name);
23451231Ssheldonh				if (sblock.fs_optim == i) {
23529300Sdanny					warnx("%s remains unchanged as %s",
23625184Sjkh					    name, chg[i]);
23751231Ssheldonh					continue;
23851231Ssheldonh				}
23951231Ssheldonh				warnx("%s changes from %s to %s",
24051231Ssheldonh				    name, chg[sblock.fs_optim], chg[i]);
24151231Ssheldonh				sblock.fs_optim = i;
24251231Ssheldonh				if (sblock.fs_minfree >= MINFREE &&
24351231Ssheldonh				    i == FS_OPTSPACE)
24451231Ssheldonh					warnx(OPTWARN, "time", ">=", MINFREE);
24551231Ssheldonh				if (sblock.fs_minfree < MINFREE &&
24651231Ssheldonh				    i == FS_OPTTIME)
24740006Sphk					warnx(OPTWARN, "space", "<", MINFREE);
24851231Ssheldonh				continue;
24951231Ssheldonh
25051231Ssheldonh			default:
25151231Ssheldonh				usage();
25251231Ssheldonh			}
25351231Ssheldonh	}
25451231Ssheldonh	if (argc != 1)
25551231Ssheldonh		usage();
25629300Sdanny	bwrite((daddr_t)SBOFF / dev_bsize, (char *)&sblock, SBSIZE);
25751231Ssheldonh	if (Aflag)
25851231Ssheldonh		for (i = 0; i < sblock.fs_ncg; i++)
25951231Ssheldonh			bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)),
26051231Ssheldonh			    (char *)&sblock, SBSIZE);
26151231Ssheldonh	close(fi);
26251231Ssheldonh	if (active) {
26351231Ssheldonh		bzero(&args, sizeof(args));
26451231Ssheldonh		if (mount("ufs", fs->fs_file,
26551231Ssheldonh		    stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0)
26625184Sjkh			err(9, "%s: reload", special);
26751231Ssheldonh		warnx("file system reloaded");
26851231Ssheldonh	}
26951231Ssheldonh	exit(0);
27051231Ssheldonh}
27151231Ssheldonh
27251231Ssheldonhvoid
27345096Simpusage()
27451231Ssheldonh{
27551231Ssheldonh	fprintf(stderr, "%s\n%s\n%s\n",
27651231Ssheldonh"usage: tunefs [-A] [-a maxcontig] [-d rotdelay] [-e maxbpg] [-m minfree]",
27751231Ssheldonh"              [-p] [-n enable | disable] [-o optimize_preference]",
27851231Ssheldonh"              [special | filesystem]");
27951231Ssheldonh	exit(2);
28039267Sjkoshy}
28151231Ssheldonh
28251231Ssheldonhvoid
28351231Ssheldonhgetsb(fs, file)
28451231Ssheldonh	register struct fs *fs;
28551231Ssheldonh	char *file;
28651231Ssheldonh{
28733439Sguido
28851231Ssheldonh	fi = open(file, 2);
28951231Ssheldonh	if (fi < 0)
29051231Ssheldonh		err(3, "cannot open %s", file);
29151231Ssheldonh	if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE))
29251231Ssheldonh		err(4, "%s: bad super block", file);
29351231Ssheldonh	if (fs->fs_magic != FS_MAGIC)
29433439Sguido		err(5, "%s: bad magic number", file);
29551231Ssheldonh	dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
29651231Ssheldonh}
29751231Ssheldonh
29851231Ssheldonhvoid
29951231Ssheldonhprintfs()
30051231Ssheldonh{
30147752Sphk	warnx("soft updates:  (-n)                                %s",
30251231Ssheldonh		(sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled");
30351231Ssheldonh	warnx("maximum contiguous block count: (-a)               %d",
30451231Ssheldonh	      sblock.fs_maxcontig);
30551231Ssheldonh	warnx("rotational delay between contiguous blocks: (-d)   %d ms",
30651231Ssheldonh	      sblock.fs_rotdelay);
30751231Ssheldonh	warnx("maximum blocks per file in a cylinder group: (-e)  %d",
30851209Sdes	      sblock.fs_maxbpg);
30951231Ssheldonh	warnx("minimum percentage of free space: (-m)             %d%%",
31051231Ssheldonh	      sblock.fs_minfree);
31151231Ssheldonh	warnx("optimization preference: (-o)                      %s",
31251231Ssheldonh	      sblock.fs_optim == FS_OPTSPACE ? "space" : "time");
31351231Ssheldonh	if (sblock.fs_minfree >= MINFREE &&
31451231Ssheldonh	    sblock.fs_optim == FS_OPTSPACE)
31551209Sdes		warnx(OPTWARN, "time", ">=", MINFREE);
31651231Ssheldonh	if (sblock.fs_minfree < MINFREE &&
31751231Ssheldonh	    sblock.fs_optim == FS_OPTTIME)
31851231Ssheldonh		warnx(OPTWARN, "space", "<", MINFREE);
31951231Ssheldonh}
32051231Ssheldonh
32151231Ssheldonhvoid
32236174Sjkhbwrite(blk, buf, size)
32351231Ssheldonh	daddr_t blk;
32451231Ssheldonh	char *buf;
32551231Ssheldonh	int size;
32651231Ssheldonh{
32751231Ssheldonh
32851231Ssheldonh	if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0)
32936174Sjkh		err(6, "FS SEEK");
33051231Ssheldonh	if (write(fi, buf, size) != size)
33151231Ssheldonh		err(7, "FS WRITE");
33251231Ssheldonh}
33351231Ssheldonh
33451231Ssheldonhint
33551231Ssheldonhbread(bno, buf, cnt)
33651231Ssheldonh	daddr_t bno;
33751231Ssheldonh	char *buf;
33851231Ssheldonh	int cnt;
33951231Ssheldonh{
34051231Ssheldonh	int i;
34151231Ssheldonh
34251231Ssheldonh	if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0)
34351231Ssheldonh		return(1);
34451231Ssheldonh	if ((i = read(fi, buf, cnt)) != cnt) {
34551231Ssheldonh		for(i=0; i<sblock.fs_bsize; i++)
34651231Ssheldonh			buf[i] = 0;
34751231Ssheldonh		return (1);
34851231Ssheldonh	}
34951231Ssheldonh	return (0);
35051231Ssheldonh}
35151231Ssheldonh
35251231Ssheldonhchar *
35351231Ssheldonhrawname(special, pathbuf)
35451231Ssheldonh	char *special;
35551231Ssheldonh	char *pathbuf;
35651231Ssheldonh{
35751231Ssheldonh	char *p;
35851231Ssheldonh	int n;
35951231Ssheldonh
36051231Ssheldonh	p = strrchr(special, '/');
36151231Ssheldonh	if (p) {
36251231Ssheldonh		n = ++p - special;
36351231Ssheldonh		bcopy(special, pathbuf, n);
36451231Ssheldonh	} else {
36551231Ssheldonh		strcpy(pathbuf, _PATH_DEV);
36651231Ssheldonh		n = strlen(pathbuf);
36751231Ssheldonh		p = special;
36851231Ssheldonh	}
36951231Ssheldonh	pathbuf[n++] = 'r';
37051231Ssheldonh	strcpy(pathbuf + n, p);
37151231Ssheldonh	return pathbuf;
37251231Ssheldonh}
37351231Ssheldonh