xref: /original-bsd/sbin/tunefs/tunefs.c (revision e58c8952)
1 /*
2  * Copyright (c) 1983, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1983, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)tunefs.c	8.2 (Berkeley) 04/19/94";
16 #endif /* not lint */
17 
18 /*
19  * tunefs: change layout parameters to an existing file system.
20  */
21 #include <sys/param.h>
22 #include <sys/stat.h>
23 
24 #include <ufs/ffs/fs.h>
25 
26 #include <errno.h>
27 #include <err.h>
28 #include <fcntl.h>
29 #include <fstab.h>
30 #include <stdio.h>
31 #include <paths.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 
35 /* the optimization warning string template */
36 #define	OPTWARN	"should optimize for %s with minfree %s %d%%"
37 
38 union {
39 	struct	fs sb;
40 	char pad[MAXBSIZE];
41 } sbun;
42 #define	sblock sbun.sb
43 
44 int fi;
45 long dev_bsize = 1;
46 
47 void bwrite(daddr_t, char *, int);
48 int bread(daddr_t, char *, int);
49 void getsb(struct fs *, char *);
50 void usage __P((void));
51 
52 int
53 main(argc, argv)
54 	int argc;
55 	char *argv[];
56 {
57 	char *cp, *special, *name;
58 	struct stat st;
59 	int i;
60 	int Aflag = 0;
61 	struct fstab *fs;
62 	char *chg[2], device[MAXPATHLEN];
63 
64 	argc--, argv++;
65 	if (argc < 2)
66 		usage();
67 	special = argv[argc - 1];
68 	fs = getfsfile(special);
69 	if (fs)
70 		special = fs->fs_spec;
71 again:
72 	if (stat(special, &st) < 0) {
73 		if (*special != '/') {
74 			if (*special == 'r')
75 				special++;
76 			(void)sprintf(device, "%s/%s", _PATH_DEV, special);
77 			special = device;
78 			goto again;
79 		}
80 		err(1, "%s", special);
81 	}
82 	if ((st.st_mode & S_IFMT) != S_IFBLK &&
83 	    (st.st_mode & S_IFMT) != S_IFCHR)
84 		errx(10, "%s: not a block or character device", special);
85 	getsb(&sblock, special);
86 	for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
87 		for (cp = &argv[0][1]; *cp; cp++)
88 			switch (*cp) {
89 
90 			case 'A':
91 				Aflag++;
92 				continue;
93 
94 			case 'a':
95 				name = "maximum contiguous block count";
96 				if (argc < 1)
97 					errx(10, "-a: missing %s", name);
98 				argc--, argv++;
99 				i = atoi(*argv);
100 				if (i < 1)
101 					errx(10, "%s must be >= 1 (was %s)",
102 					    name, *argv);
103 				warnx("%s changes from %d to %d",
104 				    name, sblock.fs_maxcontig, i);
105 				sblock.fs_maxcontig = i;
106 				continue;
107 
108 			case 'd':
109 				name =
110 				   "rotational delay between contiguous blocks";
111 				if (argc < 1)
112 					errx(10, "-d: missing %s", name);
113 				argc--, argv++;
114 				i = atoi(*argv);
115 				warnx("%s changes from %dms to %dms",
116 				    name, sblock.fs_rotdelay, i);
117 				sblock.fs_rotdelay = i;
118 				continue;
119 
120 			case 'e':
121 				name =
122 				  "maximum blocks per file in a cylinder group";
123 				if (argc < 1)
124 					errx(10, "-e: missing %s", name);
125 				argc--, argv++;
126 				i = atoi(*argv);
127 				if (i < 1)
128 					errx(10, "%s must be >= 1 (was %s)",
129 					    name, *argv);
130 				warnx("%s changes from %d to %d",
131 				    name, sblock.fs_maxbpg, i);
132 				sblock.fs_maxbpg = i;
133 				continue;
134 
135 			case 'm':
136 				name = "minimum percentage of free space";
137 				if (argc < 1)
138 					errx(10, "-m: missing %s", name);
139 				argc--, argv++;
140 				i = atoi(*argv);
141 				if (i < 0 || i > 99)
142 					errx(10, "bad %s (%s)", name, *argv);
143 				warnx("%s changes from %d%% to %d%%",
144 				    name, sblock.fs_minfree, i);
145 				sblock.fs_minfree = i;
146 				if (i >= MINFREE &&
147 				    sblock.fs_optim == FS_OPTSPACE)
148 					warnx(OPTWARN, "time", ">=", MINFREE);
149 				if (i < MINFREE &&
150 				    sblock.fs_optim == FS_OPTTIME)
151 					warnx(OPTWARN, "space", "<", MINFREE);
152 				continue;
153 
154 			case 'o':
155 				name = "optimization preference";
156 				if (argc < 1)
157 					errx(10, "-o: missing %s", name);
158 				argc--, argv++;
159 				chg[FS_OPTSPACE] = "space";
160 				chg[FS_OPTTIME] = "time";
161 				if (strcmp(*argv, chg[FS_OPTSPACE]) == 0)
162 					i = FS_OPTSPACE;
163 				else if (strcmp(*argv, chg[FS_OPTTIME]) == 0)
164 					i = FS_OPTTIME;
165 				else
166 					errx(10, "bad %s (options are `space' or `time')",
167 					    name);
168 				if (sblock.fs_optim == i) {
169 					warnx("%s remains unchanged as %s",
170 					    name, chg[i]);
171 					continue;
172 				}
173 				warnx("%s changes from %s to %s",
174 				    name, chg[sblock.fs_optim], chg[i]);
175 				sblock.fs_optim = i;
176 				if (sblock.fs_minfree >= MINFREE &&
177 				    i == FS_OPTSPACE)
178 					warnx(OPTWARN, "time", ">=", MINFREE);
179 				if (sblock.fs_minfree < MINFREE &&
180 				    i == FS_OPTTIME)
181 					warnx(OPTWARN, "space", "<", MINFREE);
182 				continue;
183 
184 			default:
185 				usage();
186 			}
187 	}
188 	if (argc != 1)
189 		usage();
190 	bwrite((daddr_t)SBOFF / dev_bsize, (char *)&sblock, SBSIZE);
191 	if (Aflag)
192 		for (i = 0; i < sblock.fs_ncg; i++)
193 			bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)),
194 			    (char *)&sblock, SBSIZE);
195 	close(fi);
196 	exit(0);
197 }
198 
199 void
200 usage()
201 {
202 
203 	fprintf(stderr, "Usage: tunefs tuneup-options special-device\n");
204 	fprintf(stderr, "where tuneup-options are:\n");
205 	fprintf(stderr, "\t-a maximum contiguous blocks\n");
206 	fprintf(stderr, "\t-d rotational delay between contiguous blocks\n");
207 	fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
208 	fprintf(stderr, "\t-m minimum percentage of free space\n");
209 	fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
210 	exit(2);
211 }
212 
213 void
214 getsb(fs, file)
215 	register struct fs *fs;
216 	char *file;
217 {
218 
219 	fi = open(file, 2);
220 	if (fi < 0)
221 		err(3, "cannot open %s", file);
222 	if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE))
223 		err(4, "%s: bad super block", file);
224 	if (fs->fs_magic != FS_MAGIC)
225 		err(5, "%s: bad magic number", file);
226 	dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
227 }
228 
229 void
230 bwrite(blk, buf, size)
231 	daddr_t blk;
232 	char *buf;
233 	int size;
234 {
235 
236 	if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0)
237 		err(6, "FS SEEK");
238 	if (write(fi, buf, size) != size)
239 		err(7, "FS WRITE");
240 }
241 
242 int
243 bread(bno, buf, cnt)
244 	daddr_t bno;
245 	char *buf;
246 	int cnt;
247 {
248 	int i;
249 
250 	if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0)
251 		return(1);
252 	if ((i = read(fi, buf, cnt)) != cnt) {
253 		for(i=0; i<sblock.fs_bsize; i++)
254 			buf[i] = 0;
255 		return (1);
256 	}
257 	return (0);
258 }
259