This change sanitizes the way fsck deals with pass numbers.
Consider this /etc/fstab: # Device Mountpoint FStype Options Dump Pass# /dev/ad1s1b none swap sw 0 0 /dev/ad0s1b none swap sw 0 0 /dev/ad0s1a / ufs rw 1 1 /dev/ad0s1e /home ufs rw 2 2 /dev/ad1s1e /tmp ufs rw 2 2 /dev/ad1s1f /usr ufs rw 2 2 /dev/ccd0c /syv ufs rw 2 11 proc /proc procfs rw 0 0 ccd0c is striped over /dev/ad0f and /dev/ad1g Without this pass, fsck in preen mode will check ad0s1a first, and then issue three processes in parallel: One process doing ad0s1e One process doing ad1s1e and ad1s1f One process doing ccd0c There is no way to tell it that ccd0c overlaps ad0 and ad1. With the patch, it will do it this way: pass 2: One process doing ad0s1e One process doing ad1s1e and ad1s1f and when they are complete: pass 11: One process doing ccd0c This is much faster and more sane. Valid pass numbers are anything from 1 to INTMAX-1. I retired the '-l' option which tried to allow people to do something like this, but which didn't work and which complicated the code an awful lot.
This commit is contained in:
parent
759dbf1c02
commit
c59a8fb48c
@ -62,12 +62,24 @@ to determine which filesystems to check.
|
|||||||
Only partitions in fstab that are mounted ``rw,'' ``rq'' or ``ro''
|
Only partitions in fstab that are mounted ``rw,'' ``rq'' or ``ro''
|
||||||
and that have non-zero pass number are checked.
|
and that have non-zero pass number are checked.
|
||||||
Filesystems with pass number 1 (normally just the root filesystem)
|
Filesystems with pass number 1 (normally just the root filesystem)
|
||||||
are checked one at a time.
|
are always checked one at a time.
|
||||||
When pass 1 completes, all remaining filesystems are checked,
|
.Pp
|
||||||
running one process per disk drive.
|
If not in preen mode, the remaining entries are checked in order of
|
||||||
|
increasing pass number one at a time.
|
||||||
|
This is needed when interaction with fsck is required.
|
||||||
|
.Pp
|
||||||
|
In preen mode, after pass 1 completes, all remaining filesystems are checked,
|
||||||
|
in pass number order running one process per disk drive in parallel for each
|
||||||
|
pass number in increasing order.
|
||||||
|
.Pp
|
||||||
|
In other words: In preen mode all pass 1 partitions are checked sequentially.
|
||||||
|
Next all pass 2 partitions are checked in parallel, one process per disk drive.
|
||||||
|
Next all pass 3 partitions are checked in parallel, one process per disk drive.
|
||||||
|
etc.
|
||||||
|
.Pp
|
||||||
The disk drive containing each filesystem is inferred from the shortest prefix
|
The disk drive containing each filesystem is inferred from the shortest prefix
|
||||||
of the device name that ends in a digit; the remaining characters are assumed
|
of the device name that ends in a digit; the remaining characters are assumed
|
||||||
to be the partition and slice designator.
|
to be the partition and slice designators.
|
||||||
.Pp
|
.Pp
|
||||||
The options are as follows:
|
The options are as follows:
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
@ -79,11 +91,6 @@ is compiled to support it.
|
|||||||
.It Fl f
|
.It Fl f
|
||||||
Force checking of filesystems, even when they are marked clean (for filesystems
|
Force checking of filesystems, even when they are marked clean (for filesystems
|
||||||
that support this).
|
that support this).
|
||||||
.It Fl l Ar maxparallel
|
|
||||||
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 giv-
|
|
||||||
en, the disks are checked round-robin, one filesystem at a time.
|
|
||||||
.It Fl n
|
.It Fl n
|
||||||
Causes
|
Causes
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -76,7 +76,6 @@ struct entry {
|
|||||||
TAILQ_ENTRY(entry) entries;
|
TAILQ_ENTRY(entry) entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int maxrun = 0;
|
|
||||||
static char *options = NULL;
|
static char *options = NULL;
|
||||||
static int flags = 0;
|
static int flags = 0;
|
||||||
|
|
||||||
@ -132,7 +131,7 @@ main(argc, argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
maxrun = atoi(optarg);
|
warnx("Ignoring obsolete -l option\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'T':
|
case 'T':
|
||||||
@ -158,7 +157,7 @@ main(argc, argv)
|
|||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
if (argc == 0)
|
if (argc == 0)
|
||||||
return checkfstab(flags, maxrun, isok, checkfs);
|
return checkfstab(flags, isok, checkfs);
|
||||||
|
|
||||||
#define BADTYPE(type) \
|
#define BADTYPE(type) \
|
||||||
(strcmp(type, FSTAB_RO) && \
|
(strcmp(type, FSTAB_RO) && \
|
||||||
|
@ -58,5 +58,5 @@ char *estrdup __P((const char *));
|
|||||||
#define CHECK_DEBUG 4
|
#define CHECK_DEBUG 4
|
||||||
|
|
||||||
struct fstab;
|
struct fstab;
|
||||||
int checkfstab __P((int, int, void *(*)(struct fstab *),
|
int checkfstab __P((int, void *(*)(struct fstab *),
|
||||||
int (*) (const char *, const char *, const char *, void *, pid_t *)));
|
int (*) (const char *, const char *, const char *, void *, pid_t *)));
|
||||||
|
@ -87,8 +87,8 @@ static int startdisk __P((struct diskentry *,
|
|||||||
static void printpart __P((void));
|
static void printpart __P((void));
|
||||||
|
|
||||||
int
|
int
|
||||||
checkfstab(flags, maxrun, docheck, checkit)
|
checkfstab(flags, docheck, checkit)
|
||||||
int flags, maxrun;
|
int flags;
|
||||||
void *(*docheck) __P((struct fstab *));
|
void *(*docheck) __P((struct fstab *));
|
||||||
int (*checkit) __P((const char *, const char *, const char *, void *,
|
int (*checkit) __P((const char *, const char *, const char *, void *,
|
||||||
pid_t *));
|
pid_t *));
|
||||||
@ -96,7 +96,7 @@ checkfstab(flags, maxrun, docheck, checkit)
|
|||||||
struct fstab *fs;
|
struct fstab *fs;
|
||||||
struct diskentry *d, *nextdisk;
|
struct diskentry *d, *nextdisk;
|
||||||
struct partentry *p;
|
struct partentry *p;
|
||||||
int ret, pid, retcode, passno, sumstatus, status;
|
int ret, pid, retcode, passno, sumstatus, status, nextpass;
|
||||||
void *auxarg;
|
void *auxarg;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
@ -105,7 +105,12 @@ checkfstab(flags, maxrun, docheck, checkit)
|
|||||||
|
|
||||||
sumstatus = 0;
|
sumstatus = 0;
|
||||||
|
|
||||||
for (passno = 1; passno <= 2; passno++) {
|
nextpass = 0;
|
||||||
|
for (passno = 1; nextpass != INT_MAX; passno = nextpass) {
|
||||||
|
if (flags & CHECK_DEBUG)
|
||||||
|
printf("pass %d\n", passno);
|
||||||
|
|
||||||
|
nextpass = INT_MAX;
|
||||||
if (setfsent() == 0) {
|
if (setfsent() == 0) {
|
||||||
warnx("Can't open checklist file: %s\n", _PATH_FSTAB);
|
warnx("Can't open checklist file: %s\n", _PATH_FSTAB);
|
||||||
return (8);
|
return (8);
|
||||||
@ -114,14 +119,17 @@ checkfstab(flags, maxrun, docheck, checkit)
|
|||||||
if ((auxarg = (*docheck)(fs)) == NULL)
|
if ((auxarg = (*docheck)(fs)) == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* XXX We don't need to search for blockdevs .. */
|
|
||||||
/* name = blockcheck(fs->fs_spec); */
|
|
||||||
name = fs->fs_spec;
|
name = fs->fs_spec;
|
||||||
|
if (fs->fs_passno > passno && fs->fs_passno < nextpass)
|
||||||
|
nextpass = fs->fs_passno;
|
||||||
|
|
||||||
|
if (passno != fs->fs_passno)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (flags & CHECK_DEBUG)
|
if (flags & CHECK_DEBUG)
|
||||||
printf("pass %d, name %s\n", passno, name);
|
printf("pass %d, name %s\n", passno, name);
|
||||||
|
|
||||||
if ((flags & CHECK_PREEN) == 0 ||
|
if ((flags & CHECK_PREEN) == 0 || passno == 1) {
|
||||||
(passno == 1 && fs->fs_passno == 1)) {
|
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
if (flags & CHECK_PREEN)
|
if (flags & CHECK_PREEN)
|
||||||
return 8;
|
return 8;
|
||||||
@ -133,36 +141,33 @@ checkfstab(flags, maxrun, docheck, checkit)
|
|||||||
|
|
||||||
if (sumstatus)
|
if (sumstatus)
|
||||||
return (sumstatus);
|
return (sumstatus);
|
||||||
} else if (passno == 2 && fs->fs_passno > 1) {
|
continue;
|
||||||
if (name == NULL) {
|
}
|
||||||
(void) fprintf(stderr,
|
if (name == NULL) {
|
||||||
"BAD DISK NAME %s\n", fs->fs_spec);
|
(void) fprintf(stderr,
|
||||||
sumstatus |= 8;
|
"BAD DISK NAME %s\n", fs->fs_spec);
|
||||||
continue;
|
sumstatus |= 8;
|
||||||
}
|
continue;
|
||||||
addpart(fs->fs_vfstype, name, fs->fs_file,
|
|
||||||
auxarg);
|
|
||||||
}
|
}
|
||||||
|
addpart(fs->fs_vfstype, name, fs->fs_file,
|
||||||
|
auxarg);
|
||||||
}
|
}
|
||||||
if ((flags & CHECK_PREEN) == 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & CHECK_DEBUG)
|
if ((flags & CHECK_PREEN) == 0 || passno == 1)
|
||||||
printpart();
|
continue;
|
||||||
|
|
||||||
if (flags & CHECK_PREEN) {
|
if (flags & CHECK_DEBUG) {
|
||||||
if (maxrun == 0)
|
printf("Parallel start\n");
|
||||||
maxrun = ndisks;
|
printpart();
|
||||||
if (maxrun > ndisks)
|
}
|
||||||
maxrun = ndisks;
|
|
||||||
nextdisk = TAILQ_FIRST(&diskh);
|
TAILQ_FOREACH(nextdisk, &diskh, d_entries) {
|
||||||
for (passno = 0; passno < maxrun; ++passno) {
|
|
||||||
if ((ret = startdisk(nextdisk, checkit)) != 0)
|
if ((ret = startdisk(nextdisk, checkit)) != 0)
|
||||||
return ret;
|
return ret;
|
||||||
nextdisk = TAILQ_NEXT(nextdisk, d_entries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & CHECK_DEBUG)
|
||||||
|
printf("Parallel wait\n");
|
||||||
while ((pid = wait(&status)) != -1) {
|
while ((pid = wait(&status)) != -1) {
|
||||||
TAILQ_FOREACH(d, &diskh, d_entries)
|
TAILQ_FOREACH(d, &diskh, d_entries)
|
||||||
if (d->d_pid == pid)
|
if (d->d_pid == pid)
|
||||||
@ -207,28 +212,20 @@ checkfstab(flags, maxrun, docheck, checkit)
|
|||||||
d->d_pid = 0;
|
d->d_pid = 0;
|
||||||
nrun--;
|
nrun--;
|
||||||
|
|
||||||
if (TAILQ_EMPTY(&d->d_part))
|
if (TAILQ_EMPTY(&d->d_part)) {
|
||||||
|
TAILQ_REMOVE(&diskh, d, d_entries);
|
||||||
ndisks--;
|
ndisks--;
|
||||||
|
|
||||||
if (nextdisk == NULL) {
|
|
||||||
if (!TAILQ_EMPTY(&d->d_part)) {
|
|
||||||
if ((ret = startdisk(d, checkit)) != 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
} else if (nrun < maxrun && nrun < ndisks) {
|
|
||||||
for ( ;; ) {
|
|
||||||
nextdisk = TAILQ_NEXT(nextdisk, d_entries);
|
|
||||||
if (nextdisk == NULL)
|
|
||||||
nextdisk = TAILQ_FIRST(&diskh);
|
|
||||||
if (!TAILQ_EMPTY(&nextdisk->d_part)
|
|
||||||
&& nextdisk->d_pid == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((ret = startdisk(nextdisk, checkit)) != 0)
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (flags & CHECK_DEBUG) {
|
||||||
|
printf("Parallel end\n");
|
||||||
|
printpart();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(flags & CHECK_PREEN))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (sumstatus) {
|
if (sumstatus) {
|
||||||
p = TAILQ_FIRST(&badh);
|
p = TAILQ_FIRST(&badh);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
|
Loading…
Reference in New Issue
Block a user