git: 0c6c748f7827 - stable/13 - Skip Pass 5 in fsck_ffs(8) when corrupt cylinder groups remain unfixed.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 29 Apr 2023 18:16:12 UTC
The branch stable/13 has been updated by mckusick:
URL: https://cgit.FreeBSD.org/src/commit/?id=0c6c748f7827b2e9c86a61193a9147a26df1ce33
commit 0c6c748f7827b2e9c86a61193a9147a26df1ce33
Author: Kirk McKusick <mckusick@FreeBSD.org>
AuthorDate: 2023-04-18 23:10:49 +0000
Commit: Kirk McKusick <mckusick@FreeBSD.org>
CommitDate: 2023-04-29 18:12:12 +0000
Skip Pass 5 in fsck_ffs(8) when corrupt cylinder groups remain unfixed.
Sponsored by: FreeBSD Foundation
(cherry picked from commit da86e7a20dc4a4b17e8d9e7630ed9b675cf71702)
---
sbin/fsck_ffs/fsck.h | 3 ++-
sbin/fsck_ffs/fsutil.c | 8 ++++++--
sbin/fsck_ffs/globs.c | 2 ++
sbin/fsck_ffs/inode.c | 4 ++--
sbin/fsck_ffs/main.c | 9 +++++++--
sbin/fsck_ffs/pass1.c | 30 +++++++++++++++++-------------
6 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index 5ce5ca9e29a5..12a06e69b5fc 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -346,6 +346,7 @@ extern off_t bflag; /* location of alternate super block */
extern int bkgrdflag; /* use a snapshot to run on an active system */
extern char *blockmap; /* ptr to primary blk allocation map */
extern char *cdevname; /* name of device being checked */
+extern int cgheader_corrupt; /* one or more CG headers are corrupt */
extern char ckclean; /* only do work if not cleanly unmounted */
extern int ckhashadd; /* check hashes to be added */
extern char *copybuf; /* buffer to copy snapshot blocks */
@@ -494,7 +495,7 @@ int ftypeok(union dinode *dp);
void getblk(struct bufarea *bp, ufs2_daddr_t blk, long size);
struct bufarea *getdatablk(ufs2_daddr_t blkno, long size, int type);
struct inoinfo *getinoinfo(ino_t inumber);
-union dinode *getnextinode(ino_t inumber, int rebuildcg);
+union dinode *getnextinode(ino_t inumber, int rebuiltcg);
void getpathname(char *namebuf, ino_t curdir, ino_t ino);
void ginode(ino_t, struct inode *);
void gjournal_check(const char *filesys);
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c
index 8f5b09cfe610..974dba4be79b 100644
--- a/sbin/fsck_ffs/fsutil.c
+++ b/sbin/fsck_ffs/fsutil.c
@@ -987,6 +987,10 @@ blzero(int fd, ufs2_daddr_t blk, long size)
/*
* Verify cylinder group's magic number and other parameters. If the
* test fails, offer an option to rebuild the whole cylinder group.
+ *
+ * Return 1 if the cylinder group is good or if repair is requested
+ * and is completed successfully. Return 0 if it is bad or if a repair
+ * has been requested but is not completed successfully.
*/
#undef CHK
#define CHK(lhs, op, rhs, fmt) \
@@ -1079,7 +1083,7 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
if (!reply("REBUILD CYLINDER GROUP")) {
printf("YOU WILL NEED TO RERUN FSCK.\n");
rerun = 1;
- return (1);
+ return (0);
}
/*
* Zero out the cylinder group and then initialize critical fields.
@@ -1122,7 +1126,7 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
}
cgp->cg_ckhash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize);
cgdirty(cgbp);
- return (0);
+ return (1);
}
/*
diff --git a/sbin/fsck_ffs/globs.c b/sbin/fsck_ffs/globs.c
index 09dbcc6694a2..92e77b61f9d4 100644
--- a/sbin/fsck_ffs/globs.c
+++ b/sbin/fsck_ffs/globs.c
@@ -111,6 +111,7 @@ 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 */
+int cgheader_corrupt; /* one or more CG headers are corrupt */
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 */
@@ -166,6 +167,7 @@ fsckinit(void)
lfmode = 0700;
n_blks = 0;
n_files = 0;
+ cgheader_corrupt = 0;
got_siginfo = 0;
got_sigalarm = 0;
bzero(&zino.dp1, sizeof(struct ufs1_dinode));
diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c
index 37b0f9ebc1b1..2d563f617a56 100644
--- a/sbin/fsck_ffs/inode.c
+++ b/sbin/fsck_ffs/inode.c
@@ -510,7 +510,7 @@ static ino_t nextinum, lastvalidinum;
static long readcount, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
union dinode *
-getnextinode(ino_t inumber, int rebuildcg)
+getnextinode(ino_t inumber, int rebuiltcg)
{
int j;
long size;
@@ -569,7 +569,7 @@ getnextinode(ino_t inumber, int rebuildcg)
dirty(&inobuf);
}
}
- if (rebuildcg && (char *)dp == inobuf.b_un.b_buf) {
+ if (rebuiltcg && (char *)dp == inobuf.b_un.b_buf) {
/*
* Try to determine if we have reached the end of the
* allocated inodes.
diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c
index 74329bdb9483..e559f6cb4ea6 100644
--- a/sbin/fsck_ffs/main.c
+++ b/sbin/fsck_ffs/main.c
@@ -490,8 +490,13 @@ checkfilesys(char *filesys)
if (preen == 0)
printf("** Phase 5 - Check Cyl groups\n");
snapflush(std_checkblkavail);
- pass5();
- IOstats("Pass5");
+ if (cgheader_corrupt) {
+ printf("PHASE 5 SKIPPED DUE TO CORRUPT CYLINDER GROUP "
+ "HEADER(S)\n");
+ } else {
+ pass5();
+ IOstats("Pass5");
+ }
/*
* print out summary statistics
diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c
index afe9f7f2b789..55233e0bc4f4 100644
--- a/sbin/fsck_ffs/pass1.c
+++ b/sbin/fsck_ffs/pass1.c
@@ -56,7 +56,7 @@ static ufs2_daddr_t badblk;
static ufs2_daddr_t dupblk;
static ino_t lastino; /* last inode in use */
-static int checkinode(ino_t inumber, struct inodesc *, int rebuildcg);
+static int checkinode(ino_t inumber, struct inodesc *, int rebuiltcg);
void
pass1(void)
@@ -68,7 +68,7 @@ pass1(void)
ino_t inumber, inosused, mininos;
ufs2_daddr_t i, cgd;
u_int8_t *cp;
- int c, rebuildcg;
+ int c, rebuiltcg;
badblk = dupblk = lastino = 0;
@@ -99,10 +99,14 @@ pass1(void)
inumber = c * sblock.fs_ipg;
cgbp = cglookup(c);
cgp = cgbp->b_un.b_cg;
- rebuildcg = 0;
- if (!check_cgmagic(c, cgbp, 1))
- rebuildcg = 1;
- if (!rebuildcg && sblock.fs_magic == FS_UFS2_MAGIC) {
+ rebuiltcg = 0;
+ if (!check_cgmagic(c, cgbp, 0)) {
+ if (!check_cgmagic(c, cgbp, 1))
+ cgheader_corrupt = 1;
+ else
+ rebuiltcg = 1;
+ }
+ if (!rebuiltcg && sblock.fs_magic == FS_UFS2_MAGIC) {
inosused = cgp->cg_initediblk;
if (inosused > sblock.fs_ipg) {
pfatal("Too many initialized inodes (%ju > %d) "
@@ -132,7 +136,7 @@ pass1(void)
* to find the inodes that are really in use, and then
* read only those inodes in from disk.
*/
- if ((preen || inoopt) && usedsoftdep && !rebuildcg) {
+ if ((preen || inoopt) && usedsoftdep && !rebuiltcg) {
cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT];
for ( ; inosused != 0; cp--) {
if (*cp == 0) {
@@ -169,7 +173,7 @@ pass1(void)
setinodebuf(c, inosused);
for (i = 0; i < inosused; i++, inumber++) {
if (inumber < UFS_ROOTINO) {
- (void)getnextinode(inumber, rebuildcg);
+ (void)getnextinode(inumber, rebuiltcg);
continue;
}
/*
@@ -178,7 +182,7 @@ pass1(void)
* We always keep trying until we get to the minimum
* valid number for this cylinder group.
*/
- if (checkinode(inumber, &idesc, rebuildcg) == 0 &&
+ if (checkinode(inumber, &idesc, rebuiltcg) == 0 &&
i > cgp->cg_initediblk)
break;
}
@@ -189,7 +193,7 @@ pass1(void)
* fewer in use.
*/
mininos = roundup(inosused + INOPB(&sblock), INOPB(&sblock));
- if (inoopt && !preen && !rebuildcg &&
+ if (inoopt && !preen && !rebuiltcg &&
sblock.fs_magic == FS_UFS2_MAGIC &&
cgp->cg_initediblk > 2 * INOPB(&sblock) &&
mininos < cgp->cg_initediblk) {
@@ -209,7 +213,7 @@ pass1(void)
inosused = 0;
else
inosused = lastino - (c * sblock.fs_ipg);
- if (rebuildcg && inosused > cgp->cg_initediblk &&
+ if (rebuiltcg && inosused > cgp->cg_initediblk &&
sblock.fs_magic == FS_UFS2_MAGIC) {
cgp->cg_initediblk = roundup(inosused, INOPB(&sblock));
pwarn("CYLINDER GROUP %d: FOUND %d VALID INODES\n", c,
@@ -242,7 +246,7 @@ pass1(void)
}
static int
-checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
+checkinode(ino_t inumber, struct inodesc *idesc, int rebuiltcg)
{
struct inode ip;
union dinode *dp;
@@ -252,7 +256,7 @@ checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
intmax_t size, fixsize;
int j, ret, offset;
- if ((dp = getnextinode(inumber, rebuildcg)) == NULL) {
+ if ((dp = getnextinode(inumber, rebuiltcg)) == NULL) {
pfatal("INVALID INODE");
goto unknown;
}