Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 May 2023 20:32:27 GMT
From:      Chuck Silvers <chs@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 406475581246 - main - fsck_ffs: fix the previous change that skipped pass 5 in some cases
Message-ID:  <202305032032.343KWRi9067698@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by chs:

URL: https://cgit.FreeBSD.org/src/commit/?id=406475581246360faa7af9891dc8ad2423284e18

commit 406475581246360faa7af9891dc8ad2423284e18
Author:     Chuck Silvers <chs@FreeBSD.org>
AuthorDate: 2023-05-03 20:21:19 +0000
Commit:     Chuck Silvers <chs@FreeBSD.org>
CommitDate: 2023-05-03 20:31:32 +0000

    fsck_ffs: fix the previous change that skipped pass 5 in some cases
    
    The previous change involved calling check_cgmagic() twice in a row
    for the same CG in order to differentiate when the CG was already ok vs.
    when the CG was rebuilt, but that doesn't work because the second call
    (which was supposed to rebuild the CG) returns 0 (indicating that
    the CG was not rebuilt) due to the prevfailcg check causing an early
    failure return.  Fix this by moving the rebuild part of check_cgmagic()
    out into a separate function which is called by pass1() when it wants to
    rebuild a CG.
    
    Fixes: da86e7a20dc4a4b17e8d9e7630ed9b675cf71702
    Reported by:    pho
    Discussed with: mckusick
    Sponsored by:   Netflix
---
 sbin/fsck_ffs/fsck.h     |  3 ++-
 sbin/fsck_ffs/fsutil.c   | 28 +++++++++++++---------------
 sbin/fsck_ffs/gjournal.c |  2 +-
 sbin/fsck_ffs/inode.c    |  2 +-
 sbin/fsck_ffs/main.c     |  2 +-
 sbin/fsck_ffs/pass1.c    | 12 +++++++++---
 sbin/fsck_ffs/suj.c      |  4 ++--
 7 files changed, 29 insertions(+), 24 deletions(-)

diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index 95dccf0d672d..1c8b9169e590 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -466,7 +466,8 @@ void		cgdirty(struct bufarea *);
 struct bufarea *cglookup(int cg);
 int		changeino(ino_t dir, const char *name, ino_t newnum, int depth);
 void		check_blkcnt(struct inode *ip);
-int		check_cgmagic(int cg, struct bufarea *cgbp, int requestrebuild);
+int		check_cgmagic(int cg, struct bufarea *cgbp);
+void		rebuild_cg(int cg, struct bufarea *cgbp);
 void		check_dirdepth(struct inoinfo *inp);
 int		chkrange(ufs2_daddr_t blk, int cnt);
 void		ckfini(int markclean);
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c
index 1df52b7cfdc9..48810954ba94 100644
--- a/sbin/fsck_ffs/fsutil.c
+++ b/sbin/fsck_ffs/fsutil.c
@@ -989,9 +989,7 @@ 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.
+ * Return 1 if the cylinder group is good or return 0 if it is bad.
  */
 #undef CHK
 #define CHK(lhs, op, rhs, fmt)						\
@@ -1003,7 +1001,7 @@ blzero(int fd, ufs2_daddr_t blk, long size)
 		error = 1;						\
 	}
 int
