diff options
author | Kirk McKusick <mckusick@FreeBSD.org> | 2013-03-22 21:45:28 +0000 |
---|---|---|
committer | Kirk McKusick <mckusick@FreeBSD.org> | 2013-03-22 21:45:28 +0000 |
commit | baa12a84a7aefc1a1932a7568eaf7d2d55b5d21c (patch) | |
tree | 4dd79ec73ca7a215a3694baba70bbfe162604d09 /sbin/tunefs | |
parent | 209dddb90e6ee833590836dc48a58957fd6f3026 (diff) | |
download | src-baa12a84a7aefc1a1932a7568eaf7d2d55b5d21c.tar.gz src-baa12a84a7aefc1a1932a7568eaf7d2d55b5d21c.zip |
The purpose of this change to the FFS layout policy is to reduce the
running time for a full fsck. It also reduces the random access time
for large files and speeds the traversal time for directory tree walks.
The key idea is to reserve a small area in each cylinder group
immediately following the inode blocks for the use of metadata,
specifically indirect blocks and directory contents. The new policy
is to preferentially place metadata in the metadata area and
everything else in the blocks that follow the metadata area.
The size of this area can be set when creating a filesystem using
newfs(8) or changed in an existing filesystem using tunefs(8).
Both utilities use the `-k held-for-metadata-blocks' option to
specify the amount of space to be held for metadata blocks in each
cylinder group. By default, newfs(8) sets this area to half of
minfree (typically 4% of the data area).
This work was inspired by a paper presented at Usenix's FAST '13:
www.usenix.org/conference/fast13/ffsck-fast-file-system-checker
Details of this implementation appears in the April 2013 of ;login:
www.usenix.org/publications/login/april-2013-volume-38-number-2.
A copy of the April 2013 ;login: paper can also be downloaded
from: www.mckusick.com/publications/faster_fsck.pdf.
Reviewed by: kib
Tested by: Peter Holm
MFC after: 4 weeks
Notes
Notes:
svn path=/head/; revision=248623
Diffstat (limited to 'sbin/tunefs')
-rw-r--r-- | sbin/tunefs/tunefs.8 | 14 | ||||
-rw-r--r-- | sbin/tunefs/tunefs.c | 41 |
2 files changed, 47 insertions, 8 deletions
diff --git a/sbin/tunefs/tunefs.8 b/sbin/tunefs/tunefs.8 index 5b522e585060..a58c17479d7a 100644 --- a/sbin/tunefs/tunefs.8 +++ b/sbin/tunefs/tunefs.8 @@ -42,6 +42,7 @@ .Op Fl f Ar avgfilesize .Op Fl j Cm enable | disable .Op Fl J Cm enable | disable +.Op Fl k Ar held-for-metadata-blocks .Op Fl L Ar volname .Op Fl l Cm enable | disable .Op Fl m Ar minfree @@ -96,6 +97,19 @@ Specify the expected average file size. Turn on/off soft updates journaling. .It Fl J Cm enable | disable Turn on/off gjournal flag. +.It Fl k Ar held-for-metadata-blocks +Set the amount of space to be held for metadata blocks. +When set, the file system preference routines will try to save +the specified amount of space immediately following the inode blocks +in each cylinder group for use by metadata blocks. +Clustering the metadata blocks speeds up random file access +and decreases the running time of +.Xr fsck 8 . +While this option can be set at any time, +it is most effective if set before any data is loaded into the file system. +By default +.Xr newfs 8 +sets it to half of the space reserved to minfree. .It Fl L Ar volname Add/modify an optional file system volume label. .It Fl l Cm enable | disable diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c index 39e08f760904..0671d1de5896 100644 --- a/sbin/tunefs/tunefs.c +++ b/sbin/tunefs/tunefs.c @@ -89,10 +89,9 @@ main(int argc, char *argv[]) const char *special, *on; const char *name; int active; - int Aflag, aflag, eflag, evalue, fflag, fvalue, jflag, Jflag, Lflag; - int lflag, mflag, mvalue, Nflag, nflag, oflag, ovalue, pflag, sflag; - int tflag; - int svalue, Svalue; + int Aflag, aflag, eflag, evalue, fflag, fvalue, jflag, Jflag, kflag; + int kvalue, Lflag, lflag, mflag, mvalue, Nflag, nflag, oflag, ovalue; + int pflag, sflag, svalue, Svalue, tflag; int ch, found_arg, i; const char *chg[2]; struct ufs_args args; @@ -100,13 +99,13 @@ main(int argc, char *argv[]) if (argc < 3) usage(); - Aflag = aflag = eflag = fflag = jflag = Jflag = Lflag = lflag = 0; - mflag = Nflag = nflag = oflag = pflag = sflag = tflag = 0; + Aflag = aflag = eflag = fflag = jflag = Jflag = kflag = Lflag = 0; + lflag = mflag = Nflag = nflag = oflag = pflag = sflag = tflag = 0; avalue = jvalue = Jvalue = Lvalue = lvalue = Nvalue = nvalue = NULL; evalue = fvalue = mvalue = ovalue = svalue = Svalue = 0; active = 0; found_arg = 0; /* At least one arg is required. */ - while ((ch = getopt(argc, argv, "Aa:e:f:j:J:L:l:m:N:n:o:ps:S:t:")) + while ((ch = getopt(argc, argv, "Aa:e:f:j:J:k:L:l:m:N:n:o:ps:S:t:")) != -1) switch (ch) { @@ -171,6 +170,14 @@ main(int argc, char *argv[]) Jflag = 1; break; + case 'k': + found_arg = 1; + name = "space to hold for metadata blocks"; + kvalue = atoi(optarg); + if (mvalue < 0) + errx(10, "bad %s (%s)", name, optarg); + kflag = 1; + break; case 'L': found_arg = 1; @@ -404,6 +411,22 @@ main(int argc, char *argv[]) } } } + if (kflag) { + name = "space to hold for metadata blocks"; + if (sblock.fs_metaspace == kvalue) + warnx("%s remains unchanged as %d", name, kvalue); + else { + kvalue = blknum(&sblock, kvalue); + if (kvalue > sblock.fs_fpg / 2) { + kvalue = blknum(&sblock, sblock.fs_fpg / 2); + warnx("%s cannot exceed half the file system " + "space", name); + } + warnx("%s changes from %jd to %d", + name, sblock.fs_metaspace, kvalue); + sblock.fs_metaspace = kvalue; + } + } if (lflag) { name = "multilabel"; if (strcmp(lvalue, "enable") == 0) { @@ -1064,7 +1087,7 @@ usage(void) { fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n", "usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]", -" [-J enable | disable] [-j enable | disable]", +" [-J enable | disable] [-j enable | disable] [-k metaspace]", " [-L volname] [-l enable | disable] [-m minfree]", " [-N enable | disable] [-n enable | disable]", " [-o space | time] [-p] [-s avgfpdir] [-t enable | disable]", @@ -1097,6 +1120,8 @@ printfs(void) sblock.fs_avgfpdir); warnx("minimum percentage of free space: (-m) %d%%", sblock.fs_minfree); + warnx("space to hold for metadata blocks: (-k) %jd", + sblock.fs_metaspace); warnx("optimization preference: (-o) %s", sblock.fs_optim == FS_OPTSPACE ? "space" : "time"); if (sblock.fs_minfree >= MINFREE && |