2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
35 static const char copyright[] =
36 "@(#) Copyright (c) 1983, 1993\n\
37 The Regents of the University of California. All rights reserved.\n";
42 static char sccsid[] = "@(#)tunefs.c 8.2 (Berkeley) 4/19/94";
44 static const char rcsid[] =
49 * tunefs: change layout parameters to an existing file system.
51 #include <sys/param.h>
52 #include <sys/mount.h>
53 #include <sys/disklabel.h>
56 #include <ufs/ufs/ufsmount.h>
57 #include <ufs/ufs/dinode.h>
58 #include <ufs/ffs/fs.h>
69 /* the optimization warning string template */
70 #define OPTWARN "should optimize for %s with minfree %s %d%%"
76 #define sblock sbun.sb
81 void bwrite(ufs2_daddr_t, const char *, int);
82 int bread(ufs2_daddr_t, char *, int);
83 void getsb(struct fs *, const char *);
84 void putsb(struct fs *, const char *, int);
96 int Aflag = 0, active = 0, aflag = 0;
97 int eflag = 0, fflag = 0, lflag = 0, mflag = 0;
98 int nflag = 0, oflag = 0, pflag = 0, sflag = 0;
99 int evalue = 0, fvalue = 0;
100 int mvalue = 0, ovalue = 0, svalue = 0;
101 char *avalue = NULL, *lvalue = NULL, *nvalue = NULL;
104 char device[MAXPATHLEN];
105 struct ufs_args args;
111 found_arg = 0; /* at least one arg is required */
112 while ((ch = getopt(argc, argv, "Aa:e:f:l:m:n:o:ps:")) != -1)
122 if (strcmp(avalue, "enable") && strcmp(avalue, "disable")) {
123 errx(10, "bad %s (options are %s)", name,
124 "`enable' or `disable'");
130 name = "maximum blocks per file in a cylinder group";
131 evalue = atoi(optarg);
133 errx(10, "%s must be >= 1 (was %s)", name, optarg);
138 name = "average file size";
139 fvalue = atoi(optarg);
141 errx(10, "%s must be >= 1 (was %s)", name, optarg);
146 name = "multilabel MAC file system";
148 if (strcmp(lvalue, "enable") && strcmp(lvalue, "disable")) {
149 errx(10, "bad %s (options are %s)", name,
150 "`enable' or `disable'");
156 name = "minimum percentage of free space";
157 mvalue = atoi(optarg);
158 if (mvalue < 0 || mvalue > 99)
159 errx(10, "bad %s (%s)", name, optarg);
164 name = "soft updates";
166 if (strcmp(nvalue, "enable") && strcmp(nvalue, "disable")) {
167 errx(10, "bad %s (options are %s)",
168 name, "`enable' or `disable'");
174 name = "optimization preference";
175 chg[FS_OPTSPACE] = "space";
176 chg[FS_OPTTIME] = "time";
177 if (strcmp(optarg, chg[FS_OPTSPACE]) == 0)
178 ovalue = FS_OPTSPACE;
179 else if (strcmp(optarg, chg[FS_OPTTIME]) == 0)
182 errx(10, "bad %s (options are `space' or `time')",
192 name = "expected number of files per directory";
193 svalue = atoi(optarg);
195 errx(10, "%s must be >= 1 (was %s)", name, optarg);
204 if (found_arg == 0 || argc != 1)
208 fs = getfsfile(special);
210 if (statfs(special, &stfs) == 0 &&
211 strcmp(special, stfs.f_mntonname) == 0) {
214 special = fs->fs_spec;
217 if (stat(special, &st) < 0) {
218 if (*special != '/') {
221 (void)snprintf(device, sizeof(device), "%s%s",
226 err(1, "%s", special);
228 if (fs == NULL && (st.st_mode & S_IFMT) == S_IFDIR)
229 errx(10, "%s: unknown file system", special);
230 getsb(&sblock, special);
238 if (strcmp(avalue, "enable") == 0) {
239 if (sblock.fs_flags & FS_ACLS) {
240 warnx("%s remains unchanged as enabled", name);
242 sblock.fs_flags |= FS_ACLS;
243 warnx("%s set", name);
245 } else if (strcmp(avalue, "disable") == 0) {
246 if ((~sblock.fs_flags & FS_ACLS) ==
248 warnx("%s remains unchanged as disabled",
251 sblock.fs_flags &= ~FS_ACLS;
252 warnx("%s cleared", name);
257 name = "maximum blocks per file in a cylinder group";
258 if (sblock.fs_maxbpg == evalue) {
259 warnx("%s remains unchanged as %d", name, evalue);
262 warnx("%s changes from %d to %d",
263 name, sblock.fs_maxbpg, evalue);
264 sblock.fs_maxbpg = evalue;
268 name = "average file size";
269 if (sblock.fs_avgfilesize == fvalue) {
270 warnx("%s remains unchanged as %d", name, fvalue);
273 warnx("%s changes from %d to %d",
274 name, sblock.fs_avgfilesize, fvalue);
275 sblock.fs_avgfilesize = fvalue;
280 if (strcmp(lvalue, "enable") == 0) {
281 if (sblock.fs_flags & FS_MULTILABEL) {
282 warnx("%s remains unchanged as enabled", name);
284 sblock.fs_flags |= FS_MULTILABEL;
285 warnx("%s set", name);
287 } else if (strcmp(lvalue, "disable") == 0) {
288 if ((~sblock.fs_flags & FS_MULTILABEL) ==
290 warnx("%s remains unchanged as disabled",
293 sblock.fs_flags &= ~FS_MULTILABEL;
294 warnx("%s cleared", name);
299 name = "minimum percentage of free space";
300 if (sblock.fs_minfree == mvalue) {
301 warnx("%s remains unchanged as %d%%", name, mvalue);
304 warnx("%s changes from %d%% to %d%%",
305 name, sblock.fs_minfree, mvalue);
306 sblock.fs_minfree = mvalue;
307 if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE)
308 warnx(OPTWARN, "time", ">=", MINFREE);
309 if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME)
310 warnx(OPTWARN, "space", "<", MINFREE);
314 name = "soft updates";
315 if (strcmp(nvalue, "enable") == 0) {
316 if (sblock.fs_flags & FS_DOSOFTDEP) {
317 warnx("%s remains unchanged as enabled", name);
318 } else if (sblock.fs_clean == 0) {
319 warnx("%s cannot be enabled until fsck is run",
322 sblock.fs_flags |= FS_DOSOFTDEP;
323 warnx("%s set", name);
325 } else if (strcmp(nvalue, "disable") == 0) {
326 if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP) {
327 warnx("%s remains unchanged as disabled", name);
329 sblock.fs_flags &= ~FS_DOSOFTDEP;
330 warnx("%s cleared", name);
335 name = "optimization preference";
336 chg[FS_OPTSPACE] = "space";
337 chg[FS_OPTTIME] = "time";
338 if (sblock.fs_optim == ovalue) {
339 warnx("%s remains unchanged as %s", name, chg[ovalue]);
342 warnx("%s changes from %s to %s",
343 name, chg[sblock.fs_optim], chg[ovalue]);
344 sblock.fs_optim = ovalue;
345 if (sblock.fs_minfree >= MINFREE &&
346 ovalue == FS_OPTSPACE)
347 warnx(OPTWARN, "time", ">=", MINFREE);
348 if (sblock.fs_minfree < MINFREE &&
349 ovalue == FS_OPTTIME)
350 warnx(OPTWARN, "space", "<", MINFREE);
354 name = "expected number of files per directory";
355 if (sblock.fs_avgfpdir == svalue) {
356 warnx("%s remains unchanged as %d", name, svalue);
359 warnx("%s changes from %d to %d",
360 name, sblock.fs_avgfpdir, svalue);
361 sblock.fs_avgfpdir = svalue;
365 putsb(&sblock, special, Aflag);
367 bzero(&args, sizeof(args));
368 if (mount("ufs", fs->fs_file,
369 stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0)
370 err(9, "%s: reload", special);
371 warnx("file system reloaded");
379 fprintf(stderr, "%s\n%s\n%s\n",
380 "usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]",
381 " [-l enable | disable] [-m minfree] [-n enable | disable]",
382 " [-o space | time] [-p] [-s avgfpdir] special | filesystem");
387 * Possible superblock locations ordered from most to least likely.
389 static int sblock_try[] = SBLOCKSEARCH;
390 static ufs2_daddr_t sblockloc;
399 fi = open(file, O_RDONLY);
401 err(3, "cannot open %s", file);
402 for (i = 0; sblock_try[i] != -1; i++) {
403 if (bread(sblock_try[i], (char *)fs, SBLOCKSIZE))
404 err(4, "%s: bad super block", file);
405 if ((fs->fs_magic == FS_UFS1_MAGIC ||
406 (fs->fs_magic == FS_UFS2_MAGIC &&
407 fs->fs_sblockloc == sblock_try[i])) &&
408 fs->fs_bsize <= MAXBSIZE &&
409 fs->fs_bsize >= sizeof(struct fs))
412 if (sblock_try[i] == -1)
413 err(5, "Cannot find file system superblock");
414 dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
415 sblockloc = sblock_try[i] / dev_bsize;
427 * Re-open the device read-write. Use the read-only file
428 * descriptor as an interlock to prevent the device from
429 * being mounted while we are switching mode.
432 fi = open(file, O_RDWR);
435 err(3, "cannot open %s", file);
436 bwrite(sblockloc, (const char *)fs, SBLOCKSIZE);
438 for (i = 0; i < fs->fs_ncg; i++)
439 bwrite(fsbtodb(fs, cgsblock(fs, i)),
440 (const char *)fs, SBLOCKSIZE);
447 warnx("ACLs: (-a) %s",
448 (sblock.fs_flags & FS_ACLS)? "enabled" : "disabled");
449 warnx("MAC multilabel: (-l) %s",
450 (sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled");
451 warnx("soft updates: (-n) %s",
452 (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled");
453 warnx("maximum blocks per file in a cylinder group: (-e) %d",
455 warnx("average file size: (-f) %d",
456 sblock.fs_avgfilesize);
457 warnx("average number of files in a directory: (-s) %d",
459 warnx("minimum percentage of free space: (-m) %d%%",
461 warnx("optimization preference: (-o) %s",
462 sblock.fs_optim == FS_OPTSPACE ? "space" : "time");
463 if (sblock.fs_minfree >= MINFREE &&
464 sblock.fs_optim == FS_OPTSPACE)
465 warnx(OPTWARN, "time", ">=", MINFREE);
466 if (sblock.fs_minfree < MINFREE &&
467 sblock.fs_optim == FS_OPTTIME)
468 warnx(OPTWARN, "space", "<", MINFREE);
472 bwrite(blk, buf, size)
478 if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0)
480 if (write(fi, buf, size) != size)
492 if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0)
494 if ((i = read(fi, buf, cnt)) != cnt) {
495 for(i=0; i<sblock.fs_bsize; i++)