121184Sdist /* 235484Sbostic * Copyright (c) 1983 The Regents of the University of California. 335484Sbostic * All rights reserved. 435484Sbostic * 542712Sbostic * %sccs.include.redist.c% 621184Sdist */ 721184Sdist 811288Smckusick #ifndef lint 921184Sdist char copyright[] = 1035484Sbostic "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ 1121184Sdist All rights reserved.\n"; 1235484Sbostic #endif /* not lint */ 1311288Smckusick 1421184Sdist #ifndef lint 15*58003Sralph static char sccsid[] = "@(#)tunefs.c 5.16 (Berkeley) 02/15/93"; 1635484Sbostic #endif /* not lint */ 1721184Sdist 1811288Smckusick /* 1911288Smckusick * tunefs: change layout parameters to an existing file system. 2011288Smckusick */ 2111288Smckusick #include <sys/param.h> 2211288Smckusick #include <sys/stat.h> 2355660Sbostic 2451624Sbostic #include <ufs/ffs/fs.h> 2555660Sbostic 26*58003Sralph #include <unistd.h> 2755660Sbostic #include <errno.h> 2837959Sbostic #include <fstab.h> 2913120Ssam #include <stdio.h> 3037959Sbostic #include <paths.h> 3113120Ssam 3211288Smckusick union { 3311288Smckusick struct fs sb; 3411288Smckusick char pad[MAXBSIZE]; 3511288Smckusick } sbun; 3611288Smckusick #define sblock sbun.sb 3711288Smckusick 3811288Smckusick int fi; 3930558Smckusick long dev_bsize = 1; 4011288Smckusick 4111288Smckusick main(argc, argv) 4211288Smckusick int argc; 4311288Smckusick char *argv[]; 4411288Smckusick { 4511288Smckusick char *cp, *special, *name; 4611288Smckusick struct stat st; 4711288Smckusick int i; 4811288Smckusick int Aflag = 0; 4924700Smckusick struct fstab *fs; 5024700Smckusick char *chg[2], device[MAXPATHLEN]; 5111288Smckusick 5211288Smckusick argc--, argv++; 5311288Smckusick if (argc < 2) 5411288Smckusick goto usage; 5511288Smckusick special = argv[argc - 1]; 5613120Ssam fs = getfsfile(special); 5713120Ssam if (fs) 5813120Ssam special = fs->fs_spec; 5911288Smckusick again: 6011288Smckusick if (stat(special, &st) < 0) { 6111288Smckusick if (*special != '/') { 6211288Smckusick if (*special == 'r') 6311288Smckusick special++; 6437959Sbostic (void)sprintf(device, "%s/%s", _PATH_DEV, special); 6532453Sbostic special = device; 6611288Smckusick goto again; 6711288Smckusick } 6811288Smckusick fprintf(stderr, "tunefs: "); perror(special); 6911288Smckusick exit(1); 7011288Smckusick } 7111288Smckusick if ((st.st_mode & S_IFMT) != S_IFBLK && 7211288Smckusick (st.st_mode & S_IFMT) != S_IFCHR) 7311288Smckusick fatal("%s: not a block or character device", special); 7411288Smckusick getsb(&sblock, special); 7511288Smckusick for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) { 7611288Smckusick for (cp = &argv[0][1]; *cp; cp++) 7711288Smckusick switch (*cp) { 7811288Smckusick 7911288Smckusick case 'A': 8011288Smckusick Aflag++; 8111288Smckusick continue; 8211288Smckusick 8311288Smckusick case 'a': 8411288Smckusick name = "maximum contiguous block count"; 8511288Smckusick if (argc < 1) 8611288Smckusick fatal("-a: missing %s", name); 8711288Smckusick argc--, argv++; 8811288Smckusick i = atoi(*argv); 8911288Smckusick if (i < 1) 9011288Smckusick fatal("%s: %s must be >= 1", 9111288Smckusick *argv, name); 9211288Smckusick fprintf(stdout, "%s changes from %d to %d\n", 9311288Smckusick name, sblock.fs_maxcontig, i); 9411288Smckusick sblock.fs_maxcontig = i; 9511288Smckusick continue; 9611288Smckusick 9711288Smckusick case 'd': 9811288Smckusick name = 9911288Smckusick "rotational delay between contiguous blocks"; 10011288Smckusick if (argc < 1) 10111288Smckusick fatal("-d: missing %s", name); 10211288Smckusick argc--, argv++; 10311288Smckusick i = atoi(*argv); 10411288Smckusick fprintf(stdout, 10511288Smckusick "%s changes from %dms to %dms\n", 10611288Smckusick name, sblock.fs_rotdelay, i); 10711288Smckusick sblock.fs_rotdelay = i; 10811288Smckusick continue; 10911288Smckusick 11011288Smckusick case 'e': 11111288Smckusick name = 11211288Smckusick "maximum blocks per file in a cylinder group"; 11311288Smckusick if (argc < 1) 11411288Smckusick fatal("-e: missing %s", name); 11511288Smckusick argc--, argv++; 11611288Smckusick i = atoi(*argv); 11711288Smckusick if (i < 1) 11811288Smckusick fatal("%s: %s must be >= 1", 11911288Smckusick *argv, name); 12011288Smckusick fprintf(stdout, "%s changes from %d to %d\n", 12111288Smckusick name, sblock.fs_maxbpg, i); 12211288Smckusick sblock.fs_maxbpg = i; 12311288Smckusick continue; 12411288Smckusick 12511288Smckusick case 'm': 12611288Smckusick name = "minimum percentage of free space"; 12711288Smckusick if (argc < 1) 12811288Smckusick fatal("-m: missing %s", name); 12911288Smckusick argc--, argv++; 13011288Smckusick i = atoi(*argv); 13111288Smckusick if (i < 0 || i > 99) 13211288Smckusick fatal("%s: bad %s", *argv, name); 13311288Smckusick fprintf(stdout, 13411288Smckusick "%s changes from %d%% to %d%%\n", 13511288Smckusick name, sblock.fs_minfree, i); 13611288Smckusick sblock.fs_minfree = i; 13724704Smckusick if (i >= 10 && sblock.fs_optim == FS_OPTSPACE) 13824704Smckusick fprintf(stdout, "should optimize %s", 13924704Smckusick "for time with minfree >= 10%\n"); 14024704Smckusick if (i < 10 && sblock.fs_optim == FS_OPTTIME) 14124704Smckusick fprintf(stdout, "should optimize %s", 14224704Smckusick "for space with minfree < 10%\n"); 14311288Smckusick continue; 14411288Smckusick 14524700Smckusick case 'o': 14624700Smckusick name = "optimization preference"; 14724700Smckusick if (argc < 1) 14824700Smckusick fatal("-o: missing %s", name); 14924700Smckusick argc--, argv++; 15024700Smckusick chg[FS_OPTSPACE] = "space"; 15124700Smckusick chg[FS_OPTTIME] = "time"; 15224700Smckusick if (strcmp(*argv, chg[FS_OPTSPACE]) == 0) 15324700Smckusick i = FS_OPTSPACE; 15424700Smckusick else if (strcmp(*argv, chg[FS_OPTTIME]) == 0) 15524700Smckusick i = FS_OPTTIME; 15624700Smckusick else 15724700Smckusick fatal("%s: bad %s (options are `space' or `time')", 15824700Smckusick *argv, name); 15924700Smckusick if (sblock.fs_optim == i) { 16024700Smckusick fprintf(stdout, 16124700Smckusick "%s remains unchanged as %s\n", 16224700Smckusick name, chg[i]); 16324700Smckusick continue; 16424700Smckusick } 16524700Smckusick fprintf(stdout, 16624700Smckusick "%s changes from %s to %s\n", 16724700Smckusick name, chg[sblock.fs_optim], chg[i]); 16824700Smckusick sblock.fs_optim = i; 16924704Smckusick if (sblock.fs_minfree >= 10 && i == FS_OPTSPACE) 17024704Smckusick fprintf(stdout, "should optimize %s", 17124704Smckusick "for time with minfree >= 10%\n"); 17224704Smckusick if (sblock.fs_minfree < 10 && i == FS_OPTTIME) 17324704Smckusick fprintf(stdout, "should optimize %s", 17424704Smckusick "for space with minfree < 10%\n"); 17524700Smckusick continue; 17624700Smckusick 17711288Smckusick default: 17811288Smckusick fatal("-%c: unknown flag", *cp); 17911288Smckusick } 18011288Smckusick } 18111288Smckusick if (argc != 1) 18211288Smckusick goto usage; 18356210Shibler bwrite((daddr_t)SBOFF / dev_bsize, (char *)&sblock, SBSIZE); 18411288Smckusick if (Aflag) 18511288Smckusick for (i = 0; i < sblock.fs_ncg; i++) 18611288Smckusick bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)), 18711288Smckusick (char *)&sblock, SBSIZE); 18811288Smckusick close(fi); 18911288Smckusick exit(0); 19011288Smckusick usage: 19111288Smckusick fprintf(stderr, "Usage: tunefs tuneup-options special-device\n"); 19211288Smckusick fprintf(stderr, "where tuneup-options are:\n"); 19313555Ssam fprintf(stderr, "\t-a maximum contiguous blocks\n"); 19411288Smckusick fprintf(stderr, "\t-d rotational delay between contiguous blocks\n"); 19511288Smckusick fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); 19611288Smckusick fprintf(stderr, "\t-m minimum percentage of free space\n"); 19724700Smckusick fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); 19811288Smckusick exit(2); 19911288Smckusick } 20011288Smckusick 20111288Smckusick getsb(fs, file) 20211288Smckusick register struct fs *fs; 20311288Smckusick char *file; 20411288Smckusick { 20511288Smckusick 20611288Smckusick fi = open(file, 2); 20711288Smckusick if (fi < 0) { 20855659Sbostic fprintf(stderr, "tunefs: %s: %s\n", file, strerror(errno)); 20911288Smckusick exit(3); 21011288Smckusick } 21156210Shibler if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE)) { 21255659Sbostic fprintf(stderr, "tunefs: %s: bad super block\n", file); 21311288Smckusick exit(4); 21411288Smckusick } 21511288Smckusick if (fs->fs_magic != FS_MAGIC) { 21655659Sbostic fprintf(stderr, "tunefs: %s: bad magic number\n", file); 21711288Smckusick exit(5); 21811288Smckusick } 21930558Smckusick dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 22011288Smckusick } 22111288Smckusick 22211288Smckusick bwrite(blk, buf, size) 22311288Smckusick char *buf; 22411288Smckusick daddr_t blk; 22511288Smckusick register size; 22611288Smckusick { 227*58003Sralph if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0) { 22811288Smckusick perror("FS SEEK"); 22911288Smckusick exit(6); 23011288Smckusick } 23111288Smckusick if (write(fi, buf, size) != size) { 23211288Smckusick perror("FS WRITE"); 23311288Smckusick exit(7); 23411288Smckusick } 23511288Smckusick } 23611288Smckusick 23711288Smckusick bread(bno, buf, cnt) 23811288Smckusick daddr_t bno; 23911288Smckusick char *buf; 24011288Smckusick { 24111288Smckusick register i; 24211288Smckusick 243*58003Sralph if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0) 24411288Smckusick return(1); 24511288Smckusick if ((i = read(fi, buf, cnt)) != cnt) { 24611288Smckusick for(i=0; i<sblock.fs_bsize; i++) 24711288Smckusick buf[i] = 0; 24811288Smckusick return (1); 24911288Smckusick } 25011288Smckusick return (0); 25111288Smckusick } 25211288Smckusick 25311288Smckusick /* VARARGS1 */ 25411288Smckusick fatal(fmt, arg1, arg2) 25511288Smckusick char *fmt, *arg1, *arg2; 25611288Smckusick { 25711288Smckusick 25811295Ssam fprintf(stderr, "tunefs: "); 25911288Smckusick fprintf(stderr, fmt, arg1, arg2); 26011288Smckusick putc('\n', stderr); 26111288Smckusick exit(10); 26211288Smckusick } 263