From 9fdc3275bee6341e05021fe4f0acf93c1119a8dc Mon Sep 17 00:00:00 2001 From: mpp Date: Sat, 26 Jan 2008 12:03:26 +0000 Subject: Sync up quotacheck's preen.c with fsck's. This makes quotacheck process parallel checks in the same way as fsck, since fsck supports pass numbers other than 0, 1 or 2. Without this, quotacheck would ignore file systems with pass numbers > 2. The -l (maxrun) option is now deprecated and can be tuned with pass numbers in /etc/fstab if needed. --- sbin/quotacheck/Makefile | 4 +- sbin/quotacheck/preen.c | 355 +++++++++++++++++++++---------------------- sbin/quotacheck/quotacheck.8 | 3 + sbin/quotacheck/quotacheck.c | 31 ++-- sbin/quotacheck/quotacheck.h | 43 ++++++ 5 files changed, 237 insertions(+), 199 deletions(-) create mode 100644 sbin/quotacheck/quotacheck.h (limited to 'sbin') diff --git a/sbin/quotacheck/Makefile b/sbin/quotacheck/Makefile index b54eda3..5184bf2 100644 --- a/sbin/quotacheck/Makefile +++ b/sbin/quotacheck/Makefile @@ -2,10 +2,10 @@ # @(#)Makefile 8.1 (Berkeley) 6/5/93 PROG= quotacheck -SRCS= quotacheck.c preen.c utilities.c +SRCS= quotacheck.c preen.c fsutil.c utilities.c WARNS?= 2 MAN= quotacheck.8 -.PATH: ${.CURDIR}/../fsck_ffs +.PATH: ${.CURDIR}/../fsck ${.CURDIR}/../fsck_ffs .include diff --git a/sbin/quotacheck/preen.c b/sbin/quotacheck/preen.c index 7856091..adf2321 100644 --- a/sbin/quotacheck/preen.c +++ b/sbin/quotacheck/preen.c @@ -1,3 +1,5 @@ +/* $NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $ */ + /* * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. @@ -25,259 +27,254 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * $FreeBSD$ */ -#if 0 +#include #ifndef lint -static const char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95"; -#endif /* not lint */ +#if 0 +static char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95"; +#else +__RCSID("$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $"); #endif -#include -__FBSDID("$FreeBSD$"); +#endif /* not lint */ #include #include #include +#include -#include -#include - +#include #include -#include #include #include #include #include #include -char *blockcheck(char *origname); +#include "quotacheck.h" +struct partentry { + TAILQ_ENTRY(partentry) p_entries; + char *p_devname; /* device name */ + char *p_mntpt; /* mount point */ + char *p_type; /* file system type */ + struct quotaname *p_quota; /* quota file info ptr */ +}; -struct part { - struct part *next; /* forward link of partitions on disk */ - char *name; /* device name */ - char *fsname; /* mounted file system name */ - void *auxdata; /* auxiliary data for application */ -} *badlist, **badnext = &badlist; +TAILQ_HEAD(part, partentry) badh; -struct disk { - char *name; /* disk base name */ - struct disk *next; /* forward link for list of disks */ - struct part *part; /* head of list of partitions on disk */ - int pid; /* If != 0, pid of proc working on */ -} *disks; +struct diskentry { + TAILQ_ENTRY(diskentry) d_entries; + char *d_name; /* disk base name */ + TAILQ_HEAD(prt, partentry) d_part; /* list of partitions on disk */ + int d_pid; /* 0 or pid of fsck proc */ +}; -int nrun, ndisks; +TAILQ_HEAD(disk, diskentry) diskh; -static void addpart(char *name, char *fsname, void *auxdata); -static struct disk *finddisk(char *name); -static int startdisk(struct disk *dk, - int (*checkit)(char *, char *, void *, int)); +static struct diskentry *finddisk(const char *); +static void addpart(const char *, const char *, const char *, + struct quotaname *); +static int startdisk(struct diskentry *); +extern void *emalloc(size_t); +extern char *estrdup(const char *); int -checkfstab(int preen, int maxrun, void *(*docheck)(struct fstab *), - int (*chkit)(char *, char *, void *, int)) +checkfstab() { - struct fstab *fsp; - struct disk *dk, *nextdisk; - struct part *pt; - int ret, pid, retcode, passno, sumstatus, status; - void *auxdata; + struct fstab *fs; + struct diskentry *d, *nextdisk; + struct partentry *p; + int ret, pid, retcode, passno, sumstatus, status, nextpass; char *name; + struct quotaname *qnp; + + TAILQ_INIT(&badh); + TAILQ_INIT(&diskh); sumstatus = 0; - for (passno = 1; passno <= 2; passno++) { + + nextpass = 0; + for (passno = 1; nextpass != INT_MAX; passno = nextpass) { + nextpass = INT_MAX; if (setfsent() == 0) { - fprintf(stderr, "Can't open checklist file: %s\n", - _PATH_FSTAB); + warnx("Can't open checklist file: %s\n", _PATH_FSTAB); return (8); } - while ((fsp = getfsent()) != 0) { - if ((auxdata = (*docheck)(fsp)) == NULL) + while ((fs = getfsent()) != 0) { + name = fs->fs_spec; + if (fs->fs_passno > passno && fs->fs_passno < nextpass) + nextpass = fs->fs_passno; + + if (passno != fs->fs_passno) + continue; + + if ((qnp = needchk(fs)) == NULL) + continue; + + if (passno == 1) { + sumstatus = chkquota(name, fs->fs_file, qnp); + + if (sumstatus) + return (sumstatus); + continue; + } + if (name == NULL) { + (void) fprintf(stderr, + "BAD DISK NAME %s\n", fs->fs_spec); + sumstatus |= 8; continue; - if (preen == 0 || - (passno == 1 && fsp->fs_passno == 1)) { - if ((name = blockcheck(fsp->fs_spec)) != 0) { - if ((sumstatus = (*chkit)(name, - fsp->fs_file, auxdata, 0)) != 0) - return (sumstatus); - } else if (preen) - return (8); - } else if (passno == 2 && fsp->fs_passno > 1) { - if ((name = blockcheck(fsp->fs_spec)) == NULL) { - fprintf(stderr, "BAD DISK NAME %s\n", - fsp->fs_spec); - sumstatus |= 8; - continue; - } - addpart(name, fsp->fs_file, auxdata); } + addpart(fs->fs_vfstype, name, fs->fs_file, qnp); } - if (preen == 0) - return (0); - } - if (preen) { - if (maxrun == 0) - maxrun = ndisks; - if (maxrun > ndisks) - maxrun = ndisks; - nextdisk = disks; - for (passno = 0; passno < maxrun; ++passno) { - while ((ret = startdisk(nextdisk, chkit)) && nrun > 0) - sleep(10); - if (ret) - return (ret); - nextdisk = nextdisk->next; + + if (passno == 1) + continue; + + TAILQ_FOREACH(nextdisk, &diskh, d_entries) { + if ((ret = startdisk(nextdisk)) != 0) + return ret; } + while ((pid = wait(&status)) != -1) { - for (dk = disks; dk; dk = dk->next) - if (dk->pid == pid) + TAILQ_FOREACH(d, &diskh, d_entries) + if (d->d_pid == pid) break; - if (dk == 0) { - printf("Unknown pid %d\n", pid); + + if (d == NULL) { + warnx("Unknown pid %d\n", pid); continue; } + if (WIFEXITED(status)) retcode = WEXITSTATUS(status); else retcode = 0; + + p = TAILQ_FIRST(&d->d_part); + if (WIFSIGNALED(status)) { - printf("%s (%s): EXITED WITH SIGNAL %d\n", - dk->part->name, dk->part->fsname, - WTERMSIG(status)); + (void) fprintf(stderr, + "%s: %s (%s): EXITED WITH SIGNAL %d\n", + p->p_type, p->p_devname, p->p_mntpt, + WTERMSIG(status)); retcode = 8; } + + TAILQ_REMOVE(&d->d_part, p, p_entries); + if (retcode != 0) { + TAILQ_INSERT_TAIL(&badh, p, p_entries); sumstatus |= retcode; - *badnext = dk->part; - badnext = &dk->part->next; - dk->part = dk->part->next; - *badnext = NULL; - } else - dk->part = dk->part->next; - dk->pid = 0; - nrun--; - if (dk->part == NULL) - ndisks--; - - if (nextdisk == NULL) { - if (dk->part) { - while ((ret = startdisk(dk, chkit)) && - nrun > 0) - sleep(10); - if (ret) - return (ret); - } - } else if (nrun < maxrun && nrun < ndisks) { - for ( ;; ) { - if ((nextdisk = nextdisk->next) == NULL) - nextdisk = disks; - if (nextdisk->part != NULL && - nextdisk->pid == 0) - break; - } - while ((ret = startdisk(nextdisk, chkit)) && - nrun > 0) - sleep(10); - if (ret) - return (ret); + } else { + free(p->p_type); + free(p->p_devname); + free(p); + } + d->d_pid = 0; + + if (TAILQ_EMPTY(&d->d_part)) { + TAILQ_REMOVE(&diskh, d, d_entries); + } else { + if ((ret = startdisk(d)) != 0) + return ret; } } } + if (sumstatus) { - if (badlist == 0) + p = TAILQ_FIRST(&badh); + if (p == NULL) return (sumstatus); - fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", - badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); - for (pt = badlist; pt; pt = pt->next) - fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname, - pt->next ? ", " : "\n"); - return (sumstatus); + + (void) fprintf(stderr, + "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", + TAILQ_NEXT(p, p_entries) ? "S" : "", + "UNEXPECTED INCONSISTENCY:"); + + for (; p; p = TAILQ_NEXT(p, p_entries)) + (void) fprintf(stderr, + "%s: %s (%s)%s", p->p_type, p->p_devname, + p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n"); + + return sumstatus; } - (void)endfsent(); + (void) endfsent(); return (0); } -static struct disk * -finddisk(char *name) + +static struct diskentry * +finddisk(const char *name) { - struct disk *dk, **dkp; - char *p; - size_t len; + const char *p; + size_t len = 0; + struct diskentry *d; p = strrchr(name, '/'); - p = p == NULL ? name : p + 1; - while (*p != '\0' && !isdigit((u_char)*p)) + if (p == NULL) + p = name; + else p++; - while (isdigit((u_char)*p)) - p++; - len = (size_t)(p - name); - for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { - if (strncmp(dk->name, name, len) == 0 && - dk->name[len] == 0) - return (dk); - } - if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - dk = *dkp; - if ((dk->name = malloc(len + 1)) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - (void)strncpy(dk->name, name, len); - dk->name[len] = '\0'; - dk->part = NULL; - dk->next = NULL; - dk->pid = 0; - ndisks++; - return (dk); + for (; *p && !isdigit(*p); p++) + continue; + for (; *p && isdigit(*p); p++) + continue; + len = p - name; + if (len == 0) + len = strlen(name); + + TAILQ_FOREACH(d, &diskh, d_entries) + if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0) + return d; + + d = emalloc(sizeof(*d)); + d->d_name = estrdup(name); + d->d_name[len] = '\0'; + TAILQ_INIT(&d->d_part); + d->d_pid = 0; + + TAILQ_INSERT_TAIL(&diskh, d, d_entries); + + return d; } static void -addpart(char *name, char *fsname, void *auxdata) +addpart(const char *type, const char *devname, const char *mntpt, + struct quotaname *qnp) { - struct disk *dk = finddisk(name); - struct part *pt, **ppt = &dk->part; + struct diskentry *d = finddisk(devname); + struct partentry *p; - for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) - if (strcmp(pt->name, name) == 0) { - printf("%s in fstab more than once!\n", name); + TAILQ_FOREACH(p, &d->d_part, p_entries) + if (strcmp(p->p_devname, devname) == 0) { + warnx("%s in fstab more than once!\n", devname); return; } - if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - pt = *ppt; - if ((pt->name = malloc(strlen(name) + 1)) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - (void)strcpy(pt->name, name); - if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - (void)strcpy(pt->fsname, fsname); - pt->next = NULL; - pt->auxdata = auxdata; + + p = emalloc(sizeof(*p)); + p->p_devname = estrdup(devname); + p->p_mntpt = estrdup(mntpt); + p->p_type = estrdup(type); + p->p_quota = qnp; + + TAILQ_INSERT_TAIL(&d->d_part, p, p_entries); } + static int -startdisk(struct disk *dk, int (*checkit)(char *, char *, void *, int)) +startdisk(struct diskentry *d) { - struct part *pt = dk->part; + struct partentry *p = TAILQ_FIRST(&d->d_part); - dk->pid = fork(); - if (dk->pid < 0) { + d->d_pid = fork(); + if (d->d_pid < 0) { perror("fork"); return (8); } - if (dk->pid == 0) - exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1)); - nrun++; + if (d->d_pid == 0) + exit(chkquota(p->p_devname, p->p_mntpt, p->p_quota)); return (0); } - diff --git a/sbin/quotacheck/quotacheck.8 b/sbin/quotacheck/quotacheck.8 index 1195290..5ba2ad7 100644 --- a/sbin/quotacheck/quotacheck.8 +++ b/sbin/quotacheck/quotacheck.8 @@ -80,6 +80,9 @@ If this option is omitted, or if .Ar maxrun is zero, parallel passes are run as per .Xr fsck 8 . +This option is deprecated and parallel passes are always run +as per +.Xf fsck 8. .It Fl u Only user quotas listed in .Pa /etc/fstab diff --git a/sbin/quotacheck/quotacheck.c b/sbin/quotacheck/quotacheck.c index 7e4c026..d4e819f 100644 --- a/sbin/quotacheck/quotacheck.c +++ b/sbin/quotacheck/quotacheck.c @@ -67,6 +67,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include "quotacheck.h" + char *qfname = QUOTAFILENAME; char *qfextension[] = INITQFNAMES; char *quotagroup = QUOTAGROUP; @@ -92,11 +94,6 @@ union dinode { ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ (dp)->dp1.field : (dp)->dp2.field) -struct quotaname { - long flags; - char grpqfname[PATH_MAX]; - char usrqfname[PATH_MAX]; -}; #define HASUSR 1 #define HASGRP 2 @@ -121,9 +118,6 @@ struct fileusage * addid(u_long, int, char *, char *); char *blockcheck(char *); void bread(ufs2_daddr_t, char *, long); -extern int checkfstab(int, int, void * (*)(struct fstab *), - int (*)(char *, char *, struct quotaname *)); -int chkquota(char *, char *, struct quotaname *); void freeinodebuf(void); union dinode * getnextinode(ino_t); @@ -131,7 +125,7 @@ int getquotagid(void); int hasquota(struct fstab *, int, char **); struct fileusage * lookup(u_long, int); -void *needchk(struct fstab *); +struct quotaname *needchk(struct fstab *); int oneof(char *, char*[], int); void printchanges(char *, int, struct dqblk *, struct fileusage *, u_long); void setinodebuf(ino_t); @@ -146,7 +140,7 @@ main(argc, argv) struct fstab *fs; struct passwd *pw; struct group *gr; - struct quotaname *auxdata; + struct quotaname *qnp; int i, argnum, maxrun, errs, ch; long done = 0; char *name; @@ -196,22 +190,21 @@ main(argc, argv) endpwent(); } /* - * Setting maxrun (-l) makes no sense without the -a flag. - * Historically this was never an error, so we just warn. + * The maxrun (-l) option is now deprecated. */ - if (maxrun > 0 && !aflag) - warnx("ignoring -l without -a"); + if (maxrun > 0) + warnx("the -l option is now deprecated"); if (aflag) - exit(checkfstab(1, maxrun, needchk, chkquota)); + exit(checkfstab()); if (setfsent() == 0) errx(1, "%s: can't open", FSTAB); while ((fs = getfsent()) != NULL) { if (((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) && - (auxdata = needchk(fs)) && + (qnp = needchk(fs)) && (name = blockcheck(fs->fs_spec))) { done |= 1 << argnum; - errs += chkquota(name, fs->fs_file, auxdata); + errs += chkquota(name, fs->fs_file, qnp); } } endfsent(); @@ -231,7 +224,7 @@ usage() exit(1); } -void * +struct quotaname * needchk(fs) struct fstab *fs; { @@ -279,6 +272,8 @@ chkquota(fsname, mntpt, qnp) char *cp; struct stat sb; + if (qnp == NULL) + err(1, "null quota information passed to chkquota()\n"); if ((fi = open(fsname, O_RDONLY, 0)) < 0) { warn("%s", fsname); return (1); diff --git a/sbin/quotacheck/quotacheck.h b/sbin/quotacheck/quotacheck.h new file mode 100644 index 0000000..aad9d30 --- /dev/null +++ b/sbin/quotacheck/quotacheck.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1980, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Robert Elz at The University of Melbourne. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +struct quotaname { + long flags; + char grpqfname[PATH_MAX]; + char usrqfname[PATH_MAX]; +}; + +extern int checkfstab(); +extern int chkquota(char *, char *, struct quotaname *); +extern struct quotaname *needchk(struct fstab *); -- cgit v1.1