Add support for the -F flag which determines whether a specified

filesystem needs foreground checking (usually at boot time) or
can defer to background checking (after the system is up and running).
See the manual page, fsck_ffs(8), for details on the -F and -B options.
These options are primarily intended for use by the fsck front end.

All output is directed to stdout so that the output is coherent
when redirected to a file or a pipe. Unify the code with the fsck
front end that allows either a device or a mount point to be
specified as the argument to be checked.
This commit is contained in:
Kirk McKusick 2001-04-24 22:38:08 +00:00
parent 15418cf2bb
commit 15fca934f6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=75927
5 changed files with 117 additions and 83 deletions

View File

@ -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 */

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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 @@ blockcheck(origname)
printf(
"Can't resolve %s to character special device.\n",
origname);
return (0);
return (origname);
}
newname = fsinfo->fs_spec;
retried++;