121184Sdist /* 221184Sdist * Copyright (c) 1983 Regents of the University of California. 321184Sdist * All rights reserved. The Berkeley software License Agreement 421184Sdist * specifies the terms and conditions for redistribution. 521184Sdist */ 621184Sdist 711288Smckusick #ifndef lint 821184Sdist char copyright[] = 921184Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1021184Sdist All rights reserved.\n"; 1121184Sdist #endif not lint 1211288Smckusick 1321184Sdist #ifndef lint 14*32453Sbostic static char sccsid[] = "@(#)tunefs.c 5.5 (Berkeley) 10/22/87"; 1521184Sdist #endif not lint 1621184Sdist 1711288Smckusick /* 1811288Smckusick * tunefs: change layout parameters to an existing file system. 1911288Smckusick */ 2011288Smckusick 2111288Smckusick #include <sys/param.h> 2211288Smckusick #include <sys/stat.h> 2311288Smckusick #include <sys/fs.h> 2411288Smckusick #include <sys/inode.h> 2511288Smckusick 2613120Ssam #include <stdio.h> 2713120Ssam #include <fstab.h> 2813120Ssam 2911288Smckusick union { 3011288Smckusick struct fs sb; 3111288Smckusick char pad[MAXBSIZE]; 3211288Smckusick } sbun; 3311288Smckusick #define sblock sbun.sb 3411288Smckusick 3511288Smckusick int fi; 3630558Smckusick long dev_bsize = 1; 3711288Smckusick 3811288Smckusick main(argc, argv) 3911288Smckusick int argc; 4011288Smckusick char *argv[]; 4111288Smckusick { 4211288Smckusick char *cp, *special, *name; 4311288Smckusick struct stat st; 4411288Smckusick int i; 4511288Smckusick int Aflag = 0; 4624700Smckusick struct fstab *fs; 4724700Smckusick char *chg[2], device[MAXPATHLEN]; 4811288Smckusick 4911288Smckusick argc--, argv++; 5011288Smckusick if (argc < 2) 5111288Smckusick goto usage; 5211288Smckusick special = argv[argc - 1]; 5313120Ssam fs = getfsfile(special); 5413120Ssam if (fs) 5513120Ssam special = fs->fs_spec; 5611288Smckusick again: 5711288Smckusick if (stat(special, &st) < 0) { 5811288Smckusick if (*special != '/') { 5911288Smckusick if (*special == 'r') 6011288Smckusick special++; 61*32453Sbostic (void)sprintf(device, "/dev/%s", special); 62*32453Sbostic special = device; 6311288Smckusick goto again; 6411288Smckusick } 6511288Smckusick fprintf(stderr, "tunefs: "); perror(special); 6611288Smckusick exit(1); 6711288Smckusick } 6811288Smckusick if ((st.st_mode & S_IFMT) != S_IFBLK && 6911288Smckusick (st.st_mode & S_IFMT) != S_IFCHR) 7011288Smckusick fatal("%s: not a block or character device", special); 7111288Smckusick getsb(&sblock, special); 7211288Smckusick for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) { 7311288Smckusick for (cp = &argv[0][1]; *cp; cp++) 7411288Smckusick switch (*cp) { 7511288Smckusick 7611288Smckusick case 'A': 7711288Smckusick Aflag++; 7811288Smckusick continue; 7911288Smckusick 8011288Smckusick case 'a': 8111288Smckusick name = "maximum contiguous block count"; 8211288Smckusick if (argc < 1) 8311288Smckusick fatal("-a: missing %s", name); 8411288Smckusick argc--, argv++; 8511288Smckusick i = atoi(*argv); 8611288Smckusick if (i < 1) 8711288Smckusick fatal("%s: %s must be >= 1", 8811288Smckusick *argv, name); 8911288Smckusick fprintf(stdout, "%s changes from %d to %d\n", 9011288Smckusick name, sblock.fs_maxcontig, i); 9111288Smckusick sblock.fs_maxcontig = i; 9211288Smckusick continue; 9311288Smckusick 9411288Smckusick case 'd': 9511288Smckusick name = 9611288Smckusick "rotational delay between contiguous blocks"; 9711288Smckusick if (argc < 1) 9811288Smckusick fatal("-d: missing %s", name); 9911288Smckusick argc--, argv++; 10011288Smckusick i = atoi(*argv); 10111288Smckusick if (i < 0) 10211288Smckusick fatal("%s: bad %s", *argv, name); 10311288Smckusick fprintf(stdout, 10411288Smckusick "%s changes from %dms to %dms\n", 10511288Smckusick name, sblock.fs_rotdelay, i); 10611288Smckusick sblock.fs_rotdelay = i; 10711288Smckusick continue; 10811288Smckusick 10911288Smckusick case 'e': 11011288Smckusick name = 11111288Smckusick "maximum blocks per file in a cylinder group"; 11211288Smckusick if (argc < 1) 11311288Smckusick fatal("-e: missing %s", name); 11411288Smckusick argc--, argv++; 11511288Smckusick i = atoi(*argv); 11611288Smckusick if (i < 1) 11711288Smckusick fatal("%s: %s must be >= 1", 11811288Smckusick *argv, name); 11911288Smckusick fprintf(stdout, "%s changes from %d to %d\n", 12011288Smckusick name, sblock.fs_maxbpg, i); 12111288Smckusick sblock.fs_maxbpg = i; 12211288Smckusick continue; 12311288Smckusick 12411288Smckusick case 'm': 12511288Smckusick name = "minimum percentage of free space"; 12611288Smckusick if (argc < 1) 12711288Smckusick fatal("-m: missing %s", name); 12811288Smckusick argc--, argv++; 12911288Smckusick i = atoi(*argv); 13011288Smckusick if (i < 0 || i > 99) 13111288Smckusick fatal("%s: bad %s", *argv, name); 13211288Smckusick fprintf(stdout, 13311288Smckusick "%s changes from %d%% to %d%%\n", 13411288Smckusick name, sblock.fs_minfree, i); 13511288Smckusick sblock.fs_minfree = i; 13624704Smckusick if (i >= 10 && sblock.fs_optim == FS_OPTSPACE) 13724704Smckusick fprintf(stdout, "should optimize %s", 13824704Smckusick "for time with minfree >= 10%\n"); 13924704Smckusick if (i < 10 && sblock.fs_optim == FS_OPTTIME) 14024704Smckusick fprintf(stdout, "should optimize %s", 14124704Smckusick "for space with minfree < 10%\n"); 14211288Smckusick continue; 14311288Smckusick 14424700Smckusick case 'o': 14524700Smckusick name = "optimization preference"; 14624700Smckusick if (argc < 1) 14724700Smckusick fatal("-o: missing %s", name); 14824700Smckusick argc--, argv++; 14924700Smckusick chg[FS_OPTSPACE] = "space"; 15024700Smckusick chg[FS_OPTTIME] = "time"; 15124700Smckusick if (strcmp(*argv, chg[FS_OPTSPACE]) == 0) 15224700Smckusick i = FS_OPTSPACE; 15324700Smckusick else if (strcmp(*argv, chg[FS_OPTTIME]) == 0) 15424700Smckusick i = FS_OPTTIME; 15524700Smckusick else 15624700Smckusick fatal("%s: bad %s (options are `space' or `time')", 15724700Smckusick *argv, name); 15824700Smckusick if (sblock.fs_optim == i) { 15924700Smckusick fprintf(stdout, 16024700Smckusick "%s remains unchanged as %s\n", 16124700Smckusick name, chg[i]); 16224700Smckusick continue; 16324700Smckusick } 16424700Smckusick fprintf(stdout, 16524700Smckusick "%s changes from %s to %s\n", 16624700Smckusick name, chg[sblock.fs_optim], chg[i]); 16724700Smckusick sblock.fs_optim = i; 16824704Smckusick if (sblock.fs_minfree >= 10 && i == FS_OPTSPACE) 16924704Smckusick fprintf(stdout, "should optimize %s", 17024704Smckusick "for time with minfree >= 10%\n"); 17124704Smckusick if (sblock.fs_minfree < 10 && i == FS_OPTTIME) 17224704Smckusick fprintf(stdout, "should optimize %s", 17324704Smckusick "for space with minfree < 10%\n"); 17424700Smckusick continue; 17524700Smckusick 17611288Smckusick default: 17711288Smckusick fatal("-%c: unknown flag", *cp); 17811288Smckusick } 17911288Smckusick } 18011288Smckusick if (argc != 1) 18111288Smckusick goto usage; 18230558Smckusick bwrite(SBOFF / dev_bsize, (char *)&sblock, SBSIZE); 18311288Smckusick if (Aflag) 18411288Smckusick for (i = 0; i < sblock.fs_ncg; i++) 18511288Smckusick bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)), 18611288Smckusick (char *)&sblock, SBSIZE); 18711288Smckusick close(fi); 18811288Smckusick exit(0); 18911288Smckusick usage: 19011288Smckusick fprintf(stderr, "Usage: tunefs tuneup-options special-device\n"); 19111288Smckusick fprintf(stderr, "where tuneup-options are:\n"); 19213555Ssam fprintf(stderr, "\t-a maximum contiguous blocks\n"); 19311288Smckusick fprintf(stderr, "\t-d rotational delay between contiguous blocks\n"); 19411288Smckusick fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); 19511288Smckusick fprintf(stderr, "\t-m minimum percentage of free space\n"); 19624700Smckusick fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); 19711288Smckusick exit(2); 19811288Smckusick } 19911288Smckusick 20011288Smckusick getsb(fs, file) 20111288Smckusick register struct fs *fs; 20211288Smckusick char *file; 20311288Smckusick { 20411288Smckusick 20511288Smckusick fi = open(file, 2); 20611288Smckusick if (fi < 0) { 20711288Smckusick fprintf(stderr, "cannot open"); 20811288Smckusick perror(file); 20911288Smckusick exit(3); 21011288Smckusick } 21130558Smckusick if (bread(SBOFF, (char *)fs, SBSIZE)) { 21211288Smckusick fprintf(stderr, "bad super block"); 21311288Smckusick perror(file); 21411288Smckusick exit(4); 21511288Smckusick } 21611288Smckusick if (fs->fs_magic != FS_MAGIC) { 21711288Smckusick fprintf(stderr, "%s: bad magic number\n", file); 21811288Smckusick exit(5); 21911288Smckusick } 22030558Smckusick dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 22111288Smckusick } 22211288Smckusick 22311288Smckusick bwrite(blk, buf, size) 22411288Smckusick char *buf; 22511288Smckusick daddr_t blk; 22611288Smckusick register size; 22711288Smckusick { 22830558Smckusick if (lseek(fi, blk * dev_bsize, 0) < 0) { 22911288Smckusick perror("FS SEEK"); 23011288Smckusick exit(6); 23111288Smckusick } 23211288Smckusick if (write(fi, buf, size) != size) { 23311288Smckusick perror("FS WRITE"); 23411288Smckusick exit(7); 23511288Smckusick } 23611288Smckusick } 23711288Smckusick 23811288Smckusick bread(bno, buf, cnt) 23911288Smckusick daddr_t bno; 24011288Smckusick char *buf; 24111288Smckusick { 24211288Smckusick register i; 24311288Smckusick 24430558Smckusick if (lseek(fi, bno * dev_bsize, 0) < 0) 24511288Smckusick return(1); 24611288Smckusick if ((i = read(fi, buf, cnt)) != cnt) { 24711288Smckusick for(i=0; i<sblock.fs_bsize; i++) 24811288Smckusick buf[i] = 0; 24911288Smckusick return (1); 25011288Smckusick } 25111288Smckusick return (0); 25211288Smckusick } 25311288Smckusick 25411288Smckusick /* VARARGS1 */ 25511288Smckusick fatal(fmt, arg1, arg2) 25611288Smckusick char *fmt, *arg1, *arg2; 25711288Smckusick { 25811288Smckusick 25911295Ssam fprintf(stderr, "tunefs: "); 26011288Smckusick fprintf(stderr, fmt, arg1, arg2); 26111288Smckusick putc('\n', stderr); 26211288Smckusick exit(10); 26311288Smckusick } 264