1 /* 2 * Copyright (c) 1983 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)tunefs.c 5.16 (Berkeley) 02/15/93"; 16 #endif /* not lint */ 17 18 /* 19 * tunefs: change layout parameters to an existing file system. 20 */ 21 #include <sys/param.h> 22 #include <sys/stat.h> 23 24 #include <ufs/ffs/fs.h> 25 26 #include <unistd.h> 27 #include <errno.h> 28 #include <fstab.h> 29 #include <stdio.h> 30 #include <paths.h> 31 32 union { 33 struct fs sb; 34 char pad[MAXBSIZE]; 35 } sbun; 36 #define sblock sbun.sb 37 38 int fi; 39 long dev_bsize = 1; 40 41 main(argc, argv) 42 int argc; 43 char *argv[]; 44 { 45 char *cp, *special, *name; 46 struct stat st; 47 int i; 48 int Aflag = 0; 49 struct fstab *fs; 50 char *chg[2], device[MAXPATHLEN]; 51 52 argc--, argv++; 53 if (argc < 2) 54 goto usage; 55 special = argv[argc - 1]; 56 fs = getfsfile(special); 57 if (fs) 58 special = fs->fs_spec; 59 again: 60 if (stat(special, &st) < 0) { 61 if (*special != '/') { 62 if (*special == 'r') 63 special++; 64 (void)sprintf(device, "%s/%s", _PATH_DEV, special); 65 special = device; 66 goto again; 67 } 68 fprintf(stderr, "tunefs: "); perror(special); 69 exit(1); 70 } 71 if ((st.st_mode & S_IFMT) != S_IFBLK && 72 (st.st_mode & S_IFMT) != S_IFCHR) 73 fatal("%s: not a block or character device", special); 74 getsb(&sblock, special); 75 for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) { 76 for (cp = &argv[0][1]; *cp; cp++) 77 switch (*cp) { 78 79 case 'A': 80 Aflag++; 81 continue; 82 83 case 'a': 84 name = "maximum contiguous block count"; 85 if (argc < 1) 86 fatal("-a: missing %s", name); 87 argc--, argv++; 88 i = atoi(*argv); 89 if (i < 1) 90 fatal("%s: %s must be >= 1", 91 *argv, name); 92 fprintf(stdout, "%s changes from %d to %d\n", 93 name, sblock.fs_maxcontig, i); 94 sblock.fs_maxcontig = i; 95 continue; 96 97 case 'd': 98 name = 99 "rotational delay between contiguous blocks"; 100 if (argc < 1) 101 fatal("-d: missing %s", name); 102 argc--, argv++; 103 i = atoi(*argv); 104 fprintf(stdout, 105 "%s changes from %dms to %dms\n", 106 name, sblock.fs_rotdelay, i); 107 sblock.fs_rotdelay = i; 108 continue; 109 110 case 'e': 111 name = 112 "maximum blocks per file in a cylinder group"; 113 if (argc < 1) 114 fatal("-e: missing %s", name); 115 argc--, argv++; 116 i = atoi(*argv); 117 if (i < 1) 118 fatal("%s: %s must be >= 1", 119 *argv, name); 120 fprintf(stdout, "%s changes from %d to %d\n", 121 name, sblock.fs_maxbpg, i); 122 sblock.fs_maxbpg = i; 123 continue; 124 125 case 'm': 126 name = "minimum percentage of free space"; 127 if (argc < 1) 128 fatal("-m: missing %s", name); 129 argc--, argv++; 130 i = atoi(*argv); 131 if (i < 0 || i > 99) 132 fatal("%s: bad %s", *argv, name); 133 fprintf(stdout, 134 "%s changes from %d%% to %d%%\n", 135 name, sblock.fs_minfree, i); 136 sblock.fs_minfree = i; 137 if (i >= 10 && sblock.fs_optim == FS_OPTSPACE) 138 fprintf(stdout, "should optimize %s", 139 "for time with minfree >= 10%\n"); 140 if (i < 10 && sblock.fs_optim == FS_OPTTIME) 141 fprintf(stdout, "should optimize %s", 142 "for space with minfree < 10%\n"); 143 continue; 144 145 case 'o': 146 name = "optimization preference"; 147 if (argc < 1) 148 fatal("-o: missing %s", name); 149 argc--, argv++; 150 chg[FS_OPTSPACE] = "space"; 151 chg[FS_OPTTIME] = "time"; 152 if (strcmp(*argv, chg[FS_OPTSPACE]) == 0) 153 i = FS_OPTSPACE; 154 else if (strcmp(*argv, chg[FS_OPTTIME]) == 0) 155 i = FS_OPTTIME; 156 else 157 fatal("%s: bad %s (options are `space' or `time')", 158 *argv, name); 159 if (sblock.fs_optim == i) { 160 fprintf(stdout, 161 "%s remains unchanged as %s\n", 162 name, chg[i]); 163 continue; 164 } 165 fprintf(stdout, 166 "%s changes from %s to %s\n", 167 name, chg[sblock.fs_optim], chg[i]); 168 sblock.fs_optim = i; 169 if (sblock.fs_minfree >= 10 && i == FS_OPTSPACE) 170 fprintf(stdout, "should optimize %s", 171 "for time with minfree >= 10%\n"); 172 if (sblock.fs_minfree < 10 && i == FS_OPTTIME) 173 fprintf(stdout, "should optimize %s", 174 "for space with minfree < 10%\n"); 175 continue; 176 177 default: 178 fatal("-%c: unknown flag", *cp); 179 } 180 } 181 if (argc != 1) 182 goto usage; 183 bwrite((daddr_t)SBOFF / dev_bsize, (char *)&sblock, SBSIZE); 184 if (Aflag) 185 for (i = 0; i < sblock.fs_ncg; i++) 186 bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)), 187 (char *)&sblock, SBSIZE); 188 close(fi); 189 exit(0); 190 usage: 191 fprintf(stderr, "Usage: tunefs tuneup-options special-device\n"); 192 fprintf(stderr, "where tuneup-options are:\n"); 193 fprintf(stderr, "\t-a maximum contiguous blocks\n"); 194 fprintf(stderr, "\t-d rotational delay between contiguous blocks\n"); 195 fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); 196 fprintf(stderr, "\t-m minimum percentage of free space\n"); 197 fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); 198 exit(2); 199 } 200 201 getsb(fs, file) 202 register struct fs *fs; 203 char *file; 204 { 205 206 fi = open(file, 2); 207 if (fi < 0) { 208 fprintf(stderr, "tunefs: %s: %s\n", file, strerror(errno)); 209 exit(3); 210 } 211 if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE)) { 212 fprintf(stderr, "tunefs: %s: bad super block\n", file); 213 exit(4); 214 } 215 if (fs->fs_magic != FS_MAGIC) { 216 fprintf(stderr, "tunefs: %s: bad magic number\n", file); 217 exit(5); 218 } 219 dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 220 } 221 222 bwrite(blk, buf, size) 223 char *buf; 224 daddr_t blk; 225 register size; 226 { 227 if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0) { 228 perror("FS SEEK"); 229 exit(6); 230 } 231 if (write(fi, buf, size) != size) { 232 perror("FS WRITE"); 233 exit(7); 234 } 235 } 236 237 bread(bno, buf, cnt) 238 daddr_t bno; 239 char *buf; 240 { 241 register i; 242 243 if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0) 244 return(1); 245 if ((i = read(fi, buf, cnt)) != cnt) { 246 for(i=0; i<sblock.fs_bsize; i++) 247 buf[i] = 0; 248 return (1); 249 } 250 return (0); 251 } 252 253 /* VARARGS1 */ 254 fatal(fmt, arg1, arg2) 255 char *fmt, *arg1, *arg2; 256 { 257 258 fprintf(stderr, "tunefs: "); 259 fprintf(stderr, fmt, arg1, arg2); 260 putc('\n', stderr); 261 exit(10); 262 } 263