From b62727f2522e8e7d74b7cf0c4f6a12b7056a57b4 Mon Sep 17 00:00:00 2001 From: scottl Date: Thu, 2 Jan 2014 01:44:14 +0000 Subject: [PATCH] MFC r260068, r260069, r260076 Add the -R option to allow fsck_ffs to restart itself when too many critical errors have been detected in a particular run. Clean up the global state variables so that a restart can happen correctly. Separate the global variables in fsck_ffs and fsdb to their own file. This fixes header sharing with fscd. Correctly initialize, static-ize, and remove global variables as needed in dir.c. This fixes a problem with lost+found directories that was causing a segfault. Correctly initialize, static-ize, and remove global variables as needed in suj.c. Initialize the suj globals before allocating the disk object, not after. Also ensure that 'preen' mode doesn't conflict with 'restart' mode Obtained from: Netflix git-svn-id: svn://svn.freebsd.org/base/stable/10@260178 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sbin/fsck_ffs/Makefile | 3 +- sbin/fsck_ffs/dir.c | 11 +-- sbin/fsck_ffs/fsck.h | 136 ++++++++++++++++--------------- sbin/fsck_ffs/fsck_ffs.8 | 7 +- sbin/fsck_ffs/fsutil.c | 19 +++++ sbin/fsck_ffs/globs.c | 165 ++++++++++++++++++++++++++++++++++++++ sbin/fsck_ffs/main.c | 35 +++++++- sbin/fsck_ffs/pass1.c | 5 ++ sbin/fsck_ffs/pass1b.c | 8 +- sbin/fsck_ffs/suj.c | 56 +++++++++---- sbin/fsck_ffs/utilities.c | 11 --- sbin/fsdb/Makefile | 2 +- 12 files changed, 349 insertions(+), 109 deletions(-) create mode 100644 sbin/fsck_ffs/globs.c diff --git a/sbin/fsck_ffs/Makefile b/sbin/fsck_ffs/Makefile index db2930bea..028a4867c 100644 --- a/sbin/fsck_ffs/Makefile +++ b/sbin/fsck_ffs/Makefile @@ -7,7 +7,8 @@ LINKS+= ${BINDIR}/fsck_ffs ${BINDIR}/fsck_4.2bsd MAN= fsck_ffs.8 MLINKS= fsck_ffs.8 fsck_ufs.8 fsck_ffs.8 fsck_4.2bsd.8 SRCS= dir.c ea.c fsutil.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c \ - pass4.c pass5.c setup.c suj.c utilities.c gjournal.c getmntopts.c + pass4.c pass5.c setup.c suj.c utilities.c gjournal.c getmntopts.c \ + globs.c DPADD= ${LIBUFS} LDADD= -lufs WARNS?= 2 diff --git a/sbin/fsck_ffs/dir.c b/sbin/fsck_ffs/dir.c index 965e3e398..7640f704b 100644 --- a/sbin/fsck_ffs/dir.c +++ b/sbin/fsck_ffs/dir.c @@ -48,20 +48,14 @@ __FBSDID("$FreeBSD$"); #include "fsck.h" -const char *lfname = "lost+found"; -int lfmode = 0700; -struct dirtemplate emptydir = { +static struct dirtemplate emptydir = { 0, DIRBLKSIZ, DT_UNKNOWN, 0, "", 0, 0, DT_UNKNOWN, 0, "" }; -struct dirtemplate dirhead = { +static struct dirtemplate dirhead = { 0, 12, DT_DIR, 1, ".", 0, DIRBLKSIZ - 12, DT_DIR, 2, ".." }; -struct odirtemplate odirhead = { - 0, 12, 1, ".", - 0, DIRBLKSIZ - 12, 2, ".." -}; static int chgino(struct inodesc *); static int dircheck(struct inodesc *, struct direct *); @@ -133,6 +127,7 @@ dirscan(struct inodesc *idesc) (size_t)dsize); dirty(bp); sbdirty(); + rerun = 1; } if (n & STOP) return (n); diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index 632d45433..a7b5961a5 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -192,15 +192,15 @@ struct bufarea { "Inode Block", \ "Directory Contents", \ "User Data" } -long readcnt[BT_NUMBUFTYPES]; -long totalreadcnt[BT_NUMBUFTYPES]; -struct timespec readtime[BT_NUMBUFTYPES]; -struct timespec totalreadtime[BT_NUMBUFTYPES]; -struct timespec startprog; +extern long readcnt[BT_NUMBUFTYPES]; +extern long totalreadcnt[BT_NUMBUFTYPES]; +extern struct timespec readtime[BT_NUMBUFTYPES]; +extern struct timespec totalreadtime[BT_NUMBUFTYPES]; +extern struct timespec startprog; -struct bufarea sblk; /* file system superblock */ -struct bufarea *pdirbp; /* current directory contents */ -struct bufarea *pbp; /* current inode block */ +extern struct bufarea sblk; /* file system superblock */ +extern struct bufarea *pdirbp; /* current directory contents */ +extern struct bufarea *pbp; /* current inode block */ #define dirty(bp) do { \ if (fswritefd < 0) \ @@ -219,7 +219,7 @@ struct bufarea *pbp; /* current inode block */ #define sblock (*sblk.b_un.b_fs) enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE}; -ino_t cursnapshot; +extern ino_t cursnapshot; struct inodesc { enum fixstate id_fix; /* policy on fixing errors */ @@ -282,63 +282,64 @@ struct inoinfo { u_int i_numblks; /* size of block array in bytes */ ufs2_daddr_t i_blks[1]; /* actually longer */ } **inphead, **inpsort; -long numdirs, dirhash, listmax, inplast; -long countdirs; /* number of directories we actually found */ +extern long numdirs, dirhash, listmax, inplast; +extern long countdirs; /* number of directories we actually found */ #define MIBSIZE 3 /* size of fsck sysctl MIBs */ -int adjrefcnt[MIBSIZE]; /* MIB command to adjust inode reference cnt */ -int adjblkcnt[MIBSIZE]; /* MIB command to adjust inode block count */ -int adjndir[MIBSIZE]; /* MIB command to adjust number of directories */ -int adjnbfree[MIBSIZE]; /* MIB command to adjust number of free blocks */ -int adjnifree[MIBSIZE]; /* MIB command to adjust number of free inodes */ -int adjnffree[MIBSIZE]; /* MIB command to adjust number of free frags */ -int adjnumclusters[MIBSIZE]; /* MIB command to adjust number of free clusters */ -int freefiles[MIBSIZE]; /* MIB command to free a set of files */ -int freedirs[MIBSIZE]; /* MIB command to free a set of directories */ -int freeblks[MIBSIZE]; /* MIB command to free a set of data blocks */ -struct fsck_cmd cmd; /* sysctl file system update commands */ -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 */ -u_int real_dev_bsize; /* actual disk sector size, not overriden */ -char nflag; /* assume a no response */ -char yflag; /* assume a yes response */ -int bkgrdflag; /* use a snapshot to run on an active system */ -int bflag; /* location of alternate super block */ -int debug; /* output debugging info */ -int Eflag; /* delete empty data blocks */ -int Zflag; /* zero empty data blocks */ -int inoopt; /* trim out unused inodes */ -char ckclean; /* only do work if not cleanly unmounted */ -int cvtlevel; /* convert to newer file system format */ -int bkgrdcheck; /* determine if background check is possible */ -int bkgrdsumadj; /* whether the kernel have ability to adjust superblock summary */ -char usedsoftdep; /* just fix soft dependency inconsistencies */ -char preen; /* just fix normal inconsistencies */ -char rerun; /* rerun fsck. Only used in non-preen mode */ -int returntosingle; /* 1 => return to single user mode on exit */ -char resolved; /* cleared if unresolved changes => not clean */ -char havesb; /* superblock has been read */ -char skipclean; /* skip clean file systems if preening */ -int fsmodified; /* 1 => write done to file system */ -int fsreadfd; /* file descriptor for reading file system */ -int fswritefd; /* file descriptor for writing file system */ -int surrender; /* Give up if reads fail */ - -ufs2_daddr_t maxfsblock; /* number of blocks in the file system */ -char *blockmap; /* ptr to primary blk allocation map */ -ino_t maxino; /* number of inodes in file system */ - -ino_t lfdir; /* lost & found directory inode number */ -const char *lfname; /* lost & found directory name */ -int lfmode; /* lost & found directory creation mode */ - -ufs2_daddr_t n_blks; /* number of blocks in use */ -ino_t n_files; /* number of files in use */ - -volatile sig_atomic_t got_siginfo; /* received a SIGINFO */ -volatile sig_atomic_t got_sigalarm; /* received a SIGALRM */ +extern int adjrefcnt[MIBSIZE]; /* MIB command to adjust inode reference cnt */ +extern int adjblkcnt[MIBSIZE]; /* MIB command to adjust inode block count */ +extern int adjndir[MIBSIZE]; /* MIB command to adjust number of directories */ +extern int adjnbfree[MIBSIZE]; /* MIB command to adjust number of free blocks */ +extern int adjnifree[MIBSIZE]; /* MIB command to adjust number of free inodes */ +extern int adjnffree[MIBSIZE]; /* MIB command to adjust number of free frags */ +extern int adjnumclusters[MIBSIZE]; /* MIB command to adjust number of free clusters */ +extern int freefiles[MIBSIZE]; /* MIB command to free a set of files */ +extern int freedirs[MIBSIZE]; /* MIB command to free a set of directories */ +extern int freeblks[MIBSIZE]; /* MIB command to free a set of data blocks */ +extern struct fsck_cmd cmd; /* sysctl file system update commands */ +extern char snapname[BUFSIZ]; /* when doing snapshots, the name of the file */ +extern char *cdevname; /* name of device being checked */ +extern long dev_bsize; /* computed value of DEV_BSIZE */ +extern long secsize; /* actual disk sector size */ +extern u_int real_dev_bsize; /* actual disk sector size, not overriden */ +extern char nflag; /* assume a no response */ +extern char yflag; /* assume a yes response */ +extern int bkgrdflag; /* use a snapshot to run on an active system */ +extern int bflag; /* location of alternate super block */ +extern int debug; /* output debugging info */ +extern int Eflag; /* delete empty data blocks */ +extern int Zflag; /* zero empty data blocks */ +extern int inoopt; /* trim out unused inodes */ +extern char ckclean; /* only do work if not cleanly unmounted */ +extern int cvtlevel; /* convert to newer file system format */ +extern int bkgrdcheck; /* determine if background check is possible */ +extern int bkgrdsumadj; /* whether the kernel have ability to adjust superblock summary */ +extern char usedsoftdep; /* just fix soft dependency inconsistencies */ +extern char preen; /* just fix normal inconsistencies */ +extern char rerun; /* rerun fsck. Only used in non-preen mode */ +extern int returntosingle; /* 1 => return to single user mode on exit */ +extern char resolved; /* cleared if unresolved changes => not clean */ +extern char havesb; /* superblock has been read */ +extern char skipclean; /* skip clean file systems if preening */ +extern int fsmodified; /* 1 => write done to file system */ +extern int fsreadfd; /* file descriptor for reading file system */ +extern int fswritefd; /* file descriptor for writing file system */ +extern int surrender; /* Give up if reads fail */ +extern int wantrestart; /* Restart fsck on early termination */ + +extern ufs2_daddr_t maxfsblock; /* number of blocks in the file system */ +extern char *blockmap; /* ptr to primary blk allocation map */ +extern ino_t maxino; /* number of inodes in file system */ + +extern ino_t lfdir; /* lost & found directory inode number */ +extern const char *lfname; /* lost & found directory name */ +extern int lfmode; /* lost & found directory creation mode */ + +extern ufs2_daddr_t n_blks; /* number of blocks in use */ +extern ino_t n_files; /* number of files in use */ + +extern volatile sig_atomic_t got_siginfo; /* received a SIGINFO */ +extern volatile sig_atomic_t got_sigalarm; /* received a SIGALRM */ #define clearinode(dp) \ if (sblock.fs_magic == FS_UFS1_MAGIC) { \ @@ -346,8 +347,8 @@ volatile sig_atomic_t got_sigalarm; /* received a SIGALRM */ } else { \ (dp)->dp2 = ufs2_zino; \ } -struct ufs1_dinode ufs1_zino; -struct ufs2_dinode ufs2_zino; +extern struct ufs1_dinode ufs1_zino; +extern struct ufs2_dinode ufs2_zino; #define setbmap(blkno) setbit(blockmap, blkno) #define testbmap(blkno) isset(blockmap, blkno) @@ -360,6 +361,7 @@ struct ufs2_dinode ufs2_zino; #define FOUND 0x10 #define EEXIT 8 /* Standard error exit. */ +#define ERESTART -1 int flushentry(void); /* @@ -428,6 +430,7 @@ void flush(int fd, struct bufarea *bp); void freeblk(ufs2_daddr_t blkno, long frags); void freeino(ino_t ino); void freeinodebuf(void); +void fsutilinit(void); int ftypeok(union dinode *dp); void getblk(struct bufarea *bp, ufs2_daddr_t blk, long size); struct bufarea *cgget(int cg); @@ -466,5 +469,6 @@ int setup(char *dev); void gjournal_check(const char *filesys); int suj_check(const char *filesys); void update_maps(struct cg *, struct cg*, int); +void fsckinit(void); #endif /* !_FSCK_H_ */ diff --git a/sbin/fsck_ffs/fsck_ffs.8 b/sbin/fsck_ffs/fsck_ffs.8 index adf08d7bb..828df2756 100644 --- a/sbin/fsck_ffs/fsck_ffs.8 +++ b/sbin/fsck_ffs/fsck_ffs.8 @@ -38,7 +38,7 @@ .Nd file system consistency check and interactive repair .Sh SYNOPSIS .Nm -.Op Fl BEFfnpryZ +.Op Fl BEFfnpRryZ .Op Fl b Ar block .Op Fl c Ar level .Op Fl m Ar mode @@ -266,6 +266,11 @@ which is assumed to be affirmative; do not open the file system for writing. .It Fl p Preen file systems (see above). +.It Fl R +Instruct fsck_ffs to restart itself if it encounters certain errors that +warrant another run. It will limit itself to a maximum of 10 restarts +in a given run in order to avoid an endless loop with extremely corrupted +filesystems. .It Fl r Free up excess unused inodes. Decreasing the number of preallocated inodes reduces the diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c index 16ef8193f..4b44fd4ec 100644 --- a/sbin/fsck_ffs/fsutil.c +++ b/sbin/fsck_ffs/fsutil.c @@ -74,6 +74,25 @@ static struct bufarea cgblk; /* backup buffer for cylinder group blocks */ static TAILQ_HEAD(buflist, bufarea) bufhead; /* head of buffer cache list */ static int numbufs; /* size of buffer cache */ static char *buftype[BT_NUMBUFTYPES] = BT_NAMES; +static struct bufarea *cgbufs; /* header for cylinder group cache */ +static int flushtries; /* number of tries to reclaim memory */ + +void +fsutilinit(void) +{ + diskreads = totaldiskreads = totalreads = 0; + bzero(&startpass, sizeof(struct timespec)); + bzero(&finishpass, sizeof(struct timespec)); + bzero(&slowio_starttime, sizeof(struct timeval)); + slowio_delay_usec = 10000; + slowio_pollcnt = 0; + bzero(&cgblk, sizeof(struct bufarea)); + TAILQ_INIT(&bufhead); + numbufs = 0; + /* buftype ? */ + cgbufs = NULL; + flushtries = 0; +} int ftypeok(union dinode *dp) diff --git a/sbin/fsck_ffs/globs.c b/sbin/fsck_ffs/globs.c new file mode 100644 index 000000000..c5b1e1b19 --- /dev/null +++ b/sbin/fsck_ffs/globs.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1980, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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. + */ + +#if 0 +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1980, 1986, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95"; +#endif /* not lint */ +#endif +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include "fsck.h" + +long readcnt[BT_NUMBUFTYPES]; +long totalreadcnt[BT_NUMBUFTYPES]; +struct timespec readtime[BT_NUMBUFTYPES]; +struct timespec totalreadtime[BT_NUMBUFTYPES]; +struct timespec startprog; +struct bufarea sblk; /* file system superblock */ +struct bufarea *pdirbp; /* current directory contents */ +struct bufarea *pbp; /* current inode block */ +ino_t cursnapshot; +long numdirs, dirhash, listmax, inplast; +long countdirs; /* number of directories we actually found */ +int adjrefcnt[MIBSIZE]; /* MIB command to adjust inode reference cnt */ +int adjblkcnt[MIBSIZE]; /* MIB command to adjust inode block count */ +int adjndir[MIBSIZE]; /* MIB command to adjust number of directories */ +int adjnbfree[MIBSIZE]; /* MIB command to adjust number of free blocks */ +int adjnifree[MIBSIZE]; /* MIB command to adjust number of free inodes */ +int adjnffree[MIBSIZE]; /* MIB command to adjust number of free frags */ +int adjnumclusters[MIBSIZE]; /* MIB command to adjust number of free clusters */ +int freefiles[MIBSIZE]; /* MIB command to free a set of files */ +int freedirs[MIBSIZE]; /* MIB command to free a set of directories */ +int freeblks[MIBSIZE]; /* MIB command to free a set of data blocks */ +struct fsck_cmd cmd; /* sysctl file system update commands */ +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 */ +u_int real_dev_bsize; /* actual disk sector size, not overriden */ +char nflag; /* assume a no response */ +char yflag; /* assume a yes response */ +int bkgrdflag; /* use a snapshot to run on an active system */ +int bflag; /* location of alternate super block */ +int debug; /* output debugging info */ +int Eflag; /* delete empty data blocks */ +int Zflag; /* zero empty data blocks */ +int inoopt; /* trim out unused inodes */ +char ckclean; /* only do work if not cleanly unmounted */ +int cvtlevel; /* convert to newer file system format */ +int bkgrdcheck; /* determine if background check is possible */ +int bkgrdsumadj; /* whether the kernel have ability to adjust superblock summary */ +char usedsoftdep; /* just fix soft dependency inconsistencies */ +char preen; /* just fix normal inconsistencies */ +char rerun; /* rerun fsck. Only used in non-preen mode */ +int returntosingle; /* 1 => return to single user mode on exit */ +char resolved; /* cleared if unresolved changes => not clean */ +char havesb; /* superblock has been read */ +char skipclean; /* skip clean file systems if preening */ +int fsmodified; /* 1 => write done to file system */ +int fsreadfd; /* file descriptor for reading file system */ +int fswritefd; /* file descriptor for writing file system */ +int surrender; /* Give up if reads fail */ +int wantrestart; /* Restart fsck on early termination */ +ufs2_daddr_t maxfsblock; /* number of blocks in the file system */ +char *blockmap; /* ptr to primary blk allocation map */ +ino_t maxino; /* number of inodes in file system */ +ino_t lfdir; /* lost & found directory inode number */ +const char *lfname; /* lost & found directory name */ +int lfmode; /* lost & found directory creation mode */ +ufs2_daddr_t n_blks; /* number of blocks in use */ +ino_t n_files; /* number of files in use */ +volatile sig_atomic_t got_siginfo; /* received a SIGINFO */ +volatile sig_atomic_t got_sigalarm; /* received a SIGALRM */ +struct ufs1_dinode ufs1_zino; +struct ufs2_dinode ufs2_zino; + +void +fsckinit(void) +{ + bzero(readcnt, sizeof(long) * BT_NUMBUFTYPES); + bzero(totalreadcnt, sizeof(long) * BT_NUMBUFTYPES); + bzero(readtime, sizeof(struct timespec) * BT_NUMBUFTYPES); + bzero(totalreadtime, sizeof(struct timespec) * BT_NUMBUFTYPES); + bzero(&startprog, sizeof(struct timespec));; + bzero(&sblk, sizeof(struct bufarea)); + pdirbp = NULL; + pbp = NULL; + cursnapshot = 0; + numdirs = dirhash = listmax = inplast = 0; + countdirs = 0; + bzero(adjrefcnt, sizeof(int) * MIBSIZE); + bzero(adjblkcnt, sizeof(int) * MIBSIZE); + bzero(adjndir, sizeof(int) * MIBSIZE); + bzero(adjnbfree, sizeof(int) * MIBSIZE); + bzero(adjnifree, sizeof(int) * MIBSIZE); + bzero(adjnffree, sizeof(int) * MIBSIZE); + bzero(adjnumclusters, sizeof(int) * MIBSIZE); + bzero(freefiles, sizeof(int) * MIBSIZE); + bzero(freedirs, sizeof(int) * MIBSIZE); + bzero(freeblks, sizeof(int) * MIBSIZE); + bzero(&cmd, sizeof(struct fsck_cmd)); + bzero(snapname, sizeof(char) * BUFSIZ); + cdevname = NULL; + dev_bsize = 0; + secsize = 0; + real_dev_bsize = 0; + bkgrdsumadj = 0; + usedsoftdep = 0; + rerun = 0; + returntosingle = 0; + resolved = 0; + havesb = 0; + fsmodified = 0; + fsreadfd = 0; + fswritefd = 0; + maxfsblock = 0; + blockmap = NULL; + maxino = 0; + lfdir = 0; + lfname = "lost+found"; + lfmode = 0700; + n_blks = 0; + n_files = 0; + got_siginfo = 0; + got_sigalarm = 0; + bzero(&ufs1_zino, sizeof(struct ufs1_dinode)); + bzero(&ufs2_zino, sizeof(struct ufs2_dinode)); +} diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c index 1a1c03bc7..08c774572 100644 --- a/sbin/fsck_ffs/main.c +++ b/sbin/fsck_ffs/main.c @@ -65,6 +65,8 @@ __FBSDID("$FreeBSD$"); #include "fsck.h" +int restarts; + static void usage(void) __dead2; static int argtoi(int flag, const char *req, const char *str, int base); static int checkfilesys(char *filesys); @@ -82,7 +84,7 @@ main(int argc, char *argv[]) sync(); skipclean = 1; inoopt = 0; - while ((ch = getopt(argc, argv, "b:Bc:CdEfFm:nprSyZ")) != -1) { + while ((ch = getopt(argc, argv, "b:Bc:CdEfFm:npRrSyZ")) != -1) { switch (ch) { case 'b': skipclean = 0; @@ -138,6 +140,9 @@ main(int argc, char *argv[]) ckclean++; break; + case 'R': + wantrestart = 1; + break; case 'r': inoopt++; break; @@ -186,8 +191,12 @@ main(int argc, char *argv[]) rlimit.rlim_cur = rlimit.rlim_max; (void)setrlimit(RLIMIT_DATA, &rlimit); } - while (argc-- > 0) - (void)checkfilesys(*argv++); + while (argc > 0) { + if (checkfilesys(*argv) == ERESTART) + continue; + argc--; + argv++; + } if (returntosingle) ret = 2; @@ -228,6 +237,8 @@ checkfilesys(char *filesys) iov = NULL; iovlen = 0; errmsg[0] = '\0'; + fsutilinit(); + fsckinit(); cdevname = filesys; if (debug && ckclean) @@ -550,8 +561,12 @@ checkfilesys(char *filesys) inostathead = NULL; if (fsmodified && !preen) printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); - if (rerun) + if (rerun) { + if (wantrestart && (restarts++ < 10) && + (preen || reply("RESTART"))) + return (ERESTART); printf("\n***** PLEASE RERUN FSCK *****\n"); + } if (chkdoreload(mntp) != 0) { if (!fsmodified) return (0); @@ -654,3 +669,15 @@ usage(void) getprogname()); exit(1); } + +void +infohandler(int sig __unused) +{ + got_siginfo = 1; +} + +void +alarmhandler(int sig __unused) +{ + got_sigalarm = 1; +} diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c index 319954122..67fba6eaa 100644 --- a/sbin/fsck_ffs/pass1.c +++ b/sbin/fsck_ffs/pass1.c @@ -68,6 +68,8 @@ pass1(void) u_int8_t *cp; int c, rebuildcg; + badblk = dupblk = lastino = 0; + /* * Set file system reserved blocks in used block map. */ @@ -463,6 +465,7 @@ pass1check(struct inodesc *idesc) ckfini(0); exit(EEXIT); } + rerun = 1; return (STOP); } } @@ -483,6 +486,7 @@ pass1check(struct inodesc *idesc) ckfini(0); exit(EEXIT); } + rerun = 1; return (STOP); } new = (struct dups *)Malloc(sizeof(struct dups)); @@ -492,6 +496,7 @@ pass1check(struct inodesc *idesc) ckfini(0); exit(EEXIT); } + rerun = 1; return (STOP); } new->dup = blkno; diff --git a/sbin/fsck_ffs/pass1b.c b/sbin/fsck_ffs/pass1b.c index e635935fc..69a23c207 100644 --- a/sbin/fsck_ffs/pass1b.c +++ b/sbin/fsck_ffs/pass1b.c @@ -80,8 +80,10 @@ pass1b(void) continue; idesc.id_number = inumber; if (inoinfo(inumber)->ino_state != USTATE && - (ckinode(dp, &idesc) & STOP)) + (ckinode(dp, &idesc) & STOP)) { + rerun = 1; return; + } } } } @@ -106,8 +108,10 @@ pass1bcheck(struct inodesc *idesc) if (dlp == muldup) break; } - if (muldup == 0 || duphead == muldup->next) + if (muldup == 0 || duphead == muldup->next) { + rerun = 1; return (STOP); + } } return (res); } diff --git a/sbin/fsck_ffs/suj.c b/sbin/fsck_ffs/suj.c index 5fca0f5fb..9d6a2eccd 100644 --- a/sbin/fsck_ffs/suj.c +++ b/sbin/fsck_ffs/suj.c @@ -125,26 +125,26 @@ struct suj_cg { int sc_cgx; }; -LIST_HEAD(cghd, suj_cg) cghash[SUJ_HASHSIZE]; -LIST_HEAD(dblkhd, data_blk) dbhash[SUJ_HASHSIZE]; -struct suj_cg *lastcg; -struct data_blk *lastblk; +static LIST_HEAD(cghd, suj_cg) cghash[SUJ_HASHSIZE]; +static LIST_HEAD(dblkhd, data_blk) dbhash[SUJ_HASHSIZE]; +static struct suj_cg *lastcg; +static struct data_blk *lastblk; -TAILQ_HEAD(seghd, suj_seg) allsegs; -uint64_t oldseq; +static TAILQ_HEAD(seghd, suj_seg) allsegs; +static uint64_t oldseq; static struct uufsd *disk = NULL; static struct fs *fs = NULL; -ino_t sujino; +static ino_t sujino; /* * Summary statistics. */ -uint64_t freefrags; -uint64_t freeblocks; -uint64_t freeinos; -uint64_t freedir; -uint64_t jbytes; -uint64_t jrecs; +static uint64_t freefrags; +static uint64_t freeblocks; +static uint64_t freeinos; +static uint64_t freedir; +static uint64_t jbytes; +static uint64_t jrecs; static jmp_buf jmpbuf; @@ -155,6 +155,7 @@ static void ino_decr(ino_t); static void ino_adjust(struct suj_ino *); static void ino_build(struct suj_ino *); static int blk_isfree(ufs2_daddr_t); +static void initsuj(void); static void * errmalloc(size_t n) @@ -2413,7 +2414,7 @@ struct jextent { int je_blocks; /* Disk block count. */ }; -struct jblocks *suj_jblocks; +static struct jblocks *suj_jblocks; static struct jblocks * jblocks_create(void) @@ -2673,8 +2674,8 @@ suj_check(const char *filesys) struct suj_seg *seg; struct suj_seg *segn; + initsuj(); opendisk(filesys); - TAILQ_INIT(&allsegs); /* * Set an exit point when SUJ check failed @@ -2763,3 +2764,28 @@ suj_check(const char *filesys) return (0); } + +static void +initsuj(void) +{ + int i; + + for (i = 0; i < SUJ_HASHSIZE; i++) { + LIST_INIT(&cghash[i]); + LIST_INIT(&dbhash[i]); + } + lastcg = NULL; + lastblk = NULL; + TAILQ_INIT(&allsegs); + oldseq = 0; + disk = NULL; + fs = NULL; + sujino = 0; + freefrags = 0; + freeblocks = 0; + freeinos = 0; + freedir = 0; + jbytes = 0; + jrecs = 0; + suj_jblocks = NULL; +} diff --git a/sbin/fsck_ffs/utilities.c b/sbin/fsck_ffs/utilities.c index 5e7d69c1f..4e82c3164 100644 --- a/sbin/fsck_ffs/utilities.c +++ b/sbin/fsck_ffs/utilities.c @@ -108,14 +108,3 @@ blockcheck(char *origname) return (origname); } -void -infohandler(int sig __unused) -{ - got_siginfo = 1; -} - -void -alarmhandler(int sig __unused) -{ - got_sigalarm = 1; -} diff --git a/sbin/fsdb/Makefile b/sbin/fsdb/Makefile index 65333ef07..f921e8982 100644 --- a/sbin/fsdb/Makefile +++ b/sbin/fsdb/Makefile @@ -6,7 +6,7 @@ PROG= fsdb MAN= fsdb.8 SRCS= fsdb.c fsdbutil.c \ dir.c ea.c fsutil.c inode.c pass1.c pass1b.c pass2.c pass3.c pass4.c \ - pass5.c setup.c utilities.c ffs_subr.c ffs_tables.c + pass5.c setup.c utilities.c ffs_subr.c ffs_tables.c globs.c CFLAGS+= -I${.CURDIR}/../fsck_ffs WARNS?= 2 LDADD= -ledit -ltermcap -- 2.45.0