aboutsummaryrefslogtreecommitdiffstats
path: root/sbin/fsck_ffs
diff options
context:
space:
mode:
authorKirk McKusick <mckusick@FreeBSD.org>2018-12-05 06:31:50 +0000
committerKirk McKusick <mckusick@FreeBSD.org>2018-12-05 06:31:50 +0000
commit8ebae128befbc3cca0ba1597e46fe12c0340663d (patch)
treeb36a903fb578855d31b7fb657a2a4413a80500c0 /sbin/fsck_ffs
parentdb19a093bba2009eaed0fbc545210480a2108dda (diff)
downloadsrc-8ebae128befbc3cca0ba1597e46fe12c0340663d.tar.gz
src-8ebae128befbc3cca0ba1597e46fe12c0340663d.zip
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
Notes
Notes: svn path=/head/; revision=341510
Diffstat (limited to 'sbin/fsck_ffs')
-rw-r--r--sbin/fsck_ffs/fsck.h1
-rw-r--r--sbin/fsck_ffs/fsutil.c26
-rw-r--r--sbin/fsck_ffs/inode.c2
-rw-r--r--sbin/fsck_ffs/pass1.c2
-rw-r--r--sbin/fsck_ffs/pass5.c20
-rw-r--r--sbin/fsck_ffs/setup.c7
6 files changed, 42 insertions, 16 deletions
diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index ffe41be6cf3b..ed7e8f129c35 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -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);
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c
index 91be4234ae48..117698a09c32 100644
--- a/sbin/fsck_ffs/fsutil.c
+++ b/sbin/fsck_ffs/fsutil.c
@@ -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);
}
}
diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c
index 3f1cab8b3bd5..a914be8b87a5 100644
--- a/sbin/fsck_ffs/inode.c
+++ b/sbin/fsck_ffs/inode.c
@@ -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) {
diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c
index 40e5e6d07e14..c9064ea704e4 100644
--- a/sbin/fsck_ffs/pass1.c
+++ b/sbin/fsck_ffs/pass1.c
@@ -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;
diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c
index 436d184c327b..674ca91e22f3 100644
--- a/sbin/fsck_ffs/pass5.c
+++ b/sbin/fsck_ffs/pass5.c
@@ -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 &&
diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c
index 4767b079e8c0..82a970e12858 100644
--- a/sbin/fsck_ffs/setup.c
+++ b/sbin/fsck_ffs/setup.c
@@ -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);