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:
phk 2001-03-30 08:01:34 +00:00
parent 759dbf1c02
commit c59a8fb48c
4 changed files with 64 additions and 61 deletions

View File

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

View File

@ -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) && \

View File

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

View File

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