summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/fsck_ffs/fsck.h1
-rw-r--r--sbin/fsck_ffs/fsck_ffs.889
-rw-r--r--sbin/fsck_ffs/fsutil.c20
-rw-r--r--sbin/fsck_ffs/main.c76
-rw-r--r--sbin/fsck_ffs/utilities.c14
5 files changed, 117 insertions, 83 deletions
diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index 813202b..9321560 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -212,6 +212,7 @@ int cvtlevel; /* convert to newer file system format */
int doinglevel1; /* converting to new cylinder group format */
int doinglevel2; /* converting to new inode format */
int newinofmt; /* filesystem has new inode format */
+int bkgrdcheck; /* determine if background check is possible */
char usedsoftdep; /* just fix soft dependency inconsistencies */
char preen; /* just fix normal inconsistencies */
char rerun; /* rerun fsck. Only used in non-preen mode */
diff --git a/sbin/fsck_ffs/fsck_ffs.8 b/sbin/fsck_ffs/fsck_ffs.8
index a666fda..1422d90 100644
--- a/sbin/fsck_ffs/fsck_ffs.8
+++ b/sbin/fsck_ffs/fsck_ffs.8
@@ -42,41 +42,14 @@
.Nd filesystem consistency check and interactive repair
.Sh SYNOPSIS
.Nm
-.Fl p
-.Op Fl f
-.Op Fl m Ar mode
-.Op Ar filesystem
-.Ar ...
-.Nm
-.Op Fl ny
+.Op Fl BFpfny
.Op Fl b Ar block#
.Op Fl c Ar level
-.Op Fl l Ar maxparallel
.Op Fl m Ar mode
-.Op Ar filesystem
+.Ar filesystem
.Ar ...
.Sh DESCRIPTION
-The first form of
-.Nm
-preens a standard set of filesystems or the specified filesystems.
-It is normally used in the script
-.Pa /etc/rc
-during automatic reboot.
-Here
-.Nm
-reads the table
-.Pa /etc/fstab
-to determine which filesystems to check.
-Only partitions in fstab that are mounted ``rw,'' ``rq'' or ``ro''
-and that have non-zero pass number are checked.
-Filesystems with pass number 1 (normally just the root filesystem)
-are checked one at a time.
-When pass 1 completes, all remaining filesystems are checked,
-running one process per disk drive.
-The disk drive containing each filesystem is inferred from the longest prefix
-of the device name that ends in a digit; the remaining characters are assumed
-to be the partition designator.
-.Pp
+The specified disk partitions and/or filesystems are checked.
In "preen" mode the clean flag of each filesystem's superblock is examined
and only those filesystems that
are not marked clean are checked.
@@ -166,17 +139,40 @@ will default to a
.Fl n
action.
.Pp
-.Nm Fsck
-has more consistency checks than
-its predecessors
-.Em check , dcheck , fcheck ,
-and
-.Em icheck
-combined.
-.Pp
The following flags are interpreted by
-.Nm .
+.Nm
.Bl -tag -width indent
+.It Fl F
+Determine whether the filesystem needs to be cleaned immediately
+in foreground, or if its cleaning can be deferred to background.
+To be eligible for background cleaning it must have been running
+with soft updates, not have been marked as needing a foreground check,
+and be mounted and writable when the background check is to be done.
+If these conditions are met, then
+.Nm
+exits with a zero exit status.
+Otherwise it exits with a non-zero exit status.
+If the filesystem is clean,
+it will exit with a non-zero exit status so that the clean status
+of the filesystem can be verified and reported during the foreground
+checks.
+Note that when invoked with the
+.Fl F
+flag, no cleanups are done.
+The only thing that
+.Nm
+does is to determine whether a foreground or background
+check is needed and exit with an appropriate status code.
+.It Fl B
+A check is done on the specified and possibly active filesystem.
+The set of corrections that can be done is limited to those done
+when running in preen mode (see the
+.Fl p
+flag).
+If unexpected errors are found,
+the filesystem is marked as needing a foreground check and
+.Nm
+exits without attempting any further cleaning.
.It Fl b
Use the block specified immediately after the flag as
the super block for the filesystem. Block 32 is usually
@@ -220,12 +216,6 @@ Force
to check
.Sq clean
filesystems when preening.
-.It Fl l
-Limit the number of parallel checks to the number specified in the following
-argument.
-By default, the limit is the number of disks, running one process per disk.
-If a smaller limit is given, the disks are checked round-robin, one filesystem
-at a time.
.It Fl m
Use the mode specified in octal immediately after the flag as the
permission bits to use when creating the
@@ -250,12 +240,6 @@ this should be used with great caution as this is a free license
to continue after essentially unlimited trouble has been encountered.
.El
.Pp
-If no filesystems are given to
-.Nm
-then a default list of filesystems is read from
-the file
-.Pa /etc/fstab .
-.Pp
Inconsistencies checked are as follows:
.Pp
.Bl -enum -compact
@@ -312,9 +296,6 @@ If the
.Pa lost+found
directory does not exist, it is created.
If there is insufficient space its size is increased.
-.Pp
-Because of inconsistencies between the block device and the buffer cache,
-the raw device should always be used.
.Sh FILES
.Bl -tag -width /etc/fstab -compact
.It Pa /etc/fstab
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c
index c743aca..325fe5c 100644
--- a/sbin/fsck_ffs/fsutil.c
+++ b/sbin/fsck_ffs/fsutil.c
@@ -264,6 +264,8 @@ rwerror(mesg, blk)
ufs_daddr_t blk;
{
+ if (bkgrdcheck)
+ exit(EEXIT);
if (preen == 0)
printf("\n");
pfatal("CANNOT %s: %ld", mesg, blk);
@@ -645,10 +647,10 @@ pfatal(fmt, va_alist)
va_start(ap);
#endif
if (!preen) {
- (void)vfprintf(stderr, fmt, ap);
+ (void)vfprintf(stdout, fmt, ap);
va_end(ap);
if (usedsoftdep)
- (void)fprintf(stderr,
+ (void)fprintf(stdout,
"\nUNEXPECTED SOFT UPDATE INCONSISTENCY\n");
/*
* Force foreground fsck to clean up inconsistency.
@@ -659,7 +661,7 @@ pfatal(fmt, va_alist)
if (sysctlbyname("vfs.ffs.setflags", 0, 0,
&cmd, sizeof cmd) == -1)
pwarn("CANNOT SET FS_NEEDSFSCK FLAG\n");
- fprintf(stderr, "CANNOT RUN IN BACKGROUND\n");
+ fprintf(stdout, "CANNOT RUN IN BACKGROUND\n");
ckfini(0);
exit(EEXIT);
}
@@ -667,9 +669,9 @@ pfatal(fmt, va_alist)
}
if (cdevname == NULL)
cdevname = "fsck";
- (void)fprintf(stderr, "%s: ", cdevname);
- (void)vfprintf(stderr, fmt, ap);
- (void)fprintf(stderr,
+ (void)fprintf(stdout, "%s: ", cdevname);
+ (void)vfprintf(stdout, fmt, ap);
+ (void)fprintf(stdout,
"\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n",
cdevname, usedsoftdep ? " SOFT UPDATE " : " ");
/*
@@ -706,8 +708,8 @@ pwarn(fmt, va_alist)
va_start(ap);
#endif
if (preen)
- (void)fprintf(stderr, "%s: ", cdevname);
- (void)vfprintf(stderr, fmt, ap);
+ (void)fprintf(stdout, "%s: ", cdevname);
+ (void)vfprintf(stdout, fmt, ap);
va_end(ap);
}
@@ -730,7 +732,7 @@ panic(fmt, va_alist)
va_start(ap);
#endif
pfatal("INTERNAL INCONSISTENCY:");
- (void)vfprintf(stderr, fmt, ap);
+ (void)vfprintf(stdout, fmt, ap);
va_end(ap);
exit(EEXIT);
}
diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c
index 83bb312..930a4c4 100644
--- a/sbin/fsck_ffs/main.c
+++ b/sbin/fsck_ffs/main.c
@@ -63,8 +63,6 @@ static const char rcsid[] =
#include "fsck.h"
-int returntosingle;
-
static void usage __P((void));
static int argtoi __P((int flag, char *req, char *str, int base));
static int docheck __P((struct fstab *fsp));
@@ -84,7 +82,7 @@ main(argc, argv)
sync();
skipclean = 1;
- while ((ch = getopt(argc, argv, "b:Bc:dfm:npy")) != -1) {
+ while ((ch = getopt(argc, argv, "b:Bc:dfFm:npy")) != -1) {
switch (ch) {
case 'b':
skipclean = 0;
@@ -109,6 +107,10 @@ main(argc, argv)
skipclean = 0;
break;
+ case 'F':
+ bkgrdcheck = 1;
+ break;
+
case 'm':
lfmode = argtoi('m', "mode", optarg, 8);
if (lfmode &~ 07777)
@@ -154,7 +156,7 @@ main(argc, argv)
(void)setrlimit(RLIMIT_DATA, &rlimit);
}
while (argc-- > 0)
- (void)checkfilesys(blockcheck(*argv++), 0, 0L, 0);
+ (void)checkfilesys(*argv++, 0, 0L, 0);
if (returntosingle)
ret = 2;
@@ -193,15 +195,46 @@ checkfilesys(filesys, mntpt, auxdata, child)
struct zlncnt *zlnp;
ufs_daddr_t blks;
ufs_daddr_t files;
- int cylno;
+ int cylno, size;
if (preen && child)
(void)signal(SIGQUIT, voidquit);
cdevname = filesys;
if (debug && preen)
pwarn("starting\n");
+ /*
+ * Make best effort to get the disk name. Check first to see
+ * if it is listed among the mounted filesystems. Failing that
+ * check to see if it is listed in /etc/fstab.
+ */
+ mntp = getmntpt(filesys);
+ if (mntp != NULL)
+ filesys = mntp->f_mntfromname;
+ else
+ filesys = blockcheck(filesys);
+ /*
+ * If -F flag specified, check to see whether a background check
+ * is possible and needed. If possible and needed, exit with
+ * status zero. Otherwise exit with status non-zero. A non-zero
+ * exit status will cause a foreground check to be run.
+ */
sblock_init();
-
+ if (bkgrdcheck) {
+ if ((fsreadfd = open(filesys, O_RDONLY)) < 0 || readsb(0) == 0)
+ exit(3); /* Cannot read superblock */
+ close(fsreadfd);
+ if (sblock.fs_flags & FS_NEEDSFSCK)
+ exit(4); /* Earlier background failed */
+ if ((sblock.fs_flags & FS_DOSOFTDEP) == 0)
+ exit(5); /* Not running soft updates */
+ size = MIBSIZE;
+ if (sysctlnametomib("vfs.ffs.adjrefcnt", adjrefcnt, &size) < 0)
+ exit(6); /* Lacks kernel support */
+ if ((mntp == NULL && sblock.fs_clean == 1) ||
+ (mntp != NULL && (sblock.fs_flags & FS_UNCLEAN) == 0))
+ exit(7); /* Filesystem clean, report it now */
+ exit(0);
+ }
/*
* If we are to do a background check:
* Get the mount point information of the filesystem
@@ -209,7 +242,6 @@ checkfilesys(filesys, mntpt, auxdata, child)
* return created snapshot file
* if not found, clear bkgrdflag and proceed with normal fsck
*/
- mntp = getmntpt(filesys);
if (bkgrdflag) {
if (mntp == NULL) {
bkgrdflag = 0;
@@ -432,7 +464,7 @@ checkfilesys(filesys, mntpt, auxdata, child)
}
/*
- * Get the directory that the device is mounted on.
+ * Get the mount point information for name.
*/
static struct statfs *
getmntpt(name)
@@ -441,27 +473,35 @@ getmntpt(name)
struct stat devstat, mntdevstat;
char device[sizeof(_PATH_DEV) - 1 + MNAMELEN];
char *devname;
- struct statfs *mntbuf;
- int i, mntsize;
+ struct statfs *mntbuf, *statfsp;
+ int i, mntsize, isdev;
- if (stat(name, &devstat) != 0 ||
- !(S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode)))
+ if (stat(name, &devstat) != 0)
return (NULL);
+ if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode))
+ isdev = 1;
+ else
+ isdev = 0;
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
for (i = 0; i < mntsize; i++) {
- if (strcmp(mntbuf[i].f_fstypename, "ufs") != 0)
- continue;
- devname = mntbuf[i].f_mntfromname;
+ statfsp = &mntbuf[i];
+ devname = statfsp->f_mntfromname;
if (*devname != '/') {
strcpy(device, _PATH_DEV);
strcat(device, devname);
- devname = device;
+ strcpy(statfsp->f_mntfromname, device);
+ }
+ if (isdev == 0) {
+ if (strcmp(name, statfsp->f_mntonname))
+ continue;
+ return (statfsp);
}
if (stat(devname, &mntdevstat) == 0 &&
mntdevstat.st_rdev == devstat.st_rdev)
- return (&mntbuf[i]);
+ return (statfsp);
}
- return (NULL);
+ statfsp = NULL;
+ return (statfsp);
}
static void
diff --git a/sbin/fsck_ffs/utilities.c b/sbin/fsck_ffs/utilities.c
index 81b96e6..e584c8f 100644
--- a/sbin/fsck_ffs/utilities.c
+++ b/sbin/fsck_ffs/utilities.c
@@ -52,6 +52,7 @@ static const char rcsid[] =
#include <string.h>
#include <ctype.h>
#include <fstab.h>
+#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -64,11 +65,20 @@ blockcheck(origname)
char *origname;
{
struct stat stslash, stblock, stchar;
- char *newname, *raw;
+ char *newname, *raw, *cp;
struct fstab *fsinfo;
int retried = 0, len;
+ static char device[MAXPATHLEN];
newname = origname;
+ if (stat(newname, &stblock) < 0) {
+ cp = strrchr(newname, '/');
+ if (cp == 0) {
+ (void)snprintf(device, sizeof(device), "%s%s",
+ _PATH_DEV, newname);
+ newname = device;
+ }
+ }
retry:
if (stat(newname, &stblock) < 0) {
printf("Can't stat %s: %s\n", newname, strerror(errno));
@@ -90,7 +100,7 @@ retry:
printf(
"Can't resolve %s to character special device.\n",
origname);
- return (0);
+ return (origname);
}
newname = fsinfo->fs_spec;
retried++;
OpenPOWER on IntegriCloud