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: da86e7a20d
Reported by:	pho
Discussed with:	mckusick
Sponsored by:	Netflix
This commit is contained in:
Chuck Silvers 2023-05-03 13:21:19 -07:00
parent 9f27341c33
commit 4064755812
7 changed files with 29 additions and 24 deletions

View File

@ -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);

View File

@ -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++) {

View File

@ -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;

View File

@ -1394,7 +1394,7 @@ allocino(ino_t request, int type)
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;

View File

@ -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");

View File

@ -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;

View File

@ -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++) {