- add -F; indicates "special" is a file system image in a regular file

- reorder "special" validation to after option parsing
- use getopt(3) instead of homegrown code
- add getnum() to parse and validate a number
- clean up man page
- ansi KNF, WARNS=2
This commit is contained in:
lukem 2001-08-19 09:39:24 +00:00
parent e04fd20395
commit 5157971af5
3 changed files with 234 additions and 212 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.9 1999/01/15 13:32:06 bouyer Exp $
# $NetBSD: Makefile,v 1.10 2001/08/19 09:39:24 lukem Exp $
# @(#)Makefile 8.1 (Berkeley) 6/5/93
PROG= tunefs
@ -6,4 +6,6 @@ MAN= tunefs.8
SRCS= tunefs.c ffs_bswap.c
.PATH: ${.CURDIR}/../../sys/ufs/ffs
WARNS?=2
.include <bsd.prog.mk>

View File

@ -1,4 +1,4 @@
.\" $NetBSD: tunefs.8,v 1.22 2001/06/05 11:22:54 wiz Exp $
.\" $NetBSD: tunefs.8,v 1.23 2001/08/19 09:39:24 lukem Exp $
.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -33,7 +33,7 @@
.\"
.\" @(#)tunefs.8 8.3 (Berkeley) 5/3/95
.\"
.Dd May 3, 1995
.Dd August 19, 2001
.Dt TUNEFS 8
.Os
.Sh NAME
@ -41,7 +41,7 @@
.Nd tune up an existing file system
.Sh SYNOPSIS
.Nm ""
.Op Fl AN
.Op Fl AFN
.Op Fl a Ar maxcontig
.Op Fl d Ar rotdelay
.Op Fl e Ar maxbpg
@ -51,34 +51,36 @@
.Op Fl o Ar optimize_preference
.Ek
.Op Fl t Ar trackskew
.Op Ar special | Ar filesys
.Ar special | Ar filesys
.Sh DESCRIPTION
.Nm
is designed to change the dynamic parameters of a file system
which affect the layout policies.
The
.Fl N
flag displays all the settable options
(after any changes from the tuning options)
but does not cause any of them to be changed.
The
.Fl A
flag causes the values to be updated in all the alternate
.Pp
The following options are supported by
.Nm "" :
.Bl -tag -width Ds
.It Fl A
Cause the values to be updated in all the alternate
superblocks instead of just the standard superblock.
If this option is not used,
then use of a backup superblock by
.Xr fsck 8
will lose anything changed by
.Nm "" .
The
.Fl A
flag is ignored when the
is ignored when
.Fl N
flag is specified.
.Pp
The parameters which are to be changed are indicated by the flags
given below:
.Bl -tag -width Ds
is specified.
.It Fl F
Indicates that
.Ar special
is a file system image in a regular file, rather than a special device
or file system mount point.
.It Fl N
Display all the settable options
(after any changes from the tuning options)
but do not cause any of them to be changed.
.It Fl a Ar maxcontig
This specifies the maximum number of contiguous blocks that will
be laid out before forcing a rotational delay (see
@ -120,13 +122,13 @@ Note that if the value is raised above the current usage level,
users will be unable to allocate files until enough files have
been deleted to get under the higher threshold.
.\" .It Fl n Ar soft_dependency_enabling
.\" The soft dependency code allows most filesystem I/O to be done
.\" The soft dependency code allows most file system I/O to be done
.\" asynchronously by reordering dependant writes to ensure that the
.\" on-disk metadata is self-consistent even when updates are deferred.
.\" Additionally, metadata updates are aggregated, reducing the total
.\" number of writes performed.
.\" Use of this facility does not require any changes to the filesystem,
.\" so it can be enabled or disabled any time that the filesystem is unmounted.
.\" Use of this facility does not require any changes to the file system,
.\" so it can be enabled or disabled any time that the file system is unmounted.
.\" This experimental facility is turned off by default.
.\" It is turned on by using
.\" .Fl n
@ -176,7 +178,7 @@ the same rotational position.
This program should work on mounted and active file systems.
Because the super-block is not kept in the buffer cache,
the changes will only take effect if the program
is run on dismounted file systems.
is run on unmounted file systems.
To change the root file system, the system must be rebooted
after the file system is tuned.
.Pp

View File

@ -1,4 +1,4 @@
/* $NetBSD: tunefs.c,v 1.21 2001/08/17 02:18:48 lukem Exp $ */
/* $NetBSD: tunefs.c,v 1.22 2001/08/19 09:39:24 lukem Exp $ */
/*
* Copyright (c) 1983, 1993
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\
#if 0
static char sccsid[] = "@(#)tunefs.c 8.3 (Berkeley) 5/3/95";
#else
__RCSID("$NetBSD: tunefs.c,v 1.21 2001/08/17 02:18:48 lukem Exp $");
__RCSID("$NetBSD: tunefs.c,v 1.22 2001/08/19 09:39:24 lukem Exp $");
#endif
#endif /* not lint */
@ -59,12 +59,12 @@ __RCSID("$NetBSD: tunefs.c,v 1.21 2001/08/17 02:18:48 lukem Exp $");
#include <machine/bswap.h>
#include <errno.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <fstab.h>
#include <stdio.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@ -79,42 +79,124 @@ union {
#define sblock sbun.sb
char buf[MAXBSIZE];
int fi;
long dev_bsize = 1;
int needswap = 0;
int fi;
long dev_bsize = 1;
int needswap = 0;
void bwrite __P((daddr_t, char *, int));
int bread __P((daddr_t, char *, int));
void getsb __P((struct fs *, const char *));
int main __P((int, char *[]));
void usage __P((void));
static void bwrite(daddr_t, char *, int);
static int bread(daddr_t, char *, int);
static int getnum(const char *, const char *, int, int);
static void getsb(struct fs *, const char *);
static void usage(void);
int main(int, char *[]);
int
main(argc, argv)
int argc;
char *argv[];
main(int argc, char *argv[])
{
char *cp, *name;
#ifdef TUNEFS_SOFTDEP
char *action;
int softdep;
#define OPTSTRING "AFNa:d:e:m:n:o:t:"
#else
#define OPTSTRING "AFNa:d:e:m:o:t:"
#endif
const char *special;
struct stat st;
int i;
int Aflag = 0, Nflag = 0;
struct fstab *fs;
char *chg[2], device[MAXPATHLEN];
struct stat st;
int i, ch, Aflag, Fflag, Nflag;
struct fstab *fs;
const char *special, *chg[2];
char device[MAXPATHLEN];
int maxbpg, maxcontig, minfree, rotdelay, optim, trackskew;
argc--, argv++;
if (argc < 2)
Aflag = Fflag = Nflag = 0;
maxbpg = maxcontig = minfree = rotdelay = optim = trackskew = -1;
#ifdef TUNEFS_SOFTDEP
softdep = -1;
#endif
chg[FS_OPTSPACE] = "space";
chg[FS_OPTTIME] = "time";
while ((ch = getopt(argc, argv, OPTSTRING)) != -1) {
switch (ch) {
case 'A':
Aflag++;
break;
case 'F':
Fflag++;
break;
case 'N':
Nflag++;
break;
case 'a':
maxcontig = getnum(optarg,
"maximum contiguous block count", 1, INT_MAX);
break;
case 'd':
rotdelay = getnum(optarg,
"rotational delay between contiguous blocks",
0, INT_MAX);
break;
case 'e':
maxbpg = getnum(optarg,
"maximum blocks per file in a cylinder group",
1, INT_MAX);
break;
case 'm':
minfree = getnum(optarg,
"minimum percentage of free space", 0, 99);
break;
#ifdef TUNEFS_SOFTDEP
case 'n':
if (strcmp(optarg, "enable") == 0)
softdep = 1;
else if (strcmp(optarg, "disable") == 0)
softdep = 0;
else {
errx(10, "bad soft dependencies "
"(options are `enable' or `disable')");
}
break;
#endif
case 'o':
if (strcmp(optarg, chg[FS_OPTSPACE]) == 0)
optim = FS_OPTSPACE;
else if (strcmp(optarg, chg[FS_OPTTIME]) == 0)
optim = FS_OPTTIME;
else
errx(10,
"bad %s (options are `space' or `time')",
"optimization preference");
break;
case 't':
trackskew = getnum(optarg,
"track skew in sectors", 0, INT_MAX);
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc != 1)
usage();
special = argv[argc - 1];
special = argv[0];
fs = getfsfile(special);
if (fs)
special = fs->fs_spec;
again:
again:
if (stat(special, &st) < 0) {
if (*special != '/') {
if (!Fflag && *special != '/') {
if (*special == 'r')
special++;
(void)snprintf(device, sizeof(device), "%s/%s",
@ -124,152 +206,78 @@ again:
}
err(1, "%s", special);
}
if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
if (Fflag) {
if (!S_ISREG(st.st_mode))
errx(10, "%s: not a regular file", special);
} else if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
errx(10, "%s: not a block or character device", special);
getsb(&sblock, special);
chg[FS_OPTSPACE] = "space";
chg[FS_OPTTIME] = "time";
for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
for (cp = &argv[0][1]; *cp; cp++)
switch (*cp) {
case 'A':
Aflag++;
continue;
case 'N':
Nflag++;
continue;
case 'a':
name = "maximum contiguous block count";
if (argc < 1)
errx(10, "-a: missing %s", name);
argc--, argv++;
i = atoi(*argv);
if (i < 1)
errx(10, "%s must be >= 1 (was %s)",
name, *argv);
warnx("%s changes from %d to %d",
name, sblock.fs_maxcontig, i);
sblock.fs_maxcontig = i;
continue;
case 'd':
name =
"rotational delay between contiguous blocks";
if (argc < 1)
errx(10, "-d: missing %s", name);
argc--, argv++;
i = atoi(*argv);
warnx("%s changes from %dms to %dms",
name, sblock.fs_rotdelay, i);
sblock.fs_rotdelay = i;
continue;
case 'e':
name =
"maximum blocks per file in a cylinder group";
if (argc < 1)
errx(10, "-e: missing %s", name);
argc--, argv++;
i = atoi(*argv);
if (i < 1)
errx(10, "%s must be >= 1 (was %s)",
name, *argv);
warnx("%s changes from %d to %d",
name, sblock.fs_maxbpg, i);
sblock.fs_maxbpg = i;
continue;
case 'm':
name = "minimum percentage of free space";
if (argc < 1)
errx(10, "-m: missing %s", name);
argc--, argv++;
i = atoi(*argv);
if (i < 0 || i > 99)
errx(10, "bad %s (%s)", name, *argv);
warnx("%s changes from %d%% to %d%%",
name, sblock.fs_minfree, i);
sblock.fs_minfree = i;
if (i >= MINFREE &&
sblock.fs_optim == FS_OPTSPACE)
warnx(OPTWARN, "time", ">=", MINFREE);
if (i < MINFREE &&
sblock.fs_optim == FS_OPTTIME)
warnx(OPTWARN, "space", "<", MINFREE);
continue;
#ifdef TUNEFS_SOFTDEP
case 'n':
name = "soft dependencies";
if (argc < 1)
errx(10, "-n: missing %s", name);
argc--, argv++;
if (strcmp(*argv, "enable") == 0) {
sblock.fs_flags |= FS_DOSOFTDEP;
action = "set";
} else if (strcmp(*argv, "disable") == 0) {
sblock.fs_flags &= ~FS_DOSOFTDEP;
action = "cleared";
} else {
errx(10, "bad %s (options are %s)",
name, "`enable' or `disable'");
}
warnx("%s %s", name, action);
continue;
#endif
case 'o':
name = "optimization preference";
if (argc < 1)
errx(10, "-o: missing %s", name);
argc--, argv++;
if (strcmp(*argv, chg[FS_OPTSPACE]) == 0)
i = FS_OPTSPACE;
else if (strcmp(*argv, chg[FS_OPTTIME]) == 0)
i = FS_OPTTIME;
else
errx(10, "bad %s (options are `space' or `time')",
name);
if (sblock.fs_optim == i) {
warnx("%s remains unchanged as %s",
name, chg[i]);
continue;
}
warnx("%s changes from %s to %s",
name, chg[sblock.fs_optim], chg[i]);
sblock.fs_optim = i;
if (sblock.fs_minfree >= MINFREE &&
i == FS_OPTSPACE)
warnx(OPTWARN, "time", ">=", MINFREE);
if (sblock.fs_minfree < MINFREE &&
i == FS_OPTTIME)
warnx(OPTWARN, "space", "<", MINFREE);
continue;
case 't':
name = "track skew in sectors";
if (argc < 1)
errx(10, "-t: missing %s", name);
argc--, argv++;
i = atoi(*argv);
if (i < 0)
errx(10, "%s: %s must be >= 0",
*argv, name);
warnx("%s changes from %d to %d",
name, sblock.fs_trackskew, i);
sblock.fs_trackskew = i;
continue;
default:
usage();
}
if (maxcontig != -1) {
warnx("%s changes from %d to %d",
"maximum contiguous block count",
sblock.fs_maxcontig, maxcontig);
sblock.fs_maxcontig = maxcontig;
}
if (argc != 1)
usage();
if (rotdelay != -1) {
warnx("%s changes from %dms to %dms",
"rotational delay between contiguous blocks",
sblock.fs_rotdelay, rotdelay);
sblock.fs_rotdelay = rotdelay;
}
if (maxbpg != -1) {
warnx("%s changes from %d to %d",
"maximum blocks per file in a cylinder group",
sblock.fs_maxbpg, maxbpg);
sblock.fs_maxbpg = maxbpg;
}
if (minfree != -1) {
warnx("%s changes from %d%% to %d%%",
"minimum percentage of free space",
sblock.fs_minfree, minfree);
sblock.fs_minfree = minfree;
if (minfree >= MINFREE &&
sblock.fs_optim == FS_OPTSPACE)
warnx(OPTWARN, "time", ">=", MINFREE);
if (minfree < MINFREE &&
sblock.fs_optim == FS_OPTTIME)
warnx(OPTWARN, "space", "<", MINFREE);
}
#ifdef TUNEFS_SOFTDEP
if (softdep == 1) {
sblock.fs_flags |= FS_DOSOFTDEP;
warnx("soft dependencies set");
} else if (softdep == 0) {
sblock.fs_flags &= ~FS_DOSOFTDEP;
warnx("soft dependencies cleared");
}
#endif
if (optim != -1) {
if (sblock.fs_optim == optim) {
warnx("%s remains unchanged as %s",
"optimization preference",
chg[optim]);
} else {
warnx("%s changes from %s to %s",
"optimization preference",
chg[sblock.fs_optim], chg[optim]);
sblock.fs_optim = optim;
if (sblock.fs_minfree >= MINFREE &&
optim == FS_OPTSPACE)
warnx(OPTWARN, "time", ">=", MINFREE);
if (sblock.fs_minfree < MINFREE &&
optim == FS_OPTTIME)
warnx(OPTWARN, "space", "<", MINFREE);
}
}
if (trackskew != -1) {
warnx("%s changes from %d to %d",
"track skew in sectors", sblock.fs_trackskew, trackskew);
sblock.fs_trackskew = trackskew;
}
if (Nflag) {
fprintf(stdout, "tunefs: current settings\n");
fprintf(stdout, "tunefs: current settings of %s\n", special);
fprintf(stdout, "\tmaximum contiguous block count %d\n",
sblock.fs_maxcontig);
fprintf(stdout,
@ -291,6 +299,7 @@ again:
fprintf(stdout, "tunefs: no changes made\n");
exit(0);
}
fi = open(special, 1);
if (fi < 0)
err(3, "cannot open %s for writing", special);
@ -306,11 +315,27 @@ again:
exit(0);
}
void
usage()
static int
getnum(const char *num, const char *desc, int min, int max)
{
long n;
char *ep;
n = strtol(num, &ep, 10);
if (ep[0] != '\0')
errx(1, "Invalid number `%s' for %s", num, desc);
if ((int) n < min)
errx(1, "%s `%s' too small (minimum is %d)", desc, num, min);
if ((int) n > max)
errx(1, "%s `%s' too large (maximum is %d)", desc, num, max);
return ((int)n);
}
static void
usage(void)
{
fprintf(stderr, "Usage: tunefs [-AN] tuneup-options special-device\n");
fprintf(stderr, "Usage: tunefs [-AFN] tuneup-options special-device\n");
fprintf(stderr, "where tuneup-options are:\n");
fprintf(stderr, "\t-d rotational delay between contiguous blocks\n");
fprintf(stderr, "\t-a maximum contiguous blocks\n");
@ -324,10 +349,8 @@ usage()
exit(2);
}
void
getsb(fs, file)
struct fs *fs;
const char *file;
static void
getsb(struct fs *fs, const char *file)
{
fi = open(file, 0);
@ -337,6 +360,7 @@ getsb(fs, file)
err(4, "%s: bad super block", file);
if (fs->fs_magic != FS_MAGIC) {
if (fs->fs_magic == bswap32(FS_MAGIC)) {
warnx("%s: swapping byte order", file);
needswap = 1;
ffs_sb_swap(fs, fs);
} else
@ -346,30 +370,24 @@ getsb(fs, file)
close(fi);
}
void
bwrite(blk, buf, size)
daddr_t blk;
char *buf;
int size;
static void
bwrite(daddr_t blk, char *buffer, int size)
{
if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0)
err(6, "FS SEEK");
if (write(fi, buf, size) != size)
if (write(fi, buffer, size) != size)
err(7, "FS WRITE");
}
int
bread(bno, buf, cnt)
daddr_t bno;
char *buf;
int cnt;
static int
bread(daddr_t bno, char *buffer, int cnt)
{
int i;
if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0)
return(1);
if ((i = read(fi, buf, cnt)) != cnt) {
if ((i = read(fi, buffer, cnt)) != cnt) {
for(i=0; i<sblock.fs_bsize; i++)
buf[i] = 0;
return (1);