tunefs.c revision 1.17
1/* $NetBSD: tunefs.c,v 1.17 1998/08/25 19:18:17 ross Exp $ */ 2 3/* 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include <sys/cdefs.h> 37#ifndef lint 38__COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\ 39 The Regents of the University of California. All rights reserved.\n"); 40#endif /* not lint */ 41 42#ifndef lint 43#if 0 44static char sccsid[] = "@(#)tunefs.c 8.3 (Berkeley) 5/3/95"; 45#else 46__RCSID("$NetBSD: tunefs.c,v 1.17 1998/08/25 19:18:17 ross Exp $"); 47#endif 48#endif /* not lint */ 49 50/* 51 * tunefs: change layout parameters to an existing file system. 52 */ 53#include <sys/param.h> 54#include <sys/stat.h> 55 56#include <ufs/ufs/dinode.h> 57#include <ufs/ffs/fs.h> 58#include <ufs/ffs/ffs_extern.h> 59 60#include <errno.h> 61#include <err.h> 62#include <fcntl.h> 63#include <fstab.h> 64#include <stdio.h> 65#include <paths.h> 66#include <stdlib.h> 67#include <string.h> 68#include <unistd.h> 69 70/* the optimization warning string template */ 71#define OPTWARN "should optimize for %s with minfree %s %d%%" 72 73union { 74 struct fs sb; 75 char pad[MAXBSIZE]; 76} sbun; 77#define sblock sbun.sb 78char buf[MAXBSIZE]; 79 80int fi; 81long dev_bsize = 1; 82int needswap = 0; 83 84void bwrite __P((daddr_t, char *, int)); 85int bread __P((daddr_t, char *, int)); 86void getsb __P((struct fs *, const char *)); 87int main __P((int, char *[])); 88void usage __P((void)); 89 90int 91main(argc, argv) 92 int argc; 93 char *argv[]; 94{ 95 char *cp, *name; 96 const char *special; 97 struct stat st; 98 int i; 99 int Aflag = 0, Nflag = 0; 100 struct fstab *fs; 101 char *chg[2], device[MAXPATHLEN]; 102 103 argc--, argv++; 104 if (argc < 2) 105 usage(); 106 special = argv[argc - 1]; 107 fs = getfsfile(special); 108 if (fs) 109 special = fs->fs_spec; 110again: 111 if (stat(special, &st) < 0) { 112 if (*special != '/') { 113 if (*special == 'r') 114 special++; 115 (void)snprintf(device, sizeof(device), "%s/%s", 116 _PATH_DEV, special); 117 special = device; 118 goto again; 119 } 120 err(1, "%s", special); 121 } 122 if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) 123 errx(10, "%s: not a block or character device", special); 124 getsb(&sblock, special); 125 chg[FS_OPTSPACE] = "space"; 126 chg[FS_OPTTIME] = "time"; 127 for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) { 128 for (cp = &argv[0][1]; *cp; cp++) 129 switch (*cp) { 130 131 case 'A': 132 Aflag++; 133 continue; 134 135 case 'N': 136 Nflag++; 137 continue; 138 139 case 'a': 140 name = "maximum contiguous block count"; 141 if (argc < 1) 142 errx(10, "-a: missing %s", name); 143 argc--, argv++; 144 i = atoi(*argv); 145 if (i < 1) 146 errx(10, "%s must be >= 1 (was %s)", 147 name, *argv); 148 warnx("%s changes from %d to %d", 149 name, sblock.fs_maxcontig, i); 150 sblock.fs_maxcontig = i; 151 continue; 152 153 case 'd': 154 name = 155 "rotational delay between contiguous blocks"; 156 if (argc < 1) 157 errx(10, "-d: missing %s", name); 158 argc--, argv++; 159 i = atoi(*argv); 160 warnx("%s changes from %dms to %dms", 161 name, sblock.fs_rotdelay, i); 162 sblock.fs_rotdelay = i; 163 continue; 164 165 case 'e': 166 name = 167 "maximum blocks per file in a cylinder group"; 168 if (argc < 1) 169 errx(10, "-e: missing %s", name); 170 argc--, argv++; 171 i = atoi(*argv); 172 if (i < 1) 173 errx(10, "%s must be >= 1 (was %s)", 174 name, *argv); 175 warnx("%s changes from %d to %d", 176 name, sblock.fs_maxbpg, i); 177 sblock.fs_maxbpg = i; 178 continue; 179 180 case 'm': 181 name = "minimum percentage of free space"; 182 if (argc < 1) 183 errx(10, "-m: missing %s", name); 184 argc--, argv++; 185 i = atoi(*argv); 186 if (i < 0 || i > 99) 187 errx(10, "bad %s (%s)", name, *argv); 188 warnx("%s changes from %d%% to %d%%", 189 name, sblock.fs_minfree, i); 190 sblock.fs_minfree = i; 191 if (i >= MINFREE && 192 sblock.fs_optim == FS_OPTSPACE) 193 warnx(OPTWARN, "time", ">=", MINFREE); 194 if (i < MINFREE && 195 sblock.fs_optim == FS_OPTTIME) 196 warnx(OPTWARN, "space", "<", MINFREE); 197 continue; 198 199 case 'o': 200 name = "optimization preference"; 201 if (argc < 1) 202 errx(10, "-o: missing %s", name); 203 argc--, argv++; 204 if (strcmp(*argv, chg[FS_OPTSPACE]) == 0) 205 i = FS_OPTSPACE; 206 else if (strcmp(*argv, chg[FS_OPTTIME]) == 0) 207 i = FS_OPTTIME; 208 else 209 errx(10, "bad %s (options are `space' or `time')", 210 name); 211 if (sblock.fs_optim == i) { 212 warnx("%s remains unchanged as %s", 213 name, chg[i]); 214 continue; 215 } 216 warnx("%s changes from %s to %s", 217 name, chg[sblock.fs_optim], chg[i]); 218 sblock.fs_optim = i; 219 if (sblock.fs_minfree >= MINFREE && 220 i == FS_OPTSPACE) 221 warnx(OPTWARN, "time", ">=", MINFREE); 222 if (sblock.fs_minfree < MINFREE && 223 i == FS_OPTTIME) 224 warnx(OPTWARN, "space", "<", MINFREE); 225 continue; 226 227 case 't': 228 name = "track skew in sectors"; 229 if (argc < 1) 230 errx(10, "-t: missing %s", name); 231 argc--, argv++; 232 i = atoi(*argv); 233 if (i < 0) 234 errx(10, "%s: %s must be >= 0", 235 *argv, name); 236 warnx("%s changes from %d to %d", 237 name, sblock.fs_trackskew, i); 238 sblock.fs_trackskew = i; 239 continue; 240 241 default: 242 usage(); 243 } 244 } 245 if (argc != 1) 246 usage(); 247 if (Nflag) { 248 fprintf(stdout, "tunefs: current settings\n"); 249 fprintf(stdout, "\tmaximum contiguous block count %d\n", 250 sblock.fs_maxcontig); 251 fprintf(stdout, 252 "\trotational delay between contiguous blocks %dms\n", 253 sblock.fs_rotdelay); 254 fprintf(stdout, 255 "\tmaximum blocks per file in a cylinder group %d\n", 256 sblock.fs_maxbpg); 257 fprintf(stdout, "\tminimum percentage of free space %d%%\n", 258 sblock.fs_minfree); 259 fprintf(stdout, "\toptimization preference: %s\n", 260 chg[sblock.fs_optim]); 261 fprintf(stdout, "\ttrack skew %d sectors\n", 262 sblock.fs_trackskew); 263 fprintf(stdout, "tunefs: no changes made\n"); 264 exit(0); 265 } 266 fi = open(special, 1); 267 if (fi < 0) 268 err(3, "cannot open %s for writing", special); 269 memcpy(buf, (char *)&sblock, SBSIZE); 270 if (needswap) 271 ffs_sb_swap((struct fs*)buf, (struct fs*)buf, 1); 272 bwrite((daddr_t)SBOFF / dev_bsize, buf, SBSIZE); 273 if (Aflag) 274 for (i = 0; i < sblock.fs_ncg; i++) 275 bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)), 276 buf, SBSIZE); 277 close(fi); 278 exit(0); 279} 280 281void 282usage() 283{ 284 285 fprintf(stderr, "Usage: tunefs [-AN] tuneup-options special-device\n"); 286 fprintf(stderr, "where tuneup-options are:\n"); 287 fprintf(stderr, "\t-d rotational delay between contiguous blocks\n"); 288 fprintf(stderr, "\t-a maximum contiguous blocks\n"); 289 fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); 290 fprintf(stderr, "\t-m minimum percentage of free space\n"); 291 fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); 292 fprintf(stderr, "\t-t track skew in sectors\n"); 293 exit(2); 294} 295 296void 297getsb(fs, file) 298 struct fs *fs; 299 const char *file; 300{ 301 302 fi = open(file, 0); 303 if (fi < 0) 304 err(3, "cannot open %s for reading", file); 305 if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE)) 306 err(4, "%s: bad super block", file); 307 if (fs->fs_magic != FS_MAGIC) { 308 if (fs->fs_magic == bswap32(FS_MAGIC)) { 309 needswap = 1; 310 ffs_sb_swap(fs, fs, 0); 311 } else 312 err(5, "%s: bad magic number", file); 313 } 314 dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 315 close(fi); 316} 317 318void 319bwrite(blk, buf, size) 320 daddr_t blk; 321 char *buf; 322 int size; 323{ 324 325 if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0) 326 err(6, "FS SEEK"); 327 if (write(fi, buf, size) != size) 328 err(7, "FS WRITE"); 329} 330 331int 332bread(bno, buf, cnt) 333 daddr_t bno; 334 char *buf; 335 int cnt; 336{ 337 int i; 338 339 if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0) 340 return(1); 341 if ((i = read(fi, buf, cnt)) != cnt) { 342 for(i=0; i<sblock.fs_bsize; i++) 343 buf[i] = 0; 344 return (1); 345 } 346 return (0); 347} 348