Date: Wed, 5 Dec 2018 06:31:50 +0000 (UTC) From: Kirk McKusick <mckusick@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r341510 - head/sbin/fsck_ffs Message-ID: <201812050631.wB56VoiL055810@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mckusick Date: Wed Dec 5 06:31:50 2018 New Revision: 341510 URL: https://svnweb.freebsd.org/changeset/base/341510 Log: 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 Modified: head/sbin/fsck_ffs/fsck.h head/sbin/fsck_ffs/fsutil.c head/sbin/fsck_ffs/inode.c head/sbin/fsck_ffs/pass1.c head/sbin/fsck_ffs/pass5.c head/sbin/fsck_ffs/setup.c Modified: head/sbin/fsck_ffs/fsck.h ============================================================================== --- head/sbin/fsck_ffs/fsck.h Wed Dec 5 00:46:09 2018 (r341509) +++ head/sbin/fsck_ffs/fsck.h Wed Dec 5 06:31:50 2018 (r341510) @@ -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); Modified: head/sbin/fsck_ffs/fsutil.c ============================================================================== --- head/sbin/fsck_ffs/fsutil.c Wed Dec 5 00:46:09 2018 (r341509) +++ head/sbin/fsck_ffs/fsutil.c Wed Dec 5 06:31:50 2018 (r341510) @@ -249,6 +249,24 @@ cglookup(int cg) } /* + * 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); } } Modified: head/sbin/fsck_ffs/inode.c ============================================================================== --- head/sbin/fsck_ffs/inode.c Wed Dec 5 00:46:09 2018 (r341509) +++ head/sbin/fsck_ffs/inode.c Wed Dec 5 06:31:50 2018 (r341510) @@ -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) { Modified: head/sbin/fsck_ffs/pass1.c ============================================================================== --- head/sbin/fsck_ffs/pass1.c Wed Dec 5 00:46:09 2018 (r341509) +++ head/sbin/fsck_ffs/pass1.c Wed Dec 5 06:31:50 2018 (r341510) @@ -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; Modified: head/sbin/fsck_ffs/pass5.c ============================================================================== --- head/sbin/fsck_ffs/pass5.c Wed Dec 5 00:46:09 2018 (r341509) +++ head/sbin/fsck_ffs/pass5.c Wed Dec 5 06:31:50 2018 (r341510) @@ -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 && Modified: head/sbin/fsck_ffs/setup.c ============================================================================== --- head/sbin/fsck_ffs/setup.c Wed Dec 5 00:46:09 2018 (r341509) +++ head/sbin/fsck_ffs/setup.c Wed Dec 5 06:31:50 2018 (r341510) @@ -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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201812050631.wB56VoiL055810>