xref: /csrg-svn/sbin/tunefs/tunefs.c (revision 69181)
121184Sdist /*
261556Sbostic  * Copyright (c) 1983, 1993
361556Sbostic  *	The Regents of the University of California.  All rights reserved.
435484Sbostic  *
542712Sbostic  * %sccs.include.redist.c%
621184Sdist  */
721184Sdist 
811288Smckusick #ifndef lint
961556Sbostic static char copyright[] =
1061556Sbostic "@(#) Copyright (c) 1983, 1993\n\
1161556Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1235484Sbostic #endif /* not lint */
1311288Smckusick 
1421184Sdist #ifndef lint
15*69181Smckusick static char sccsid[] = "@(#)tunefs.c	8.3 (Berkeley) 05/03/95";
1635484Sbostic #endif /* not lint */
1721184Sdist 
1811288Smckusick /*
1911288Smckusick  * tunefs: change layout parameters to an existing file system.
2011288Smckusick  */
2111288Smckusick #include <sys/param.h>
2211288Smckusick #include <sys/stat.h>
2355660Sbostic 
24*69181Smckusick #include <ufs/ufs/dinode.h>
2551624Sbostic #include <ufs/ffs/fs.h>
2655660Sbostic 
2755660Sbostic #include <errno.h>
2866924Smckusick #include <err.h>
2966924Smckusick #include <fcntl.h>
3037959Sbostic #include <fstab.h>
3113120Ssam #include <stdio.h>
3237959Sbostic #include <paths.h>
3366924Smckusick #include <stdlib.h>
3466924Smckusick #include <unistd.h>
3513120Ssam 
3666924Smckusick /* the optimization warning string template */
3766924Smckusick #define	OPTWARN	"should optimize for %s with minfree %s %d%%"
3866924Smckusick 
3911288Smckusick union {
4011288Smckusick 	struct	fs sb;
4111288Smckusick 	char pad[MAXBSIZE];
4211288Smckusick } sbun;
4311288Smckusick #define	sblock sbun.sb
4411288Smckusick 
4511288Smckusick int fi;
4630558Smckusick long dev_bsize = 1;
4711288Smckusick 
4866924Smckusick void bwrite(daddr_t, char *, int);
4966924Smckusick int bread(daddr_t, char *, int);
5066924Smckusick void getsb(struct fs *, char *);
5166924Smckusick void usage __P((void));
5266924Smckusick 
5366924Smckusick int
main(argc,argv)5411288Smckusick main(argc, argv)
5511288Smckusick 	int argc;
5611288Smckusick 	char *argv[];
5711288Smckusick {
5811288Smckusick 	char *cp, *special, *name;
5911288Smckusick 	struct stat st;
6011288Smckusick 	int i;
61*69181Smckusick 	int Aflag = 0, Nflag = 0;
6224700Smckusick 	struct fstab *fs;
6324700Smckusick 	char *chg[2], device[MAXPATHLEN];
6411288Smckusick 
6511288Smckusick 	argc--, argv++;
6611288Smckusick 	if (argc < 2)
6766924Smckusick 		usage();
6811288Smckusick 	special = argv[argc - 1];
6913120Ssam 	fs = getfsfile(special);
7013120Ssam 	if (fs)
7113120Ssam 		special = fs->fs_spec;
7211288Smckusick again:
7311288Smckusick 	if (stat(special, &st) < 0) {
7411288Smckusick 		if (*special != '/') {
7511288Smckusick 			if (*special == 'r')
7611288Smckusick 				special++;
7737959Sbostic 			(void)sprintf(device, "%s/%s", _PATH_DEV, special);
7832453Sbostic 			special = device;
7911288Smckusick 			goto again;
8011288Smckusick 		}
8166924Smckusick 		err(1, "%s", special);
8211288Smckusick 	}
8311288Smckusick 	if ((st.st_mode & S_IFMT) != S_IFBLK &&
8411288Smckusick 	    (st.st_mode & S_IFMT) != S_IFCHR)
8566924Smckusick 		errx(10, "%s: not a block or character device", special);
8611288Smckusick 	getsb(&sblock, special);
87*69181Smckusick 	chg[FS_OPTSPACE] = "space";
88*69181Smckusick 	chg[FS_OPTTIME] = "time";
8911288Smckusick 	for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
9011288Smckusick 		for (cp = &argv[0][1]; *cp; cp++)
9111288Smckusick 			switch (*cp) {
9211288Smckusick 
9311288Smckusick 			case 'A':
9411288Smckusick 				Aflag++;
9511288Smckusick 				continue;
9611288Smckusick 
97*69181Smckusick 			case 'N':
98*69181Smckusick 				Nflag++;
99*69181Smckusick 				continue;
100*69181Smckusick 
10111288Smckusick 			case 'a':
10211288Smckusick 				name = "maximum contiguous block count";
10311288Smckusick 				if (argc < 1)
10466924Smckusick 					errx(10, "-a: missing %s", name);
10511288Smckusick 				argc--, argv++;
10611288Smckusick 				i = atoi(*argv);
10711288Smckusick 				if (i < 1)
10866924Smckusick 					errx(10, "%s must be >= 1 (was %s)",
10966924Smckusick 					    name, *argv);
11066924Smckusick 				warnx("%s changes from %d to %d",
11166924Smckusick 				    name, sblock.fs_maxcontig, i);
11211288Smckusick 				sblock.fs_maxcontig = i;
11311288Smckusick 				continue;
11411288Smckusick 
11511288Smckusick 			case 'd':
11611288Smckusick 				name =
11711288Smckusick 				   "rotational delay between contiguous blocks";
11811288Smckusick 				if (argc < 1)
11966924Smckusick 					errx(10, "-d: missing %s", name);
12011288Smckusick 				argc--, argv++;
12111288Smckusick 				i = atoi(*argv);
12266924Smckusick 				warnx("%s changes from %dms to %dms",
12366924Smckusick 				    name, sblock.fs_rotdelay, i);
12411288Smckusick 				sblock.fs_rotdelay = i;
12511288Smckusick 				continue;
12611288Smckusick 
12711288Smckusick 			case 'e':
12811288Smckusick 				name =
12911288Smckusick 				  "maximum blocks per file in a cylinder group";
13011288Smckusick 				if (argc < 1)
13166924Smckusick 					errx(10, "-e: missing %s", name);
13211288Smckusick 				argc--, argv++;
13311288Smckusick 				i = atoi(*argv);
13411288Smckusick 				if (i < 1)
13566924Smckusick 					errx(10, "%s must be >= 1 (was %s)",
13666924Smckusick 					    name, *argv);
13766924Smckusick 				warnx("%s changes from %d to %d",
13866924Smckusick 				    name, sblock.fs_maxbpg, i);
13911288Smckusick 				sblock.fs_maxbpg = i;
14011288Smckusick 				continue;
14111288Smckusick 
14211288Smckusick 			case 'm':
14311288Smckusick 				name = "minimum percentage of free space";
14411288Smckusick 				if (argc < 1)
14566924Smckusick 					errx(10, "-m: missing %s", name);
14611288Smckusick 				argc--, argv++;
14711288Smckusick 				i = atoi(*argv);
14811288Smckusick 				if (i < 0 || i > 99)
14966924Smckusick 					errx(10, "bad %s (%s)", name, *argv);
15066924Smckusick 				warnx("%s changes from %d%% to %d%%",
15166924Smckusick 				    name, sblock.fs_minfree, i);
15211288Smckusick 				sblock.fs_minfree = i;
15366924Smckusick 				if (i >= MINFREE &&
15466924Smckusick 				    sblock.fs_optim == FS_OPTSPACE)
15566924Smckusick 					warnx(OPTWARN, "time", ">=", MINFREE);
15666924Smckusick 				if (i < MINFREE &&
15766924Smckusick 				    sblock.fs_optim == FS_OPTTIME)
15866924Smckusick 					warnx(OPTWARN, "space", "<", MINFREE);
15911288Smckusick 				continue;
16011288Smckusick 
16124700Smckusick 			case 'o':
16224700Smckusick 				name = "optimization preference";
16324700Smckusick 				if (argc < 1)
16466924Smckusick 					errx(10, "-o: missing %s", name);
16524700Smckusick 				argc--, argv++;
16624700Smckusick 				if (strcmp(*argv, chg[FS_OPTSPACE]) == 0)
16724700Smckusick 					i = FS_OPTSPACE;
16824700Smckusick 				else if (strcmp(*argv, chg[FS_OPTTIME]) == 0)
16924700Smckusick 					i = FS_OPTTIME;
17024700Smckusick 				else
17166924Smckusick 					errx(10, "bad %s (options are `space' or `time')",
17266924Smckusick 					    name);
17324700Smckusick 				if (sblock.fs_optim == i) {
17466924Smckusick 					warnx("%s remains unchanged as %s",
17566924Smckusick 					    name, chg[i]);
17624700Smckusick 					continue;
17724700Smckusick 				}
17866924Smckusick 				warnx("%s changes from %s to %s",
17966924Smckusick 				    name, chg[sblock.fs_optim], chg[i]);
18024700Smckusick 				sblock.fs_optim = i;
18166924Smckusick 				if (sblock.fs_minfree >= MINFREE &&
18266924Smckusick 				    i == FS_OPTSPACE)
18366924Smckusick 					warnx(OPTWARN, "time", ">=", MINFREE);
18466924Smckusick 				if (sblock.fs_minfree < MINFREE &&
18566924Smckusick 				    i == FS_OPTTIME)
18666924Smckusick 					warnx(OPTWARN, "space", "<", MINFREE);
18724700Smckusick 				continue;
18824700Smckusick 
189*69181Smckusick 			case 't':
190*69181Smckusick 				name = "track skew in sectors";
191*69181Smckusick 				if (argc < 1)
192*69181Smckusick 					errx(10, "-t: missing %s", name);
193*69181Smckusick 				argc--, argv++;
194*69181Smckusick 				i = atoi(*argv);
195*69181Smckusick 				if (i < 0)
196*69181Smckusick 					errx(10, "%s: %s must be >= 0",
197*69181Smckusick 						*argv, name);
198*69181Smckusick 				warnx("%s changes from %d to %d",
199*69181Smckusick 					name, sblock.fs_trackskew, i);
200*69181Smckusick 				sblock.fs_trackskew = i;
201*69181Smckusick 				continue;
202*69181Smckusick 
20311288Smckusick 			default:
20466924Smckusick 				usage();
20511288Smckusick 			}
20611288Smckusick 	}
20711288Smckusick 	if (argc != 1)
20866924Smckusick 		usage();
209*69181Smckusick 	if (Nflag) {
210*69181Smckusick 		fprintf(stdout, "tunefs: current settings\n");
211*69181Smckusick 		fprintf(stdout, "\tmaximum contiguous block count %d\n",
212*69181Smckusick 		    sblock.fs_maxcontig);
213*69181Smckusick 		fprintf(stdout,
214*69181Smckusick 		    "\trotational delay between contiguous blocks %dms\n",
215*69181Smckusick 		    sblock.fs_rotdelay);
216*69181Smckusick 		fprintf(stdout,
217*69181Smckusick 		    "\tmaximum blocks per file in a cylinder group %d\n",
218*69181Smckusick 		    sblock.fs_maxbpg);
219*69181Smckusick 		fprintf(stdout, "\tminimum percentage of free space %d%%\n",
220*69181Smckusick 		    sblock.fs_minfree);
221*69181Smckusick 		fprintf(stdout, "\toptimization preference: %s\n",
222*69181Smckusick 		    chg[sblock.fs_optim]);
223*69181Smckusick 		fprintf(stdout, "\ttrack skew %d sectors\n",
224*69181Smckusick 			sblock.fs_trackskew);
225*69181Smckusick 		fprintf(stdout, "tunefs: no changes made\n");
226*69181Smckusick 		exit(0);
227*69181Smckusick 	}
228*69181Smckusick 	fi = open(special, 1);
229*69181Smckusick 	if (fi < 0)
230*69181Smckusick 		err(3, "cannot open %s for writing", special);
23156210Shibler 	bwrite((daddr_t)SBOFF / dev_bsize, (char *)&sblock, SBSIZE);
23211288Smckusick 	if (Aflag)
23311288Smckusick 		for (i = 0; i < sblock.fs_ncg; i++)
23411288Smckusick 			bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)),
23511288Smckusick 			    (char *)&sblock, SBSIZE);
23611288Smckusick 	close(fi);
23711288Smckusick 	exit(0);
23866924Smckusick }
23966924Smckusick 
24066924Smckusick void
usage()24166924Smckusick usage()
24266924Smckusick {
24366924Smckusick 
244*69181Smckusick 	fprintf(stderr, "Usage: tunefs [-AN] tuneup-options special-device\n");
24511288Smckusick 	fprintf(stderr, "where tuneup-options are:\n");
246*69181Smckusick 	fprintf(stderr, "\t-d rotational delay between contiguous blocks\n");
24713555Ssam 	fprintf(stderr, "\t-a maximum contiguous blocks\n");
24811288Smckusick 	fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
24911288Smckusick 	fprintf(stderr, "\t-m minimum percentage of free space\n");
25024700Smckusick 	fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
251*69181Smckusick 	fprintf(stderr, "\t-t track skew in sectors\n");
25211288Smckusick 	exit(2);
25311288Smckusick }
25411288Smckusick 
25566924Smckusick void
getsb(fs,file)25611288Smckusick getsb(fs, file)
25711288Smckusick 	register struct fs *fs;
25811288Smckusick 	char *file;
25911288Smckusick {
26011288Smckusick 
261*69181Smckusick 	fi = open(file, 0);
26266924Smckusick 	if (fi < 0)
263*69181Smckusick 		err(3, "cannot open %s for reading", file);
26466924Smckusick 	if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE))
26566924Smckusick 		err(4, "%s: bad super block", file);
26666924Smckusick 	if (fs->fs_magic != FS_MAGIC)
26766924Smckusick 		err(5, "%s: bad magic number", file);
26830558Smckusick 	dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
269*69181Smckusick 	close(fi);
27011288Smckusick }
27111288Smckusick 
27266924Smckusick void
bwrite(blk,buf,size)27311288Smckusick bwrite(blk, buf, size)
27466924Smckusick 	daddr_t blk;
27511288Smckusick 	char *buf;
27666924Smckusick 	int size;
27711288Smckusick {
27866924Smckusick 
27966924Smckusick 	if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0)
28066924Smckusick 		err(6, "FS SEEK");
28166924Smckusick 	if (write(fi, buf, size) != size)
28266924Smckusick 		err(7, "FS WRITE");
28311288Smckusick }
28411288Smckusick 
28566924Smckusick int
bread(bno,buf,cnt)28611288Smckusick bread(bno, buf, cnt)
28711288Smckusick 	daddr_t bno;
28811288Smckusick 	char *buf;
28966924Smckusick 	int cnt;
29011288Smckusick {
29166924Smckusick 	int i;
29211288Smckusick 
29358003Sralph 	if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0)
29411288Smckusick 		return(1);
29511288Smckusick 	if ((i = read(fi, buf, cnt)) != cnt) {
29611288Smckusick 		for(i=0; i<sblock.fs_bsize; i++)
29711288Smckusick 			buf[i] = 0;
29811288Smckusick 		return (1);
29911288Smckusick 	}
30011288Smckusick 	return (0);
30111288Smckusick }
302