18fae3551SRodney W. Grimes /* 28fae3551SRodney W. Grimes * Copyright (c) 1983, 1993 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 68fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 78fae3551SRodney W. Grimes * are met: 88fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 98fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 108fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 118fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 128fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 138fae3551SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 148fae3551SRodney W. Grimes * must display the following acknowledgement: 158fae3551SRodney W. Grimes * This product includes software developed by the University of 168fae3551SRodney W. Grimes * California, Berkeley and its contributors. 178fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 188fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 198fae3551SRodney W. Grimes * without specific prior written permission. 208fae3551SRodney W. Grimes * 218fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 228fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 238fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 248fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 258fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 268fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 278fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 288fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 298fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 308fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 318fae3551SRodney W. Grimes * SUCH DAMAGE. 328fae3551SRodney W. Grimes */ 338fae3551SRodney W. Grimes 348fae3551SRodney W. Grimes #ifndef lint 358fae3551SRodney W. Grimes static char copyright[] = 368fae3551SRodney W. Grimes "@(#) Copyright (c) 1983, 1993\n\ 378fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 388fae3551SRodney W. Grimes #endif /* not lint */ 398fae3551SRodney W. Grimes 408fae3551SRodney W. Grimes #ifndef lint 418fae3551SRodney W. Grimes static char sccsid[] = "@(#)tunefs.c 8.2 (Berkeley) 4/19/94"; 428fae3551SRodney W. Grimes #endif /* not lint */ 438fae3551SRodney W. Grimes 448fae3551SRodney W. Grimes /* 458fae3551SRodney W. Grimes * tunefs: change layout parameters to an existing file system. 468fae3551SRodney W. Grimes */ 478fae3551SRodney W. Grimes #include <sys/param.h> 488fae3551SRodney W. Grimes #include <sys/stat.h> 498fae3551SRodney W. Grimes 508fae3551SRodney W. Grimes #include <ufs/ffs/fs.h> 518fae3551SRodney W. Grimes 528fae3551SRodney W. Grimes #include <errno.h> 538fae3551SRodney W. Grimes #include <err.h> 548fae3551SRodney W. Grimes #include <fcntl.h> 558fae3551SRodney W. Grimes #include <fstab.h> 568fae3551SRodney W. Grimes #include <stdio.h> 578fae3551SRodney W. Grimes #include <paths.h> 588fae3551SRodney W. Grimes #include <stdlib.h> 598fae3551SRodney W. Grimes #include <unistd.h> 608fae3551SRodney W. Grimes 618fae3551SRodney W. Grimes /* the optimization warning string template */ 628fae3551SRodney W. Grimes #define OPTWARN "should optimize for %s with minfree %s %d%%" 638fae3551SRodney W. Grimes 648fae3551SRodney W. Grimes union { 658fae3551SRodney W. Grimes struct fs sb; 668fae3551SRodney W. Grimes char pad[MAXBSIZE]; 678fae3551SRodney W. Grimes } sbun; 688fae3551SRodney W. Grimes #define sblock sbun.sb 698fae3551SRodney W. Grimes 708fae3551SRodney W. Grimes int fi; 718fae3551SRodney W. Grimes long dev_bsize = 1; 728fae3551SRodney W. Grimes 738fae3551SRodney W. Grimes void bwrite(daddr_t, char *, int); 748fae3551SRodney W. Grimes int bread(daddr_t, char *, int); 758fae3551SRodney W. Grimes void getsb(struct fs *, char *); 768fae3551SRodney W. Grimes void usage __P((void)); 778fae3551SRodney W. Grimes 788fae3551SRodney W. Grimes int 798fae3551SRodney W. Grimes main(argc, argv) 808fae3551SRodney W. Grimes int argc; 818fae3551SRodney W. Grimes char *argv[]; 828fae3551SRodney W. Grimes { 838fae3551SRodney W. Grimes char *cp, *special, *name; 848fae3551SRodney W. Grimes struct stat st; 858fae3551SRodney W. Grimes int i; 868fae3551SRodney W. Grimes int Aflag = 0; 878fae3551SRodney W. Grimes struct fstab *fs; 888fae3551SRodney W. Grimes char *chg[2], device[MAXPATHLEN]; 898fae3551SRodney W. Grimes 908fae3551SRodney W. Grimes argc--, argv++; 918fae3551SRodney W. Grimes if (argc < 2) 928fae3551SRodney W. Grimes usage(); 938fae3551SRodney W. Grimes special = argv[argc - 1]; 948fae3551SRodney W. Grimes fs = getfsfile(special); 958fae3551SRodney W. Grimes if (fs) 968fae3551SRodney W. Grimes special = fs->fs_spec; 978fae3551SRodney W. Grimes again: 988fae3551SRodney W. Grimes if (stat(special, &st) < 0) { 998fae3551SRodney W. Grimes if (*special != '/') { 1008fae3551SRodney W. Grimes if (*special == 'r') 1018fae3551SRodney W. Grimes special++; 1028fae3551SRodney W. Grimes (void)sprintf(device, "%s/%s", _PATH_DEV, special); 1038fae3551SRodney W. Grimes special = device; 1048fae3551SRodney W. Grimes goto again; 1058fae3551SRodney W. Grimes } 1068fae3551SRodney W. Grimes err(1, "%s", special); 1078fae3551SRodney W. Grimes } 1088fae3551SRodney W. Grimes if ((st.st_mode & S_IFMT) != S_IFBLK && 1098fae3551SRodney W. Grimes (st.st_mode & S_IFMT) != S_IFCHR) 1108fae3551SRodney W. Grimes errx(10, "%s: not a block or character device", special); 1118fae3551SRodney W. Grimes getsb(&sblock, special); 1128fae3551SRodney W. Grimes for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) { 1138fae3551SRodney W. Grimes for (cp = &argv[0][1]; *cp; cp++) 1148fae3551SRodney W. Grimes switch (*cp) { 1158fae3551SRodney W. Grimes 1168fae3551SRodney W. Grimes case 'A': 1178fae3551SRodney W. Grimes Aflag++; 1188fae3551SRodney W. Grimes continue; 1198fae3551SRodney W. Grimes 1208fae3551SRodney W. Grimes case 'a': 1218fae3551SRodney W. Grimes name = "maximum contiguous block count"; 1228fae3551SRodney W. Grimes if (argc < 1) 1238fae3551SRodney W. Grimes errx(10, "-a: missing %s", name); 1248fae3551SRodney W. Grimes argc--, argv++; 1258fae3551SRodney W. Grimes i = atoi(*argv); 1268fae3551SRodney W. Grimes if (i < 1) 1278fae3551SRodney W. Grimes errx(10, "%s must be >= 1 (was %s)", 1288fae3551SRodney W. Grimes name, *argv); 1298fae3551SRodney W. Grimes warnx("%s changes from %d to %d", 1308fae3551SRodney W. Grimes name, sblock.fs_maxcontig, i); 1318fae3551SRodney W. Grimes sblock.fs_maxcontig = i; 1328fae3551SRodney W. Grimes continue; 1338fae3551SRodney W. Grimes 1348fae3551SRodney W. Grimes case 'd': 1358fae3551SRodney W. Grimes name = 1368fae3551SRodney W. Grimes "rotational delay between contiguous blocks"; 1378fae3551SRodney W. Grimes if (argc < 1) 1388fae3551SRodney W. Grimes errx(10, "-d: missing %s", name); 1398fae3551SRodney W. Grimes argc--, argv++; 1408fae3551SRodney W. Grimes i = atoi(*argv); 1418fae3551SRodney W. Grimes warnx("%s changes from %dms to %dms", 1428fae3551SRodney W. Grimes name, sblock.fs_rotdelay, i); 1438fae3551SRodney W. Grimes sblock.fs_rotdelay = i; 1448fae3551SRodney W. Grimes continue; 1458fae3551SRodney W. Grimes 1468fae3551SRodney W. Grimes case 'e': 1478fae3551SRodney W. Grimes name = 1488fae3551SRodney W. Grimes "maximum blocks per file in a cylinder group"; 1498fae3551SRodney W. Grimes if (argc < 1) 1508fae3551SRodney W. Grimes errx(10, "-e: missing %s", name); 1518fae3551SRodney W. Grimes argc--, argv++; 1528fae3551SRodney W. Grimes i = atoi(*argv); 1538fae3551SRodney W. Grimes if (i < 1) 1548fae3551SRodney W. Grimes errx(10, "%s must be >= 1 (was %s)", 1558fae3551SRodney W. Grimes name, *argv); 1568fae3551SRodney W. Grimes warnx("%s changes from %d to %d", 1578fae3551SRodney W. Grimes name, sblock.fs_maxbpg, i); 1588fae3551SRodney W. Grimes sblock.fs_maxbpg = i; 1598fae3551SRodney W. Grimes continue; 1608fae3551SRodney W. Grimes 1618fae3551SRodney W. Grimes case 'm': 1628fae3551SRodney W. Grimes name = "minimum percentage of free space"; 1638fae3551SRodney W. Grimes if (argc < 1) 1648fae3551SRodney W. Grimes errx(10, "-m: missing %s", name); 1658fae3551SRodney W. Grimes argc--, argv++; 1668fae3551SRodney W. Grimes i = atoi(*argv); 1678fae3551SRodney W. Grimes if (i < 0 || i > 99) 1688fae3551SRodney W. Grimes errx(10, "bad %s (%s)", name, *argv); 1698fae3551SRodney W. Grimes warnx("%s changes from %d%% to %d%%", 1708fae3551SRodney W. Grimes name, sblock.fs_minfree, i); 1718fae3551SRodney W. Grimes sblock.fs_minfree = i; 1728fae3551SRodney W. Grimes if (i >= MINFREE && 1738fae3551SRodney W. Grimes sblock.fs_optim == FS_OPTSPACE) 1748fae3551SRodney W. Grimes warnx(OPTWARN, "time", ">=", MINFREE); 1758fae3551SRodney W. Grimes if (i < MINFREE && 1768fae3551SRodney W. Grimes sblock.fs_optim == FS_OPTTIME) 1778fae3551SRodney W. Grimes warnx(OPTWARN, "space", "<", MINFREE); 1788fae3551SRodney W. Grimes continue; 1798fae3551SRodney W. Grimes 1808fae3551SRodney W. Grimes case 'o': 1818fae3551SRodney W. Grimes name = "optimization preference"; 1828fae3551SRodney W. Grimes if (argc < 1) 1838fae3551SRodney W. Grimes errx(10, "-o: missing %s", name); 1848fae3551SRodney W. Grimes argc--, argv++; 1858fae3551SRodney W. Grimes chg[FS_OPTSPACE] = "space"; 1868fae3551SRodney W. Grimes chg[FS_OPTTIME] = "time"; 1878fae3551SRodney W. Grimes if (strcmp(*argv, chg[FS_OPTSPACE]) == 0) 1888fae3551SRodney W. Grimes i = FS_OPTSPACE; 1898fae3551SRodney W. Grimes else if (strcmp(*argv, chg[FS_OPTTIME]) == 0) 1908fae3551SRodney W. Grimes i = FS_OPTTIME; 1918fae3551SRodney W. Grimes else 1928fae3551SRodney W. Grimes errx(10, "bad %s (options are `space' or `time')", 1938fae3551SRodney W. Grimes name); 1948fae3551SRodney W. Grimes if (sblock.fs_optim == i) { 1958fae3551SRodney W. Grimes warnx("%s remains unchanged as %s", 1968fae3551SRodney W. Grimes name, chg[i]); 1978fae3551SRodney W. Grimes continue; 1988fae3551SRodney W. Grimes } 1998fae3551SRodney W. Grimes warnx("%s changes from %s to %s", 2008fae3551SRodney W. Grimes name, chg[sblock.fs_optim], chg[i]); 2018fae3551SRodney W. Grimes sblock.fs_optim = i; 2028fae3551SRodney W. Grimes if (sblock.fs_minfree >= MINFREE && 2038fae3551SRodney W. Grimes i == FS_OPTSPACE) 2048fae3551SRodney W. Grimes warnx(OPTWARN, "time", ">=", MINFREE); 2058fae3551SRodney W. Grimes if (sblock.fs_minfree < MINFREE && 2068fae3551SRodney W. Grimes i == FS_OPTTIME) 2078fae3551SRodney W. Grimes warnx(OPTWARN, "space", "<", MINFREE); 2088fae3551SRodney W. Grimes continue; 2098fae3551SRodney W. Grimes 2108fae3551SRodney W. Grimes default: 2118fae3551SRodney W. Grimes usage(); 2128fae3551SRodney W. Grimes } 2138fae3551SRodney W. Grimes } 2148fae3551SRodney W. Grimes if (argc != 1) 2158fae3551SRodney W. Grimes usage(); 2168fae3551SRodney W. Grimes bwrite((daddr_t)SBOFF / dev_bsize, (char *)&sblock, SBSIZE); 2178fae3551SRodney W. Grimes if (Aflag) 2188fae3551SRodney W. Grimes for (i = 0; i < sblock.fs_ncg; i++) 2198fae3551SRodney W. Grimes bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)), 2208fae3551SRodney W. Grimes (char *)&sblock, SBSIZE); 2218fae3551SRodney W. Grimes close(fi); 2228fae3551SRodney W. Grimes exit(0); 2238fae3551SRodney W. Grimes } 2248fae3551SRodney W. Grimes 2258fae3551SRodney W. Grimes void 2268fae3551SRodney W. Grimes usage() 2278fae3551SRodney W. Grimes { 2288fae3551SRodney W. Grimes 2298fae3551SRodney W. Grimes fprintf(stderr, "Usage: tunefs tuneup-options special-device\n"); 2308fae3551SRodney W. Grimes fprintf(stderr, "where tuneup-options are:\n"); 2318fae3551SRodney W. Grimes fprintf(stderr, "\t-a maximum contiguous blocks\n"); 2328fae3551SRodney W. Grimes fprintf(stderr, "\t-d rotational delay between contiguous blocks\n"); 2338fae3551SRodney W. Grimes fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); 2348fae3551SRodney W. Grimes fprintf(stderr, "\t-m minimum percentage of free space\n"); 2358fae3551SRodney W. Grimes fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); 2368fae3551SRodney W. Grimes exit(2); 2378fae3551SRodney W. Grimes } 2388fae3551SRodney W. Grimes 2398fae3551SRodney W. Grimes void 2408fae3551SRodney W. Grimes getsb(fs, file) 2418fae3551SRodney W. Grimes register struct fs *fs; 2428fae3551SRodney W. Grimes char *file; 2438fae3551SRodney W. Grimes { 2448fae3551SRodney W. Grimes 2458fae3551SRodney W. Grimes fi = open(file, 2); 2468fae3551SRodney W. Grimes if (fi < 0) 2478fae3551SRodney W. Grimes err(3, "cannot open %s", file); 2488fae3551SRodney W. Grimes if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE)) 2498fae3551SRodney W. Grimes err(4, "%s: bad super block", file); 2508fae3551SRodney W. Grimes if (fs->fs_magic != FS_MAGIC) 2518fae3551SRodney W. Grimes err(5, "%s: bad magic number", file); 2528fae3551SRodney W. Grimes dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 2538fae3551SRodney W. Grimes } 2548fae3551SRodney W. Grimes 2558fae3551SRodney W. Grimes void 2568fae3551SRodney W. Grimes bwrite(blk, buf, size) 2578fae3551SRodney W. Grimes daddr_t blk; 2588fae3551SRodney W. Grimes char *buf; 2598fae3551SRodney W. Grimes int size; 2608fae3551SRodney W. Grimes { 2618fae3551SRodney W. Grimes 2628fae3551SRodney W. Grimes if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0) 2638fae3551SRodney W. Grimes err(6, "FS SEEK"); 2648fae3551SRodney W. Grimes if (write(fi, buf, size) != size) 2658fae3551SRodney W. Grimes err(7, "FS WRITE"); 2668fae3551SRodney W. Grimes } 2678fae3551SRodney W. Grimes 2688fae3551SRodney W. Grimes int 2698fae3551SRodney W. Grimes bread(bno, buf, cnt) 2708fae3551SRodney W. Grimes daddr_t bno; 2718fae3551SRodney W. Grimes char *buf; 2728fae3551SRodney W. Grimes int cnt; 2738fae3551SRodney W. Grimes { 2748fae3551SRodney W. Grimes int i; 2758fae3551SRodney W. Grimes 2768fae3551SRodney W. Grimes if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0) 2778fae3551SRodney W. Grimes return(1); 2788fae3551SRodney W. Grimes if ((i = read(fi, buf, cnt)) != cnt) { 2798fae3551SRodney W. Grimes for(i=0; i<sblock.fs_bsize; i++) 2808fae3551SRodney W. Grimes buf[i] = 0; 2818fae3551SRodney W. Grimes return (1); 2828fae3551SRodney W. Grimes } 2838fae3551SRodney W. Grimes return (0); 2848fae3551SRodney W. Grimes } 285