From 10c5ccc30ae8155c4d8bd25aeffd9ed0e476c387 Mon Sep 17 00:00:00 2001 From: julian Date: Sun, 8 Mar 1998 09:59:44 +0000 Subject: Reviewed by: dyson@freebsd.org (john Dyson), dg@root.com (david greenman) Submitted by: Kirk McKusick (mcKusick@mckusick.com) Obtained from: WHistle development tree --- sbin/fsck_ifs/dir.c | 9 ++++--- sbin/fsck_ifs/fsck.h | 2 ++ sbin/fsck_ifs/inode.c | 11 +++++++++ sbin/fsck_ifs/main.c | 22 ++++++++++------- sbin/fsck_ifs/pass1.c | 16 +++++++++---- sbin/fsck_ifs/pass2.c | 31 +++++++++++++++++------- sbin/fsck_ifs/pass5.c | 60 +++++++++++++++++++++++++++++++++++------------ sbin/fsck_ifs/setup.c | 8 ++++++- sbin/fsck_ifs/utilities.c | 41 +++++++++++++++++++++++++------- 9 files changed, 152 insertions(+), 48 deletions(-) (limited to 'sbin/fsck_ifs') diff --git a/sbin/fsck_ifs/dir.c b/sbin/fsck_ifs/dir.c index 4b6999b..6ab67d3 100644 --- a/sbin/fsck_ifs/dir.c +++ b/sbin/fsck_ifs/dir.c @@ -315,12 +315,13 @@ adjust(idesc, lcnt) pinode(idesc->id_number); printf(" COUNT %d SHOULD BE %d", dp->di_nlink, dp->di_nlink - lcnt); - if (preen) { + if (preen || usedsoftdep) { if (lcnt < 0) { printf("\n"); pfatal("LINK COUNT INCREASING"); } - printf(" (ADJUSTED)\n"); + if (preen) + printf(" (ADJUSTED)\n"); } if (preen || reply("ADJUST") == 1) { dp->di_nlink -= lcnt; @@ -406,13 +407,15 @@ linkup(orphan, parentdir) lostdir = (dp->di_mode & IFMT) == IFDIR; pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); pinode(orphan); - if (preen && dp->di_size == 0) + if ((preen || usedsoftdep) && dp->di_size == 0) return (0); if (preen) printf(" (RECONNECTED)\n"); else if (reply("RECONNECT") == 0) return (0); + if (parentdir != 0) + lncntp[parentdir]++; if (lfdir == 0) { dp = ginode(ROOTINO); idesc.id_name = lfname; diff --git a/sbin/fsck_ifs/fsck.h b/sbin/fsck_ifs/fsck.h index 1967691..4e0271d 100644 --- a/sbin/fsck_ifs/fsck.h +++ b/sbin/fsck_ifs/fsck.h @@ -176,6 +176,8 @@ int cvtlevel; /* convert to newer file system format */ int doinglevel1; /* converting to new cylinder group format */ int doinglevel2; /* converting to new inode format */ int newinofmt; /* filesystem has new inode format */ +char usedsoftdep; /* just fix soft dependency inconsistencies */ +char resolved; /* cleared if unresolved changes => not clean */ char preen; /* just fix normal inconsistencies */ char hotroot; /* checking root device */ char havesb; /* superblock has been read */ diff --git a/sbin/fsck_ifs/inode.c b/sbin/fsck_ifs/inode.c index 429dd3b..74561c8 100644 --- a/sbin/fsck_ifs/inode.c +++ b/sbin/fsck_ifs/inode.c @@ -559,6 +559,8 @@ allocino(request, type) { register ino_t ino; register struct dinode *dp; + struct cg *cgp = &cgrp; + int cg; if (request == 0) request = ROOTINO; @@ -569,9 +571,16 @@ allocino(request, type) break; if (ino == maxino) return (0); + cg = ino_to_cg(&sblock, ino); + getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); + if (!cg_chkmagic(cgp)) + pfatal("CG %d: BAD MAGIC NUMBER\n", cg); + setbit(cg_inosused(cgp), ino % sblock.fs_ipg); + cgp->cg_cs.cs_nifree--; switch (type & IFMT) { case IFDIR: statemap[ino] = DSTATE; + cgp->cg_cs.cs_ndir++; break; case IFREG: case IFLNK: @@ -580,12 +589,14 @@ allocino(request, type) default: return (0); } + cgdirty(); dp = ginode(ino); dp->di_db[0] = allocblk((long)1); if (dp->di_db[0] == 0) { statemap[ino] = USTATE; return (0); } + dp->di_flags = 0; dp->di_mode = type; dp->di_atime = time(NULL); dp->di_mtime = dp->di_ctime = dp->di_atime; diff --git a/sbin/fsck_ifs/main.c b/sbin/fsck_ifs/main.c index dcb7006..b4bc2c9 100644 --- a/sbin/fsck_ifs/main.c +++ b/sbin/fsck_ifs/main.c @@ -42,7 +42,7 @@ static const char copyright[] = static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95"; #endif static const char rcsid[] = - "$Id$"; + "$Id: main.c,v 1.12 1997/12/20 22:24:32 bde Exp $"; #endif /* not lint */ #include @@ -210,6 +210,11 @@ checkfilesys(filesys, mntpt, auxdata, child) } /* + * Cleared if any questions answered no. Used to decide if + * the superblock should be marked clean. + */ + resolved = 1; + /* * 1: scan inodes tallying blocks used */ if (preen == 0) { @@ -224,7 +229,7 @@ checkfilesys(filesys, mntpt, auxdata, child) * 1b: locate first references to duplicates, if any */ if (duplist) { - if (preen) + if (preen || usedsoftdep) pfatal("INTERNAL ERROR: dups with -p"); printf("** Phase 1b - Rescan For More DUPS\n"); pass1b(); @@ -306,19 +311,20 @@ checkfilesys(filesys, mntpt, auxdata, child) bwrite(fswritefd, (char *)&sblock, fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE); } - if (!hotroot) { - ckfini(1); - } else { + if (rerun) + resolved = 0; + flags = 0; + if (hotroot) { struct statfs stfs_buf; /* * Check to see if root is mounted read-write. */ if (statfs("/", &stfs_buf) == 0) flags = stfs_buf.f_flags; - else - flags = 0; - ckfini(flags & MNT_RDONLY); + if ((flags & MNT_RDONLY) == 0) + resolved = 0; } + ckfini(resolved); free(blockmap); free(statemap); free((char *)lncntp); diff --git a/sbin/fsck_ifs/pass1.c b/sbin/fsck_ifs/pass1.c index 9958277..181f858 100644 --- a/sbin/fsck_ifs/pass1.c +++ b/sbin/fsck_ifs/pass1.c @@ -200,8 +200,10 @@ checkinode(inumber, idesc) zlnp = (struct zlncnt *)malloc(sizeof *zlnp); if (zlnp == NULL) { pfatal("LINK COUNT TABLE OVERFLOW"); - if (reply("CONTINUE") == 0) + if (reply("CONTINUE") == 0) { + ckfini(0); exit(EEXIT); + } } else { zlnp->zlncnt = inumber; zlnp->next = zlnhead; @@ -270,8 +272,10 @@ pass1check(idesc) idesc->id_number); if (preen) printf(" (SKIPPING)\n"); - else if (reply("CONTINUE") == 0) + else if (reply("CONTINUE") == 0) { + ckfini(0); exit(EEXIT); + } return (STOP); } } @@ -288,15 +292,19 @@ pass1check(idesc) idesc->id_number); if (preen) printf(" (SKIPPING)\n"); - else if (reply("CONTINUE") == 0) + else if (reply("CONTINUE") == 0) { + ckfini(0); exit(EEXIT); + } return (STOP); } new = (struct dups *)malloc(sizeof(struct dups)); if (new == NULL) { pfatal("DUP TABLE OVERFLOW."); - if (reply("CONTINUE") == 0) + if (reply("CONTINUE") == 0) { + ckfini(0); exit(EEXIT); + } return (STOP); } new->dup = blkno; diff --git a/sbin/fsck_ifs/pass2.c b/sbin/fsck_ifs/pass2.c index 445f6f1..ebc33b8 100644 --- a/sbin/fsck_ifs/pass2.c +++ b/sbin/fsck_ifs/pass2.c @@ -66,8 +66,10 @@ pass2() case USTATE: pfatal("ROOT INODE UNALLOCATED"); - if (reply("ALLOCATE") == 0) + if (reply("ALLOCATE") == 0) { + ckfini(0); exit(EEXIT); + } if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); break; @@ -80,8 +82,10 @@ pass2() errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); break; } - if (reply("CONTINUE") == 0) + if (reply("CONTINUE") == 0) { + ckfini(0); exit(EEXIT); + } break; case FSTATE: @@ -93,8 +97,10 @@ pass2() errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); break; } - if (reply("FIX") == 0) + if (reply("FIX") == 0) { + ckfini(0); exit(EEXIT); + } dp = ginode(ROOTINO); dp->di_mode &= ~IFMT; dp->di_mode |= IFDIR; @@ -139,8 +145,14 @@ pass2() } } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) { getpathname(pathbuf, inp->i_number, inp->i_number); - pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d", - pathbuf, inp->i_isize, DIRBLKSIZ); + if (usedsoftdep) + pfatal("%s %s: LENGTH %d NOT MULTIPLE OF %d", + "DIRECTORY", pathbuf, inp->i_isize, + DIRBLKSIZ); + else + pwarn("%s %s: LENGTH %d NOT MULTIPLE OF %d", + "DIRECTORY", pathbuf, inp->i_isize, + DIRBLKSIZ); if (preen) printf(" (ADJUSTED)\n"); inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ); @@ -394,7 +406,7 @@ again: break; if (statemap[dirp->d_ino] == FCLEAR) errmsg = "DUP/BAD"; - else if (!preen) + else if (!preen && !usedsoftdep) errmsg = "ZERO LENGTH DIRECTORY"; else { n = 1; @@ -423,8 +435,11 @@ again: pwarn("%s %s %s\n", pathbuf, "IS AN EXTRANEOUS HARD LINK TO DIRECTORY", namebuf); - if (preen) - printf(" (IGNORED)\n"); + if (preen) { + printf(" (REMOVED)\n"); + n = 1; + break; + } else if ((n = reply("REMOVE")) == 1) break; } diff --git a/sbin/fsck_ifs/pass5.c b/sbin/fsck_ifs/pass5.c index 3dd0c1a..873f008 100644 --- a/sbin/fsck_ifs/pass5.c +++ b/sbin/fsck_ifs/pass5.c @@ -50,11 +50,12 @@ void pass5() { int c, blk, frags, basesize, sumsize, mapsize, savednrpos; + int inomapsize, blkmapsize; struct fs *fs = &sblock; struct cg *cg = &cgrp; ufs_daddr_t dbase, dmax; ufs_daddr_t d; - long i, j; + long i, j, k; struct csum *cs; struct csum cstotal; struct inodesc idesc[3]; @@ -112,6 +113,8 @@ pass5() sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]); mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] - (u_char *)&ocg->cg_iused[0]; + blkmapsize = howmany(fs->fs_fpg, NBBY); + inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0]; ocg->cg_magic = CG_MAGIC; savednrpos = fs->fs_nrpos; fs->fs_nrpos = 8; @@ -126,12 +129,12 @@ pass5() fs->fs_cpg * fs->fs_nrpos * sizeof(short); newcg->cg_freeoff = newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY); - if (fs->fs_contigsumsize <= 0) { - newcg->cg_nextfreeoff = newcg->cg_freeoff + - howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY); - } else { - newcg->cg_clustersumoff = newcg->cg_freeoff + - howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY) - + inomapsize = newcg->cg_freeoff - newcg->cg_iusedoff; + newcg->cg_nextfreeoff = newcg->cg_freeoff + + howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY); + blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff; + if (fs->fs_contigsumsize > 0) { + newcg->cg_clustersumoff = newcg->cg_nextfreeoff - sizeof(long); newcg->cg_clustersumoff = roundup(newcg->cg_clustersumoff, sizeof(long)); @@ -148,7 +151,7 @@ pass5() break; default: - sumsize = 0; /* keep lint happy */ + inomapsize = blkmapsize = sumsize = 0; /* keep lint happy */ errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d", fs->fs_postblformat); } @@ -299,13 +302,6 @@ pass5() cgdirty(); continue; } - if (memcmp(cg_inosused(newcg), - cg_inosused(cg), mapsize) != 0 && - dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) { - memmove(cg_inosused(cg), cg_inosused(newcg), - (size_t)mapsize); - cgdirty(); - } if ((memcmp(newcg, cg, basesize) != 0 || memcmp(&cg_blktot(newcg)[0], &cg_blktot(cg)[0], sumsize) != 0) && @@ -315,6 +311,40 @@ pass5() &cg_blktot(newcg)[0], (size_t)sumsize); cgdirty(); } + if (usedsoftdep) { + for (i = 0; i < inomapsize; i++) { + j = cg_inosused(newcg)[i]; + if ((cg_inosused(cg)[i] & j) == j) + continue; + for (k = 0; k < NBBY; k++) { + if ((j & (1 << k)) == 0) + continue; + if (cg_inosused(cg)[i] & (1 << k)) + continue; + pwarn("ALLOCATED INODE %d MARKED FREE", + c * fs->fs_ipg + i * 8 + k); + } + } + for (i = 0; i < blkmapsize; i++) { + j = cg_blksfree(cg)[i]; + if ((cg_blksfree(newcg)[i] & j) == j) + continue; + for (k = 0; k < NBBY; k++) { + if ((j & (1 << k)) == 0) + continue; + if (cg_inosused(cg)[i] & (1 << k)) + continue; + pwarn("ALLOCATED FRAG %d MARKED FREE", + c * fs->fs_fpg + i * 8 + k); + } + } + } + if (memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0 && + dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) { + memmove(cg_inosused(cg), cg_inosused(newcg), + (size_t)mapsize); + cgdirty(); + } } if (fs->fs_postblformat == FS_42POSTBLFMT) fs->fs_nrpos = savednrpos; diff --git a/sbin/fsck_ifs/setup.c b/sbin/fsck_ifs/setup.c index 28e7e4b..f464b63 100644 --- a/sbin/fsck_ifs/setup.c +++ b/sbin/fsck_ifs/setup.c @@ -255,8 +255,10 @@ setup(dev) fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), size) != 0 && !asked) { pfatal("BAD SUMMARY INFORMATION"); - if (reply("CONTINUE") == 0) + if (reply("CONTINUE") == 0) { + ckfini(0); exit(EEXIT); + } asked++; } } @@ -311,6 +313,10 @@ setup(dev) goto badsb; } bufinit(); + if (sblock.fs_flags & FS_DOSOFTDEP) + usedsoftdep = 1; + else + usedsoftdep = 0; return (1); badsb: diff --git a/sbin/fsck_ifs/utilities.c b/sbin/fsck_ifs/utilities.c index 30c31cf..465fb3b 100644 --- a/sbin/fsck_ifs/utilities.c +++ b/sbin/fsck_ifs/utilities.c @@ -87,6 +87,7 @@ reply(question) printf("\n"); if (!persevere && (nflag || fswritefd < 0)) { printf("%s? no\n\n", question); + resolved = 0; return (0); } if (yflag || (persevere && nflag)) { @@ -97,13 +98,17 @@ reply(question) printf("%s? [yn] ", question); (void) fflush(stdout); c = getc(stdin); - while (c != '\n' && getc(stdin) != '\n') - if (feof(stdin)) + while (c != '\n' && getc(stdin) != '\n') { + if (feof(stdin)) { + resolved = 0; return (0); + } + } } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); printf("\n"); if (c == 'y' || c == 'Y') return (1); + resolved = 0; return (0); } @@ -360,7 +365,8 @@ ufs_daddr_t allocblk(frags) long frags; { - register int i, j, k; + int i, j, k, cg, baseblk; + struct cg *cgp = &cgrp; if (frags <= 0 || frags > sblock.fs_frag) return (0); @@ -375,9 +381,21 @@ allocblk(frags) j += k; continue; } - for (k = 0; k < frags; k++) + cg = dtog(&sblock, i + j); + getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); + if (!cg_chkmagic(cgp)) + pfatal("CG %d: BAD MAGIC NUMBER\n", cg); + baseblk = dtogd(&sblock, i + j); + for (k = 0; k < frags; k++) { setbmap(i + j + k); + clrbit(cg_blksfree(cgp), baseblk + k); + } n_blks += frags; + if (frags == sblock.fs_frag) + cgp->cg_cs.cs_nbfree--; + else + cgp->cg_cs.cs_nffree -= frags; + cgdirty(); return (i + j); } } @@ -545,7 +563,8 @@ dofix(idesc, msg) /* * An unexpected inconsistency occured. - * Die if preening, otherwise just print message and continue. + * Die if preening or filesystem is running with soft dependency protocol, + * otherwise just print message and continue. */ void #if __STDC__ @@ -565,19 +584,23 @@ pfatal(fmt, va_alist) if (!preen) { (void)vfprintf(stderr, fmt, ap); va_end(ap); + if (usedsoftdep) + (void)fprintf(stderr, + "\nUNEXPECTED SOFTDEP INCONSISTENCY\n"); return; } (void)fprintf(stderr, "%s: ", cdevname); (void)vfprintf(stderr, fmt, ap); (void)fprintf(stderr, - "\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", - cdevname); + "\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n", + cdevname, usedsoftdep ? " SOFTDEP " : " "); + ckfini(0); exit(EEXIT); } /* - * Pwarn just prints a message when not preening, - * or a warning (preceded by filename) when preening. + * Pwarn just prints a message when not preening or running soft dependency + * protocol, or a warning (preceded by filename) when preening. */ void #if __STDC__ -- cgit v1.1