Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 Oct 2019 19:47:19 +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: r354036 - head/sys/ufs/ffs
Message-ID:  <201910241947.x9OJlJQp025605@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mckusick
Date: Thu Oct 24 19:47:18 2019
New Revision: 354036
URL: https://svnweb.freebsd.org/changeset/base/354036

Log:
  Soft updates needs to keep an on-disk linked list of inodes that
  have been unlinked, but are still referenced by open file descriptors.
  These inodes cannot be freed until the final file descriptor reference
  has been closed. If the system crashes while they are still being
  referenced, these inodes and their referenced blocks need to be
  freed by fsck. By having them on a linked list with the head pointer
  in the superblock, fsck can quickly find and process them rather
  than having to check every inode in the filesystem to see if it is
  unreferenced.
  
  When updating the head pointer of this list of unlinked inodes in
  the superblock, the superblock check-hash was not getting updated.
  If the system crashed with the incorrect superblock check-hash, the
  superblock would appear to be corrupted. This patch ensures that
  the superblock check-hash is updated when updating the head pointer
  of the unlinked inodes list.
  
  There is no need to MFC as superblock check hashes first appeared in
  13.0.
  
  Tested by:    Peter Holm
  Sponsored by: Netflix

Modified:
  head/sys/ufs/ffs/ffs_softdep.c

Modified: head/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- head/sys/ufs/ffs/ffs_softdep.c	Thu Oct 24 19:18:49 2019	(r354035)
+++ head/sys/ufs/ffs/ffs_softdep.c	Thu Oct 24 19:47:18 2019	(r354036)
@@ -9587,6 +9587,11 @@ initiate_write_sbdep(sbdep)
 	} else
 		fs->fs_sujfree = 0;
 	bpfs->fs_sujfree = fs->fs_sujfree;
+	/*
+	 * Because we have made changes to the superblock, we need to
+	 * recompute its check-hash.
+	 */
+	bpfs->fs_ckhash = ffs_calc_sbhash(bpfs);
 }
 
 /*
@@ -9665,7 +9670,7 @@ clear_unlinked_inodedep(inodedep)
 	struct ufsmount *ump;
 	struct inodedep *idp;
 	struct inodedep *idn;
-	struct fs *fs;
+	struct fs *fs, *bpfs;
 	struct buf *bp;
 	ino_t ino;
 	ino_t nino;
@@ -9762,9 +9767,14 @@ clear_unlinked_inodedep(inodedep)
 		 */
 		if (pino == 0) {
 			bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
-			ffs_oldfscompat_write((struct fs *)bp->b_data, ump);
-			softdep_setup_sbupdate(ump, (struct fs *)bp->b_data,
-			    bp);
+			bpfs = (struct fs *)bp->b_data;
+			ffs_oldfscompat_write(bpfs, ump);
+			softdep_setup_sbupdate(ump, bpfs, bp);
+			/*
+			 * Because we may have made changes to the superblock,
+			 * we need to recompute its check-hash.
+			 */
+			bpfs->fs_ckhash = ffs_calc_sbhash(bpfs);
 		} else if (fs->fs_magic == FS_UFS1_MAGIC) {
 			((struct ufs1_dinode *)bp->b_data +
 			    ino_to_fsbo(fs, pino))->di_freelink = nino;
@@ -9789,9 +9799,14 @@ clear_unlinked_inodedep(inodedep)
 			bp = getblk(ump->um_devvp, btodb(fs->fs_sblockloc),
 			    (int)fs->fs_sbsize, 0, 0, 0);
 			bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
-			ffs_oldfscompat_write((struct fs *)bp->b_data, ump);
-			softdep_setup_sbupdate(ump, (struct fs *)bp->b_data,
-			    bp);
+			bpfs = (struct fs *)bp->b_data;
+			ffs_oldfscompat_write(bpfs, ump);
+			softdep_setup_sbupdate(ump, bpfs, bp);
+			/*
+			 * Because we may have made changes to the superblock,
+			 * we need to recompute its check-hash.
+			 */
+			bpfs->fs_ckhash = ffs_calc_sbhash(bpfs);
 			bwrite(bp);
 			ACQUIRE_LOCK(ump);
 		}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201910241947.x9OJlJQp025605>