diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2007-05-02 14:39:13 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2007-05-02 14:39:13 +0000 |
commit | 2112e11d99b1de106544d481008605b9060c59f2 (patch) | |
tree | 1c9d9880fa34ed48d3249bbe554385d81f8cd309 /sbin | |
parent | 9cd9e4fbaef004550217e3b63ec931cd00d618ce (diff) |
FFS2 savvy tunefs from NetBSD. Some cleanup will be done after this.
ok millert@ and jmc@ for the man page.
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/tunefs/Makefile | 4 | ||||
-rw-r--r-- | sbin/tunefs/tunefs.8 | 134 | ||||
-rw-r--r-- | sbin/tunefs/tunefs.c | 555 |
3 files changed, 353 insertions, 340 deletions
diff --git a/sbin/tunefs/Makefile b/sbin/tunefs/Makefile index ccec3d53ab6..29531d273a3 100644 --- a/sbin/tunefs/Makefile +++ b/sbin/tunefs/Makefile @@ -1,6 +1,8 @@ -# $OpenBSD: Makefile,v 1.3 1997/09/21 11:38:23 deraadt Exp $ +# $OpenBSD: Makefile,v 1.4 2007/05/02 14:39:12 otto Exp $ PROG= tunefs MAN= tunefs.8 +DPADD= ${LIBUTIL} +LDADD= -lutil .include <bsd.prog.mk> diff --git a/sbin/tunefs/tunefs.8 b/sbin/tunefs/tunefs.8 index 5ab03fd23ad..351787054ce 100644 --- a/sbin/tunefs/tunefs.8 +++ b/sbin/tunefs/tunefs.8 @@ -1,5 +1,5 @@ -.\" $OpenBSD: tunefs.8,v 1.22 2004/07/28 21:27:52 jmc Exp $ -.\" $NetBSD: tunefs.8,v 1.8 1995/03/18 15:01:29 cgd Exp $ +.\" $OpenBSD: tunefs.8,v 1.23 2007/05/02 14:39:12 otto Exp $ +.\" $NetBSD: tunefs.8,v 1.36 2004/12/20 10:28:47 hubertf Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -28,61 +28,57 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" @(#)tunefs.8 8.2 (Berkeley) 12/11/93 +.\" @(#)tunefs.8 8.3 (Berkeley) 5/3/95 .\" -.Dd December 11, 1993 +.Dd April 26, 2004 .Dt TUNEFS 8 .Os .Sh NAME .Nm tunefs .Nd tune up an existing file system .Sh SYNOPSIS -.Nm tunefs -.Op Fl Ap -.Op Fl a Ar maxcontig -.Op Fl d Ar rotdelay +.Nm +.Op Fl AFN .Op Fl e Ar maxbpg -.Op Fl f Ar avgfilesize -.Bk -words +.Op Fl g Ar avgfilesize +.Op Fl h Ar avgfpdir .Op Fl m Ar minfree -.Ek -.Op Fl n Ar avgfpdir .Bk -words +.\" .Op Fl n Ar soft_dependency_enabling .Op Fl o Ar optimize_preference .Ek -.Bk -words -.Op Ar special | Ar filesys -.Ek +.Ar special | Ar filesys .Sh DESCRIPTION .Nm is designed to change the dynamic parameters of a file system which affect the layout policies. -The parameters which are to be changed are indicated by the flags -given below: +.Pp +The following options are supported by +.Nm : .Bl -tag -width Ds .It Fl A -The file system has several backups of the super-block. -Specifying this option will cause all backups to be modified as well as the -primary super-block. -This is potentially dangerous - use with caution. -.It Fl a Ar maxcontig -This specifies the maximum number of contiguous blocks that will -be laid out before forcing a rotational delay (see -.Fl d -below). -The default value depends on the block size -(4 for 16KB blocks, 8 for 8KB blocks and 16 for 4KB blocks). -Most device drivers can chain several buffers together in a single transfer. -For optimal performance, the value of -.Ar maxcontig -should be chosen based on the maximum chain length supported by -the device driver. -.It Fl d Ar rotdelay -This specifies the expected time (in milliseconds) -to service a transfer completion -interrupt and initiate a new transfer on the same disk. -It is used to decide how much rotational spacing to place between -successive blocks in a file. +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 . +.Fl A +is ignored when +.Fl N +is specified. +.It Fl F +Indicates that +.Ar special +is a file system image, rather than a device name or file system mount point. +.Ar special +will be accessed +.Sq as-is . +.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 e Ar maxbpg This indicates the maximum number of blocks any single file can allocate out of a cylinder group before it is forced to begin @@ -98,68 +94,42 @@ more frequently than if they were allowed to allocate all the blocks in a cylinder group before seeking elsewhere. For file systems with exclusively large files, this parameter should be set higher. -.It Fl f Ar avgfilesize -Specifies the expected average file size in bytes. -This value could be used for various optimizations, but for now it is only -used together with -.Ar avgfpdir -to optimize the directory allocation policy. -To take effect, both -.Ar avgfpdir -and -.Ar avgfilesize -must be greater than zero. -(Also see -.Ar avgfpdir . ) +.It Fl g Ar avgfilesize +This specifies the expected average file size. +.It Fl h Ar avgfpdir +This specifies the expected number of files per directory. .It Fl m Ar minfree This value specifies the percentage of space held back from normal users; the minimum free space threshold. -The default value used is 5%. -This value can be set to zero; however, a factor of up to three +The default value is set during creation of the filesystem, see +.Xr newfs 8 . +This value can be set to zero, however up to a factor of three in throughput will be lost over the performance obtained at a 5% threshold. 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 avgfpdir -Specifies the expected average number of files per directory in -the file system. -This value is used only if both -.Ar avgfilesize -and -.Ar avgfpdir -are greater than zero. -It is used to limit number of directories which may be allocated one after -another in the same cylinder group without intervention by regular files. -This value does not affect most file system operations but is useful for -applications which at first create a directory structure and then populate -with files later. -(Also see -.Ar avgfilesize . ) .It Fl o Ar optimize_preference The file system can either try to minimize the time spent allocating blocks, or it can attempt to minimize the space fragmentation on the disk. -If the value of -.Ar minfree -(see above) is less than 5%, +If the value of minfree (see above) is less than 5%, then the file system should optimize for space to avoid running out of full sized blocks. -For values of -.Ar minfree -greater than or equal to 5%, +For values of minfree greater than or equal to 5%, fragmentation is unlikely to be problematical, and the file system can be optimized for time. -.It Fl p -This option shows a summary of what the current tuneable settings -are on the selected file system. -More detailed information can be obtained in the -.Xr dumpfs 8 -manual page. +.Pp +.Ar optimize_preference +can be specified as either +.Li space +or +.Li time . .El .Sh SEE ALSO .Xr fs 5 , .Xr dumpfs 8 , +.Xr fsck_ffs 8 , .Xr growfs 8 , .Xr newfs 8 .Rs @@ -183,7 +153,7 @@ command appeared in 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 diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c index 02e69aa93e4..a9208fe9b67 100644 --- a/sbin/tunefs/tunefs.c +++ b/sbin/tunefs/tunefs.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tunefs.c,v 1.23 2003/07/10 00:00:58 david Exp $ */ -/* $NetBSD: tunefs.c,v 1.10 1995/03/18 15:01:31 cgd Exp $ */ +/* $OpenBSD */ +/* $NetBSD: tunefs.c,v 1.33 2005/01/19 20:46:16 xtraeme Exp $ */ /* * Copyright (c) 1983, 1993 @@ -38,10 +38,9 @@ static const char copyright[] = #ifndef lint #if 0 -static char sccsid[] = "@(#)tunefs.c 8.2 (Berkeley) 4/19/94"; +static char sccsid[] = "@(#)tunefs.c 8.3 (Berkeley) 5/3/95"; #else -static const char rcsid[] = - "$OpenBSD: tunefs.c,v 1.23 2003/07/10 00:00:58 david Exp $"; +static const char rcsid[] = "$OpenBSD"; #endif #endif /* not lint */ @@ -49,19 +48,21 @@ static const char rcsid[] = * tunefs: change layout parameters to an existing file system. */ #include <sys/param.h> -#include <sys/stat.h> +#include <ufs/ufs/dinode.h> #include <ufs/ffs/fs.h> +#include <ufs/ffs/ffs_extern.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> +#include <util.h> /* the optimization warning string template */ #define OPTWARN "should optimize for %s with minfree %s %d%%" @@ -71,289 +72,329 @@ union { char pad[MAXBSIZE]; } sbun; #define sblock sbun.sb +char buf[MAXBSIZE]; -int fi = -1; -long dev_bsize = 1; +int fi; +long dev_bsize = 512; +int is_ufs2 = 0; +off_t sblockloc; -void bwrite(daddr_t, char *, int); -int bread(daddr_t, char *, int); -void getsb(struct fs *, char *, int); -void usage(void); -void printfs(void); +static off_t sblock_try[] = SBLOCKSEARCH; -extern char *__progname; +static void bwrite(daddr_t, char *, int, const char *); +static void bread(daddr_t, char *, int, const char *); +static int getnum(const char *, const char *, int, int); +static void getsb(struct fs *, const char *); +static int openpartition(const char *, int, char *, size_t); +static void usage(void); int main(int argc, char *argv[]) { - char *cp, *special, *name; - struct stat st; - int i; - int Aflag = 0; - struct fstab *fs; - char *chg[2], device[MAXPATHLEN]; +#define OPTSTRINGBASE "AFNe:g:h:m:o:" +#ifdef TUNEFS_SOFTDEP + int softdep; +#define OPTSTRING OPTSTRINGBASE ## "n:" +#else +#define OPTSTRING OPTSTRINGBASE +#endif + int i, ch, Aflag, Fflag, Nflag, openflags; + const char *special, *chg[2]; + char device[MAXPATHLEN]; + int maxbpg, minfree, optim; + int avgfilesize, avgfpdir; + + Aflag = Fflag = Nflag = 0; + maxbpg = minfree = optim = -1; + avgfilesize = avgfpdir = -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 'e': + maxbpg = getnum(optarg, + "maximum blocks per file in a cylinder group", + 1, INT_MAX); + break; + + case 'g': + avgfilesize = getnum(optarg, + "average file size", 1, INT_MAX); + break; + + case 'h': + avgfpdir = getnum(optarg, + "expected number of files per directory", + 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 - argc--, argv++; - if (argc < 2) - usage(); - special = argv[argc - 1]; - fs = getfsfile(special); - if (fs) - special = fs->fs_spec; -again: - if (stat(special, &st) < 0) { - if (*special != '/') { - if (*special == 'r') - special++; - (void)snprintf(device, sizeof(device), "%s%s", - _PATH_DEV, special); - special = device; - goto again; + 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; + + default: + usage(); } - err(1, "%s", special); - } - if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) - errx(10, "%s: not a block or character device", special); - for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) { - for (cp = &argv[0][1]; *cp; cp++) - switch (*cp) { - - case 'A': - Aflag++; - continue; - - case 'p': - getsb(&sblock, special, O_RDONLY); - printfs(); - return (0); - - case 'a': - getsb(&sblock, special, O_RDWR); - 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': - getsb(&sblock, special, O_RDWR); - 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': - getsb(&sblock, special, O_RDWR); - 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 'f': - getsb(&sblock, special, O_RDWR); - name = "average file size"; - if (argc < 1) - errx(10, "-f: missing %s", name); - argc--, argv++; - i = atoi(*argv); - if (i < 0) - errx(10, "%s must be >= 0 (was %s)", - name, *argv); - warnx("%s changes from %d to %d", - name, sblock.fs_avgfilesize, i); - sblock.fs_avgfilesize = i; - continue; - - case 'm': - getsb(&sblock, special, O_RDWR); - 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; - - case 'n': - getsb(&sblock, special, O_RDWR); - name = "expected number of files per directory"; - if (argc < 1) - errx(10, "-n: missing %s", name); - argc--, argv++; - i = atoi(*argv); - if (i < 0) - errx(10, "%s must be >= 0 (was %s)", - name, *argv); - warnx("%s changes from %d to %d", - name, sblock.fs_avgfpdir, i); - sblock.fs_avgfpdir = i; - continue; - - case 's': - errx(1, "See mount(8) for details about" - " how to enable soft updates."); - - case 'o': - getsb(&sblock, special, O_RDWR); - name = "optimization preference"; - if (argc < 1) - errx(10, "-o: missing %s", name); - argc--, argv++; - chg[FS_OPTSPACE] = "space"; - chg[FS_OPTTIME] = "time"; - 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; - - default: - usage(); - } } + argc -= optind; + argv += optind; if (argc != 1) usage(); - bwrite((daddr_t)SBOFF / dev_bsize, (char *)&sblock, SBSIZE); + + special = argv[0]; + openflags = Nflag ? O_RDONLY : O_RDWR; + if (Fflag) + fi = open(special, openflags); + else { + fi = openpartition(special, openflags, device, sizeof(device)); + special = device; + } + if (fi == -1) + err(1, "%s", special); + getsb(&sblock, special); + +#define CHANGEVAL(old, new, type, suffix) do \ + if ((new) != -1) { \ + if ((new) == (old)) \ + warnx("%s remains unchanged at %d%s", \ + (type), (old), (suffix)); \ + else { \ + warnx("%s changes from %d%s to %d%s", \ + (type), (old), (suffix), (new), (suffix)); \ + (old) = (new); \ + } \ + } while (/* CONSTCOND */0) + + warnx("tuning %s", special); + CHANGEVAL(sblock.fs_maxbpg, maxbpg, + "maximum blocks per file in a cylinder group", ""); + CHANGEVAL(sblock.fs_minfree, minfree, + "minimum percentage of free space", "%"); + if (minfree != -1) { + 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); + } + } + CHANGEVAL(sblock.fs_avgfilesize, avgfilesize, + "average file size", ""); + CHANGEVAL(sblock.fs_avgfpdir, avgfpdir, + "expected number of files per directory", ""); + + if (Nflag) { + fprintf(stdout, "tunefs: current settings of %s\n", special); + fprintf(stdout, "\tmaximum contiguous block count %d\n", + sblock.fs_maxcontig); + fprintf(stdout, + "\tmaximum blocks per file in a cylinder group %d\n", + sblock.fs_maxbpg); + fprintf(stdout, "\tminimum percentage of free space %d%%\n", + sblock.fs_minfree); +#ifdef TUNEFS_SOFTDEP + fprintf(stdout, "\tsoft dependencies: %s\n", + (sblock.fs_flags & FS_DOSOFTDEP) ? "on" : "off"); +#endif + fprintf(stdout, "\toptimization preference: %s\n", + chg[sblock.fs_optim]); + fprintf(stdout, "\taverage file size: %d\n", + sblock.fs_avgfilesize); + fprintf(stdout, + "\texpected number of files per directory: %d\n", + sblock.fs_avgfpdir); + fprintf(stdout, "tunefs: no changes made\n"); + exit(0); + } + + memcpy(buf, (char *)&sblock, SBLOCKSIZE); + bwrite(sblockloc, buf, SBLOCKSIZE, special); if (Aflag) for (i = 0; i < sblock.fs_ncg; i++) bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)), - (char *)&sblock, SBSIZE); - if (close(fi)) - err(1, "close: %s", special); + buf, SBLOCKSIZE, special); + close(fi); + exit(0); +} - return (0); +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); } -void +static void usage(void) { - fprintf(stderr, - "Usage: %s tuneup-options special-device\n" - "where tuneup-options are:\n" - "\t-A modify all backups of the super-block\n" - "\t-a maximum contiguous blocks\n" - "\t-d rotational delay between contiguous blocks\n" - "\t-e maximum blocks per file in a cylinder group\n" - "\t-f expected average file size\n" - "\t-m minimum percentage of free space\n" - "\t-n expected number of files per directory\n" - "\t-o optimization preference (`space' or `time')\n" - "\t-p no change - just prints current tuneable settings\n", - __progname); + + fprintf(stderr, "usage: tunefs [-AFN] tuneup-options special-device\n"); + fprintf(stderr, "where tuneup-options are:\n"); + fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); + fprintf(stderr, "\t-g average file size\n"); + fprintf(stderr, "\t-h expected number of files per directory\n"); + fprintf(stderr, "\t-m minimum percentage of free space\n"); +#ifdef TUNEFS_SOFTDEP + fprintf(stderr, "\t-n soft dependencies (`enable' or `disable')\n"); +#endif + fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); exit(2); } -void -getsb(struct fs *fs, char *file, int flags) +static void +getsb(struct fs *fs, const char *file) { + int i; + + for (i = 0; ; i++) { + if (sblock_try[i] == -1) + errx(5, "cannot find filesystem superblock"); + bread(sblock_try[i] / dev_bsize, (char *)fs, SBLOCKSIZE, file); + switch(fs->fs_magic) { + case FS_UFS2_MAGIC: + is_ufs2 = 1; + /*FALLTHROUGH*/ + case FS_UFS1_MAGIC: + break; + default: + continue; + } + if (!is_ufs2 && sblock_try[i] == SBLOCK_UFS2) + continue; + if ((is_ufs2 || fs->fs_flags & FS_FLAGS_UPDATED) + && fs->fs_sblockloc != sblock_try[i]) + continue; + break; + } - if (fi >= 0) - return; - fi = open(file, flags); - if (fi < 0) - err(3, "cannot open %s", file); - if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE)) - err(4, "%s: bad super block", file); - if (fs->fs_magic != FS_MAGIC) - errx(5, "%s: bad magic number", file); dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); + sblockloc = sblock_try[i] / dev_bsize; } -void -printfs(void) +static void +bwrite(daddr_t blk, char *buffer, int size, const char *file) { - warnx("maximum contiguous block count: (-a) %d", - sblock.fs_maxcontig); - warnx("rotational delay between contiguous blocks: (-d) %d ms", - sblock.fs_rotdelay); - warnx("maximum blocks per file in a cylinder group: (-e) %d", - sblock.fs_maxbpg); - warnx("expected average file size: (-f) %d", - sblock.fs_avgfilesize); - warnx("minimum percentage of free space: (-m) %d%%", - sblock.fs_minfree); - warnx("expected number of files per directory: (-n) %d", - sblock.fs_avgfpdir); - warnx("optimization preference: (-o) %s", - sblock.fs_optim == FS_OPTSPACE ? "space" : "time"); - if (sblock.fs_minfree >= MINFREE && - sblock.fs_optim == FS_OPTSPACE) - warnx(OPTWARN, "time", ">=", MINFREE); - if (sblock.fs_minfree < MINFREE && - sblock.fs_optim == FS_OPTTIME) - warnx(OPTWARN, "space", "<", MINFREE); + off_t offset; + + offset = (off_t)blk * dev_bsize; + if (lseek(fi, offset, SEEK_SET) == -1) + err(6, "%s: seeking to %lld", file, (long long)offset); + if (write(fi, buffer, size) != size) + err(7, "%s: writing %d bytes", file, size); } -void -bwrite(daddr_t blk, char *buf, int size) +static void +bread(daddr_t blk, char *buffer, int cnt, const char *file) { - - if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0) - err(6, "FS SEEK"); - if (write(fi, buf, size) != size) - err(7, "FS WRITE"); + off_t offset; + int i; + + offset = (off_t)blk * dev_bsize; + if (lseek(fi, offset, SEEK_SET) == -1) + err(4, "%s: seeking to %lld", file, (long long)offset); + if ((i = read(fi, buffer, cnt)) != cnt) + errx(5, "%s: short read", file); } -int -bread(daddr_t bno, char *buf, int cnt) +static int +openpartition(const char *name, int flags, char *device, size_t devicelen) { - int i; - - if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0) - return(1); - if ((i = read(fi, buf, cnt)) != cnt) { - for(i=0; i<sblock.fs_bsize; i++) - buf[i] = 0; - return (1); + char rawspec[MAXPATHLEN], *p; + struct fstab *fs; + int fd, oerrno; + + fs = getfsfile(name); + if (fs) { + if ((p = strrchr(fs->fs_spec, '/')) != NULL) { + snprintf(rawspec, sizeof(rawspec), "%.*s/r%s", + (int)(p - fs->fs_spec), fs->fs_spec, p + 1); + name = rawspec; + } else + name = fs->fs_spec; + } + fd = opendisk(name, flags, device, devicelen, 0); + if (fd == -1 && errno == ENOENT) { + oerrno = errno; + strlcpy(device, name, devicelen); + errno = oerrno; } - return (0); + return (fd); } |