tunefs.c revision 38040
1/*
2 * Copyright (c) 1983, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static const char copyright[] =
36"@(#) Copyright (c) 1983, 1993\n\
37	The Regents of the University of California.  All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41#if 0
42static char sccsid[] = "@(#)tunefs.c	8.2 (Berkeley) 4/19/94";
43#endif
44static const char rcsid[] =
45	"$Id$";
46#endif /* not lint */
47
48/*
49 * tunefs: change layout parameters to an existing file system.
50 */
51#include <sys/param.h>
52#include <sys/stat.h>
53
54#include <ufs/ffs/fs.h>
55
56#include <err.h>
57#include <fcntl.h>
58#include <fstab.h>
59#include <paths.h>
60#include <stdio.h>
61#include <stdlib.h>
62#include <unistd.h>
63
64/* the optimization warning string template */
65#define	OPTWARN	"should optimize for %s with minfree %s %d%%"
66
67union {
68	struct	fs sb;
69	char pad[MAXBSIZE];
70} sbun;
71#define	sblock sbun.sb
72
73int fi;
74long dev_bsize = 1;
75
76void bwrite(daddr_t, char *, int);
77int bread(daddr_t, char *, int);
78void getsb(struct fs *, char *);
79void usage __P((void));
80void printfs __P((void));
81
82int
83main(argc, argv)
84	int argc;
85	char *argv[];
86{
87	char *cp, *special, *name, *action;
88	struct stat st;
89	int i;
90	int Aflag = 0;
91	struct fstab *fs;
92	char *chg[2], device[MAXPATHLEN];
93
94	argc--, argv++;
95	if (argc < 2)
96		usage();
97	special = argv[argc - 1];
98	fs = getfsfile(special);
99	if (fs)
100		special = fs->fs_spec;
101again:
102	if (stat(special, &st) < 0) {
103		if (*special != '/') {
104			if (*special == 'r')
105				special++;
106			(void)sprintf(device, "%s/%s", _PATH_DEV, special);
107			special = device;
108			goto again;
109		}
110		err(1, "%s", special);
111	}
112	if ((st.st_mode & S_IFMT) != S_IFBLK &&
113	    (st.st_mode & S_IFMT) != S_IFCHR)
114		errx(10, "%s: not a block or character device", special);
115	getsb(&sblock, special);
116	for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
117		for (cp = &argv[0][1]; *cp; cp++)
118			switch (*cp) {
119
120			case 'A':
121				Aflag++;
122				continue;
123
124			case 'p':
125				printfs();
126				exit(0);
127
128			case 'a':
129				name = "maximum contiguous block count";
130				if (argc < 1)
131					errx(10, "-a: missing %s", name);
132				argc--, argv++;
133				i = atoi(*argv);
134				if (i < 1)
135					errx(10, "%s must be >= 1 (was %s)",
136					    name, *argv);
137				warnx("%s changes from %d to %d",
138				    name, sblock.fs_maxcontig, i);
139				sblock.fs_maxcontig = i;
140				continue;
141
142			case 'd':
143				name =
144				   "rotational delay between contiguous blocks";
145				if (argc < 1)
146					errx(10, "-d: missing %s", name);
147				argc--, argv++;
148				i = atoi(*argv);
149				warnx("%s changes from %dms to %dms",
150				    name, sblock.fs_rotdelay, i);
151				sblock.fs_rotdelay = i;
152				continue;
153
154			case 'e':
155				name =
156				  "maximum blocks per file in a cylinder group";
157				if (argc < 1)
158					errx(10, "-e: missing %s", name);
159				argc--, argv++;
160				i = atoi(*argv);
161				if (i < 1)
162					errx(10, "%s must be >= 1 (was %s)",
163					    name, *argv);
164				warnx("%s changes from %d to %d",
165				    name, sblock.fs_maxbpg, i);
166				sblock.fs_maxbpg = i;
167				continue;
168
169			case 'm':
170				name = "minimum percentage of free space";
171				if (argc < 1)
172					errx(10, "-m: missing %s", name);
173				argc--, argv++;
174				i = atoi(*argv);
175				if (i < 0 || i > 99)
176					errx(10, "bad %s (%s)", name, *argv);
177				warnx("%s changes from %d%% to %d%%",
178				    name, sblock.fs_minfree, i);
179				sblock.fs_minfree = i;
180				if (i >= MINFREE &&
181				    sblock.fs_optim == FS_OPTSPACE)
182					warnx(OPTWARN, "time", ">=", MINFREE);
183				if (i < MINFREE &&
184				    sblock.fs_optim == FS_OPTTIME)
185					warnx(OPTWARN, "space", "<", MINFREE);
186				continue;
187
188			case 'n':
189 				name = "soft updates";
190 				if (argc < 1)
191 					errx(10, "-s: missing %s", name);
192 				argc--, argv++;
193 				if (strcmp(*argv, "enable") == 0) {
194 					sblock.fs_flags |= FS_DOSOFTDEP;
195 					action = "set";
196 				} else if (strcmp(*argv, "disable") == 0) {
197 					sblock.fs_flags &= ~FS_DOSOFTDEP;
198 					action = "cleared";
199 				} else {
200 					errx(10, "bad %s (options are %s)",
201 					    name, "`enable' or `disable'");
202 				}
203 				warnx("%s %s", name, action);
204 				continue;
205
206			case 'o':
207				name = "optimization preference";
208				if (argc < 1)
209					errx(10, "-o: missing %s", name);
210				argc--, argv++;
211				chg[FS_OPTSPACE] = "space";
212				chg[FS_OPTTIME] = "time";
213				if (strcmp(*argv, chg[FS_OPTSPACE]) == 0)
214					i = FS_OPTSPACE;
215				else if (strcmp(*argv, chg[FS_OPTTIME]) == 0)
216					i = FS_OPTTIME;
217				else
218					errx(10, "bad %s (options are `space' or `time')",
219					    name);
220				if (sblock.fs_optim == i) {
221					warnx("%s remains unchanged as %s",
222					    name, chg[i]);
223					continue;
224				}
225				warnx("%s changes from %s to %s",
226				    name, chg[sblock.fs_optim], chg[i]);
227				sblock.fs_optim = i;
228				if (sblock.fs_minfree >= MINFREE &&
229				    i == FS_OPTSPACE)
230					warnx(OPTWARN, "time", ">=", MINFREE);
231				if (sblock.fs_minfree < MINFREE &&
232				    i == FS_OPTTIME)
233					warnx(OPTWARN, "space", "<", MINFREE);
234				continue;
235
236			default:
237				usage();
238			}
239	}
240	if (argc != 1)
241		usage();
242	bwrite((daddr_t)SBOFF / dev_bsize, (char *)&sblock, SBSIZE);
243	if (Aflag)
244		for (i = 0; i < sblock.fs_ncg; i++)
245			bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)),
246			    (char *)&sblock, SBSIZE);
247	close(fi);
248	exit(0);
249}
250
251void
252usage()
253{
254	fprintf(stderr, "%s\n%s\n%s\n",
255"usage: tunefs [-A] [-a maxcontig] [-d rotdelay] [-e maxbpg] [-m minfree]",
256"              [-p] [-n enable | disable] [-o optimize_preference]",
257"              [special | filesystem]");
258	exit(2);
259}
260
261void
262getsb(fs, file)
263	register struct fs *fs;
264	char *file;
265{
266
267	fi = open(file, 2);
268	if (fi < 0)
269		err(3, "cannot open %s", file);
270	if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE))
271		err(4, "%s: bad super block", file);
272	if (fs->fs_magic != FS_MAGIC)
273		err(5, "%s: bad magic number", file);
274	dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
275}
276
277void
278printfs()
279{
280	warnx("soft updates:  (-n)                                %s",
281		(sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled");
282	warnx("maximum contiguous block count: (-a)               %d",
283	      sblock.fs_maxcontig);
284	warnx("rotational delay between contiguous blocks: (-d)   %d ms",
285	      sblock.fs_rotdelay);
286	warnx("maximum blocks per file in a cylinder group: (-e)  %d",
287	      sblock.fs_maxbpg);
288	warnx("minimum percentage of free space: (-m)             %d%%",
289	      sblock.fs_minfree);
290	warnx("optimization preference: (-o)                      %s",
291	      sblock.fs_optim == FS_OPTSPACE ? "space" : "time");
292	if (sblock.fs_minfree >= MINFREE &&
293	    sblock.fs_optim == FS_OPTSPACE)
294		warnx(OPTWARN, "time", ">=", MINFREE);
295	if (sblock.fs_minfree < MINFREE &&
296	    sblock.fs_optim == FS_OPTTIME)
297		warnx(OPTWARN, "space", "<", MINFREE);
298}
299
300void
301bwrite(blk, buf, size)
302	daddr_t blk;
303	char *buf;
304	int size;
305{
306
307	if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0)
308		err(6, "FS SEEK");
309	if (write(fi, buf, size) != size)
310		err(7, "FS WRITE");
311}
312
313int
314bread(bno, buf, cnt)
315	daddr_t bno;
316	char *buf;
317	int cnt;
318{
319	int i;
320
321	if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0)
322		return(1);
323	if ((i = read(fi, buf, cnt)) != cnt) {
324		for(i=0; i<sblock.fs_bsize; i++)
325			buf[i] = 0;
326		return (1);
327	}
328	return (0);
329}
330