git: aaf65a13c06a - main - stand: add fs_ops.fs_flag

From: Simon J. Gerraty <sjg_at_FreeBSD.org>
Date: Wed, 20 Aug 2025 22:46:57 UTC
The branch main has been updated by sjg:

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

commit aaf65a13c06a2555257a75b7f2fe63319238cf4f
Author:     Simon J. Gerraty <sjg@FreeBSD.org>
AuthorDate: 2025-08-20 22:42:35 +0000
Commit:     Simon J. Gerraty <sjg@FreeBSD.org>
CommitDate: 2025-08-20 22:42:35 +0000

    stand: add fs_ops.fs_flag
    
    To avoid a layering violation in open() allow fs_ops to
    indicate that devopen() should be skipped.
    
    This is only true for pkgfs.
    
    Sponsored by:   Juniper Networks, Inc.
    Differential Revision:  https://reviews.freebsd.org/D51684
---
 stand/libsa/bzipfs.c  |  1 +
 stand/libsa/cd9660.c  |  1 +
 stand/libsa/dosfs.c   |  1 +
 stand/libsa/ext2fs.c  |  1 +
 stand/libsa/gzipfs.c  |  1 +
 stand/libsa/nfs.c     |  1 +
 stand/libsa/open.c    | 33 +++++++++++++++++++--------------
 stand/libsa/pkgfs.c   |  1 +
 stand/libsa/splitfs.c |  1 +
 stand/libsa/stand.h   |  3 +++
 stand/libsa/tftp.c    |  1 +
 stand/libsa/ufs.c     |  1 +
 12 files changed, 32 insertions(+), 14 deletions(-)

