121184Sdist /* 261556Sbostic * Copyright (c) 1983, 1993 361556Sbostic * The Regents of the University of California. All rights reserved. 435484Sbostic * 542712Sbostic * %sccs.include.redist.c% 621184Sdist */ 721184Sdist 811288Smckusick #ifndef lint 961556Sbostic static char copyright[] = 1061556Sbostic "@(#) Copyright (c) 1983, 1993\n\ 1161556Sbostic The Regents of the University of California. All rights reserved.\n"; 1235484Sbostic #endif /* not lint */ 1311288Smckusick 1421184Sdist #ifndef lint 15*66924Smckusick static char sccsid[] = "@(#)tunefs.c 8.2 (Berkeley) 04/19/94"; 1635484Sbostic #endif /* not lint */ 1721184Sdist 1811288Smckusick /* 1911288Smckusick * tunefs: change layout parameters to an existing file system. 2011288Smckusick */ 2111288Smckusick #include <sys/param.h> 2211288Smckusick #include <sys/stat.h> 2355660Sbostic 2451624Sbostic #include <ufs/ffs/fs.h> 2555660Sbostic 2655660Sbostic #include <errno.h> 27*66924Smckusick #include <err.h> 28*66924Smckusick #include <fcntl.h> 2937959Sbostic #include <fstab.h> 3013120Ssam #include <stdio.h> 3137959Sbostic #include <paths.h> 32*66924Smckusick #include <stdlib.h> 33*66924Smckusick #include <unistd.h> 3413120Ssam 35*66924Smckusick /* the optimization warning string template */ 36*66924Smckusick #define OPTWARN "should optimize for %s with minfree %s %d%%" 37*66924Smckusick 3811288Smckusick union { 3911288Smckusick struct fs sb; 4011288Smckusick char pad[MAXBSIZE]; 4111288Smckusick } sbun; 4211288Smckusick #define sblock sbun.sb 4311288Smckusick 4411288Smckusick int fi; 4530558Smckusick long dev_bsize = 1; 4611288Smckusick 47*66924Smckusick void bwrite(daddr_t, char *, int); 48*66924Smckusick int bread(daddr_t, char *, int); 49*66924Smckusick void getsb(struct fs *, char *); 50*66924Smckusick void usage __P((void)); 51*66924Smckusick 52*66924Smckusick int 5311288Smckusick main(argc, argv) 5411288Smckusick int argc; 5511288Smckusick char *argv[]; 5611288Smckusick { 5711288Smckusick char *cp, *special, *name; 5811288Smckusick struct stat st; 5911288Smckusick int i; 6011288Smckusick int Aflag = 0; 6124700Smckusick struct fstab *fs; 6224700Smckusick char *chg[2], device[MAXPATHLEN]; 6311288Smckusick 6411288Smckusick argc--, argv++; 6511288Smckusick if (argc < 2) 66*66924Smckusick usage(); 6711288Smckusick special = argv[argc - 1]; 6813120Ssam fs = getfsfile(special); 6913120Ssam if (fs) 7013120Ssam special = fs->fs_spec; 7111288Smckusick again: 7211288Smckusick if (stat(special, &st) < 0) { 7311288Smckusick if (*special != '/') { 7411288Smckusick if (*special == 'r') 7511288Smckusick special++; 7637959Sbostic (void)sprintf(device, "%s/%s", _PATH_DEV, special); 7732453Sbostic special = device; 7811288Smckusick goto again; 7911288Smckusick } 80*66924Smckusick err(1, "%s", special); 8111288Smckusick } 8211288Smckusick if ((st.st_mode & S_IFMT) != S_IFBLK && 8311288Smckusick (st.st_mode & S_IFMT) != S_IFCHR) 84*66924Smckusick errx(10, "%s: not a block or character device", special); 8511288Smckusick getsb(&sblock, special); 8611288Smckusick for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) { 8711288Smckusick for (cp = &argv[0][1]; *cp; cp++) 8811288Smckusick switch (*cp) { 8911288Smckusick 9011288Smckusick case 'A': 9111288Smckusick Aflag++; 9211288Smckusick continue; 9311288Smckusick 9411288Smckusick case 'a': 9511288Smckusick name = "maximum contiguous block count"; 9611288Smckusick if (argc < 1) 97*66924Smckusick errx(10, "-a: missing %s", name); 9811288Smckusick argc--, argv++; 9911288Smckusick i = atoi(*argv); 10011288Smckusick if (i < 1) 101*66924Smckusick errx(10, "%s must be >= 1 (was %s)", 102*66924Smckusick name, *argv); 103*66924Smckusick warnx("%s changes from %d to %d", 104*66924Smckusick name, sblock.fs_maxcontig, i); 10511288Smckusick sblock.fs_maxcontig = i; 10611288Smckusick continue; 10711288Smckusick 10811288Smckusick case 'd': 10911288Smckusick name = 11011288Smckusick "rotational delay between contiguous blocks"; 11111288Smckusick if (argc < 1) 112*66924Smckusick errx(10, "-d: missing %s", name); 11311288Smckusick argc--, argv++; 11411288Smckusick i = atoi(*argv); 115*66924Smckusick warnx("%s changes from %dms to %dms", 116*66924Smckusick name, sblock.fs_rotdelay, i); 11711288Smckusick sblock.fs_rotdelay = i; 11811288Smckusick continue; 11911288Smckusick 12011288Smckusick case 'e': 12111288Smckusick name = 12211288Smckusick "maximum blocks per file in a cylinder group"; 12311288Smckusick if (argc < 1) 124*66924Smckusick errx(10, "-e: missing %s", name); 12511288Smckusick argc--, argv++; 12611288Smckusick i = atoi(*argv); 12711288Smckusick if (i < 1) 128*66924Smckusick errx(10, "%s must be >= 1 (was %s)", 129*66924Smckusick name, *argv); 130*66924Smckusick warnx("%s changes from %d to %d", 131*66924Smckusick name, sblock.fs_maxbpg, i); 13211288Smckusick sblock.fs_maxbpg = i; 13311288Smckusick continue; 13411288Smckusick 13511288Smckusick case 'm': 13611288Smckusick name = "minimum percentage of free space"; 13711288Smckusick if (argc < 1) 138*66924Smckusick errx(10, "-m: missing %s", name); 13911288Smckusick argc--, argv++; 14011288Smckusick i = atoi(*argv); 14111288Smckusick if (i < 0 || i > 99) 142*66924Smckusick errx(10, "bad %s (%s)", name, *argv); 143*66924Smckusick warnx("%s changes from %d%% to %d%%", 144*66924Smckusick name, sblock.fs_minfree, i); 14511288Smckusick sblock.fs_minfree = i; 146*66924Smckusick if (i >= MINFREE && 147*66924Smckusick sblock.fs_optim == FS_OPTSPACE) 148*66924Smckusick warnx(OPTWARN, "time", ">=", MINFREE); 149*66924Smckusick if (i < MINFREE && 150*66924Smckusick sblock.fs_optim == FS_OPTTIME) 151*66924Smckusick warnx(OPTWARN, "space", "<", MINFREE); 15211288Smckusick continue; 15311288Smckusick 15424700Smckusick case 'o': 15524700Smckusick name = "optimization preference"; 15624700Smckusick if (argc < 1) 157*66924Smckusick errx(10, "-o: missing %s", name); 15824700Smckusick argc--, argv++; 15924700Smckusick chg[FS_OPTSPACE] = "space"; 16024700Smckusick chg[FS_OPTTIME] = "time"; 16124700Smckusick if (strcmp(*argv, chg[FS_OPTSPACE]) == 0) 16224700Smckusick i = FS_OPTSPACE; 16324700Smckusick else if (strcmp(*argv, chg[FS_OPTTIME]) == 0) 16424700Smckusick i = FS_OPTTIME; 16524700Smckusick else 166*66924Smckusick errx(10, "bad %s (options are `space' or `time')", 167*66924Smckusick name); 16824700Smckusick if (sblock.fs_optim == i) { 169*66924Smckusick warnx("%s remains unchanged as %s", 170*66924Smckusick name, chg[i]); 17124700Smckusick continue; 17224700Smckusick } 173*66924Smckusick warnx("%s changes from %s to %s", 174*66924Smckusick name, chg[sblock.fs_optim], chg[i]); 17524700Smckusick sblock.fs_optim = i; 176*66924Smckusick if (sblock.fs_minfree >= MINFREE && 177*66924Smckusick i == FS_OPTSPACE) 178*66924Smckusick warnx(OPTWARN, "time", ">=", MINFREE); 179*66924Smckusick if (sblock.fs_minfree < MINFREE && 180*66924Smckusick i == FS_OPTTIME) 181*66924Smckusick warnx(OPTWARN, "space", "<", MINFREE); 18224700Smckusick continue; 18324700Smckusick 18411288Smckusick default: 185*66924Smckusick usage(); 18611288Smckusick } 18711288Smckusick } 18811288Smckusick if (argc != 1) 189*66924Smckusick usage(); 19056210Shibler bwrite((daddr_t)SBOFF / dev_bsize, (char *)&sblock, SBSIZE); 19111288Smckusick if (Aflag) 19211288Smckusick for (i = 0; i < sblock.fs_ncg; i++) 19311288Smckusick bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)), 19411288Smckusick (char *)&sblock, SBSIZE); 19511288Smckusick close(fi); 19611288Smckusick exit(0); 197*66924Smckusick } 198*66924Smckusick 199*66924Smckusick void 200*66924Smckusick usage() 201*66924Smckusick { 202*66924Smckusick 20311288Smckusick fprintf(stderr, "Usage: tunefs tuneup-options special-device\n"); 20411288Smckusick fprintf(stderr, "where tuneup-options are:\n"); 20513555Ssam fprintf(stderr, "\t-a maximum contiguous blocks\n"); 20611288Smckusick fprintf(stderr, "\t-d rotational delay between contiguous blocks\n"); 20711288Smckusick fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); 20811288Smckusick fprintf(stderr, "\t-m minimum percentage of free space\n"); 20924700Smckusick fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); 21011288Smckusick exit(2); 21111288Smckusick } 21211288Smckusick 213*66924Smckusick void 21411288Smckusick getsb(fs, file) 21511288Smckusick register struct fs *fs; 21611288Smckusick char *file; 21711288Smckusick { 21811288Smckusick 21911288Smckusick fi = open(file, 2); 220*66924Smckusick if (fi < 0) 221*66924Smckusick err(3, "cannot open %s", file); 222*66924Smckusick if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE)) 223*66924Smckusick err(4, "%s: bad super block", file); 224*66924Smckusick if (fs->fs_magic != FS_MAGIC) 225*66924Smckusick err(5, "%s: bad magic number", file); 22630558Smckusick dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 22711288Smckusick } 22811288Smckusick 229*66924Smckusick void 23011288Smckusick bwrite(blk, buf, size) 231*66924Smckusick daddr_t blk; 23211288Smckusick char *buf; 233*66924Smckusick int size; 23411288Smckusick { 235*66924Smckusick 236*66924Smckusick if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0) 237*66924Smckusick err(6, "FS SEEK"); 238*66924Smckusick if (write(fi, buf, size) != size) 239*66924Smckusick err(7, "FS WRITE"); 24011288Smckusick } 24111288Smckusick 242*66924Smckusick int 24311288Smckusick bread(bno, buf, cnt) 24411288Smckusick daddr_t bno; 24511288Smckusick char *buf; 246*66924Smckusick int cnt; 24711288Smckusick { 248*66924Smckusick int i; 24911288Smckusick 25058003Sralph if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0) 25111288Smckusick return(1); 25211288Smckusick if ((i = read(fi, buf, cnt)) != cnt) { 25311288Smckusick for(i=0; i<sblock.fs_bsize; i++) 25411288Smckusick buf[i] = 0; 25511288Smckusick return (1); 25611288Smckusick } 25711288Smckusick return (0); 25811288Smckusick } 259