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