-check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
+check_cgmagic(int cg, struct bufarea *cgbp)
 {
 	struct cg *cgp = cgbp->b_un.b_cg;
 	uint32_t cghash, calchash;
@@ -1077,15 +1075,16 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
 		return (0);
 	prevfailcg = cg;
 	pfatal("CYLINDER GROUP %d: INTEGRITY CHECK FAILED", cg);
-	if (!request_rebuild) {
-		printf("\n");
-		return (0);
-	}
-	if (!reply("REBUILD CYLINDER GROUP")) {
-		printf("YOU WILL NEED TO RERUN FSCK.\n");
-		rerun = 1;
-		return (0);
-	}
+	printf("\n");
+	return (0);
+}
+
+void
+rebuild_cg(int cg, struct bufarea *cgbp)
+{
+	struct cg *cgp = cgbp->b_un.b_cg;
+	long start;
+
 	/*
 	 * Zero out the cylinder group and then initialize critical fields.
 	 * Bit maps and summaries will be recalculated by later passes.
@@ -1127,7 +1126,6 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
 	}
 	cgp->cg_ckhash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize);
 	cgdirty(cgbp);
-	return (1);
 }
 
 /*
@@ -1191,7 +1189,7 @@ std_checkblkavail(ufs2_daddr_t blkno, long frags)
 		cg = dtog(&sblock, blkno + j);
 		cgbp = cglookup(cg);
 		cgp = cgbp->b_un.b_cg;
-		if (!check_cgmagic(cg, cgbp, 0))
+		if (!check_cgmagic(cg, cgbp))
 			return (-((cg + 1) * sblock.fs_fpg - sblock.fs_frag));
 		baseblk = dtogd(&sblock, blkno + j);
 		for (k = 0; k < frags; k++) {
diff --git a/sbin/fsck_ffs/gjournal.c b/sbin/fsck_ffs/gjournal.c
index b65589b5bd08..cd2c9df878a8 100644
--- a/sbin/fsck_ffs/gjournal.c
+++ b/sbin/fsck_ffs/gjournal.c
@@ -97,7 +97,7 @@ gjournal_check(const char *filesys)
 		}
 		cgbp = cglookup(cg);
 		cgp = cgbp->b_un.b_cg;
-		if (!check_cgmagic(cg, cgbp, 0)) {
+		if (!check_cgmagic(cg, cgbp)) {
 			rerun = 1;
 			ckfini(0);
 			return;
diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c
index 2d563f617a56..04891447254e 100644
--- a/sbin/fsck_ffs/inode.c
+++ b/sbin/fsck_ffs/inode.c
@@ -1394,7 +1394,7 @@ retry:
 	cg = ino_to_cg(&sblock, ino);
 	cgbp = cglookup(cg);
 	cgp = cgbp->b_un.b_cg;
-	if (!check_cgmagic(cg, cgbp, 0)) {
+	if (!check_cgmagic(cg, cgbp)) {
 		if (anyino == 0)
 			return (0);
 		request = (cg + 1) * sblock.fs_ipg;
diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c
index 2bd61dda7030..566fbe5ccd15 100644
--- a/sbin/fsck_ffs/main.c
+++ b/sbin/fsck_ffs/main.c
@@ -492,7 +492,7 @@ checkfilesys(char *filesys)
 	snapflush(std_checkblkavail);
 	if (cgheader_corrupt) {
 		printf("PHASE 5 SKIPPED DUE TO CORRUPT CYLINDER GROUP "
-		    "HEADER(S)\n");
+		    "HEADER(S)\n\n");
 	} else {
 		pass5();
 		IOstats("Pass5");
diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c
index 55233e0bc4f4..e784fd29dc1c 100644
--- a/sbin/fsck_ffs/pass1.c
+++ b/sbin/fsck_ffs/pass1.c
@@ -100,11 +100,17 @@ pass1(void)
 		cgbp = cglookup(c);
 		cgp = cgbp->b_un.b_cg;
 		rebuiltcg = 0;
-		if (!check_cgmagic(c, cgbp, 0)) {
-			if (!check_cgmagic(c, cgbp, 1))
+		if (!check_cgmagic(c, cgbp)) {
+			if (!reply("REBUILD CYLINDER GROUP")) {
 				cgheader_corrupt = 1;
-			else
+				if (!nflag) {
+					printf("YOU WILL NEED TO RERUN FSCK.\n");
+					rerun = 1;
+				}
+			} else {
+				rebuild_cg(c, cgbp);
 				rebuiltcg = 1;
+			}
 		}
 		if (!rebuiltcg && sblock.fs_magic == FS_UFS2_MAGIC) {
 			inosused = cgp->cg_initediblk;
diff --git a/sbin/fsck_ffs/suj.c b/sbin/fsck_ffs/suj.c
index 40bbe340bfc6..9c8e1322b801 100644
--- a/sbin/fsck_ffs/suj.c
+++ b/sbin/fsck_ffs/suj.c
@@ -183,7 +183,7 @@ cg_lookup(int cgx)
 	if (lastcg && lastcg->sc_cgx == cgx)
 		return (lastcg);
 	cgbp = cglookup(cgx);
-	if (!check_cgmagic(cgx, cgbp, 0))
+	if (!check_cgmagic(cgx, cgbp))
 		err_suj("UNABLE TO REBUILD CYLINDER GROUP %d", cgx);
 	hd = &cghash[HASH(cgx)];
 	LIST_FOREACH(sc, hd, sc_next)
@@ -396,7 +396,7 @@ suj_checkblkavail(ufs2_daddr_t blkno, long frags)
 	cg = dtog(&sblock, blkno);
 	cgbp = cglookup(cg);
 	cgp = cgbp->b_un.b_cg;
-	if (!check_cgmagic(cg, cgbp, 0))
+	if (!check_cgmagic(cg, cgbp))
 		return (-((cg + 1) * sblock.fs_fpg - sblock.fs_frag));
 	baseblk = dtogd(&sblock, blkno);
 	for (j = 0; j <= sblock.fs_frag - frags; j++) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202305032032.343KWRi9067698>