aboutsummaryrefslogtreecommitdiffstats
path: root/sbin/fsck_ffs
diff options
context:
space:
mode:
authorKirk McKusick <mckusick@FreeBSD.org>2020-04-10 23:49:34 +0000
committerKirk McKusick <mckusick@FreeBSD.org>2020-04-10 23:49:34 +0000
commit2a18059670480dbe6eb49a3258463fe5dfcf00a9 (patch)
tree04f5a4fe8d84bf10080168c958168b8ed376520e /sbin/fsck_ffs
parent6ca096da088fad42b6692758c13f44dc7ebf5721 (diff)
downloadsrc-2a18059670480dbe6eb49a3258463fe5dfcf00a9.tar.gz
src-2a18059670480dbe6eb49a3258463fe5dfcf00a9.zip
Add an inode check-hash verification when running the journalled
soft update recovery code with the debugging (-d) option. As inode check-hash was first introduced to UFS in FreeBSD 13, there is no need to MFC this commit. Reported by: Chuck Silvers Sponsored by: Netflix
Notes
Notes: svn path=/head/; revision=359789
Diffstat (limited to 'sbin/fsck_ffs')
-rw-r--r--sbin/fsck_ffs/suj.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/sbin/fsck_ffs/suj.c b/sbin/fsck_ffs/suj.c
index be742e1b6773..1090b450046d 100644
--- a/sbin/fsck_ffs/suj.c
+++ b/sbin/fsck_ffs/suj.c
@@ -109,6 +109,7 @@ struct ino_blk {
LIST_ENTRY(ino_blk) ib_next;
uint8_t *ib_buf;
int ib_dirty;
+ ino_t ib_startinginum;
ufs2_daddr_t ib_blk;
};
LIST_HEAD(iblkhd, ino_blk);
@@ -157,6 +158,7 @@ static void ino_adjust(struct suj_ino *);
static void ino_build(struct suj_ino *);
static int blk_isfree(ufs2_daddr_t);
static void initsuj(void);
+static void ino_dirty(ino_t);
static void *
errmalloc(size_t n)
@@ -394,6 +396,7 @@ ino_read(ino_t ino)
struct iblkhd *hd;
struct suj_cg *sc;
ufs2_daddr_t blk;
+ union dinode *dp;
int off;
blk = ino_to_fsba(fs, ino);
@@ -412,6 +415,7 @@ ino_read(ino_t ino)
bzero(iblk, sizeof(*iblk));
iblk->ib_buf = errmalloc(fs->fs_bsize);
iblk->ib_blk = blk;
+ iblk->ib_startinginum = rounddown(ino, INOPB(fs));
LIST_INSERT_HEAD(hd, iblk, ib_next);
if (bread(&disk, fsbtodb(fs, blk), iblk->ib_buf, fs->fs_bsize) == -1)
err_suj("Failed to read inode block %jd\n", blk);
@@ -420,8 +424,18 @@ found:
off = ino_to_fsbo(fs, ino);
if (fs->fs_magic == FS_UFS1_MAGIC)
return (union dinode *)&((struct ufs1_dinode *)iblk->ib_buf)[off];
- else
- return (union dinode *)&((struct ufs2_dinode *)iblk->ib_buf)[off];
+ dp = (union dinode *)&((struct ufs2_dinode *)iblk->ib_buf)[off];
+ if (debug &&
+ ffs_verify_dinode_ckhash(fs, (struct ufs2_dinode *)dp) != 0) {
+ pwarn("ino_read: INODE CHECK-HASH FAILED");
+ prtinode(ino, dp);
+ if (preen || reply("FIX") != 0) {
+ if (preen)
+ printf(" (FIXED)\n");
+ ino_dirty(ino);
+ }
+ }
+ return (dp);
}
static void
@@ -464,9 +478,25 @@ ino_dirty(ino_t ino)
static void
iblk_write(struct ino_blk *iblk)
{
+ struct ufs2_dinode *dp;
+ int i;
if (iblk->ib_dirty == 0)
return;
+ if (debug && fs->fs_magic == FS_UFS2_MAGIC) {
+ dp = (struct ufs2_dinode *)iblk->ib_buf;
+ for (i = 0; i < INOPB(fs); dp++, i++) {
+ if (ffs_verify_dinode_ckhash(fs, dp) == 0)
+ continue;
+ pwarn("iblk_write: INODE CHECK-HASH FAILED");
+ prtinode(iblk->ib_startinginum + i, (union dinode *)dp);
+ if (preen || reply("FIX") != 0) {
+ if (preen)
+ printf(" (FIXED)\n");
+ ino_dirty(iblk->ib_startinginum + i);
+ }
+ }
+ }
if (bwrite(&disk, fsbtodb(fs, iblk->ib_blk), iblk->ib_buf,
fs->fs_bsize) == -1)
err_suj("Failed to write inode block %jd\n", iblk->ib_blk);