Provide better diagnostic messages for bad cylinder groups.

Like the detailed diagnostics produced when a bad superblock
is read, provide similar detailed diagnostics when bad
cylinder groups are read.

Reported by:  Peter Holm
Tested by:    Peter Holm
Sponsored by: The FreeBSD Foundation
This commit is contained in:
Kirk McKusick 2022-08-25 23:56:31 -07:00
parent 8e59ec29e4
commit 495b1baac3

View File

@ -949,12 +949,21 @@ blzero(int fd, ufs2_daddr_t blk, long size)
* Verify cylinder group's magic number and other parameters. If the * Verify cylinder group's magic number and other parameters. If the
* test fails, offer an option to rebuild the whole cylinder group. * test fails, offer an option to rebuild the whole cylinder group.
*/ */
#undef CHK
#define CHK(lhs, op, rhs, fmt) \
if (lhs op rhs) { \
pwarn("UFS%d superblock failed: %s (" #fmt ") %s %s (" \
#fmt ")\n", sblock.fs_magic == FS_UFS1_MAGIC ? 1 : \
2, #lhs, (intmax_t)lhs, #op, #rhs, (intmax_t)rhs); \
error = 1; \
}
int int
check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild) check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
{ {
struct cg *cgp = cgbp->b_un.b_cg; struct cg *cgp = cgbp->b_un.b_cg;
uint32_t cghash, calchash; uint32_t cghash, calchash;
static int prevfailcg = -1; static int prevfailcg = -1;
int error;
/* /*
* Extended cylinder group checks. * Extended cylinder group checks.
@ -967,19 +976,20 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
calchash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize); calchash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize);
cgp->cg_ckhash = cghash; cgp->cg_ckhash = cghash;
} }
if (cgp->cg_ckhash == calchash && error = 0;
cg_chkmagic(cgp) && CHK(cgp->cg_ckhash, !=, calchash, "%jd");
cgp->cg_cgx == cg && CHK(cg_chkmagic(cgp), ==, 0, "%jd");
((sblock.fs_magic == FS_UFS1_MAGIC && CHK(cgp->cg_cgx, !=, cg, "%jd");
cgp->cg_old_niblk == sblock.fs_ipg && CHK(cgp->cg_ndblk, >, sblock.fs_fpg, "%jd");
cgp->cg_ndblk <= sblock.fs_fpg && if (sblock.fs_magic == FS_UFS1_MAGIC) {
cgp->cg_old_ncyl <= sblock.fs_old_cpg) || CHK(cgp->cg_old_niblk, !=, sblock.fs_ipg, "%jd");
(sblock.fs_magic == FS_UFS2_MAGIC && CHK(cgp->cg_old_ncyl, >, sblock.fs_old_cpg, "%jd");
cgp->cg_niblk == sblock.fs_ipg && } else if (sblock.fs_magic == FS_UFS2_MAGIC) {
cgp->cg_ndblk <= sblock.fs_fpg && CHK(cgp->cg_niblk, !=, sblock.fs_ipg, "%jd");
cgp->cg_initediblk <= sblock.fs_ipg))) { CHK(cgp->cg_initediblk, >, sblock.fs_ipg, "%jd");
return (1);
} }
if (error == 0)
return (1);
if (prevfailcg == cg) if (prevfailcg == cg)
return (0); return (0);
prevfailcg = cg; prevfailcg = cg;
@ -1030,6 +1040,7 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
cgp->cg_nextfreeoff = cgp->cg_clusteroff + cgp->cg_nextfreeoff = cgp->cg_clusteroff +
howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT); howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
} }
cgp->cg_ckhash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize);
cgdirty(cgbp); cgdirty(cgbp);
return (0); return (0);
} }