From 38375c40b8a306ea04b5a442334a0cafd6ac746d Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Mon, 16 Apr 2001 22:22:21 +0000 Subject: [PATCH] Minor background cleanups: 1) Set the FS_NEEDSFSCK flag when unexpected problems are encountered. 2) Clear the FS_NEEDSFSCK flag after a successful foreground cleanup. 3) Refuse to run in background when the FS_NEEDSFSCK flag is set. 4) Avoid taking and removing a snapshot when the filesystem is already clean. 5) Properly implement the force cleaning (-f) flag when in preen mode. Note that you need to have revision 1.21 (date: 2001/04/14 05:26:28) of fs.h installed in defining FS_NEEDSFSCK for this to compile. --- sbin/fsck_ffs/fsck.h | 2 +- sbin/fsck_ffs/fsutil.c | 28 ++++++++++++++++++++++++++-- sbin/fsck_ffs/main.c | 34 +++++++++++++++++++++++++++++----- sbin/fsck_ffs/pass5.c | 13 +++++++++---- sbin/fsck_ffs/setup.c | 40 ++++++++++++++++++++++------------------ 5 files changed, 87 insertions(+), 30 deletions(-) diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index e598b3583a0e..dee89c72c857 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -203,7 +203,6 @@ char snapname[BUFSIZ]; /* when doing snapshots, the name of the file */ char *cdevname; /* name of device being checked */ long dev_bsize; /* computed value of DEV_BSIZE */ long secsize; /* actual disk sector size */ -char fflag; /* force check, ignore clean flag */ char nflag; /* assume a no response */ char yflag; /* assume a yes response */ int bkgrdflag; /* use a snapshot to run on an active system */ @@ -313,6 +312,7 @@ void pfatal __P((const char *fmt, ...)); void pinode __P((ino_t ino)); void propagate __P((void)); void pwarn __P((const char *fmt, ...)); +int readsb __P((int listerr)); int reply __P((char *question)); void rwerror __P((char *mesg, ufs_daddr_t blk)); void setinodebuf __P((ino_t)); diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c index fa06dfbc8666..c743acab83aa 100644 --- a/sbin/fsck_ffs/fsutil.c +++ b/sbin/fsck_ffs/fsutil.c @@ -321,7 +321,8 @@ ckfini(markclean) errx(EEXIT, "panic: lost %d buffers", bufhead.b_size - cnt); pbp = pdirbp = (struct bufarea *)0; if (cursnapshot == 0 && sblock.fs_clean != markclean) { - sblock.fs_clean = markclean; + if ((sblock.fs_clean = markclean) != 0) + sblock.fs_flags &= ~(FS_UNCLEAN | FS_NEEDSFSCK); sbdirty(); ofsmodified = fsmodified; flush(fswritefd, &sblk); @@ -336,7 +337,7 @@ ckfini(markclean) printf("\n***** FILE SYSTEM STILL DIRTY *****\n"); rerun = 1; } - if (debug) + if (debug && totalreads > 0) printf("cache missed %ld of %ld (%d%%)\n", diskreads, totalreads, (int)(diskreads * 100 / totalreads)); (void)close(fsreadfd); @@ -649,6 +650,19 @@ pfatal(fmt, va_alist) if (usedsoftdep) (void)fprintf(stderr, "\nUNEXPECTED SOFT UPDATE INCONSISTENCY\n"); + /* + * Force foreground fsck to clean up inconsistency. + */ + if (bkgrdflag) { + cmd.value = FS_NEEDSFSCK; + cmd.size = 1; + 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"); + ckfini(0); + exit(EEXIT); + } return; } if (cdevname == NULL) @@ -658,6 +672,16 @@ pfatal(fmt, va_alist) (void)fprintf(stderr, "\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n", cdevname, usedsoftdep ? " SOFT UPDATE " : " "); + /* + * Force foreground fsck to clean up inconsistency. + */ + if (bkgrdflag) { + cmd.value = FS_NEEDSFSCK; + cmd.size = 1; + if (sysctlbyname("vfs.ffs.setflags", 0, 0, + &cmd, sizeof cmd) == -1) + pwarn("CANNOT SET FS_NEEDSFSCK FLAG\n"); + } ckfini(0); exit(EEXIT); } diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c index a9e7e90b5e70..83bb3126a2f7 100644 --- a/sbin/fsck_ffs/main.c +++ b/sbin/fsck_ffs/main.c @@ -47,6 +47,7 @@ static const char rcsid[] = #include #include +#include #include #include #include @@ -199,6 +200,7 @@ checkfilesys(filesys, mntpt, auxdata, child) cdevname = filesys; if (debug && preen) pwarn("starting\n"); + sblock_init(); /* * If we are to do a background check: @@ -211,14 +213,35 @@ checkfilesys(filesys, mntpt, auxdata, child) if (bkgrdflag) { if (mntp == NULL) { bkgrdflag = 0; - pwarn("NOT MOUNTED, CANNOT RUN IN BACKGROUND\n"); + pfatal("NOT MOUNTED, CANNOT RUN IN BACKGROUND\n"); } else if ((mntp->f_flags & MNT_SOFTDEP) == 0) { bkgrdflag = 0; - pwarn("NOT USING SOFT UPDATES, CANNOT RUN IN BACKGROUND\n"); + pfatal("NOT USING SOFT UPDATES, %s\n", + "CANNOT RUN IN BACKGROUND"); } else if ((mntp->f_flags & MNT_RDONLY) != 0) { bkgrdflag = 0; - pwarn("MOUNTED READ-ONLY, CANNOT RUN IN BACKGROUND\n"); - } else { + pfatal("MOUNTED READ-ONLY, CANNOT RUN IN BACKGROUND\n"); + } else if ((fsreadfd = open(filesys, O_RDONLY)) >= 0) { + if (readsb(0) != 0) { + if (sblock.fs_flags & FS_NEEDSFSCK) { + bkgrdflag = 0; + pfatal("UNEXPECTED INCONSISTENCY, %s\n", + "CANNOT RUN IN BACKGROUND\n"); + } + if ((sblock.fs_flags & FS_UNCLEAN) == 0 && + skipclean && preen) { + /* + * filesystem is clean; + * skip snapshot and report it clean + */ + pwarn("FILESYSTEM CLEAN; %s\n", + "SKIPPING CHECKS"); + goto clean; + } + } + close(fsreadfd); + } + if (bkgrdflag) { snprintf(snapname, sizeof snapname, "%s/.fsck_snapshot", mntp->f_mntonname); args.fspec = snapname; @@ -228,7 +251,7 @@ checkfilesys(filesys, mntpt, auxdata, child) if (errno == EEXIST && unlink(snapname) == 0) continue; bkgrdflag = 0; - pwarn("CANNOT CREATE SNAPSHOT %s: %s\n", + pfatal("CANNOT CREATE SNAPSHOT %s: %s\n", snapname, strerror(errno)); break; } @@ -243,6 +266,7 @@ checkfilesys(filesys, mntpt, auxdata, child) pfatal("CAN'T CHECK FILE SYSTEM."); return (0); case -1: + clean: pwarn("clean, %ld free ", sblock.fs_cstotal.cs_nffree + sblock.fs_frag * sblock.fs_cstotal.cs_nbfree); printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c index 5d334f901284..58d706c59506 100644 --- a/sbin/fsck_ffs/pass5.c +++ b/sbin/fsck_ffs/pass5.c @@ -377,7 +377,12 @@ check_maps(map1, map2, mapsize, startvalue, name, opcode, skip, limit) char buf[BUFSIZE]; long i, j, k, l, m, n, size; int astart, aend, ustart, uend; + void (*msg) __P((const char *fmt, ...)); + if (bkgrdflag) + msg = pfatal; + else + msg = pwarn; astart = ustart = aend = uend = -1; for (i = 0; i < mapsize; i++) { j = *map1++; @@ -398,10 +403,10 @@ check_maps(map1, map2, mapsize, startvalue, name, opcode, skip, limit) continue; } if (astart == aend) - pfatal("ALLOCATED %s %d MARKED FREE\n", + (*msg)("ALLOCATED %s %d MARKED FREE\n", name, astart); else - pfatal("%s %sS %d-%d MARKED FREE\n", + (*msg)("%s %sS %d-%d MARKED FREE\n", "ALLOCATED", name, astart, aend); astart = aend = n; } else { @@ -452,9 +457,9 @@ check_maps(map1, map2, mapsize, startvalue, name, opcode, skip, limit) } if (astart != -1) if (astart == aend) - pfatal("ALLOCATED %s %d MARKED FREE\n", name, astart); + (*msg)("ALLOCATED %s %d MARKED FREE\n", name, astart); else - pfatal("ALLOCATED %sS %d-%d MARKED FREE\n", + (*msg)("ALLOCATED %sS %d-%d MARKED FREE\n", name, astart, aend); if (ustart != -1) { size = uend - ustart + 1; diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c index d8d77a55e93c..517547dd9be4 100644 --- a/sbin/fsck_ffs/setup.c +++ b/sbin/fsck_ffs/setup.c @@ -62,7 +62,6 @@ struct bufarea asblk; static void badsb __P((int listerr, char *s)); static int calcsb __P((char *dev, int devfd, struct fs *fs)); static struct disklabel *getdisklabel __P((char *s, int fd)); -static int readsb __P((int listerr)); /* * Read in a superblock finding an alternate if necessary. @@ -74,8 +73,7 @@ setup(dev) char *dev; { long cg, size, asked, i, j; - long skipclean, bmapsize; - struct disklabel *lp; + long bmapsize; off_t sizepb; struct stat statb; struct fs proto; @@ -83,7 +81,6 @@ setup(dev) havesb = 0; fswritefd = -1; cursnapshot = 0; - skipclean = fflag ? 0 : preen; if (stat(dev, &statb) < 0) { printf("Can't stat %s: %s\n", dev, strerror(errno)); if (bkgrdflag) { @@ -160,18 +157,6 @@ setup(dev) } if (preen == 0) printf("\n"); - fsmodified = 0; - lfdir = 0; - initbarea(&sblk); - initbarea(&asblk); - sblk.b_un.b_buf = malloc(SBSIZE); - asblk.b_un.b_buf = malloc(SBSIZE); - if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) - errx(EEXIT, "cannot allocate space for superblock"); - if ((lp = getdisklabel(NULL, fsreadfd))) - dev_bsize = secsize = lp->d_secsize; - else - dev_bsize = secsize = DEV_BSIZE; /* * Read in the superblock, looking for alternates if necessary */ @@ -200,7 +185,7 @@ setup(dev) pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); bflag = 0; } - if (skipclean && sblock.fs_clean) { + if (skipclean && preen && sblock.fs_clean) { pwarn("FILESYSTEM CLEAN; SKIPPING CHECKS\n"); return (-1); } @@ -372,7 +357,7 @@ setup(dev) /* * Read in the super block and its summary info. */ -static int +int readsb(listerr) int listerr; { @@ -490,6 +475,25 @@ badsb(listerr, s) pfatal("BAD SUPER BLOCK: %s\n", s); } +sblock_init() +{ + struct disklabel *lp; + + fswritefd = -1; + fsmodified = 0; + lfdir = 0; + initbarea(&sblk); + initbarea(&asblk); + sblk.b_un.b_buf = malloc(SBSIZE); + asblk.b_un.b_buf = malloc(SBSIZE); + if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) + errx(EEXIT, "cannot allocate space for superblock"); + if ((lp = getdisklabel(NULL, fsreadfd))) + dev_bsize = secsize = lp->d_secsize; + else + dev_bsize = secsize = DEV_BSIZE; +} + /* * Calculate a prototype superblock based on information in the disk label. * When done the cgsblock macro can be calculated and the fs_ncg field