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.4 (Berkeley) 02/23/87"; 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 extern char *sprintf(); 49 50 argc--, argv++; 51 if (argc < 2) 52 goto usage; 53 special = argv[argc - 1]; 54 fs = getfsfile(special); 55 if (fs) 56 special = fs->fs_spec; 57 again: 58 if (stat(special, &st) < 0) { 59 if (*special != '/') { 60 if (*special == 'r') 61 special++; 62 special = sprintf(device, "/dev/%s", special); 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 if (i < 0) 102 fatal("%s: bad %s", *argv, name); 103 fprintf(stdout, 104 "%s changes from %dms to %dms\n", 105 name, sblock.fs_rotdelay, i); 106 sblock.fs_rotdelay = i; 107 continue; 108 109 case 'e': 110 name = 111 "maximum blocks per file in a cylinder group"; 112 if (argc < 1) 113 fatal("-e: missing %s", name); 114 argc--, argv++; 115 i = atoi(*argv); 116 if (i < 1) 117 fatal("%s: %s must be >= 1", 118 *argv, name); 119 fprintf(stdout, "%s changes from %d to %d\n", 120 name, sblock.fs_maxbpg, i); 121 sblock.fs_maxbpg = i; 122 continue; 123 124 case 'm': 125 name = "minimum percentage of free space"; 126 if (argc < 1) 127 fatal("-m: missing %s", name); 128 argc--, argv++; 129 i = atoi(*argv); 130 if (i < 0 || i > 99) 131 fatal("%s: bad %s", *argv, name); 132 fprintf(stdout, 133 "%s changes from %d%% to %d%%\n", 134 name, sblock.fs_minfree, i); 135 sblock.fs_minfree = i; 136 if (i >= 10 && sblock.fs_optim == FS_OPTSPACE) 137 fprintf(stdout, "should optimize %s", 138 "for time with minfree >= 10%\n"); 139 if (i < 10 && sblock.fs_optim == FS_OPTTIME) 140 fprintf(stdout, "should optimize %s", 141 "for space with minfree < 10%\n"); 142 continue; 143 144 case 'o': 145 name = "optimization preference"; 146 if (argc < 1) 147 fatal("-o: missing %s", name); 148 argc--, argv++; 149 chg[FS_OPTSPACE] = "space"; 150 chg[FS_OPTTIME] = "time"; 151 if (strcmp(*argv, chg[FS_OPTSPACE]) == 0) 152 i = FS_OPTSPACE; 153 else if (strcmp(*argv, chg[FS_OPTTIME]) == 0) 154 i = FS_OPTTIME; 155 else 156 fatal("%s: bad %s (options are `space' or `time')", 157 *argv, name); 158 if (sblock.fs_optim == i) { 159 fprintf(stdout, 160 "%s remains unchanged as %s\n", 161 name, chg[i]); 162 continue; 163 } 164 fprintf(stdout, 165 "%s changes from %s to %s\n", 166 name, chg[sblock.fs_optim], chg[i]); 167 sblock.fs_optim = i; 168 if (sblock.fs_minfree >= 10 && i == FS_OPTSPACE) 169 fprintf(stdout, "should optimize %s", 170 "for time with minfree >= 10%\n"); 171 if (sblock.fs_minfree < 10 && i == FS_OPTTIME) 172 fprintf(stdout, "should optimize %s", 173 "for space with minfree < 10%\n"); 174 continue; 175 176 default: 177 fatal("-%c: unknown flag", *cp); 178 } 179 } 180 if (argc != 1) 181 goto usage; 182 bwrite(SBOFF / dev_bsize, (char *)&sblock, SBSIZE); 183 if (Aflag) 184 for (i = 0; i < sblock.fs_ncg; i++) 185 bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)), 186 (char *)&sblock, SBSIZE); 187 close(fi); 188 exit(0); 189 usage: 190 fprintf(stderr, "Usage: tunefs tuneup-options special-device\n"); 191 fprintf(stderr, "where tuneup-options are:\n"); 192 fprintf(stderr, "\t-a maximum contiguous blocks\n"); 193 fprintf(stderr, "\t-d rotational delay between contiguous blocks\n"); 194 fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); 195 fprintf(stderr, "\t-m minimum percentage of free space\n"); 196 fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); 197 exit(2); 198 } 199 200 getsb(fs, file) 201 register struct fs *fs; 202 char *file; 203 { 204 205 fi = open(file, 2); 206 if (fi < 0) { 207 fprintf(stderr, "cannot open"); 208 perror(file); 209 exit(3); 210 } 211 if (bread(SBOFF, (char *)fs, SBSIZE)) { 212 fprintf(stderr, "bad super block"); 213 perror(file); 214 exit(4); 215 } 216 if (fs->fs_magic != FS_MAGIC) { 217 fprintf(stderr, "%s: bad magic number\n", file); 218 exit(5); 219 } 220 dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 221 } 222 223 bwrite(blk, buf, size) 224 char *buf; 225 daddr_t blk; 226 register size; 227 { 228 if (lseek(fi, blk * dev_bsize, 0) < 0) { 229 perror("FS SEEK"); 230 exit(6); 231 } 232 if (write(fi, buf, size) != size) { 233 perror("FS WRITE"); 234 exit(7); 235 } 236 } 237 238 bread(bno, buf, cnt) 239 daddr_t bno; 240 char *buf; 241 { 242 register i; 243 244 if (lseek(fi, bno * dev_bsize, 0) < 0) 245 return(1); 246 if ((i = read(fi, buf, cnt)) != cnt) { 247 for(i=0; i<sblock.fs_bsize; i++) 248 buf[i] = 0; 249 return (1); 250 } 251 return (0); 252 } 253 254 /* VARARGS1 */ 255 fatal(fmt, arg1, arg2) 256 char *fmt, *arg1, *arg2; 257 { 258 259 fprintf(stderr, "tunefs: "); 260 fprintf(stderr, fmt, arg1, arg2); 261 putc('\n', stderr); 262 exit(10); 263 } 264