aboutsummaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorXin LI <delphij@FreeBSD.org>2005-02-20 08:02:15 +0000
committerXin LI <delphij@FreeBSD.org>2005-02-20 08:02:15 +0000
commita16baf37b9a9ad6ee0280cc0718c94d8a7968cf4 (patch)
treecacb781306afa3ef7a585d142dfcfeee26259805 /sbin
parentd505db6ae2bdcf6175570495576bc1ef16c85034 (diff)
downloadsrc-a16baf37b9a9ad6ee0280cc0718c94d8a7968cf4.tar.gz
src-a16baf37b9a9ad6ee0280cc0718c94d8a7968cf4.zip
The recomputation of file system summary at mount time can be a
very slow process, especially for large file systems that is just recovered from a crash. Since the summary is already re-sync'ed every 30 second, we will not lag behind too much after a crash. With this consideration in mind, it is more reasonable to transfer the responsibility to background fsck, to reduce the delay after a crash. Add a new sysctl variable, vfs.ffs.compute_summary_at_mount, to control this behavior. When set to nonzero, we will get the "old" behavior, that the summary is computed immediately at mount time. Add five new sysctl variables to adjust ndir, nbfree, nifree, nffree and numclusters respectively. Teach fsck_ffs about these API, however, intentionally not to check the existence, since kernels without these sysctls must have recomputed the summary and hence no adjustments are necessary. This change has eliminated the usual tens of minutes of delay of mounting large dirty volumes. Reviewed by: mckusick MFC After: 1 week
Notes
Notes: svn path=/head/; revision=142123
Diffstat (limited to 'sbin')
-rw-r--r--sbin/fsck_ffs/fsck.h5
-rw-r--r--sbin/fsck_ffs/pass5.c55
2 files changed, 60 insertions, 0 deletions
diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index 487dcd42a669..55a57bc6959f 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -252,6 +252,11 @@ long countdirs; /* number of directories we actually found */
#define MIBSIZE 3 /* size of fsck sysctl MIBs */
int adjrefcnt[MIBSIZE]; /* MIB command to adjust inode reference cnt */
int adjblkcnt[MIBSIZE]; /* MIB command to adjust inode block count */
+int adjndir[MIBSIZE]; /* MIB command to adjust number of directories */
+int adjnbfree[MIBSIZE]; /* MIB command to adjust number of free blocks */
+int adjnifree[MIBSIZE]; /* MIB command to adjust number of free inodes */
+int adjnffree[MIBSIZE]; /* MIB command to adjust number of free frags */
+int adjnumclusters[MIBSIZE]; /* MIB command to adjust number of free clusters */
int freefiles[MIBSIZE]; /* MIB command to free a set of files */
int freedirs[MIBSIZE]; /* MIB command to free a set of directories */
int freeblks[MIBSIZE]; /* MIB command to free a set of data blocks */
diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c
index c3c564e7700c..796b546b9516 100644
--- a/sbin/fsck_ffs/pass5.c
+++ b/sbin/fsck_ffs/pass5.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <ufs/ffs/fs.h>
#include <err.h>
+#include <inttypes.h>
#include <limits.h>
#include <string.h>
@@ -344,6 +345,60 @@ pass5(void)
fs->fs_fmod = 0;
sbdirty();
}
+
+ /*
+ * When doing background fsck on a snapshot, figure out whether
+ * the superblock summary is inaccurate and correct it when
+ * necessary.
+ */
+ if (cursnapshot != 0) {
+ cmd.size = 1;
+
+ cmd.value = cstotal.cs_ndir - fs->fs_cstotal.cs_ndir;
+ if (cmd.value != 0) {
+ if (debug)
+ printf("adjndir by %+" PRIi64 "\n", cmd.value);
+ if (sysctl(adjndir, MIBSIZE, 0, 0,
+ &cmd, sizeof cmd) == -1)
+ rwerror("ADJUST NUMBER OF DIRECTORIES", cmd.value);
+ }
+
+ cmd.value = cstotal.cs_nbfree - fs->fs_cstotal.cs_nbfree;
+ if (cmd.value != 0) {
+ if (debug)
+ printf("adjnbfree by %+" PRIi64 "\n", cmd.value);
+ if (sysctl(adjnbfree, MIBSIZE, 0, 0,
+ &cmd, sizeof cmd) == -1)
+ rwerror("ADJUST NUMBER OF FREE BLOCKS", cmd.value);
+ }
+
+ cmd.value = cstotal.cs_nifree - fs->fs_cstotal.cs_nifree;
+ if (cmd.value != 0) {
+ if (debug)
+ printf("adjnifree by %+" PRIi64 "\n", cmd.value);
+ if (sysctl(adjnifree, MIBSIZE, 0, 0,
+ &cmd, sizeof cmd) == -1)
+ rwerror("ADJUST NUMBER OF FREE INODES", cmd.value);
+ }
+
+ cmd.value = cstotal.cs_nffree - fs->fs_cstotal.cs_nffree;
+ if (cmd.value != 0) {
+ if (debug)
+ printf("adjnffree by %+" PRIi64 "\n", cmd.value);
+ if (sysctl(adjnffree, MIBSIZE, 0, 0,
+ &cmd, sizeof cmd) == -1)
+ rwerror("ADJUST NUMBER OF FREE FRAGS", cmd.value);
+ }
+
+ cmd.value = cstotal.cs_numclusters - fs->fs_cstotal.cs_numclusters;
+ if (cmd.value != 0) {
+ if (debug)
+ printf("adjnumclusters by %+" PRIi64 "\n", cmd.value);
+ if (sysctl(adjnumclusters, MIBSIZE, 0, 0,
+ &cmd, sizeof cmd) == -1)
+ rwerror("ADJUST NUMBER OF FREE CLUSTERS", cmd.value);
+ }
+ }
}
static void