git: 3eb80d8d7daf - main - ufs: Allow read-only mounting of NetBSD FFSv2 WAPBL filesystems

From: Warner Losh <imp_at_FreeBSD.org>
Date: Wed, 08 Jul 2026 05:17:03 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=3eb80d8d7daf4f14c22dd462d8c4e5b6fc818bd4

commit 3eb80d8d7daf4f14c22dd462d8c4e5b6fc818bd4
Author:     Ricardo Branco <rbranco@suse.de>
AuthorDate: 2026-06-13 08:26:58 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2026-07-08 05:16:01 +0000

    ufs: Allow read-only mounting of NetBSD FFSv2 WAPBL filesystems
    
    Skip UFS2 fs_metaspace upper-bound validation that rejects NetBSD FFSv2
    WAPBL filesystems due to differing superblock layouts.
    
    Detect the condition during mount instead and permit read-only mounts
    while rejecting read-write mounts with EROFS.  This follows NetBSD's
    recommendation for systems without WAPBL support and avoids modifying
    unsupported journal metadata.
    
    PR: 296022
    Signed-off-by: Ricardo Branco <rbranco@suse.de>
    Reviewed by: imp, kirk
    Pull Request: https://github.com/freebsd/freebsd-src/pull/2279
---
 sys/ufs/ffs/ffs_subr.c   | 14 +++++++++++++-
 sys/ufs/ffs/ffs_vfsops.c | 27 +++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
index 682dd60ebd44..496de9913eda 100644
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -717,7 +717,19 @@ validate_sblock(struct fs *fs, int flags)
 		howmany(fs->fs_cssize, fs->fs_fsize), %jd);
 #endif
 	WCHK(fs->fs_metaspace, <, 0, %jd);
-	WCHK(fs->fs_metaspace, >, fs->fs_fpg / 2, %jd);
+	/*
+	 * FreeBSD and NetBSD FFSv2 layouts diverge in the superblock region
+	 * following fs_maxbsize.  NetBSD's WAPBL journal metadata occupies
+	 * the same bytes as FreeBSD's fs_metaspace and other fields.
+	 * fs_flags cannot serve as a discriminator: ffs_oldfscompat_read()
+	 * may overwrite it from the 8-bit fs_old_flags before this check runs.
+	 * Skip the upper-bound check for UFS2; ffs_mountfs() detects the
+	 * condition and enforces read-only access without modifying the
+	 * on-disk superblock.  The check is preserved for UFS1 where no such
+	 * layout divergence exists.
+	 */
+	if (fs->fs_magic != FS_UFS2_MAGIC)
+		WCHK(fs->fs_metaspace, >, fs->fs_fpg / 2, %jd);
 	WCHK(fs->fs_minfree, >, 99, %jd%%);
 	maxfilesize = fs->fs_bsize * UFS_NDADDR - 1;
 	for (sizepb = fs->fs_bsize, i = 0; i < UFS_NIADDR; i++) {
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index a9b04bd290bd..f7f1d3e7ff93 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -604,6 +604,16 @@ ffs_mount(struct mount *mp)
 			if (error) {
 				return (error);
 			}
+			/*
+			 * Refuse upgrade of NetBSD WAPBL filesystem to
+			 * read-write; see validate_sblock() for details.
+			 */
+			if (fs->fs_magic == FS_UFS2_MAGIC &&
+			    fs->fs_metaspace > fs->fs_fpg / 2) {
+				vfs_mount_error(mp,
+				    "WAPBL filesystem must be mounted read-only");
+				return (EROFS);
+			}
 			fs->fs_flags &= ~FS_UNCLEAN;
 			if (fs->fs_clean == 0) {
 				fs->fs_flags |= FS_UNCLEAN;
@@ -926,6 +936,23 @@ ffs_mountfs(struct vnode *odevvp, struct mount *mp, struct thread *td)
 		    ffs_use_bread);
 	if (error != 0)
 		goto out;
+	/*
+	 * Per NetBSD's wapbl(4), systems without WAPBL support should mount it
+	 * read-only; see validate_sblock() for details.
+	 */
+	if (fs->fs_magic == FS_UFS2_MAGIC &&
+	    fs->fs_metaspace > fs->fs_fpg / 2) {
+		if ((mp->mnt_flag & MNT_RDONLY) == 0) {
+			vfs_mount_error(mp,
+			    "WAPBL filesystem must be mounted read-only");
+			error = EROFS;
+			goto out;
+		}
+		printf("WARNING: %s: WAPBL filesystem mounted read-only"
+		    "(fs_metaspace %jd, fs_fpg/2 %jd)\n",
+		    mp->mnt_stat.f_mntonname, (intmax_t)fs->fs_metaspace,
+		    (intmax_t)fs->fs_fpg / 2);
+	}
 	fs->fs_flags &= ~FS_UNCLEAN;
 	if (fs->fs_clean == 0) {
 		fs->fs_flags |= FS_UNCLEAN;