Ensure that cylinder-group check-hashes are properly updated when first
creating them and when correcting them when they are found to be corrupted. Reported by: Don Lewis (truckman@) Sponsored by: Netflix
This commit is contained in:
parent
db19a093bb
commit
8ebae128be
@ -417,6 +417,7 @@ void blzero(int fd, ufs2_daddr_t blk, long size);
|
||||
void cacheino(union dinode *dp, ino_t inumber);
|
||||
void catch(int);
|
||||
void catchquit(int);
|
||||
void cgdirty(struct bufarea *);
|
||||
int changeino(ino_t dir, const char *name, ino_t newnum);
|
||||
int check_cgmagic(int cg, struct bufarea *cgbp);
|
||||
int chkrange(ufs2_daddr_t blk, int cnt);
|
||||
|
@ -248,6 +248,24 @@ cglookup(int cg)
|
||||
return (cgbp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark a cylinder group buffer as dirty.
|
||||
* Update its check-hash if they are enabled.
|
||||
*/
|
||||
void
|
||||
cgdirty(struct bufarea *cgbp)
|
||||
{
|
||||
struct cg *cg;
|
||||
|
||||
cg = cgbp->b_un.b_cg;
|
||||
if ((sblock.fs_metackhash & CK_CYLGRP) != 0) {
|
||||
cg->cg_ckhash = 0;
|
||||
cg->cg_ckhash =
|
||||
calculate_crc32c(~0L, (void *)cg, sblock.fs_cgsize);
|
||||
}
|
||||
dirty(cgbp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to flush a cylinder group cache entry.
|
||||
* Return whether the flush was successful.
|
||||
@ -348,11 +366,11 @@ flush(int fd, struct bufarea *bp)
|
||||
if (bp != &sblk)
|
||||
pfatal("BUFFER %p DOES NOT MATCH SBLK %p\n",
|
||||
bp, &sblk);
|
||||
if (sbput(fd, (struct fs *)bp->b_un.b_buf, 0) == 0)
|
||||
if (sbput(fd, bp->b_un.b_fs, 0) == 0)
|
||||
fsmodified = 1;
|
||||
break;
|
||||
case BT_CYLGRP:
|
||||
if (cgput(&disk, (struct cg *)bp->b_un.b_buf) == 0)
|
||||
if (cgput(&disk, bp->b_un.b_cg) == 0)
|
||||
fsmodified = 1;
|
||||
break;
|
||||
default:
|
||||
@ -740,7 +758,7 @@ check_cgmagic(int cg, struct bufarea *cgbp)
|
||||
cgp->cg_nextfreeoff = cgp->cg_clusteroff +
|
||||
howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
|
||||
}
|
||||
dirty(cgbp);
|
||||
cgdirty(cgbp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -782,7 +800,7 @@ allocblk(long frags)
|
||||
cgp->cg_cs.cs_nbfree--;
|
||||
else
|
||||
cgp->cg_cs.cs_nffree -= frags;
|
||||
dirty(cgbp);
|
||||
cgdirty(cgbp);
|
||||
return (i + j);
|
||||
}
|
||||
}
|
||||
|
@ -692,7 +692,7 @@ allocino(ino_t request, int type)
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
dirty(cgbp);
|
||||
cgdirty(cgbp);
|
||||
dp = ginode(ino);
|
||||
DIP_SET(dp, di_db[0], allocblk((long)1));
|
||||
if (DIP(dp, di_db[0]) == 0) {
|
||||
|
@ -200,7 +200,7 @@ pass1(void)
|
||||
cgp->cg_initediblk = mininos;
|
||||
pwarn("CYLINDER GROUP %d: RESET FROM %ju TO %d %s\n",
|
||||
c, i, cgp->cg_initediblk, "VALID INODES");
|
||||
dirty(cgbp);
|
||||
cgdirty(cgbp);
|
||||
}
|
||||
if (inosused < sblock.fs_ipg)
|
||||
continue;
|
||||
|
@ -182,14 +182,19 @@ pass5(void)
|
||||
ckhash = cg->cg_ckhash;
|
||||
cg->cg_ckhash = 0;
|
||||
thishash = calculate_crc32c(~0L, cg, fs->fs_cgsize);
|
||||
if (ckhash != thishash)
|
||||
if (ckhash == thishash) {
|
||||
cg->cg_ckhash = ckhash;
|
||||
} else {
|
||||
pwarn("CG %d: BAD CHECK-HASH %#x vs %#x\n",
|
||||
c, ckhash, thishash);
|
||||
cg->cg_ckhash = ckhash;
|
||||
cg->cg_ckhash = thishash;
|
||||
cgdirty(cgbp);
|
||||
}
|
||||
}
|
||||
newcg->cg_time = cg->cg_time;
|
||||
newcg->cg_old_time = cg->cg_old_time;
|
||||
newcg->cg_unrefs = cg->cg_unrefs;
|
||||
newcg->cg_ckhash = cg->cg_ckhash;
|
||||
newcg->cg_cgx = c;
|
||||
dbase = cgbase(fs, c);
|
||||
dmax = dbase + fs->fs_fpg;
|
||||
@ -326,11 +331,6 @@ pass5(void)
|
||||
sump[run]++;
|
||||
}
|
||||
}
|
||||
if ((fs->fs_metackhash & CK_CYLGRP) != 0) {
|
||||
newcg->cg_ckhash = 0;
|
||||
newcg->cg_ckhash =
|
||||
calculate_crc32c(~0L, (void *)newcg, fs->fs_cgsize);
|
||||
}
|
||||
|
||||
if (bkgrdflag != 0) {
|
||||
cstotal.cs_nffree += cg->cg_cs.cs_nffree;
|
||||
@ -352,14 +352,14 @@ pass5(void)
|
||||
}
|
||||
if (rewritecg) {
|
||||
memmove(cg, newcg, (size_t)fs->fs_cgsize);
|
||||
dirty(cgbp);
|
||||
cgdirty(cgbp);
|
||||
continue;
|
||||
}
|
||||
if (cursnapshot == 0 &&
|
||||
memcmp(newcg, cg, basesize) != 0 &&
|
||||
dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
|
||||
memmove(cg, newcg, (size_t)basesize);
|
||||
dirty(cgbp);
|
||||
cgdirty(cgbp);
|
||||
}
|
||||
if (bkgrdflag != 0 || usedsoftdep || debug)
|
||||
update_maps(cg, newcg, bkgrdflag);
|
||||
@ -368,7 +368,7 @@ pass5(void)
|
||||
dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
|
||||
memmove(cg_inosused(cg), cg_inosused(newcg),
|
||||
(size_t)mapsize);
|
||||
dirty(cgbp);
|
||||
cgdirty(cgbp);
|
||||
}
|
||||
}
|
||||
if (cursnapshot == 0 &&
|
||||
|
@ -208,6 +208,13 @@ setup(char *dev)
|
||||
pwarn("USING ALTERNATE SUPERBLOCK AT %jd\n", bflag);
|
||||
bflag = 0;
|
||||
}
|
||||
/* Save copy of things needed by libufs */
|
||||
memcpy(&disk.d_fs, &sblock, sblock.fs_sbsize);
|
||||
disk.d_ufs = (sblock.fs_magic == FS_UFS1_MAGIC) ? 1 : 2;
|
||||
disk.d_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
|
||||
disk.d_sblock = sblock.fs_sblockloc / disk.d_bsize;
|
||||
disk.d_sbcsum = sblock.fs_csp;
|
||||
|
||||
if (skipclean && ckclean && sblock.fs_clean) {
|
||||
pwarn("FILE SYSTEM CLEAN; SKIPPING CHECKS\n");
|
||||
return (-1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user