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>
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D35090
This commit is contained in:
Alan Somers 2022-04-29 10:43:47 -06:00
parent 616eaa66aa
commit 2f6362484c
7 changed files with 37 additions and 8 deletions

View File

@ -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"

View File

@ -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 */

View File

@ -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);

View File

@ -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();

View File

@ -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 */

View File

@ -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

View File

@ -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)