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.15 (Berkeley) 09/07/92"; 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 <errno.h> 27 #include <fstab.h> 28 #include <stdio.h> 29 #include <paths.h> 30 31 union { 32 struct fs sb; 33 char pad[MAXBSIZE]; 34 } sbun; 35 #define sblock sbun.sb 36 37 int fi; 38 long dev_bsize = 1; 39 40 main(argc, argv) 41 int argc; 42 char *argv[]; 43 { 44 char *cp, *special, *name; 45 struct stat st; 46 int i; 47 int Aflag = 0; 48 struct fstab *fs; 49 char *chg[2], device[MAXPATHLEN]; 50 51 argc--, argv++; 52 if (argc < 2) 53 goto usage; 54 special = argv[argc - 1]; 55 fs = getfsfile(special); 56 if (fs) 57 special = fs->fs_spec; 58 again: 59 if (stat(special, &st) < 0) { 60 if (*special != '/') { 61 if (*special == 'r') 62 special++; 63 (void)sprintf(device, "%s/%s", _PATH_DEV, special); 64 special = device; 65 goto again; 66 } 67 fprintf(stderr, "tunefs: "); perror(special); 68 exit(1); 69 } 70 if ((st.st_mode & S_IFMT) != S_IFBLK && 71 (st.st_mode & S_IFMT) != S_IFCHR) 72 fatal("%s: not a block or character device", special); 73 getsb(&sblock, special); 74 for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) { 75 for (cp = &argv[0][1]; *cp; cp++) 76 switch (*cp) { 77 78 case 'A': 79 Aflag++; 80 continue; 81 82 case 'a': 83 name = "maximum contiguous block count"; 84 if (argc < 1) 85 fatal("-a: missing %s", name); 86 argc--, argv++; 87 i = atoi(*argv); 88 if (i < 1) 89 fatal("%s: %s must be >= 1", 90 *argv, name); 91 fprintf(stdout, "%s changes from %d to %d\n", 92 name, sblock.fs_maxcontig, i); 93 sblock.fs_maxcontig = i; 94 continue; 95 96 case 'd': 97 name = 98 "rotational delay between contiguous blocks"; 99 if (argc < 1) 100 fatal("-d: missing %s", name); 101 argc--, argv++; 102 i = atoi(*argv); 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((daddr_t)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, "tunefs: %s: %s\n", file, strerror(errno)); 208 exit(3); 209 } 210 if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE)) { 211 fprintf(stderr, "tunefs: %s: bad super block\n", file); 212 exit(4); 213 } 214 if (fs->fs_magic != FS_MAGIC) { 215 fprintf(stderr, "tunefs: %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