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