git: 2737e6bca78c - stable/13 - fusefs: use the fsname mount option if set

From: Alan Somers <asomers_at_FreeBSD.org>
Date: Mon, 23 May 2022 19:11:48 UTC
The branch stable/13 has been updated by asomers:

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

commit 2737e6bca78c69280bf4d36e161941c88696c0a6
Author:     Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2022-04-29 16:43:47 +0000
Commit:     Alan Somers <asomers@FreeBSD.org>
CommitDate: 2022-05-23 19:11:11 +0000

    fusefs: use the fsname mount option if set
    
    The daemon can specify fsname=XXX in its mount options.  If so, the file
    system should report f_mntfromname as XXX during statfs.  This will show
    up in the output of commands like mount and df.
    
    Submitted by:   Ali Abdallah <ali.abdallah@suse.com>
    Differential Revision:  https://reviews.freebsd.org/D35090
    
    (cherry picked from commit 2f6362484c0e1250ef6a76cccdbe4a95587e850c)
---
 sbin/mount_fusefs/mount_fusefs.c |  6 ++++--
 sys/fs/fuse/fuse_vfsops.c        |  7 +++++--
 tests/sys/fs/fusefs/mockfs.cc    |  6 +++++-
 tests/sys/fs/fusefs/mockfs.hh    |  2 +-
 tests/sys/fs/fusefs/mount.cc     | 20 +++++++++++++++++++-
 tests/sys/fs/fusefs/utils.cc     |  2 +-
 tests/sys/fs/fusefs/utils.hh     |  2 ++
 7 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/sbin/mount_fusefs/mount_fusefs.c b/sbin/mount_fusefs/mount_fusefs.c
index 33667c035e32..9cb5de66d2dd 100644
--- a/sbin/mount_fusefs/mount_fusefs.c
+++ b/sbin/mount_fusefs/mount_fusefs.c
@@ -77,6 +77,8 @@ static struct mntopt mopts[] = {
 	{ "max_read=",           0, ALTF_MAXREAD, 1 },
 	#define ALTF_SUBTYPE 0x40
 	{ "subtype=",            0, ALTF_SUBTYPE, 1 },
+	#define ALTF_FSNAME 0x80
+	{ "fsname=",             0, ALTF_FSNAME, 1 },
 	/*
 	 * MOPT_AUTOMOUNTED, included by MOPT_STDOPTS, does not fit into
 	 * the 'flags' argument to nmount(2).  We have to abuse altflags
@@ -87,7 +89,6 @@ static struct mntopt mopts[] = {
 	#define ALTF_INTR 0x200
 	{ "intr",		0, ALTF_INTR, 1 },
 	/* Linux specific options, we silently ignore them */
-	{ "fsname=",             0, 0x00, 1 },
 	{ "fd=",                 0, 0x00, 1 },
 	{ "rootmode=",           0, 0x00, 1 },
 	{ "user_id=",            0, 0x00, 1 },
@@ -110,6 +111,7 @@ struct mntval {
 static struct mntval mvals[] = {
 	{ ALTF_MAXREAD, NULL, 0 },
 	{ ALTF_SUBTYPE, NULL, 0 },
+	{ ALTF_FSNAME, NULL, 0 },
 	{ 0, NULL, 0 }
 };
 
@@ -474,8 +476,8 @@ helpmsg(void)
 	        /* "    -o nonempty            allow mounts over non-empty file/dir\n" */
 	        "    -o default_permissions enable permission checking by kernel\n"
 		"    -o intr                interruptible mount\n"
-		/*
 	        "    -o fsname=NAME         set filesystem name\n"
+		/*
 	        "    -o large_read          issue large read requests (2.4 only)\n"
 		 */
 	        "    -o subtype=NAME        set filesystem type\n"
diff --git a/sys/fs/fuse/fuse_vfsops.c b/sys/fs/fuse/fuse_vfsops.c
index 6d988f9b3136..4ff0fff4f47a 100644
--- a/sys/fs/fuse/fuse_vfsops.c
+++ b/sys/fs/fuse/fuse_vfsops.c
@@ -308,7 +308,8 @@ fuse_vfsop_mount(struct mount *mp)
 	struct fuse_data *data = NULL;
 	struct thread *td;
 	struct file *fp, *fptmp;
-	char *fspec, *subtype;
+	char *fspec, *subtype, *fsname = NULL;
+	int fsnamelen;
 	struct vfsoptlist *opts;
 
 	subtype = NULL;
@@ -440,7 +441,9 @@ fuse_vfsop_mount(struct mount *mp)
 		strlcat(mp->mnt_stat.f_fstypename, subtype, MFSNAMELEN);
 	}
 	memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
-	strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN);
+	vfs_getopt(opts, "fsname=", (void**)&fsname, &fsnamelen);
+	strlcpy(mp->mnt_stat.f_mntfromname,
+		fsname == NULL ? fspec : fsname, MNAMELEN);
 	mp->mnt_iosize_max = maxphys;
 
 	/* Now handshaking with daemon */
