tunefs.c revision 9315
11558Srgrimes/*
21558Srgrimes * Copyright (c) 1983, 1993
31558Srgrimes *	The Regents of the University of California.  All rights reserved.
41558Srgrimes *
51558Srgrimes * Redistribution and use in source and binary forms, with or without
61558Srgrimes * modification, are permitted provided that the following conditions
71558Srgrimes * are met:
81558Srgrimes * 1. Redistributions of source code must retain the above copyright
91558Srgrimes *    notice, this list of conditions and the following disclaimer.
101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111558Srgrimes *    notice, this list of conditions and the following disclaimer in the
121558Srgrimes *    documentation and/or other materials provided with the distribution.
131558Srgrimes * 3. All advertising materials mentioning features or use of this software
141558Srgrimes *    must display the following acknowledgement:
151558Srgrimes *	This product includes software developed by the University of
161558Srgrimes *	California, Berkeley and its contributors.
171558Srgrimes * 4. Neither the name of the University nor the names of its contributors
181558Srgrimes *    may be used to endorse or promote products derived from this software
191558Srgrimes *    without specific prior written permission.
201558Srgrimes *
211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311558Srgrimes * SUCH DAMAGE.
321558Srgrimes */
331558Srgrimes
341558Srgrimes#ifndef lint
351558Srgrimesstatic char copyright[] =
361558Srgrimes"@(#) Copyright (c) 1983, 1993\n\
371558Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381558Srgrimes#endif /* not lint */
391558Srgrimes
401558Srgrimes#ifndef lint
411558Srgrimesstatic char sccsid[] = "@(#)tunefs.c	8.2 (Berkeley) 4/19/94";
421558Srgrimes#endif /* not lint */
431558Srgrimes
441558Srgrimes/*
451558Srgrimes * tunefs: change layout parameters to an existing file system.
461558Srgrimes */
471558Srgrimes#include <sys/param.h>
481558Srgrimes#include <sys/stat.h>
491558Srgrimes
501558Srgrimes#include <ufs/ffs/fs.h>
511558Srgrimes
521558Srgrimes#include <errno.h>
531558Srgrimes#include <err.h>
541558Srgrimes#include <fcntl.h>
551558Srgrimes#include <fstab.h>
561558Srgrimes#include <stdio.h>
571558Srgrimes#include <paths.h>
581558Srgrimes#include <stdlib.h>
591558Srgrimes#include <unistd.h>
601558Srgrimes
611558Srgrimes/* the optimization warning string template */
621558Srgrimes#define	OPTWARN	"should optimize for %s with minfree %s %d%%"
631558Srgrimes
641558Srgrimesunion {
651558Srgrimes	struct	fs sb;
661558Srgrimes	char pad[MAXBSIZE];
671558Srgrimes} sbun;
681558Srgrimes#define	sblock sbun.sb
691558Srgrimes
701558Srgrimesint fi;
711558Srgrimeslong dev_bsize = 1;
721558Srgrimes
731558Srgrimesvoid bwrite(daddr_t, char *, int);
741558Srgrimesint bread(daddr_t, char *, int);
751558Srgrimesvoid getsb(struct fs *, char *);
761558Srgrimesvoid usage __P((void));
779315Sjoergvoid printfs __P((void));
781558Srgrimes
791558Srgrimesint
801558Srgrimesmain(argc, argv)
811558Srgrimes	int argc;
821558Srgrimes	char *argv[];
831558Srgrimes{
841558Srgrimes	char *cp, *special, *name;
851558Srgrimes	struct stat st;
861558Srgrimes	int i;
871558Srgrimes	int Aflag = 0;
881558Srgrimes	struct fstab *fs;
891558Srgrimes	char *chg[2], device[MAXPATHLEN];
901558Srgrimes
918871Srgrimes	argc--, argv++;
921558Srgrimes	if (argc < 2)
931558Srgrimes		usage();
941558Srgrimes	special = argv[argc - 1];
951558Srgrimes	fs = getfsfile(special);
961558Srgrimes	if (fs)
971558Srgrimes		special = fs->fs_spec;
981558Srgrimesagain:
991558Srgrimes	if (stat(special, &st) < 0) {
1001558Srgrimes		if (*special != '/') {
1011558Srgrimes			if (*special == 'r')
1021558Srgrimes				special++;
1031558Srgrimes			(void)sprintf(device, "%s/%s", _PATH_DEV, special);
1041558Srgrimes			special = device;
1051558Srgrimes			goto again;
1061558Srgrimes		}
1071558Srgrimes		err(1, "%s", special);
1081558Srgrimes	}
1091558Srgrimes	if ((st.st_mode & S_IFMT) != S_IFBLK &&
1101558Srgrimes	    (st.st_mode & S_IFMT) != S_IFCHR)
1111558Srgrimes		errx(10, "%s: not a block or character device", special);
1121558Srgrimes	getsb(&sblock, special);
1131558Srgrimes	for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
1141558Srgrimes		for (cp = &argv[0][1]; *cp; cp++)
1151558Srgrimes			switch (*cp) {
1161558Srgrimes
1171558Srgrimes			case 'A':
1181558Srgrimes				Aflag++;
1191558Srgrimes				continue;
1201558Srgrimes
1219315Sjoerg			case 'p':
1229315Sjoerg				printfs();
1239315Sjoerg				exit(0);
1249315Sjoerg
1251558Srgrimes			case 'a':
1261558Srgrimes				name = "maximum contiguous block count";
1271558Srgrimes				if (argc < 1)
1281558Srgrimes					errx(10, "-a: missing %s", name);
1291558Srgrimes				argc--, argv++;
1301558Srgrimes				i = atoi(*argv);
1311558Srgrimes				if (i < 1)
1321558Srgrimes					errx(10, "%s must be >= 1 (was %s)",
1331558Srgrimes					    name, *argv);
1341558Srgrimes				warnx("%s changes from %d to %d",
1351558Srgrimes				    name, sblock.fs_maxcontig, i);
1361558Srgrimes				sblock.fs_maxcontig = i;
1371558Srgrimes				continue;
1381558Srgrimes
1391558Srgrimes			case 'd':
1401558Srgrimes				name =
1411558Srgrimes				   "rotational delay between contiguous blocks";
1421558Srgrimes				if (argc < 1)
1431558Srgrimes					errx(10, "-d: missing %s", name);
1441558Srgrimes				argc--, argv++;
1451558Srgrimes				i = atoi(*argv);
1461558Srgrimes				warnx("%s changes from %dms to %dms",
1471558Srgrimes				    name, sblock.fs_rotdelay, i);
1481558Srgrimes				sblock.fs_rotdelay = i;
1491558Srgrimes				continue;
1501558Srgrimes
1511558Srgrimes			case 'e':
1521558Srgrimes				name =
1531558Srgrimes				  "maximum blocks per file in a cylinder group";
1541558Srgrimes				if (argc < 1)
1551558Srgrimes					errx(10, "-e: missing %s", name);
1561558Srgrimes				argc--, argv++;
1571558Srgrimes				i = atoi(*argv);
1581558Srgrimes				if (i < 1)
1591558Srgrimes					errx(10, "%s must be >= 1 (was %s)",
1601558Srgrimes					    name, *argv);
1611558Srgrimes				warnx("%s changes from %d to %d",
1621558Srgrimes				    name, sblock.fs_maxbpg, i);
1631558Srgrimes				sblock.fs_maxbpg = i;
1641558Srgrimes				continue;
1651558Srgrimes
1661558Srgrimes			case 'm':
1671558Srgrimes				name = "minimum percentage of free space";
1681558Srgrimes				if (argc < 1)
1691558Srgrimes					errx(10, "-m: missing %s", name);
1701558Srgrimes				argc--, argv++;
1711558Srgrimes				i = atoi(*argv);
1721558Srgrimes				if (i < 0 || i > 99)
1731558Srgrimes					errx(10, "bad %s (%s)", name, *argv);
1741558Srgrimes				warnx("%s changes from %d%% to %d%%",
1751558Srgrimes				    name, sblock.fs_minfree, i);
1761558Srgrimes				sblock.fs_minfree = i;
1771558Srgrimes				if (i >= MINFREE &&
1781558Srgrimes				    sblock.fs_optim == FS_OPTSPACE)
1791558Srgrimes					warnx(OPTWARN, "time", ">=", MINFREE);
1801558Srgrimes				if (i < MINFREE &&
1811558Srgrimes				    sblock.fs_optim == FS_OPTTIME)
1821558Srgrimes					warnx(OPTWARN, "space", "<", MINFREE);
1831558Srgrimes				continue;
1841558Srgrimes
1851558Srgrimes			case 'o':
1861558Srgrimes				name = "optimization preference";
1871558Srgrimes				if (argc < 1)
1881558Srgrimes					errx(10, "-o: missing %s", name);
1891558Srgrimes				argc--, argv++;
1901558Srgrimes				chg[FS_OPTSPACE] = "space";
1911558Srgrimes				chg[FS_OPTTIME] = "time";
1921558Srgrimes				if (strcmp(*argv, chg[FS_OPTSPACE]) == 0)
1931558Srgrimes					i = FS_OPTSPACE;
1941558Srgrimes				else if (strcmp(*argv, chg[FS_OPTTIME]) == 0)
1951558Srgrimes					i = FS_OPTTIME;
1961558Srgrimes				else
1971558Srgrimes					errx(10, "bad %s (options are `space' or `time')",
1981558Srgrimes					    name);
1991558Srgrimes				if (sblock.fs_optim == i) {
2001558Srgrimes					warnx("%s remains unchanged as %s",
2011558Srgrimes					    name, chg[i]);
2021558Srgrimes					continue;
2031558Srgrimes				}
2041558Srgrimes				warnx("%s changes from %s to %s",
2051558Srgrimes				    name, chg[sblock.fs_optim], chg[i]);
2061558Srgrimes				sblock.fs_optim = i;
2071558Srgrimes				if (sblock.fs_minfree >= MINFREE &&
2081558Srgrimes				    i == FS_OPTSPACE)
2091558Srgrimes					warnx(OPTWARN, "time", ">=", MINFREE);
2101558Srgrimes				if (sblock.fs_minfree < MINFREE &&
2111558Srgrimes				    i == FS_OPTTIME)
2121558Srgrimes					warnx(OPTWARN, "space", "<", MINFREE);
2131558Srgrimes				continue;
2141558Srgrimes
2151558Srgrimes			default:
2161558Srgrimes				usage();
2171558Srgrimes			}
2181558Srgrimes	}
2191558Srgrimes	if (argc != 1)
2201558Srgrimes		usage();
2211558Srgrimes	bwrite((daddr_t)SBOFF / dev_bsize, (char *)&sblock, SBSIZE);
2221558Srgrimes	if (Aflag)
2231558Srgrimes		for (i = 0; i < sblock.fs_ncg; i++)
2241558Srgrimes			bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)),
2251558Srgrimes			    (char *)&sblock, SBSIZE);
2261558Srgrimes	close(fi);
2271558Srgrimes	exit(0);
2281558Srgrimes}
2291558Srgrimes
2301558Srgrimesvoid
2311558Srgrimesusage()
2321558Srgrimes{
2331558Srgrimes
2341558Srgrimes	fprintf(stderr, "Usage: tunefs tuneup-options special-device\n");
2351558Srgrimes	fprintf(stderr, "where tuneup-options are:\n");
2361558Srgrimes	fprintf(stderr, "\t-a maximum contiguous blocks\n");
2371558Srgrimes	fprintf(stderr, "\t-d rotational delay between contiguous blocks\n");
2381558Srgrimes	fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
2391558Srgrimes	fprintf(stderr, "\t-m minimum percentage of free space\n");
2401558Srgrimes	fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
2419315Sjoerg	fprintf(stderr, "\t-p no change - just prints current tuneable settings\n");
2421558Srgrimes	exit(2);
2431558Srgrimes}
2441558Srgrimes
2451558Srgrimesvoid
2461558Srgrimesgetsb(fs, file)
2471558Srgrimes	register struct fs *fs;
2481558Srgrimes	char *file;
2491558Srgrimes{
2501558Srgrimes
2511558Srgrimes	fi = open(file, 2);
2521558Srgrimes	if (fi < 0)
2531558Srgrimes		err(3, "cannot open %s", file);
2541558Srgrimes	if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE))
2551558Srgrimes		err(4, "%s: bad super block", file);
2561558Srgrimes	if (fs->fs_magic != FS_MAGIC)
2571558Srgrimes		err(5, "%s: bad magic number", file);
2581558Srgrimes	dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
2591558Srgrimes}
2601558Srgrimes
2611558Srgrimesvoid
2629315Sjoergprintfs()
2639315Sjoerg{
2649315Sjoerg	warnx("maximum contiguous block count: (-a)               %d",
2659315Sjoerg	      sblock.fs_maxcontig);
2669315Sjoerg	warnx("rotational delay between contiguous blocks: (-d)   %d ms",
2679315Sjoerg	      sblock.fs_rotdelay);
2689315Sjoerg	warnx("maximum blocks per file in a cylinder group: (-e)  %d",
2699315Sjoerg	      sblock.fs_maxbpg);
2709315Sjoerg	warnx("minimum percentage of free space: (-m)             %d%%",
2719315Sjoerg	      sblock.fs_minfree);
2729315Sjoerg	warnx("optimization preference: (-o)                      %s",
2739315Sjoerg	      sblock.fs_optim == FS_OPTSPACE ? "space" : "time");
2749315Sjoerg	if (sblock.fs_minfree >= MINFREE &&
2759315Sjoerg	    sblock.fs_optim == FS_OPTSPACE)
2769315Sjoerg		warnx(OPTWARN, "time", ">=", MINFREE);
2779315Sjoerg	if (sblock.fs_minfree < MINFREE &&
2789315Sjoerg	    sblock.fs_optim == FS_OPTTIME)
2799315Sjoerg		warnx(OPTWARN, "space", "<", MINFREE);
2809315Sjoerg}
2819315Sjoerg
2829315Sjoergvoid
2831558Srgrimesbwrite(blk, buf, size)
2841558Srgrimes	daddr_t blk;
2851558Srgrimes	char *buf;
2861558Srgrimes	int size;
2871558Srgrimes{
2881558Srgrimes
2891558Srgrimes	if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0)
2901558Srgrimes		err(6, "FS SEEK");
2911558Srgrimes	if (write(fi, buf, size) != size)
2921558Srgrimes		err(7, "FS WRITE");
2931558Srgrimes}
2941558Srgrimes
2951558Srgrimesint
2961558Srgrimesbread(bno, buf, cnt)
2971558Srgrimes	daddr_t bno;
2981558Srgrimes	char *buf;
2991558Srgrimes	int cnt;
3001558Srgrimes{
3011558Srgrimes	int i;
3021558Srgrimes
3031558Srgrimes	if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0)
3041558Srgrimes		return(1);
3051558Srgrimes	if ((i = read(fi, buf, cnt)) != cnt) {
3061558Srgrimes		for(i=0; i<sblock.fs_bsize; i++)
3071558Srgrimes			buf[i] = 0;
3081558Srgrimes		return (1);
3091558Srgrimes	}
3101558Srgrimes	return (0);
3111558Srgrimes}
312