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