diff --git a/tests/sys/fs/fusefs/mockfs.cc b/tests/sys/fs/fusefs/mockfs.cc
index 4eebbc2200b0..9a197d8a80f0 100644
--- a/tests/sys/fs/fusefs/mockfs.cc
+++ b/tests/sys/fs/fusefs/mockfs.cc
@@ -410,7 +410,7 @@ MockFS::MockFS(int max_readahead, bool allow_other, bool default_permissions,
 	bool push_symlinks_in, bool ro, enum poll_method pm, uint32_t flags,
 	uint32_t kernel_minor_version, uint32_t max_write, bool async,
 	bool noclusterr, unsigned time_gran, bool nointr, bool noatime,
-	const char *subtype)
+	const char *fsname, const char *subtype)
 {
 	struct sigaction sa;
 	struct iovec *iov = NULL;
@@ -501,6 +501,10 @@ MockFS::MockFS(int max_readahead, bool allow_other, bool default_permissions,
 		build_iovec(&iov, &iovlen, "intr",
 			__DECONST(void*, &trueval), sizeof(bool));
 	}
+	if (*fsname) {
+		build_iovec(&iov, &iovlen, "fsname=",
+			__DECONST(void*, fsname), -1);
+	}
 	if (*subtype) {
 		build_iovec(&iov, &iovlen, "subtype=",
 			__DECONST(void*, subtype), -1);
diff --git a/tests/sys/fs/fusefs/mockfs.hh b/tests/sys/fs/fusefs/mockfs.hh
index 3c8a78e85072..121d985e56fe 100644
--- a/tests/sys/fs/fusefs/mockfs.hh
+++ b/tests/sys/fs/fusefs/mockfs.hh
@@ -361,7 +361,7 @@ class MockFS {
 		enum poll_method pm, uint32_t flags,
 		uint32_t kernel_minor_version, uint32_t max_write, bool async,
 		bool no_clusterr, unsigned time_gran, bool nointr,
-		bool noatime, const char *subtype);
+		bool noatime, const char *fsname, const char *subtype);
 
 	virtual ~MockFS();
 
diff --git a/tests/sys/fs/fusefs/mount.cc b/tests/sys/fs/fusefs/mount.cc
index d736377536cb..636545be74c2 100644
--- a/tests/sys/fs/fusefs/mount.cc
+++ b/tests/sys/fs/fusefs/mount.cc
@@ -56,6 +56,14 @@ void expect_statfs() {
 	})));
 }
 };
+
+class Fsname: public Mount {
+	void SetUp() {
+		m_fsname = "http://something";
+		Mount::SetUp();
+	}
+};
+
 class Subtype: public Mount {
 	void SetUp() {
 		m_subtype = "myfs";
@@ -84,6 +92,16 @@ int mntflag_from_string(const char *s)
 		return 0;
 }
 
+TEST_F(Fsname, fsname)
+{
+	struct statfs statbuf;
+
+	expect_statfs();
+
+	ASSERT_EQ(0, statfs("mountpoint", &statbuf)) << strerror(errno);
+	ASSERT_STREQ("http://something", statbuf.f_mntfromname);
+}
+
 TEST_F(Subtype, subtype)
 {
 	struct statfs statbuf;
@@ -91,7 +109,7 @@ TEST_F(Subtype, subtype)
 	expect_statfs();
 
 	ASSERT_EQ(0, statfs("mountpoint", &statbuf)) << strerror(errno);
-	ASSERT_EQ(0, strcmp("fusefs.myfs", statbuf.f_fstypename));
+	ASSERT_STREQ("fusefs.myfs", statbuf.f_fstypename);
 }
 
 /* Some mount options can be changed by mount -u */
diff --git a/tests/sys/fs/fusefs/utils.cc b/tests/sys/fs/fusefs/utils.cc
index 0d42f418c369..d4edca5ca945 100644
--- a/tests/sys/fs/fusefs/utils.cc
+++ b/tests/sys/fs/fusefs/utils.cc
@@ -161,7 +161,7 @@ void FuseTest::SetUp() {
 			m_default_permissions, m_push_symlinks_in, m_ro,
 			m_pm, m_init_flags, m_kernel_minor_version,
 			m_maxwrite, m_async, m_noclusterr, m_time_gran,
-			m_nointr, m_noatime, m_subtype);
+			m_nointr, m_noatime, m_fsname, m_subtype);
 		/* 
 		 * FUSE_ACCESS is called almost universally.  Expecting it in
 		 * each test case would be super-annoying.  Instead, set a
diff --git a/tests/sys/fs/fusefs/utils.hh b/tests/sys/fs/fusefs/utils.hh
index 7d30f2b233ab..d839dc6d2208 100644
--- a/tests/sys/fs/fusefs/utils.hh
+++ b/tests/sys/fs/fusefs/utils.hh
@@ -74,6 +74,7 @@ class FuseTest : public ::testing::Test {
 	MockFS *m_mock = NULL;
 	const static uint64_t FH = 0xdeadbeef1a7ebabe;
 	const char *reclaim_mib = "debug.try_reclaim_vnode";
+	const char *m_fsname;
 	const char *m_subtype;
 
 	public:
@@ -95,6 +96,7 @@ class FuseTest : public ::testing::Test {
 		m_noclusterr(false),
 		m_nointr(false),
 		m_time_gran(1),
+		m_fsname(""),
 		m_subtype(""),
 		m_maxbcachebuf(0),
 		m_maxphys(0)