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