xref: /original-bsd/sbin/tunefs/tunefs.c (revision 6d5a9f9c)
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.3 (Berkeley) 05/03/95";
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/ufs/dinode.h>
25 #include <ufs/ffs/fs.h>
26 
27 #include <errno.h>
28 #include <err.h>
29 #include <fcntl.h>
30 #include <fstab.h>
31 #include <stdio.h>
32 #include <paths.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 
36 /* the optimization warning string template */
37 #define	OPTWARN	"should optimize for %s with minfree %s %d%%"
38 
39 union {
40 	struct	fs sb;
41 	char pad[MAXBSIZE];
42 } sbun;
43 #define	sblock sbun.sb
44 
45 int fi;
46 long dev_bsize = 1;
47 
48 void bwrite(daddr_t, char *, int);
49 int bread(daddr_t, char *, int);
50 void getsb(struct fs *, char *);
51 void usage __P((void));
52 
53 int
54 main(argc, argv)
55 	int argc;
56 	char *argv[];
57 {
58 	char *cp, *special, *name;
59 	struct stat st;
60 	int i;
61 	int Aflag = 0, Nflag = 0;
62 	struct fstab *fs;
63 	char *chg[2], device[MAXPATHLEN];
64 
65 	argc--, argv++;
66 	if (argc < 2)
67 		usage();
68 	special = argv[argc - 1];
69 	fs = getfsfile(special);
70 	if (fs)
71 		special = fs->fs_spec;
72 again:
73 	if (stat(special, &st) < 0) {
74 		if (*special != '/') {
75 			if (*special == 'r')
76 				special++;
77 			(void)sprintf(device, "%s/%s", _PATH_DEV, special);
78 			special = device;
79 			goto again;
80 		}
81 		err(1, "%s", special);
82 	}
83 	if ((st.st_mode & S_IFMT) != S_IFBLK &&
84 	    (st.st_mode & S_IFMT) != S_IFCHR)
85 		errx(10, "%s: not a block or character device", special);
86 	getsb(&sblock, special);
87 	chg[FS_OPTSPACE] = "space";
88 	chg[FS_OPTTIME] = "time";
89 	for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
90 		for (cp = &argv[0][1]; *cp; cp++)
91 			switch (*cp) {
92 
93 			case 'A':
94 				Aflag++;
95 				continue;
96 
97 			case 'N':
98 				Nflag++;
99 				continue;
100 
101 			case 'a':
102 				name = "maximum contiguous block count";
103 				if (argc < 1)
104 					errx(10, "-a: missing %s", name);
105 				argc--, argv++;
106 				i = atoi(*argv);
107 				if (i < 1)
108 					errx(10, "%s must be >= 1 (was %s)",
109 					    name, *argv);
110 				warnx("%s changes from %d to %d",
111 				    name, sblock.fs_maxcontig, i);
112 				sblock.fs_maxcontig = i;
113 				continue;
114 
115 			case 'd':
116 				name =
117 				   "rotational delay between contiguous blocks";
118 				if (argc < 1)
119 					errx(10, "-d: missing %s", name);
120 				argc--, argv++;
121 				i = atoi(*argv);
122 				warnx("%s changes from %dms to %dms",
123 				    name, sblock.fs_rotdelay, i);
124 				sblock.fs_rotdelay = i;
125 				continue;
126 
127 			case 'e':
128 				name =
129 				  "maximum blocks per file in a cylinder group";
130 				if (argc < 1)
131 					errx(10, "-e: 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_maxbpg, i);
139 				sblock.fs_maxbpg = i;
140 				continue;
141 
142 			case 'm':
143 				name = "minimum percentage of free space";
144 				if (argc < 1)
145 					errx(10, "-m: missing %s", name);
146 				argc--, argv++;
147 				i = atoi(*argv);
148 				if (i < 0 || i > 99)
149 					errx(10, "bad %s (%s)", name, *argv);
150 				warnx("%s changes from %d%% to %d%%",
151 				    name, sblock.fs_minfree, i);
152 				sblock.fs_minfree = i;
153 				if (i >= MINFREE &&
154 				    sblock.fs_optim == FS_OPTSPACE)
155 					warnx(OPTWARN, "time", ">=", MINFREE);
156 				if (i < MINFREE &&
157 				    sblock.fs_optim == FS_OPTTIME)
158 					warnx(OPTWARN, "space", "<", MINFREE);
159 				continue;
160 
161 			case 'o':
162 				name = "optimization preference";
163 				if (argc < 1)
164 					errx(10, "-o: missing %s", name);
165 				argc--, argv++;
166 				if (strcmp(*argv, chg[FS_OPTSPACE]) == 0)
167 					i = FS_OPTSPACE;
168 				else if (strcmp(*argv, chg[FS_OPTTIME]) == 0)
169 					i = FS_OPTTIME;
170 				else
171 					errx(10, "bad %s (options are `space' or `time')",
172 					    name);
173 				if (sblock.fs_optim == i) {
174 					warnx("%s remains unchanged as %s",
175 					    name, chg[i]);
176 					continue;
177 				}
178 				warnx("%s changes from %s to %s",
179 				    name, chg[sblock.fs_optim], chg[i]);
180 				sblock.fs_optim = i;
181 				if (sblock.fs_minfree >= MINFREE &&
182 				    i == FS_OPTSPACE)
183 					warnx(OPTWARN, "time", ">=", MINFREE);
184 				if (sblock.fs_minfree < MINFREE &&
185 				    i == FS_OPTTIME)
186 					warnx(OPTWARN, "space", "<", MINFREE);
187 				continue;
188 
189 			case 't':
190 				name = "track skew in sectors";
191 				if (argc < 1)
192 					errx(10, "-t: missing %s", name);
193 				argc--, argv++;
194 				i = atoi(*argv);
195 				if (i < 0)
196 					errx(10, "%s: %s must be >= 0",
197 						*argv, name);
198 				warnx("%s changes from %d to %d",
199 					name, sblock.fs_trackskew, i);
200 				sblock.fs_trackskew = i;
201 				continue;
202 
203 			default:
204 				usage();
205 			}
206 	}
207 	if (argc != 1)
208 		usage();
209 	if (Nflag) {
210 		fprintf(stdout, "tunefs: current settings\n");
211 		fprintf(stdout, "\tmaximum contiguous block count %d\n",
212 		    sblock.fs_maxcontig);
213 		fprintf(stdout,
214 		    "\trotational delay between contiguous blocks %dms\n",
215 		    sblock.fs_rotdelay);
216 		fprintf(stdout,
217 		    "\tmaximum blocks per file in a cylinder group %d\n",
218 		    sblock.fs_maxbpg);
219 		fprintf(stdout, "\tminimum percentage of free space %d%%\n",
220 		    sblock.fs_minfree);
221 		fprintf(stdout, "\toptimization preference: %s\n",
222 		    chg[sblock.fs_optim]);
223 		fprintf(stdout, "\ttrack skew %d sectors\n",
224 			sblock.fs_trackskew);
225 		fprintf(stdout, "tunefs: no changes made\n");
226 		exit(0);
227 	}
228 	fi = open(special, 1);
229 	if (fi < 0)
230 		err(3, "cannot open %s for writing", special);
231 	bwrite((daddr_t)SBOFF / dev_bsize, (char *)&sblock, SBSIZE);
232 	if (Aflag)
233 		for (i = 0; i < sblock.fs_ncg; i++)
234 			bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)),
235 			    (char *)&sblock, SBSIZE);
236 	close(fi);
237 	exit(0);
238 }
239 
240 void
241 usage()
242 {
243 
244 	fprintf(stderr, "Usage: tunefs [-AN] tuneup-options special-device\n");
245 	fprintf(stderr, "where tuneup-options are:\n");
246 	fprintf(stderr, "\t-d rotational delay between contiguous blocks\n");
247 	fprintf(stderr, "\t-a maximum contiguous blocks\n");
248 	fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
249 	fprintf(stderr, "\t-m minimum percentage of free space\n");
250 	fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
251 	fprintf(stderr, "\t-t track skew in sectors\n");
252 	exit(2);
253 }
254 
255 void
256 getsb(fs, file)
257 	register struct fs *fs;
258 	char *file;
259 {
260 
261 	fi = open(file, 0);
262 	if (fi < 0)
263 		err(3, "cannot open %s for reading", file);
264 	if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE))
265 		err(4, "%s: bad super block", file);
266 	if (fs->fs_magic != FS_MAGIC)
267 		err(5, "%s: bad magic number", file);
268 	dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
269 	close(fi);
270 }
271 
272 void
273 bwrite(blk, buf, size)
274 	daddr_t blk;
275 	char *buf;
276 	int size;
277 {
278 
279 	if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0)
280 		err(6, "FS SEEK");
281 	if (write(fi, buf, size) != size)
282 		err(7, "FS WRITE");
283 }
284 
285 int
286 bread(bno, buf, cnt)
287 	daddr_t bno;
288 	char *buf;
289 	int cnt;
290 {
291 	int i;
292 
293 	if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0)
294 		return(1);
295 	if ((i = read(fi, buf, cnt)) != cnt) {
296 		for(i=0; i<sblock.fs_bsize; i++)
297 			buf[i] = 0;
298 		return (1);
299 	}
300 	return (0);
301 }
302