tunefs.c revision 42873
125184Sjkh/* 225184Sjkh * Copyright (c) 1983, 1993 350472Speter * The Regents of the University of California. All rights reserved. 425184Sjkh * 525184Sjkh * Redistribution and use in source and binary forms, with or without 651231Ssheldonh * modification, are permitted provided that the following conditions 751231Ssheldonh * are met: 825184Sjkh * 1. Redistributions of source code must retain the above copyright 925184Sjkh * notice, this list of conditions and the following disclaimer. 1025184Sjkh * 2. Redistributions in binary form must reproduce the above copyright 1125184Sjkh * notice, this list of conditions and the following disclaimer in the 1251231Ssheldonh * documentation and/or other materials provided with the distribution. 1325184Sjkh * 3. All advertising materials mentioning features or use of this software 1451231Ssheldonh * must display the following acknowledgement: 1525184Sjkh * This product includes software developed by the University of 1651231Ssheldonh * California, Berkeley and its contributors. 1751231Ssheldonh * 4. Neither the name of the University nor the names of its contributors 1851231Ssheldonh * may be used to endorse or promote products derived from this software 1951231Ssheldonh * without specific prior written permission. 2051231Ssheldonh * 2151231Ssheldonh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2225184Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2351231Ssheldonh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2451231Ssheldonh * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2551231Ssheldonh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2651231Ssheldonh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2751231Ssheldonh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2851231Ssheldonh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2951231Ssheldonh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3051231Ssheldonh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3151231Ssheldonh * SUCH DAMAGE. 3251231Ssheldonh */ 3340006Sphk 3451231Ssheldonh#ifndef lint 3542621Shmstatic const char copyright[] = 3651231Ssheldonh"@(#) Copyright (c) 1983, 1993\n\ 3751231Ssheldonh The Regents of the University of California. All rights reserved.\n"; 3851231Ssheldonh#endif /* not lint */ 3951231Ssheldonh 4051231Ssheldonh#ifndef lint 4151231Ssheldonh#if 0 4251231Ssheldonhstatic char sccsid[] = "@(#)tunefs.c 8.2 (Berkeley) 4/19/94"; 4351231Ssheldonh#endif 4451231Ssheldonhstatic const char rcsid[] = 4551231Ssheldonh "$Id: tunefs.c,v 1.6 1998/08/03 06:41:20 charnier Exp $"; 4642627Sjoerg#endif /* not lint */ 4751231Ssheldonh 4851231Ssheldonh/* 4951231Ssheldonh * tunefs: change layout parameters to an existing file system. 5051231Ssheldonh */ 5151231Ssheldonh#include <sys/param.h> 5251231Ssheldonh#include <sys/mount.h> 5351231Ssheldonh#include <sys/stat.h> 5451231Ssheldonh 5551231Ssheldonh#include <ufs/ffs/fs.h> 5651231Ssheldonh#include <ufs/ufs/ufsmount.h> 5751231Ssheldonh 5851231Ssheldonh#include <err.h> 5951231Ssheldonh#include <fcntl.h> 6051231Ssheldonh#include <fstab.h> 6149122Sbrian#include <paths.h> 6251231Ssheldonh#include <stdio.h> 6351231Ssheldonh#include <stdlib.h> 6451231Ssheldonh#include <string.h> 6551231Ssheldonh#include <unistd.h> 6651231Ssheldonh 6751231Ssheldonh/* the optimization warning string template */ 6851231Ssheldonh#define OPTWARN "should optimize for %s with minfree %s %d%%" 6949122Sbrian 7054458Sobrienunion { 7151231Ssheldonh struct fs sb; 7251231Ssheldonh char pad[MAXBSIZE]; 7351231Ssheldonh} sbun; 7454458Sobrien#define sblock sbun.sb 7551231Ssheldonh 7649122Sbrianint fi; 7751231Ssheldonhlong dev_bsize = 1; 7851231Ssheldonh 7951231Ssheldonhvoid bwrite(daddr_t, char *, int); 8029300Sdannyint bread(daddr_t, char *, int); 8151231Ssheldonhvoid getsb(struct fs *, char *); 8251231Ssheldonhvoid usage __P((void)); 8351231Ssheldonhvoid printfs __P((void)); 8451231Ssheldonhchar *rawname __P((char *, char *)); 8554458Sobrien 8654458Sobrienint 8754458Sobrienmain(argc, argv) 8851231Ssheldonh int argc; 8951231Ssheldonh char *argv[]; 9051231Ssheldonh{ 9154458Sobrien char *cp, *special, *name, *action; 9251231Ssheldonh struct stat st; 9351231Ssheldonh int i; 9454458Sobrien int Aflag = 0, active = 0; 9551231Ssheldonh struct fstab *fs; 9654458Sobrien char *chg[2], device[MAXPATHLEN]; 9754458Sobrien struct ufs_args args; 9854458Sobrien struct statfs stfs; 9954458Sobrien 10054458Sobrien argc--, argv++; 10151231Ssheldonh if (argc < 2) 10251231Ssheldonh usage(); 10351231Ssheldonh special = argv[argc - 1]; 10451231Ssheldonh fs = getfsfile(special); 10551231Ssheldonh if (fs) { 10651231Ssheldonh if (statfs(special, &stfs) == 0) { 10751231Ssheldonh if ((stfs.f_flags & MNT_RDONLY) == 0) { 10854458Sobrien errx(1, "cannot work on read-write mounted file system"); 10951231Ssheldonh } 11051231Ssheldonh active = 1; 11151231Ssheldonh special = rawname(fs->fs_spec, device); 11251231Ssheldonh } else 11351231Ssheldonh special = fs->fs_spec; 11451231Ssheldonh } 11551231Ssheldonhagain: 11651231Ssheldonh if (stat(special, &st) < 0) { 11751231Ssheldonh if (*special != '/') { 11851231Ssheldonh if (*special == 'r') 11951231Ssheldonh special++; 12054458Sobrien (void)sprintf(device, "%s/%s", _PATH_DEV, special); 12151231Ssheldonh special = device; 12254458Sobrien goto again; 12351231Ssheldonh } 12454458Sobrien err(1, "%s", special); 12554458Sobrien } 12654458Sobrien if ((st.st_mode & S_IFMT) != S_IFBLK && 12751231Ssheldonh (st.st_mode & S_IFMT) != S_IFCHR) 12854458Sobrien errx(10, "%s: not a block or character device", special); 12951231Ssheldonh getsb(&sblock, special); 13051231Ssheldonh for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) { 13157012Shm for (cp = &argv[0][1]; *cp; cp++) 13257012Shm switch (*cp) { 13357012Shm 13457012Shm case 'A': 13557012Shm Aflag++; 13657012Shm continue; 13757012Shm 13857012Shm case 'p': 13957012Shm printfs(); 14057012Shm exit(0); 14151231Ssheldonh 14251231Ssheldonh case 'a': 14351231Ssheldonh name = "maximum contiguous block count"; 14451231Ssheldonh if (argc < 1) 14551231Ssheldonh errx(10, "-a: missing %s", name); 14651231Ssheldonh argc--, argv++; 14751231Ssheldonh i = atoi(*argv); 14851231Ssheldonh if (i < 1) 14951231Ssheldonh errx(10, "%s must be >= 1 (was %s)", 15051231Ssheldonh name, *argv); 15151231Ssheldonh warnx("%s changes from %d to %d", 15251231Ssheldonh name, sblock.fs_maxcontig, i); 15351231Ssheldonh sblock.fs_maxcontig = i; 15451231Ssheldonh continue; 15551231Ssheldonh 15651231Ssheldonh case 'd': 15751231Ssheldonh name = 15851231Ssheldonh "rotational delay between contiguous blocks"; 15951231Ssheldonh if (argc < 1) 16051231Ssheldonh errx(10, "-d: missing %s", name); 16151231Ssheldonh argc--, argv++; 16251231Ssheldonh i = atoi(*argv); 16351231Ssheldonh warnx("%s changes from %dms to %dms", 16451231Ssheldonh name, sblock.fs_rotdelay, i); 16551231Ssheldonh sblock.fs_rotdelay = i; 16651231Ssheldonh continue; 16751231Ssheldonh 16851231Ssheldonh case 'e': 16951231Ssheldonh name = 17051231Ssheldonh "maximum blocks per file in a cylinder group"; 17151231Ssheldonh if (argc < 1) 17251231Ssheldonh errx(10, "-e: missing %s", name); 17329300Sdanny argc--, argv++; 17451231Ssheldonh i = atoi(*argv); 17529300Sdanny if (i < 1) 17629300Sdanny errx(10, "%s must be >= 1 (was %s)", 17751231Ssheldonh name, *argv); 17851231Ssheldonh warnx("%s changes from %d to %d", 17951231Ssheldonh name, sblock.fs_maxbpg, i); 18051231Ssheldonh sblock.fs_maxbpg = i; 18151231Ssheldonh continue; 18251231Ssheldonh 18351231Ssheldonh case 'm': 18451231Ssheldonh name = "minimum percentage of free space"; 18551231Ssheldonh if (argc < 1) 18651231Ssheldonh errx(10, "-m: missing %s", name); 18744992Sbrian argc--, argv++; 18851231Ssheldonh i = atoi(*argv); 18951231Ssheldonh if (i < 0 || i > 99) 19051231Ssheldonh errx(10, "bad %s (%s)", name, *argv); 19151231Ssheldonh warnx("%s changes from %d%% to %d%%", 19251231Ssheldonh name, sblock.fs_minfree, i); 19351231Ssheldonh sblock.fs_minfree = i; 19444992Sbrian if (i >= MINFREE && 19551231Ssheldonh sblock.fs_optim == FS_OPTSPACE) 19651231Ssheldonh warnx(OPTWARN, "time", ">=", MINFREE); 19751231Ssheldonh if (i < MINFREE && 19851426Sgreen sblock.fs_optim == FS_OPTTIME) 19951426Sgreen warnx(OPTWARN, "space", "<", MINFREE); 20051231Ssheldonh continue; 20151231Ssheldonh 20251231Ssheldonh case 'n': 20351231Ssheldonh name = "soft updates"; 20451231Ssheldonh if (argc < 1) 20551231Ssheldonh errx(10, "-s: missing %s", name); 20651231Ssheldonh argc--, argv++; 20751231Ssheldonh if (strcmp(*argv, "enable") == 0) { 20851231Ssheldonh sblock.fs_flags |= FS_DOSOFTDEP; 20951231Ssheldonh action = "set"; 21051231Ssheldonh } else if (strcmp(*argv, "disable") == 0) { 21151231Ssheldonh sblock.fs_flags &= ~FS_DOSOFTDEP; 21251231Ssheldonh action = "cleared"; 21351231Ssheldonh } else { 21451231Ssheldonh errx(10, "bad %s (options are %s)", 21551231Ssheldonh name, "`enable' or `disable'"); 21651231Ssheldonh } 21751231Ssheldonh warnx("%s %s", name, action); 21851231Ssheldonh continue; 21951231Ssheldonh 22051231Ssheldonh case 'o': 22151231Ssheldonh name = "optimization preference"; 22251231Ssheldonh if (argc < 1) 22351231Ssheldonh errx(10, "-o: missing %s", name); 22451231Ssheldonh argc--, argv++; 22551231Ssheldonh chg[FS_OPTSPACE] = "space"; 22651231Ssheldonh chg[FS_OPTTIME] = "time"; 22751231Ssheldonh if (strcmp(*argv, chg[FS_OPTSPACE]) == 0) 22851231Ssheldonh i = FS_OPTSPACE; 22951231Ssheldonh else if (strcmp(*argv, chg[FS_OPTTIME]) == 0) 23051231Ssheldonh i = FS_OPTTIME; 23151231Ssheldonh else 23251231Ssheldonh errx(10, "bad %s (options are `space' or `time')", 23351231Ssheldonh name); 23451231Ssheldonh if (sblock.fs_optim == i) { 23529300Sdanny warnx("%s remains unchanged as %s", 23625184Sjkh name, chg[i]); 23751231Ssheldonh continue; 23851231Ssheldonh } 23951231Ssheldonh warnx("%s changes from %s to %s", 24051231Ssheldonh name, chg[sblock.fs_optim], chg[i]); 24151231Ssheldonh sblock.fs_optim = i; 24251231Ssheldonh if (sblock.fs_minfree >= MINFREE && 24351231Ssheldonh i == FS_OPTSPACE) 24451231Ssheldonh warnx(OPTWARN, "time", ">=", MINFREE); 24551231Ssheldonh if (sblock.fs_minfree < MINFREE && 24651231Ssheldonh i == FS_OPTTIME) 24740006Sphk warnx(OPTWARN, "space", "<", MINFREE); 24851231Ssheldonh continue; 24951231Ssheldonh 25051231Ssheldonh default: 25151231Ssheldonh usage(); 25251231Ssheldonh } 25351231Ssheldonh } 25451231Ssheldonh if (argc != 1) 25551231Ssheldonh usage(); 25629300Sdanny bwrite((daddr_t)SBOFF / dev_bsize, (char *)&sblock, SBSIZE); 25751231Ssheldonh if (Aflag) 25851231Ssheldonh for (i = 0; i < sblock.fs_ncg; i++) 25951231Ssheldonh bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)), 26051231Ssheldonh (char *)&sblock, SBSIZE); 26151231Ssheldonh close(fi); 26251231Ssheldonh if (active) { 26351231Ssheldonh bzero(&args, sizeof(args)); 26451231Ssheldonh if (mount("ufs", fs->fs_file, 26551231Ssheldonh stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0) 26625184Sjkh err(9, "%s: reload", special); 26751231Ssheldonh warnx("file system reloaded"); 26851231Ssheldonh } 26951231Ssheldonh exit(0); 27051231Ssheldonh} 27151231Ssheldonh 27251231Ssheldonhvoid 27345096Simpusage() 27451231Ssheldonh{ 27551231Ssheldonh fprintf(stderr, "%s\n%s\n%s\n", 27651231Ssheldonh"usage: tunefs [-A] [-a maxcontig] [-d rotdelay] [-e maxbpg] [-m minfree]", 27751231Ssheldonh" [-p] [-n enable | disable] [-o optimize_preference]", 27851231Ssheldonh" [special | filesystem]"); 27951231Ssheldonh exit(2); 28039267Sjkoshy} 28151231Ssheldonh 28251231Ssheldonhvoid 28351231Ssheldonhgetsb(fs, file) 28451231Ssheldonh register struct fs *fs; 28551231Ssheldonh char *file; 28651231Ssheldonh{ 28733439Sguido 28851231Ssheldonh fi = open(file, 2); 28951231Ssheldonh if (fi < 0) 29051231Ssheldonh err(3, "cannot open %s", file); 29151231Ssheldonh if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE)) 29251231Ssheldonh err(4, "%s: bad super block", file); 29351231Ssheldonh if (fs->fs_magic != FS_MAGIC) 29433439Sguido err(5, "%s: bad magic number", file); 29551231Ssheldonh dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 29651231Ssheldonh} 29751231Ssheldonh 29851231Ssheldonhvoid 29951231Ssheldonhprintfs() 30051231Ssheldonh{ 30147752Sphk warnx("soft updates: (-n) %s", 30251231Ssheldonh (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled"); 30351231Ssheldonh warnx("maximum contiguous block count: (-a) %d", 30451231Ssheldonh sblock.fs_maxcontig); 30551231Ssheldonh warnx("rotational delay between contiguous blocks: (-d) %d ms", 30651231Ssheldonh sblock.fs_rotdelay); 30751231Ssheldonh warnx("maximum blocks per file in a cylinder group: (-e) %d", 30851209Sdes sblock.fs_maxbpg); 30951231Ssheldonh warnx("minimum percentage of free space: (-m) %d%%", 31051231Ssheldonh sblock.fs_minfree); 31151231Ssheldonh warnx("optimization preference: (-o) %s", 31251231Ssheldonh sblock.fs_optim == FS_OPTSPACE ? "space" : "time"); 31351231Ssheldonh if (sblock.fs_minfree >= MINFREE && 31451231Ssheldonh sblock.fs_optim == FS_OPTSPACE) 31551209Sdes warnx(OPTWARN, "time", ">=", MINFREE); 31651231Ssheldonh if (sblock.fs_minfree < MINFREE && 31751231Ssheldonh sblock.fs_optim == FS_OPTTIME) 31851231Ssheldonh warnx(OPTWARN, "space", "<", MINFREE); 31951231Ssheldonh} 32051231Ssheldonh 32151231Ssheldonhvoid 32236174Sjkhbwrite(blk, buf, size) 32351231Ssheldonh daddr_t blk; 32451231Ssheldonh char *buf; 32551231Ssheldonh int size; 32651231Ssheldonh{ 32751231Ssheldonh 32851231Ssheldonh if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0) 32936174Sjkh err(6, "FS SEEK"); 33051231Ssheldonh if (write(fi, buf, size) != size) 33151231Ssheldonh err(7, "FS WRITE"); 33251231Ssheldonh} 33351231Ssheldonh 33451231Ssheldonhint 33551231Ssheldonhbread(bno, buf, cnt) 33651231Ssheldonh daddr_t bno; 33751231Ssheldonh char *buf; 33851231Ssheldonh int cnt; 33951231Ssheldonh{ 34051231Ssheldonh int i; 34151231Ssheldonh 34251231Ssheldonh if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0) 34351231Ssheldonh return(1); 34451231Ssheldonh if ((i = read(fi, buf, cnt)) != cnt) { 34551231Ssheldonh for(i=0; i<sblock.fs_bsize; i++) 34651231Ssheldonh buf[i] = 0; 34751231Ssheldonh return (1); 34851231Ssheldonh } 34951231Ssheldonh return (0); 35051231Ssheldonh} 35151231Ssheldonh 35251231Ssheldonhchar * 35351231Ssheldonhrawname(special, pathbuf) 35451231Ssheldonh char *special; 35551231Ssheldonh char *pathbuf; 35651231Ssheldonh{ 35751231Ssheldonh char *p; 35851231Ssheldonh int n; 35951231Ssheldonh 36051231Ssheldonh p = strrchr(special, '/'); 36151231Ssheldonh if (p) { 36251231Ssheldonh n = ++p - special; 36351231Ssheldonh bcopy(special, pathbuf, n); 36451231Ssheldonh } else { 36551231Ssheldonh strcpy(pathbuf, _PATH_DEV); 36651231Ssheldonh n = strlen(pathbuf); 36751231Ssheldonh p = special; 36851231Ssheldonh } 36951231Ssheldonh pathbuf[n++] = 'r'; 37051231Ssheldonh strcpy(pathbuf + n, p); 37151231Ssheldonh return pathbuf; 37251231Ssheldonh} 37351231Ssheldonh