diff --git a/stand/libsa/bzipfs.c b/stand/libsa/bzipfs.c
index f4002796f0ae..ff7ec16e7dc6 100644
--- a/stand/libsa/bzipfs.c
+++ b/stand/libsa/bzipfs.c
@@ -68,6 +68,7 @@ static int	bzf_stat(struct open_file *f, struct stat *sb);
 #ifndef REGRESSION
 struct fs_ops bzipfs_fsops = {
 	.fs_name = "bzip",
+	.fs_flags = 0,
 	.fo_open = bzf_open,
 	.fo_close = bzf_close,
 	.fo_read = bzf_read,
diff --git a/stand/libsa/cd9660.c b/stand/libsa/cd9660.c
index 973a7dddcda9..d1da39aa479a 100644
--- a/stand/libsa/cd9660.c
+++ b/stand/libsa/cd9660.c
@@ -81,6 +81,7 @@ static ISO_SUSP_HEADER *susp_lookup_record(struct open_file *f,
 
 struct fs_ops cd9660_fsops = {
 	.fs_name = "cd9660",
+	.fs_flags = 0,
 	.fo_open = cd9660_open,
 	.fo_close = cd9660_close,
 	.fo_read = cd9660_read,
diff --git a/stand/libsa/dosfs.c b/stand/libsa/dosfs.c
index aca198cdf6fa..38610d917007 100644
--- a/stand/libsa/dosfs.c
+++ b/stand/libsa/dosfs.c
@@ -61,6 +61,7 @@ static int	dos_unmount(const char *dev, void *data);
 
 struct fs_ops dosfs_fsops = {
 	.fs_name = "dosfs",
+	.fs_flags = 0,
 	.fo_open = dos_open,
 	.fo_close = dos_close,
 	.fo_read = dos_read,
diff --git a/stand/libsa/ext2fs.c b/stand/libsa/ext2fs.c
index 47812f4543a1..f7096282f156 100644
--- a/stand/libsa/ext2fs.c
+++ b/stand/libsa/ext2fs.c
@@ -106,6 +106,7 @@ static int dtmap[] = { DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR,
 
 struct fs_ops ext2fs_fsops = {
 	.fs_name = "ext2fs",
+	.fs_flags = 0,
 	.fo_open = ext2fs_open,
 	.fo_close = ext2fs_close,
 	.fo_read = ext2fs_read,
diff --git a/stand/libsa/gzipfs.c b/stand/libsa/gzipfs.c
index 6c2b8cac9e34..6b22f750f3ef 100644
--- a/stand/libsa/gzipfs.c
+++ b/stand/libsa/gzipfs.c
@@ -50,6 +50,7 @@ static int	zf_stat(struct open_file *f, struct stat *sb);
 
 struct fs_ops gzipfs_fsops = {
 	.fs_name = "zip",
+	.fs_flags = 0,
 	.fo_open = zf_open,
 	.fo_close = zf_close,
 	.fo_read = zf_read,
diff --git a/stand/libsa/nfs.c b/stand/libsa/nfs.c
index ee6af8a726c7..f3e9060c9881 100644
--- a/stand/libsa/nfs.c
+++ b/stand/libsa/nfs.c
@@ -131,6 +131,7 @@ struct	nfs_iodesc nfs_root_node;
 
 struct fs_ops nfs_fsops = {
 	.fs_name = "nfs",
+	.fs_flags = 0,
 	.fo_open = nfs_open,
 	.fo_close = nfs_close,
 	.fo_read = nfs_read,
diff --git a/stand/libsa/open.c b/stand/libsa/open.c
index ccee4aa5c07b..c97aa5977f9e 100644
--- a/stand/libsa/open.c
+++ b/stand/libsa/open.c
@@ -154,27 +154,32 @@ open(const char *fname, int mode)
 	f->f_devdata = NULL;
 	file = NULL;
 
+	if (exclusive_file_system == NULL ||
+	    (exclusive_file_system->fs_flags & FS_OPS_NO_DEVOPEN) == 0) {
+		error = devopen(f, fname, &file);
+		if (error ||
+		    (((f->f_flags & F_NODEV) == 0) && f->f_dev == NULL))
+			goto err;
+
+		/* see if we opened a raw device; otherwise, 'file' is the file name. */
+		if (file == NULL || *file == '\0') {
+			f->f_flags |= F_RAW;
+			f->f_rabuf = NULL;
+			TSEXIT();
+			return (fd);
+		}
+	} else
+		file = fname;
+
 	if (exclusive_file_system != NULL) {
+		/* loader is forcing the filesystem to be used */
 		fs = exclusive_file_system;
-		error = (fs->fo_open)(fname, f);
+		error = (fs->fo_open)(file, f);
 		if (error == 0)
 			goto ok;
 		goto err;
 	}
 
-	error = devopen(f, fname, &file);
-	if (error ||
-	    (((f->f_flags & F_NODEV) == 0) && f->f_dev == NULL))
-		goto err;
-
-	/* see if we opened a raw device; otherwise, 'file' is the file name. */
-	if (file == NULL || *file == '\0') {
-		f->f_flags |= F_RAW;
-		f->f_rabuf = NULL;
-		TSEXIT();
-		return (fd);
-	}
-
 	/* pass file name to the different filesystem open routines */
 	besterror = ENOENT;
 	for (i = 0; file_system[i] != NULL; i++) {
diff --git a/stand/libsa/pkgfs.c b/stand/libsa/pkgfs.c
index 32d488de5cfb..6eb3badf7068 100644
--- a/stand/libsa/pkgfs.c
+++ b/stand/libsa/pkgfs.c
@@ -41,6 +41,7 @@ static off_t pkg_atol(const char *, unsigned);
 
 struct fs_ops pkgfs_fsops = {
 	.fs_name = "pkg",
+	.fs_flags = FS_OPS_NO_DEVOPEN,
 	.fo_open = pkg_open,
 	.fo_close = pkg_close,
 	.fo_read = pkg_read,
diff --git a/stand/libsa/splitfs.c b/stand/libsa/splitfs.c
index 69912522000e..eb4b3a1feb11 100644
--- a/stand/libsa/splitfs.c
+++ b/stand/libsa/splitfs.c
@@ -50,6 +50,7 @@ static int	splitfs_stat(struct open_file *f, struct stat *sb);
 
 struct fs_ops splitfs_fsops = {
 	.fs_name = "split",
+	.fs_flags = 0,
 	.fo_open = splitfs_open,
 	.fo_close = splitfs_close,
 	.fo_read = splitfs_read,
diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h
index 0e99d8778fa6..c6a08be2f7e3 100644
--- a/stand/libsa/stand.h
+++ b/stand/libsa/stand.h
@@ -94,6 +94,8 @@ __BEGIN_DECLS
 
 struct open_file;
 
+#define FS_OPS_NO_DEVOPEN 1
+
 /*
  * This structure is used to define file system operations in a file system
  * independent way.
@@ -104,6 +106,7 @@ struct open_file;
  */
 struct fs_ops {
     const char	*fs_name;
+    int		fs_flags;
     int		(*fo_open)(const char *path, struct open_file *f);
     int		(*fo_close)(struct open_file *f);
     int		(*fo_read)(struct open_file *f, void *buf,
diff --git a/stand/libsa/tftp.c b/stand/libsa/tftp.c
index c6cc8f11a765..0584246a6dea 100644
--- a/stand/libsa/tftp.c
+++ b/stand/libsa/tftp.c
@@ -73,6 +73,7 @@ static int tftp_preload(struct open_file *);
 
 struct fs_ops tftp_fsops = {
 	.fs_name = "tftp",
+	.fs_flags = 0,
 	.fo_open = tftp_open,
 	.fo_close = tftp_close,
 	.fo_read = tftp_read,
diff --git a/stand/libsa/ufs.c b/stand/libsa/ufs.c
index e1d540ed2321..86cd3be9a27a 100644
--- a/stand/libsa/ufs.c
+++ b/stand/libsa/ufs.c
@@ -93,6 +93,7 @@ static int	ufs_unmount(const char *dev, void *data);
 
 struct fs_ops ufs_fsops = {
 	.fs_name = "ufs",
+	.fs_flags = 0,
 	.fo_open = ufs_open,
 	.fo_close = ufs_close,
 	.fo_read = ufs_read,