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:
parent
15418cf2bb
commit
15fca934f6
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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++;
|
||||
|
Loading…
Reference in New Issue
Block a user