summaryrefslogtreecommitdiffstats
path: root/sbin/fsck_ffs/main.c
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2001-03-21 09:48:03 +0000
committermckusick <mckusick@FreeBSD.org>2001-03-21 09:48:03 +0000
commitdc0e22cfaf1b407ad08776ab7386543ad024a76c (patch)
treec406042339ede0ab9e543e4797322cadaef35d82 /sbin/fsck_ffs/main.c
parent37fbaa04c47b8d96f06c60428b244c77e3597218 (diff)
downloadFreeBSD-src-dc0e22cfaf1b407ad08776ab7386543ad024a76c.zip
FreeBSD-src-dc0e22cfaf1b407ad08776ab7386543ad024a76c.tar.gz
Additions to run checks on live filesystems. This change will not
affect current systems until fsck is modified to use these new facilities. To try out this change, set the fsck passno to zero in /etc/fstab to cause the filesystem to be mounted without running fsck, then run `fsck_ffs -p -B <filesystem>' after the system has been brought up multiuser to run a background cleanup on <filesystem>. Note that the <filesystem> in question must have soft updates enabled.
Diffstat (limited to 'sbin/fsck_ffs/main.c')
-rw-r--r--sbin/fsck_ffs/main.c94
1 files changed, 69 insertions, 25 deletions
diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c
index 7ee4ef0b..a9e7e90 100644
--- a/sbin/fsck_ffs/main.c
+++ b/sbin/fsck_ffs/main.c
@@ -83,8 +83,7 @@ main(argc, argv)
sync();
skipclean = 1;
- markclean = 1;
- while ((ch = getopt(argc, argv, "b:c:dfm:npy")) != -1) {
+ while ((ch = getopt(argc, argv, "b:Bc:dfm:npy")) != -1) {
switch (ch) {
case 'b':
skipclean = 0;
@@ -92,6 +91,10 @@ main(argc, argv)
printf("Alternate super block location: %d\n", bflag);
break;
+ case 'B':
+ bkgrdflag = 1;
+ break;
+
case 'c':
skipclean = 0;
cvtlevel = argtoi('c', "conversion level", optarg, 10);
@@ -183,9 +186,12 @@ checkfilesys(filesys, mntpt, auxdata, child)
int child;
{
ufs_daddr_t n_ffree, n_bfree;
+ struct ufs_args args;
struct dups *dp;
- struct statfs *mntbuf;
+ struct statfs *mntp;
struct zlncnt *zlnp;
+ ufs_daddr_t blks;
+ ufs_daddr_t files;
int cylno;
if (preen && child)
@@ -193,6 +199,44 @@ checkfilesys(filesys, mntpt, auxdata, child)
cdevname = filesys;
if (debug && preen)
pwarn("starting\n");
+
+ /*
+ * If we are to do a background check:
+ * Get the mount point information of the filesystem
+ * create snapshot file
+ * return created snapshot file
+ * if not found, clear bkgrdflag and proceed with normal fsck
+ */
+ mntp = getmntpt(filesys);
+ if (bkgrdflag) {
+ if (mntp == NULL) {
+ bkgrdflag = 0;
+ pwarn("NOT MOUNTED, CANNOT RUN IN BACKGROUND\n");
+ } else if ((mntp->f_flags & MNT_SOFTDEP) == 0) {
+ bkgrdflag = 0;
+ pwarn("NOT USING SOFT UPDATES, CANNOT RUN IN BACKGROUND\n");
+ } else if ((mntp->f_flags & MNT_RDONLY) != 0) {
+ bkgrdflag = 0;
+ pwarn("MOUNTED READ-ONLY, CANNOT RUN IN BACKGROUND\n");
+ } else {
+ snprintf(snapname, sizeof snapname, "%s/.fsck_snapshot",
+ mntp->f_mntonname);
+ args.fspec = snapname;
+ while (mount("ffs", mntp->f_mntonname,
+ mntp->f_flags | MNT_UPDATE | MNT_SNAPSHOT,
+ &args) < 0) {
+ if (errno == EEXIST && unlink(snapname) == 0)
+ continue;
+ bkgrdflag = 0;
+ pwarn("CANNOT CREATE SNAPSHOT %s: %s\n",
+ snapname, strerror(errno));
+ break;
+ }
+ if (bkgrdflag != 0)
+ filesys = snapname;
+ }
+ }
+
switch (setup(filesys)) {
case 0:
if (preen)
@@ -206,12 +250,6 @@ checkfilesys(filesys, mntpt, auxdata, child)
sblock.fs_cstotal.cs_nffree * 100.0 / sblock.fs_dsize);
return (0);
}
-
- /*
- * Get the mount point information of the filesystem, if
- * it is available.
- */
- mntbuf = getmntpt(filesys);
/*
* Cleared if any questions answered no. Used to decide if
@@ -223,7 +261,7 @@ checkfilesys(filesys, mntpt, auxdata, child)
*/
if (preen == 0) {
printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
- if (mntbuf != NULL && mntbuf->f_flags & MNT_ROOTFS)
+ if (mntp != NULL && mntp->f_flags & MNT_ROOTFS)
printf("** Root file system\n");
printf("** Phase 1 - Check Blocks and Sizes\n");
}
@@ -272,20 +310,26 @@ checkfilesys(filesys, mntpt, auxdata, child)
*/
n_ffree = sblock.fs_cstotal.cs_nffree;
n_bfree = sblock.fs_cstotal.cs_nbfree;
+ files = maxino - ROOTINO - sblock.fs_cstotal.cs_nifree - n_files;
+ blks = n_blks +
+ sblock.fs_ncg * (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
+ blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
+ blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
+ blks = maxfsblock - (n_ffree + sblock.fs_frag * n_bfree) - blks;
+ if (bkgrdflag && (files > 0 || blks > 0)) {
+ countdirs = sblock.fs_cstotal.cs_ndir - countdirs;
+ pwarn("Reclaimed: %d directories, %d files, %d fragments\n",
+ countdirs, files - countdirs, blks);
+ }
pwarn("%ld files, %ld used, %ld free ",
n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
n_ffree, n_bfree, n_ffree * 100.0 / sblock.fs_dsize);
- if (debug &&
- (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
- printf("%d files missing\n", n_files);
if (debug) {
- n_blks += sblock.fs_ncg *
- (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
- n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
- n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
- if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
- printf("%d blocks missing\n", n_blks);
+ if (files < 0)
+ printf("%d inodes missing\n", -files);
+ if (blks < 0)
+ printf("%d blocks missing\n", -blks);
if (duplist != NULL) {
printf("The following duplicate blocks remain:");
for (dp = duplist; dp; dp = dp->next)
@@ -321,7 +365,7 @@ checkfilesys(filesys, mntpt, auxdata, child)
/*
* Check to see if the filesystem is mounted read-write.
*/
- if (mntbuf != NULL && (mntbuf->f_flags & MNT_RDONLY) == 0)
+ if (bkgrdflag == 0 && mntp != NULL && (mntp->f_flags & MNT_RDONLY) == 0)
resolved = 0;
ckfini(resolved);
@@ -334,7 +378,7 @@ checkfilesys(filesys, mntpt, auxdata, child)
printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
if (rerun)
printf("\n***** PLEASE RERUN FSCK *****\n");
- if (mntbuf != NULL) {
+ if (mntp != NULL) {
struct ufs_args args;
int ret;
/*
@@ -342,16 +386,16 @@ checkfilesys(filesys, mntpt, auxdata, child)
* it unless it is read-write, so we can continue using it
* as safely as possible.
*/
- if (mntbuf->f_flags & MNT_RDONLY) {
+ if (mntp->f_flags & MNT_RDONLY) {
args.fspec = 0;
args.export.ex_flags = 0;
args.export.ex_root = 0;
- ret = mount("ufs", mntbuf->f_mntonname,
- mntbuf->f_flags | MNT_UPDATE | MNT_RELOAD, &args);
+ ret = mount("ufs", mntp->f_mntonname,
+ mntp->f_flags | MNT_UPDATE | MNT_RELOAD, &args);
if (ret == 0)
return (0);
pwarn("mount reload of '%s' failed: %s\n\n",
- mntbuf->f_mntonname, strerror(errno));
+ mntp->f_mntonname, strerror(errno));
}
if (!fsmodified)
return (0);
OpenPOWER on IntegriCloud