* [RFC PATCH 0/4] 9p: convert to the new mount API
@ 2025-07-24 2:23 Eric Sandeen
2025-07-24 2:23 ` [RFC PATCH 1/4] fs/fs_parse: add back fsparam_u32hex Eric Sandeen
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Eric Sandeen @ 2025-07-24 2:23 UTC (permalink / raw)
To: v9fs; +Cc: ericvh, lucho, asmadeus, linux_oss
This is an attempt to convert 9p to the new mount API. 9p is one of the
last conversions needed, possibly because it is one of the trickier
ones!
I was able to test this to some degree, but I am not sure how to test
all transports; there may well be bugs here. It would be great to get
some feedback on whether this approach seems reasonable, and of course
any further review or testing would be most welcome.
Thanks,
-Eric
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH 1/4] fs/fs_parse: add back fsparam_u32hex
2025-07-24 2:23 [RFC PATCH 0/4] 9p: convert to the new mount API Eric Sandeen
@ 2025-07-24 2:23 ` Eric Sandeen
2025-07-24 2:23 ` [RFC PATCH 2/4] net/9p: move structures and macros to header files Eric Sandeen
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Eric Sandeen @ 2025-07-24 2:23 UTC (permalink / raw)
To: v9fs; +Cc: ericvh, lucho, asmadeus, linux_oss, Eric Sandeen
296b67059 removed fsparam_u32hex because there were no callers
(yet) and it didn't build due to using the nonexistent symbol
fs_param_is_u32_hex.
fs/9p will need this parser, so add it back with the appropriate
fix (use fs_param_is_u32).
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
include/linux/fs_parser.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/linux/fs_parser.h b/include/linux/fs_parser.h
index 5a0e897cae80..5e8a3b546033 100644
--- a/include/linux/fs_parser.h
+++ b/include/linux/fs_parser.h
@@ -120,6 +120,8 @@ static inline bool fs_validate_description(const char *name,
#define fsparam_u32(NAME, OPT) __fsparam(fs_param_is_u32, NAME, OPT, 0, NULL)
#define fsparam_u32oct(NAME, OPT) \
__fsparam(fs_param_is_u32, NAME, OPT, 0, (void *)8)
+#define fsparam_u32hex(NAME, OPT) \
+ __fsparam(fs_param_is_u32, NAME, OPT, 0, (void *)16)
#define fsparam_s32(NAME, OPT) __fsparam(fs_param_is_s32, NAME, OPT, 0, NULL)
#define fsparam_u64(NAME, OPT) __fsparam(fs_param_is_u64, NAME, OPT, 0, NULL)
#define fsparam_enum(NAME, OPT, array) __fsparam(fs_param_is_enum, NAME, OPT, 0, array)
--
2.48.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC PATCH 2/4] net/9p: move structures and macros to header files
2025-07-24 2:23 [RFC PATCH 0/4] 9p: convert to the new mount API Eric Sandeen
2025-07-24 2:23 ` [RFC PATCH 1/4] fs/fs_parse: add back fsparam_u32hex Eric Sandeen
@ 2025-07-24 2:23 ` Eric Sandeen
2025-07-24 2:23 ` [RFC PATCH 3/4] 9p: create a v9fs_context structure to hold parsed options Eric Sandeen
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Eric Sandeen @ 2025-07-24 2:23 UTC (permalink / raw)
To: v9fs; +Cc: ericvh, lucho, asmadeus, linux_oss, Eric Sandeen
With the new mount API all option parsing will need to happen
in fs/v9fs.c, so move necessary data structures and macros to
header files to facilitate this. Rename some to reflect
the transport they are used for (rdma, fd, etc), for clarity.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
include/net/9p/client.h | 6 ++++++
include/net/9p/transport.h | 39 ++++++++++++++++++++++++++++++++++++++
net/9p/client.c | 6 ------
net/9p/trans_fd.c | 20 ++-----------------
net/9p/trans_rdma.c | 25 ++----------------------
5 files changed, 49 insertions(+), 47 deletions(-)
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 4f785098c67a..2d46f8017bd5 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -16,6 +16,12 @@
/* Number of requests per row */
#define P9_ROW_MAXTAG 255
+/* DEFAULT MSIZE = 32 pages worth of payload + P9_HDRSZ +
+ * room for write (16 extra) or read (11 extra) operands.
+ */
+
+#define DEFAULT_MSIZE ((128 * 1024) + P9_IOHDRSZ)
+
/** enum p9_proto_versions - 9P protocol versions
* @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u
* @p9_proto_2000u: 9P2000.u extension
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
index 766ec07c9599..88702953b1ef 100644
--- a/include/net/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -14,6 +14,45 @@
#define P9_DEF_MIN_RESVPORT (665U)
#define P9_DEF_MAX_RESVPORT (1023U)
+#define P9_FD_PORT 564
+
+#define P9_RDMA_PORT 5640
+#define P9_RDMA_SQ_DEPTH 32
+#define P9_RDMA_RQ_DEPTH 32
+#define P9_RDMA_TIMEOUT 30000 /* 30 seconds */
+
+/**
+ * struct p9_fd_opts - per-transport options for fd transport
+ * @rfd: file descriptor for reading (trans=fd)
+ * @wfd: file descriptor for writing (trans=fd)
+ * @port: port to connect to (trans=tcp)
+ * @privport: port is privileged
+ */
+
+struct p9_fd_opts {
+ int rfd;
+ int wfd;
+ u16 port;
+ bool privport;
+};
+
+/**
+ * struct p9_rdma_opts - Collection of mount options for rdma transport
+ * @port: port of connection
+ * @privport: Whether a privileged port may be used
+ * @sq_depth: The requested depth of the SQ. This really doesn't need
+ * to be any deeper than the number of threads used in the client
+ * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth
+ * @timeout: Time to wait in msecs for CM events
+ */
+struct p9_rdma_opts {
+ short port;
+ bool privport;
+ int sq_depth;
+ int rq_depth;
+ long timeout;
+};
+
/**
* struct p9_trans_module - transport module interface
* @list: used to maintain a list of currently available transports
diff --git a/net/9p/client.c b/net/9p/client.c
index 5c1ca57ccd28..5e3230b1bfab 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -29,12 +29,6 @@
#define CREATE_TRACE_POINTS
#include <trace/events/9p.h>
-/* DEFAULT MSIZE = 32 pages worth of payload + P9_HDRSZ +
- * room for write (16 extra) or read (11 extra) operands.
- */
-
-#define DEFAULT_MSIZE ((128 * 1024) + P9_IOHDRSZ)
-
/* Client Option Parsing (code inspired by NFS code)
* - a little lazy - parse all client options
*/
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 339ec4e54778..9ef4f2e0db3c 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -31,28 +31,12 @@
#include <linux/syscalls.h> /* killme */
-#define P9_PORT 564
#define MAX_SOCK_BUF (1024*1024)
#define MAXPOLLWADDR 2
static struct p9_trans_module p9_tcp_trans;
static struct p9_trans_module p9_fd_trans;
-/**
- * struct p9_fd_opts - per-transport options
- * @rfd: file descriptor for reading (trans=fd)
- * @wfd: file descriptor for writing (trans=fd)
- * @port: port to connect to (trans=tcp)
- * @privport: port is privileged
- */
-
-struct p9_fd_opts {
- int rfd;
- int wfd;
- u16 port;
- bool privport;
-};
-
/*
* Option Parsing (code inspired by NFS code)
* - a little lazy - parse all fd-transport options
@@ -749,7 +733,7 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
static int p9_fd_show_options(struct seq_file *m, struct p9_client *clnt)
{
if (clnt->trans_mod == &p9_tcp_trans) {
- if (clnt->trans_opts.tcp.port != P9_PORT)
+ if (clnt->trans_opts.tcp.port != P9_FD_PORT)
seq_printf(m, ",port=%u", clnt->trans_opts.tcp.port);
} else if (clnt->trans_mod == &p9_fd_trans) {
if (clnt->trans_opts.fd.rfd != ~0)
@@ -775,7 +759,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
int option;
char *options, *tmp_options;
- opts->port = P9_PORT;
+ opts->port = P9_FD_PORT;
opts->rfd = ~0;
opts->wfd = ~0;
opts->privport = false;
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
index b84748baf9cb..46ee37061faf 100644
--- a/net/9p/trans_rdma.c
+++ b/net/9p/trans_rdma.c
@@ -32,14 +32,10 @@
#include <rdma/ib_verbs.h>
#include <rdma/rdma_cm.h>
-#define P9_PORT 5640
-#define P9_RDMA_SQ_DEPTH 32
-#define P9_RDMA_RQ_DEPTH 32
#define P9_RDMA_SEND_SGE 4
#define P9_RDMA_RECV_SGE 4
#define P9_RDMA_IRD 0
#define P9_RDMA_ORD 0
-#define P9_RDMA_TIMEOUT 30000 /* 30 seconds */
#define P9_RDMA_MAXSIZE (1024*1024) /* 1MB */
/**
@@ -110,23 +106,6 @@ struct p9_rdma_context {
};
};
-/**
- * struct p9_rdma_opts - Collection of mount options
- * @port: port of connection
- * @privport: Whether a privileged port may be used
- * @sq_depth: The requested depth of the SQ. This really doesn't need
- * to be any deeper than the number of threads used in the client
- * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth
- * @timeout: Time to wait in msecs for CM events
- */
-struct p9_rdma_opts {
- short port;
- bool privport;
- int sq_depth;
- int rq_depth;
- long timeout;
-};
-
/*
* Option Parsing (code inspired by NFS code)
*/
@@ -151,7 +130,7 @@ static int p9_rdma_show_options(struct seq_file *m, struct p9_client *clnt)
{
struct p9_trans_rdma *rdma = clnt->trans;
- if (rdma->port != P9_PORT)
+ if (rdma->port != P9_RDMA_PORT)
seq_printf(m, ",port=%u", rdma->port);
if (rdma->sq_depth != P9_RDMA_SQ_DEPTH)
seq_printf(m, ",sq=%u", rdma->sq_depth);
@@ -178,7 +157,7 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts)
int option;
char *options, *tmp_options;
- opts->port = P9_PORT;
+ opts->port = P9_RDMA_PORT;
opts->sq_depth = P9_RDMA_SQ_DEPTH;
opts->rq_depth = P9_RDMA_RQ_DEPTH;
opts->timeout = P9_RDMA_TIMEOUT;
--
2.48.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC PATCH 3/4] 9p: create a v9fs_context structure to hold parsed options
2025-07-24 2:23 [RFC PATCH 0/4] 9p: convert to the new mount API Eric Sandeen
2025-07-24 2:23 ` [RFC PATCH 1/4] fs/fs_parse: add back fsparam_u32hex Eric Sandeen
2025-07-24 2:23 ` [RFC PATCH 2/4] net/9p: move structures and macros to header files Eric Sandeen
@ 2025-07-24 2:23 ` Eric Sandeen
2025-07-26 17:17 ` Eric Sandeen
2025-07-24 2:23 ` [RFC PATCH 4/4] 9p: convert to the new mount API Eric Sandeen
2025-07-26 14:09 ` David Howells
4 siblings, 1 reply; 9+ messages in thread
From: Eric Sandeen @ 2025-07-24 2:23 UTC (permalink / raw)
To: v9fs; +Cc: ericvh, lucho, asmadeus, linux_oss, Eric Sandeen
This patch creates a new v9fs_context structure which includes
v9fs_session_info as well as p9_client, p9_fd_opts, and p9_rdma_opts
to hold all parsed options. The new structure will be used in the next
commit to pass all parsed options to the appropriate transports.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
fs/9p/v9fs.h | 49 ---------------------
include/net/9p/client.h | 88 ++++++++++++++++++++++++++++++++++++++
include/net/9p/transport.h | 32 --------------
3 files changed, 88 insertions(+), 81 deletions(-)
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index f28bc763847a..4b8834daec8d 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -81,55 +81,6 @@ enum p9_cache_bits {
CACHE_FSCACHE = 0b10000000,
};
-/**
- * struct v9fs_session_info - per-instance session information
- * @flags: session options of type &p9_session_flags
- * @nodev: set to 1 to disable device mapping
- * @debug: debug level
- * @afid: authentication handle
- * @cache: cache mode of type &p9_cache_bits
- * @cachetag: the tag of the cache associated with this session
- * @fscache: session cookie associated with FS-Cache
- * @uname: string user name to mount hierarchy as
- * @aname: mount specifier for remote hierarchy
- * @maxdata: maximum data to be sent/recvd per protocol message
- * @dfltuid: default numeric userid to mount hierarchy as
- * @dfltgid: default numeric groupid to mount hierarchy as
- * @uid: if %V9FS_ACCESS_SINGLE, the numeric uid which mounted the hierarchy
- * @clnt: reference to 9P network client instantiated for this session
- * @slist: reference to list of registered 9p sessions
- *
- * This structure holds state for each session instance established during
- * a sys_mount() .
- *
- * Bugs: there seems to be a lot of state which could be condensed and/or
- * removed.
- */
-
-struct v9fs_session_info {
- /* options */
- unsigned int flags;
- unsigned char nodev;
- unsigned short debug;
- unsigned int afid;
- unsigned int cache;
-#ifdef CONFIG_9P_FSCACHE
- char *cachetag;
- struct fscache_volume *fscache;
-#endif
-
- char *uname; /* user name to mount as */
- char *aname; /* name of remote hierarchy being mounted */
- unsigned int maxdata; /* max data for client interface */
- kuid_t dfltuid; /* default uid/muid for legacy support */
- kgid_t dfltgid; /* default gid for legacy support */
- kuid_t uid; /* if ACCESS_SINGLE, the uid that has access */
- struct p9_client *clnt; /* 9p client */
- struct list_head slist; /* list of sessions registered with v9fs */
- struct rw_semaphore rename_sem;
- long session_lock_timeout; /* retry interval for blocking locks */
-};
-
/* cache_validity flags */
#define V9FS_INO_INVALID_ATTR 0x01
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 2d46f8017bd5..33b8d9a79fa7 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -132,6 +132,94 @@ struct p9_client {
char name[__NEW_UTS_LEN + 1];
};
+/**
+ * struct p9_fd_opts - per-transport options for fd transport
+ * @rfd: file descriptor for reading (trans=fd)
+ * @wfd: file descriptor for writing (trans=fd)
+ * @port: port to connect to (trans=tcp)
+ * @privport: port is privileged
+ */
+
+struct p9_fd_opts {
+ int rfd;
+ int wfd;
+ u16 port;
+ bool privport;
+};
+
+/**
+ * struct p9_rdma_opts - Collection of mount options for rdma transport
+ * @port: port of connection
+ * @privport: Whether a privileged port may be used
+ * @sq_depth: The requested depth of the SQ. This really doesn't need
+ * to be any deeper than the number of threads used in the client
+ * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth
+ * @timeout: Time to wait in msecs for CM events
+ */
+struct p9_rdma_opts {
+ short port;
+ bool privport;
+ int sq_depth;
+ int rq_depth;
+ long timeout;
+};
+
+/**
+ * struct v9fs_session_info - per-instance session information
+ * @flags: session options of type &p9_session_flags
+ * @nodev: set to 1 to disable device mapping
+ * @debug: debug level
+ * @afid: authentication handle
+ * @cache: cache mode of type &p9_cache_bits
+ * @cachetag: the tag of the cache associated with this session
+ * @fscache: session cookie associated with FS-Cache
+ * @uname: string user name to mount hierarchy as
+ * @aname: mount specifier for remote hierarchy
+ * @maxdata: maximum data to be sent/recvd per protocol message
+ * @dfltuid: default numeric userid to mount hierarchy as
+ * @dfltgid: default numeric groupid to mount hierarchy as
+ * @uid: if %V9FS_ACCESS_SINGLE, the numeric uid which mounted the hierarchy
+ * @clnt: reference to 9P network client instantiated for this session
+ * @slist: reference to list of registered 9p sessions
+ *
+ * This structure holds state for each session instance established during
+ * a sys_mount() .
+ *
+ * Bugs: there seems to be a lot of state which could be condensed and/or
+ * removed.
+ */
+struct v9fs_session_info {
+ /* options */
+ unsigned int flags;
+ unsigned char nodev;
+ unsigned short debug;
+ unsigned int afid;
+ unsigned int cache;
+#ifdef CONFIG_9P_FSCACHE
+ char *cachetag;
+ struct fscache_volume *fscache;
+#endif
+
+ char *uname; /* user name to mount as */
+ char *aname; /* name of remote hierarchy being mounted */
+ unsigned int maxdata; /* max data for client interface */
+ kuid_t dfltuid; /* default uid/muid for legacy support */
+ kgid_t dfltgid; /* default gid for legacy support */
+ kuid_t uid; /* if ACCESS_SINGLE, the uid that has access */
+ struct p9_client *clnt; /* 9p client */
+ struct list_head slist; /* list of sessions registered with v9fs */
+ struct rw_semaphore rename_sem;
+ long session_lock_timeout; /* retry interval for blocking locks */
+};
+
+/* Used by mount API to store parsed mount options */
+struct v9fs_context {
+ struct p9_client client_opts;
+ struct p9_fd_opts fd_opts;
+ struct p9_rdma_opts rdma_opts;
+ struct v9fs_session_info v9ses;
+};
+
/**
* struct p9_fid - file system entity handle
* @clnt: back pointer to instantiating &p9_client
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
index 88702953b1ef..ebbb4b50ee20 100644
--- a/include/net/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -21,38 +21,6 @@
#define P9_RDMA_RQ_DEPTH 32
#define P9_RDMA_TIMEOUT 30000 /* 30 seconds */
-/**
- * struct p9_fd_opts - per-transport options for fd transport
- * @rfd: file descriptor for reading (trans=fd)
- * @wfd: file descriptor for writing (trans=fd)
- * @port: port to connect to (trans=tcp)
- * @privport: port is privileged
- */
-
-struct p9_fd_opts {
- int rfd;
- int wfd;
- u16 port;
- bool privport;
-};
-
-/**
- * struct p9_rdma_opts - Collection of mount options for rdma transport
- * @port: port of connection
- * @privport: Whether a privileged port may be used
- * @sq_depth: The requested depth of the SQ. This really doesn't need
- * to be any deeper than the number of threads used in the client
- * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth
- * @timeout: Time to wait in msecs for CM events
- */
-struct p9_rdma_opts {
- short port;
- bool privport;
- int sq_depth;
- int rq_depth;
- long timeout;
-};
-
/**
* struct p9_trans_module - transport module interface
* @list: used to maintain a list of currently available transports
--
2.48.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC PATCH 4/4] 9p: convert to the new mount API
2025-07-24 2:23 [RFC PATCH 0/4] 9p: convert to the new mount API Eric Sandeen
` (2 preceding siblings ...)
2025-07-24 2:23 ` [RFC PATCH 3/4] 9p: create a v9fs_context structure to hold parsed options Eric Sandeen
@ 2025-07-24 2:23 ` Eric Sandeen
2025-07-26 14:09 ` David Howells
4 siblings, 0 replies; 9+ messages in thread
From: Eric Sandeen @ 2025-07-24 2:23 UTC (permalink / raw)
To: v9fs; +Cc: ericvh, lucho, asmadeus, linux_oss, Eric Sandeen
Convert 9p to the new mount API. This patch consolidates all parsing
parsing into fs/9p/v9fs.c, which stores all results into a filesystem
context which can be passed to the various transports as needed.
Some of the parsing helper functions such as get_cache_mode() can be
eliminated in favor of using the new mount API's enum param type,
for simplicity.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
fs/9p/v9fs.c | 519 ++++++++++++++++++-------------------
fs/9p/v9fs.h | 6 +-
fs/9p/vfs_super.c | 122 +++++++--
include/net/9p/client.h | 2 +-
include/net/9p/transport.h | 2 +-
net/9p/client.c | 148 +----------
net/9p/mod.c | 2 +-
net/9p/trans_fd.c | 109 +-------
net/9p/trans_rdma.c | 105 +-------
net/9p/trans_usbg.c | 4 +-
net/9p/trans_virtio.c | 5 +-
net/9p/trans_xen.c | 4 +-
12 files changed, 400 insertions(+), 628 deletions(-)
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 77e9c4387c1d..30aefd42fb3e 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -13,7 +13,8 @@
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/cred.h>
-#include <linux/parser.h>
+#include <linux/fs_parser.h>
+#include <linux/fs_context.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <net/9p/9p.h>
@@ -43,55 +44,80 @@ enum {
Opt_access, Opt_posixacl,
/* Lock timeout option */
Opt_locktimeout,
- /* Error token */
- Opt_err
+
+ /* Client options */
+ Opt_msize, Opt_trans, Opt_legacy, Opt_version,
+
+ /* fd transport options */
+ /* Options that take integer arguments */
+ Opt_rfdno, Opt_wfdno,
+ /* Options that take no arguments */
+
+ /* rdma transport options */
+ /* Options that take integer arguments */
+ Opt_rq_depth, Opt_sq_depth, Opt_timeout,
+
+ /* Options for both fd and rdma transports */
+ Opt_port, Opt_privport,
};
-static const match_table_t tokens = {
- {Opt_debug, "debug=%x"},
- {Opt_dfltuid, "dfltuid=%u"},
- {Opt_dfltgid, "dfltgid=%u"},
- {Opt_afid, "afid=%u"},
- {Opt_uname, "uname=%s"},
- {Opt_remotename, "aname=%s"},
- {Opt_nodevmap, "nodevmap"},
- {Opt_noxattr, "noxattr"},
- {Opt_directio, "directio"},
- {Opt_ignoreqv, "ignoreqv"},
- {Opt_cache, "cache=%s"},
- {Opt_cachetag, "cachetag=%s"},
- {Opt_access, "access=%s"},
- {Opt_posixacl, "posixacl"},
- {Opt_locktimeout, "locktimeout=%u"},
- {Opt_err, NULL}
+static const struct constant_table p9_versions[] = {
+ { "9p2000", p9_proto_legacy },
+ { "9p2000.u", p9_proto_2000u },
+ { "9p2000.L", p9_proto_2000L },
+ {}
};
-/* Interpret mount options for cache mode */
-static int get_cache_mode(char *s)
-{
- int version = -EINVAL;
-
- if (!strcmp(s, "loose")) {
- version = CACHE_SC_LOOSE;
- p9_debug(P9_DEBUG_9P, "Cache mode: loose\n");
- } else if (!strcmp(s, "fscache")) {
- version = CACHE_SC_FSCACHE;
- p9_debug(P9_DEBUG_9P, "Cache mode: fscache\n");
- } else if (!strcmp(s, "mmap")) {
- version = CACHE_SC_MMAP;
- p9_debug(P9_DEBUG_9P, "Cache mode: mmap\n");
- } else if (!strcmp(s, "readahead")) {
- version = CACHE_SC_READAHEAD;
- p9_debug(P9_DEBUG_9P, "Cache mode: readahead\n");
- } else if (!strcmp(s, "none")) {
- version = CACHE_SC_NONE;
- p9_debug(P9_DEBUG_9P, "Cache mode: none\n");
- } else if (kstrtoint(s, 0, &version) != 0) {
- version = -EINVAL;
- pr_info("Unknown Cache mode or invalid value %s\n", s);
- }
- return version;
-}
+static const struct constant_table p9_cache_mode[] = {
+ { "loose", CACHE_SC_LOOSE },
+ { "fscache", CACHE_SC_FSCACHE },
+ { "mmap", CACHE_SC_MMAP },
+ { "readahead", CACHE_SC_READAHEAD },
+ { "none", CACHE_SC_NONE },
+ {}
+};
+
+/*
+ * This structure contains all parameters used for the core code,
+ * the client, and all the transports.
+ */
+const struct fs_parameter_spec v9fs_param_spec[] = {
+ fsparam_u32hex ("debug", Opt_debug),
+ fsparam_uid ("dfltuid", Opt_dfltuid),
+ fsparam_gid ("dfltgid", Opt_dfltgid),
+ fsparam_u32 ("afid", Opt_afid),
+ fsparam_string ("uname", Opt_uname),
+ fsparam_string ("aname", Opt_remotename),
+ fsparam_flag ("nodevmap", Opt_nodevmap),
+ fsparam_flag ("noxattr", Opt_noxattr),
+ fsparam_flag ("directio", Opt_directio),
+ fsparam_flag ("ignoreqv", Opt_ignoreqv),
+ fsparam_enum ("cache", Opt_cache, p9_cache_mode),
+ fsparam_string ("cachetag", Opt_cachetag),
+ fsparam_string ("access", Opt_access),
+ fsparam_flag ("posixacl", Opt_posixacl),
+ fsparam_u32 ("locktimeout", Opt_locktimeout),
+
+ /* client options */
+ fsparam_u32 ("msize", Opt_msize),
+ fsparam_flag ("noextend", Opt_legacy),
+ fsparam_string ("trans", Opt_trans),
+ fsparam_enum ("version", Opt_version, p9_versions),
+
+ /* fd transport options */
+ fsparam_u32 ("rfdno", Opt_rfdno),
+ fsparam_u32 ("wfdno", Opt_wfdno),
+
+ /* rdma transport options */
+ fsparam_u32 ("sq", Opt_sq_depth),
+ fsparam_u32 ("rq", Opt_rq_depth),
+ fsparam_u32 ("timeout", Opt_timeout),
+
+ /* fd and rdma transprt options */
+ fsparam_u32 ("port", Opt_port),
+ fsparam_flag ("privport", Opt_privport),
+ {}
+};
/*
* Display the mount options in /proc/mounts.
@@ -159,225 +185,199 @@ int v9fs_show_options(struct seq_file *m, struct dentry *root)
*
* Return 0 upon success, -ERRNO upon failure.
*/
-
-static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
+int v9fs_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
- char *options, *tmp_options;
- substring_t args[MAX_OPT_ARGS];
- char *p;
- int option = 0;
+ struct v9fs_context *ctx = fc->fs_private;
+ struct fs_parse_result result;
char *s;
+ int r;
+ int opt;
int ret = 0;
-
- /* setup defaults */
- v9ses->afid = ~0;
- v9ses->debug = 0;
- v9ses->cache = CACHE_NONE;
-#ifdef CONFIG_9P_FSCACHE
- v9ses->cachetag = NULL;
-#endif
- v9ses->session_lock_timeout = P9_LOCK_TIMEOUT;
-
- if (!opts)
- return 0;
-
- tmp_options = kstrdup(opts, GFP_KERNEL);
- if (!tmp_options) {
- ret = -ENOMEM;
- goto fail_option_alloc;
- }
- options = tmp_options;
-
- while ((p = strsep(&options, ",")) != NULL) {
- int token, r;
-
- if (!*p)
- continue;
-
- token = match_token(p, tokens, args);
- switch (token) {
- case Opt_debug:
- r = match_int(&args[0], &option);
- if (r < 0) {
- p9_debug(P9_DEBUG_ERROR,
- "integer field, but no integer?\n");
- ret = r;
- } else {
- v9ses->debug = option;
+ struct p9_client *clnt = &ctx->client_opts;
+ struct p9_fd_opts *fd_opts = &ctx->fd_opts;
+ struct p9_rdma_opts *rdma_opts = &ctx->rdma_opts;
+ struct v9fs_session_info *v9ses_opts = &ctx->v9ses;
+
+ opt = fs_parse(fc, v9fs_param_spec, param, &result);
+ if (opt < 0)
+ return opt;
+
+ switch (opt) {
+ case Opt_debug:
+ v9ses_opts->debug = result.uint_32;
#ifdef CONFIG_NET_9P_DEBUG
- p9_debug_level = option;
+ p9_debug_level = result.uint_32;
#endif
- }
- break;
-
- case Opt_dfltuid:
- r = match_int(&args[0], &option);
- if (r < 0) {
- p9_debug(P9_DEBUG_ERROR,
- "integer field, but no integer?\n");
- ret = r;
- continue;
- }
- v9ses->dfltuid = make_kuid(current_user_ns(), option);
- if (!uid_valid(v9ses->dfltuid)) {
- p9_debug(P9_DEBUG_ERROR,
- "uid field, but not a uid?\n");
- ret = -EINVAL;
- }
- break;
- case Opt_dfltgid:
- r = match_int(&args[0], &option);
- if (r < 0) {
- p9_debug(P9_DEBUG_ERROR,
- "integer field, but no integer?\n");
- ret = r;
- continue;
- }
- v9ses->dfltgid = make_kgid(current_user_ns(), option);
- if (!gid_valid(v9ses->dfltgid)) {
- p9_debug(P9_DEBUG_ERROR,
- "gid field, but not a gid?\n");
- ret = -EINVAL;
- }
- break;
- case Opt_afid:
- r = match_int(&args[0], &option);
- if (r < 0) {
- p9_debug(P9_DEBUG_ERROR,
- "integer field, but no integer?\n");
- ret = r;
- } else {
- v9ses->afid = option;
- }
- break;
- case Opt_uname:
- kfree(v9ses->uname);
- v9ses->uname = match_strdup(&args[0]);
- if (!v9ses->uname) {
- ret = -ENOMEM;
- goto free_and_return;
- }
- break;
- case Opt_remotename:
- kfree(v9ses->aname);
- v9ses->aname = match_strdup(&args[0]);
- if (!v9ses->aname) {
- ret = -ENOMEM;
- goto free_and_return;
- }
- break;
- case Opt_nodevmap:
- v9ses->nodev = 1;
- break;
- case Opt_noxattr:
- v9ses->flags |= V9FS_NO_XATTR;
- break;
- case Opt_directio:
- v9ses->flags |= V9FS_DIRECT_IO;
- break;
- case Opt_ignoreqv:
- v9ses->flags |= V9FS_IGNORE_QV;
- break;
- case Opt_cachetag:
+ break;
+
+ case Opt_dfltuid:
+ v9ses_opts->dfltuid = result.uid;
+ break;
+ case Opt_dfltgid:
+ v9ses_opts->dfltgid = result.gid;
+ break;
+ case Opt_afid:
+ v9ses_opts->afid = result.uint_32;
+ break;
+ case Opt_uname:
+ kfree(v9ses_opts->uname);
+ v9ses_opts->uname = param->string;
+ param->string = NULL;
+ break;
+ case Opt_remotename:
+ kfree(v9ses_opts->aname);
+ v9ses_opts->aname = param->string;
+ param->string = NULL;
+ break;
+ case Opt_nodevmap:
+ v9ses_opts->nodev = 1;
+ break;
+ case Opt_noxattr:
+ v9ses_opts->flags |= V9FS_NO_XATTR;
+ break;
+ case Opt_directio:
+ v9ses_opts->flags |= V9FS_DIRECT_IO;
+ break;
+ case Opt_ignoreqv:
+ v9ses_opts->flags |= V9FS_IGNORE_QV;
+ break;
+ case Opt_cachetag:
#ifdef CONFIG_9P_FSCACHE
- kfree(v9ses->cachetag);
- v9ses->cachetag = match_strdup(&args[0]);
- if (!v9ses->cachetag) {
- ret = -ENOMEM;
- goto free_and_return;
- }
+ kfree(v9ses_opts->cachetag);
+ v9ses_opts->cachetag = param->string;
+ param->string = NULL;
#endif
- break;
- case Opt_cache:
- s = match_strdup(&args[0]);
- if (!s) {
- ret = -ENOMEM;
- p9_debug(P9_DEBUG_ERROR,
- "problem allocating copy of cache arg\n");
- goto free_and_return;
- }
- r = get_cache_mode(s);
- if (r < 0)
- ret = r;
- else
- v9ses->cache = r;
-
- kfree(s);
- break;
-
- case Opt_access:
- s = match_strdup(&args[0]);
- if (!s) {
- ret = -ENOMEM;
- p9_debug(P9_DEBUG_ERROR,
- "problem allocating copy of access arg\n");
- goto free_and_return;
+ break;
+ case Opt_cache:
+ v9ses_opts->cache = result.uint_32;
+ p9_debug(P9_DEBUG_9P, "Cache mode: %s\n", param->string);
+ break;
+ case Opt_access:
+ s = param->string;
+ v9ses_opts->flags &= ~V9FS_ACCESS_MASK;
+ if (strcmp(s, "user") == 0)
+ v9ses_opts->flags |= V9FS_ACCESS_USER;
+ else if (strcmp(s, "any") == 0)
+ v9ses_opts->flags |= V9FS_ACCESS_ANY;
+ else if (strcmp(s, "client") == 0) {
+ v9ses_opts->flags |= V9FS_ACCESS_CLIENT;
+ } else {
+ uid_t uid;
+
+ v9ses_opts->flags |= V9FS_ACCESS_SINGLE;
+ r = kstrtouint(s, 10, &uid);
+ if (r) {
+ pr_info("Unknown access argument %s: %d\n",
+ param->string, r);
+ return r;
}
-
- v9ses->flags &= ~V9FS_ACCESS_MASK;
- if (strcmp(s, "user") == 0)
- v9ses->flags |= V9FS_ACCESS_USER;
- else if (strcmp(s, "any") == 0)
- v9ses->flags |= V9FS_ACCESS_ANY;
- else if (strcmp(s, "client") == 0) {
- v9ses->flags |= V9FS_ACCESS_CLIENT;
- } else {
- uid_t uid;
-
- v9ses->flags |= V9FS_ACCESS_SINGLE;
- r = kstrtouint(s, 10, &uid);
- if (r) {
- ret = r;
- pr_info("Unknown access argument %s: %d\n",
- s, r);
- kfree(s);
- continue;
- }
- v9ses->uid = make_kuid(current_user_ns(), uid);
- if (!uid_valid(v9ses->uid)) {
- ret = -EINVAL;
- pr_info("Unknown uid %s\n", s);
- }
+ v9ses_opts->uid = make_kuid(current_user_ns(), uid);
+ if (!uid_valid(v9ses_opts->uid)) {
+ ret = -EINVAL;
+ pr_info("Unknown uid %s\n", s);
}
+ }
+ break;
- kfree(s);
- break;
-
- case Opt_posixacl:
+ case Opt_posixacl:
#ifdef CONFIG_9P_FS_POSIX_ACL
- v9ses->flags |= V9FS_POSIX_ACL;
+ v9ses_opts->flags |= V9FS_POSIX_ACL;
#else
- p9_debug(P9_DEBUG_ERROR,
- "Not defined CONFIG_9P_FS_POSIX_ACL. Ignoring posixacl option\n");
+ p9_debug(P9_DEBUG_ERROR,
+ "Not defined CONFIG_9P_FS_POSIX_ACL. Ignoring posixacl option\n");
#endif
- break;
-
- case Opt_locktimeout:
- r = match_int(&args[0], &option);
- if (r < 0) {
- p9_debug(P9_DEBUG_ERROR,
- "integer field, but no integer?\n");
- ret = r;
- continue;
- }
- if (option < 1) {
- p9_debug(P9_DEBUG_ERROR,
- "locktimeout must be a greater than zero integer.\n");
- ret = -EINVAL;
- continue;
- }
- v9ses->session_lock_timeout = (long)option * HZ;
- break;
+ break;
+
+ case Opt_locktimeout:
+ if (result.uint_32 < 1) {
+ p9_debug(P9_DEBUG_ERROR,
+ "locktimeout must be a greater than zero integer.\n");
+ return -EINVAL;
+ }
+ v9ses_opts->session_lock_timeout = (long)result.uint_32 * HZ;
+ break;
- default:
- continue;
+ /* Options for client */
+ case Opt_msize:
+ if (result.uint_32 < 4096) {
+ p9_debug(P9_DEBUG_ERROR, "msize should be at least 4k\n");
+ return -EINVAL;
}
+ clnt->msize = result.uint_32;
+ break;
+ case Opt_trans:
+ v9fs_put_trans(clnt->trans_mod);
+ clnt->trans_mod = v9fs_get_trans_by_name(param->string);
+ if (!clnt->trans_mod) {
+ pr_info("Could not find request transport: %s\n",
+ param->string);
+ return -EINVAL;
+ }
+ break;
+ case Opt_legacy:
+ clnt->proto_version = p9_proto_legacy;
+ break;
+ case Opt_version:
+ clnt->proto_version = result.uint_32;
+ p9_debug(P9_DEBUG_9P, "Protocol version: %s\n", param->string);
+ break;
+ /* Options for fd transport */
+ case Opt_rfdno:
+ fd_opts->rfd = result.uint_32;
+ break;
+ case Opt_wfdno:
+ fd_opts->wfd = result.uint_32;
+ break;
+ /* Options for rdma transport */
+ case Opt_sq_depth:
+ rdma_opts->sq_depth = result.uint_32;
+ break;
+ case Opt_rq_depth:
+ rdma_opts->rq_depth = result.uint_32;
+ break;
+ case Opt_timeout:
+ rdma_opts->timeout = result.uint_32;
+ break;
+ /* Options for both fd and rdma transports */
+ case Opt_port:
+ fd_opts->port = result.uint_32;
+ rdma_opts->port = result.uint_32;
+ break;
+ case Opt_privport:
+ fd_opts->privport = true;
+ rdma_opts->port = true;
+ break;
}
-free_and_return:
- kfree(tmp_options);
-fail_option_alloc:
- return ret;
+ return 0;
+}
+
+static void v9fs_apply_options(struct v9fs_session_info *v9ses,
+ struct fs_context *fc)
+{
+ struct v9fs_context *ctx = fc->fs_private;
+
+ v9ses->debug = ctx->v9ses.debug;
+ v9ses->dfltuid = ctx->v9ses.dfltuid;
+ v9ses->dfltgid = ctx->v9ses.dfltgid;
+ v9ses->afid = ctx->v9ses.afid;
+ v9ses->uname = ctx->v9ses.uname;
+ ctx->v9ses.uname = NULL;
+ v9ses->aname = ctx->v9ses.aname;
+ ctx->v9ses.aname = NULL;
+ v9ses->nodev = ctx->v9ses.nodev;
+ /*
+ * Note that we must |= flags here as session_init already
+ * set basic flags. This adds in flags from parsed options.
+ */
+ v9ses->flags |= ctx->v9ses.flags;
+#ifdef CONFIG_9P_FSCACHE
+ v9ses->cachetag = ctx->v9ses.cachetag;
+ ctx->v9ses.cachetag = NULL;
+#endif
+ v9ses->cache = ctx->v9ses.cache;
+ v9ses->uid = ctx->v9ses.uid;
+ v9ses->session_lock_timeout = ctx->v9ses.session_lock_timeout;
}
/**
@@ -389,31 +389,24 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
*/
struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
- const char *dev_name, char *data)
+ struct fs_context *fc)
{
struct p9_fid *fid;
int rc = -ENOMEM;
- v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL);
- if (!v9ses->uname)
- goto err_names;
-
- v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL);
- if (!v9ses->aname)
- goto err_names;
init_rwsem(&v9ses->rename_sem);
- v9ses->uid = INVALID_UID;
- v9ses->dfltuid = V9FS_DEFUID;
- v9ses->dfltgid = V9FS_DEFGID;
-
- v9ses->clnt = p9_client_create(dev_name, data);
+ v9ses->clnt = p9_client_create(fc);
if (IS_ERR(v9ses->clnt)) {
rc = PTR_ERR(v9ses->clnt);
p9_debug(P9_DEBUG_ERROR, "problem initializing 9p client\n");
goto err_names;
}
+ /*
+ * Initialize flags on the real v9ses. v9fs_apply_options below
+ * will |= the additional flags from parsed options.
+ */
v9ses->flags = V9FS_ACCESS_USER;
if (p9_is_proto_dotl(v9ses->clnt)) {
@@ -423,9 +416,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
v9ses->flags |= V9FS_PROTO_2000U;
}
- rc = v9fs_parse_options(v9ses, data);
- if (rc < 0)
- goto err_clnt;
+ v9fs_apply_options(v9ses, fc);
v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ;
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 4b8834daec8d..df5be70454da 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -10,6 +10,8 @@
#include <linux/backing-dev.h>
#include <linux/netfs.h>
+#include <linux/fs_parser.h>
+#include <net/9p/transport.h>
/**
* enum p9_session_flags - option flags for each 9P session
@@ -114,11 +116,13 @@ static inline struct fscache_volume *v9fs_session_cache(struct v9fs_session_info
#endif
}
+extern const struct fs_parameter_spec v9fs_param_spec[];
+extern int v9fs_parse_param(struct fs_context *fc, struct fs_parameter *param);
extern int v9fs_show_options(struct seq_file *m, struct dentry *root);
struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
- const char *dev_name, char *data);
+ struct fs_context *fc);
extern void v9fs_session_close(struct v9fs_session_info *v9ses);
extern void v9fs_session_cancel(struct v9fs_session_info *v9ses);
extern void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses);
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 489db161abc9..bcd502760ab9 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -19,6 +19,7 @@
#include <linux/statfs.h>
#include <linux/magic.h>
#include <linux/fscache.h>
+#include <linux/fs_context.h>
#include <net/9p/9p.h>
#include <net/9p/client.h>
@@ -37,25 +38,19 @@ static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl;
*
*/
-static int v9fs_set_super(struct super_block *s, void *data)
+static int v9fs_set_super(struct super_block *s, struct fs_context *fc)
{
- s->s_fs_info = data;
- return set_anon_super(s, data);
-}
+ struct v9fs_session_info *v9ses = fc->s_fs_info;
-/**
- * v9fs_fill_super - populate superblock with info
- * @sb: superblock
- * @v9ses: session information
- * @flags: flags propagated from v9fs_mount()
- *
- */
+ s->s_fs_info = v9ses;
+ return set_anon_super(s, NULL);
+}
-static int
-v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
- int flags)
+static int v9fs_fill_super(struct super_block *sb, struct fs_context *fc)
{
int ret;
+ struct v9fs_context *ctx = fc->fs_private;
+ struct v9fs_session_info *v9ses = &ctx->v9ses;
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_blocksize_bits = fls(v9ses->maxdata - 1);
@@ -103,8 +98,7 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
*
*/
-static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *data)
+static int v9fs_get_tree(struct fs_context *fc)
{
struct super_block *sb = NULL;
struct inode *inode = NULL;
@@ -117,20 +111,21 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
if (!v9ses)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
- fid = v9fs_session_init(v9ses, dev_name, data);
+ fid = v9fs_session_init(v9ses, fc);
if (IS_ERR(fid)) {
retval = PTR_ERR(fid);
goto free_session;
}
- sb = sget(fs_type, NULL, v9fs_set_super, flags, v9ses);
+ fc->s_fs_info = v9ses;
+ sb = sget_fc(fc, NULL, v9fs_set_super);
if (IS_ERR(sb)) {
retval = PTR_ERR(sb);
goto clunk_fid;
}
- retval = v9fs_fill_super(sb, v9ses, flags);
+ retval = v9fs_fill_super(sb, fc);
if (retval)
goto release_sb;
@@ -157,14 +152,15 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
v9fs_fid_add(root, &fid);
p9_debug(P9_DEBUG_VFS, " simple set mount, return 0\n");
- return dget(sb->s_root);
+ fc->root = dget(sb->s_root);
+ return 0;
clunk_fid:
p9_fid_put(fid);
v9fs_session_close(v9ses);
free_session:
kfree(v9ses);
- return ERR_PTR(retval);
+ return retval;
release_sb:
/*
@@ -175,7 +171,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
*/
p9_fid_put(fid);
deactivate_locked_super(sb);
- return ERR_PTR(retval);
+ return retval;
}
/**
@@ -301,11 +297,89 @@ static const struct super_operations v9fs_super_ops_dotl = {
.write_inode = v9fs_write_inode_dotl,
};
+static void v9fs_free_fc(struct fs_context *fc)
+{
+ struct v9fs_context *ctx = fc->fs_private;
+
+ /* These should be NULL by now but guard against leaks */
+ kfree(ctx->v9ses.uname);
+ kfree(ctx->v9ses.aname);
+#ifdef CONFIG_9P_FSCACHE
+ kfree(ctx->v9ses.cachetag);
+#endif
+ if (ctx->client_opts.trans_mod)
+ v9fs_put_trans(ctx->client_opts.trans_mod);
+ kfree(ctx);
+}
+
+static const struct fs_context_operations v9fs_context_ops = {
+ .parse_param = v9fs_parse_param,
+ .get_tree = v9fs_get_tree,
+ .free = v9fs_free_fc,
+};
+
+static int v9fs_init_fs_context(struct fs_context *fc)
+{
+ struct v9fs_context *ctx;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ /* initialize core options */
+ ctx->v9ses.afid = ~0;
+ ctx->v9ses.debug = 0;
+ ctx->v9ses.cache = CACHE_NONE;
+#ifdef CONFIG_9P_FSCACHE
+ ctx->v9ses.cachetag = NULL;
+#endif
+ ctx->v9ses.session_lock_timeout = P9_LOCK_TIMEOUT;
+ ctx->v9ses.uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL);
+ if (!ctx->v9ses.uname)
+ goto err_names;
+
+ ctx->v9ses.aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL);
+ if (!ctx->v9ses.aname)
+ goto err_names;
+
+ ctx->v9ses.uid = INVALID_UID;
+ ctx->v9ses.dfltuid = V9FS_DEFUID;
+ ctx->v9ses.dfltgid = V9FS_DEFGID;
+
+ /* initialize client options */
+ ctx->client_opts.proto_version = p9_proto_2000L;
+ ctx->client_opts.msize = DEFAULT_MSIZE;
+
+ /* initialize fd transport options */
+ ctx->fd_opts.port = P9_FD_PORT;
+ ctx->fd_opts.rfd = ~0;
+ ctx->fd_opts.wfd = ~0;
+ ctx->fd_opts.privport = false;
+
+ /* initialize rdma transport options */
+ ctx->rdma_opts.port = P9_RDMA_PORT;
+ ctx->rdma_opts.sq_depth = P9_RDMA_SQ_DEPTH;
+ ctx->rdma_opts.rq_depth = P9_RDMA_RQ_DEPTH;
+ ctx->rdma_opts.timeout = P9_RDMA_TIMEOUT;
+ ctx->rdma_opts.privport = false;
+
+ fc->ops = &v9fs_context_ops;
+ fc->fs_private = ctx;
+
+ return 0;
+err_names:
+ kfree(ctx->v9ses.uname);
+ kfree(ctx->v9ses.aname);
+ kfree(ctx);
+ return -ENOMEM;
+}
+
struct file_system_type v9fs_fs_type = {
.name = "9p",
- .mount = v9fs_mount,
.kill_sb = v9fs_kill_super,
.owner = THIS_MODULE,
.fs_flags = FS_RENAME_DOES_D_MOVE,
+ .init_fs_context = v9fs_init_fs_context,
+ .parameters = v9fs_param_spec,
};
MODULE_ALIAS_FS("9p");
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 33b8d9a79fa7..a95b8b6ea583 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -277,7 +277,7 @@ int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid,
const char *name);
int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
struct p9_fid *newdirfid, const char *new_name);
-struct p9_client *p9_client_create(const char *dev_name, char *options);
+struct p9_client *p9_client_create(struct fs_context *fc);
void p9_client_destroy(struct p9_client *clnt);
void p9_client_disconnect(struct p9_client *clnt);
void p9_client_begin_disconnect(struct p9_client *clnt);
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
index ebbb4b50ee20..e53f312191b6 100644
--- a/include/net/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -53,7 +53,7 @@ struct p9_trans_module {
int def; /* this transport should be default */
struct module *owner;
int (*create)(struct p9_client *client,
- const char *devname, char *args);
+ struct fs_context *fc);
void (*close)(struct p9_client *client);
int (*request)(struct p9_client *client, struct p9_req_t *req);
int (*cancel)(struct p9_client *client, struct p9_req_t *req);
diff --git a/net/9p/client.c b/net/9p/client.c
index 5e3230b1bfab..22b88596e2fe 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -20,8 +20,8 @@
#include <linux/uio.h>
#include <linux/netfs.h>
#include <net/9p/9p.h>
-#include <linux/parser.h>
#include <linux/seq_file.h>
+#include <linux/fs_context.h>
#include <net/9p/client.h>
#include <net/9p/transport.h>
#include "protocol.h"
@@ -33,22 +33,6 @@
* - a little lazy - parse all client options
*/
-enum {
- Opt_msize,
- Opt_trans,
- Opt_legacy,
- Opt_version,
- Opt_err,
-};
-
-static const match_table_t tokens = {
- {Opt_msize, "msize=%u"},
- {Opt_legacy, "noextend"},
- {Opt_trans, "trans=%s"},
- {Opt_version, "version=%s"},
- {Opt_err, NULL},
-};
-
inline int p9_is_proto_dotl(struct p9_client *clnt)
{
return clnt->proto_version == p9_proto_2000L;
@@ -97,124 +81,16 @@ static int safe_errno(int err)
return err;
}
-/* Interpret mount option for protocol version */
-static int get_protocol_version(char *s)
+static int apply_client_options(struct p9_client *clnt, struct fs_context *fc)
{
- int version = -EINVAL;
-
- if (!strcmp(s, "9p2000")) {
- version = p9_proto_legacy;
- p9_debug(P9_DEBUG_9P, "Protocol version: Legacy\n");
- } else if (!strcmp(s, "9p2000.u")) {
- version = p9_proto_2000u;
- p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
- } else if (!strcmp(s, "9p2000.L")) {
- version = p9_proto_2000L;
- p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.L\n");
- } else {
- pr_info("Unknown protocol version %s\n", s);
- }
+ struct v9fs_context *ctx = fc->fs_private;
- return version;
-}
-
-/**
- * parse_opts - parse mount options into client structure
- * @opts: options string passed from mount
- * @clnt: existing v9fs client information
- *
- * Return 0 upon success, -ERRNO upon failure
- */
-
-static int parse_opts(char *opts, struct p9_client *clnt)
-{
- char *options, *tmp_options;
- char *p;
- substring_t args[MAX_OPT_ARGS];
- int option;
- char *s;
- int ret = 0;
-
- clnt->proto_version = p9_proto_2000L;
- clnt->msize = DEFAULT_MSIZE;
-
- if (!opts)
- return 0;
+ clnt->msize = ctx->client_opts.msize;
+ clnt->trans_mod = ctx->client_opts.trans_mod;
+ ctx->client_opts.trans_mod = NULL;
+ clnt->proto_version = ctx->client_opts.proto_version;
- tmp_options = kstrdup(opts, GFP_KERNEL);
- if (!tmp_options)
- return -ENOMEM;
- options = tmp_options;
-
- while ((p = strsep(&options, ",")) != NULL) {
- int token, r;
-
- if (!*p)
- continue;
- token = match_token(p, tokens, args);
- switch (token) {
- case Opt_msize:
- r = match_int(&args[0], &option);
- if (r < 0) {
- p9_debug(P9_DEBUG_ERROR,
- "integer field, but no integer?\n");
- ret = r;
- continue;
- }
- if (option < 4096) {
- p9_debug(P9_DEBUG_ERROR,
- "msize should be at least 4k\n");
- ret = -EINVAL;
- continue;
- }
- clnt->msize = option;
- break;
- case Opt_trans:
- s = match_strdup(&args[0]);
- if (!s) {
- ret = -ENOMEM;
- p9_debug(P9_DEBUG_ERROR,
- "problem allocating copy of trans arg\n");
- goto free_and_return;
- }
-
- v9fs_put_trans(clnt->trans_mod);
- clnt->trans_mod = v9fs_get_trans_by_name(s);
- if (!clnt->trans_mod) {
- pr_info("Could not find request transport: %s\n",
- s);
- ret = -EINVAL;
- }
- kfree(s);
- break;
- case Opt_legacy:
- clnt->proto_version = p9_proto_legacy;
- break;
- case Opt_version:
- s = match_strdup(&args[0]);
- if (!s) {
- ret = -ENOMEM;
- p9_debug(P9_DEBUG_ERROR,
- "problem allocating copy of version arg\n");
- goto free_and_return;
- }
- r = get_protocol_version(s);
- if (r < 0)
- ret = r;
- else
- clnt->proto_version = r;
- kfree(s);
- break;
- default:
- continue;
- }
- }
-
-free_and_return:
- if (ret)
- v9fs_put_trans(clnt->trans_mod);
- kfree(tmp_options);
- return ret;
+ return 0;
}
static int p9_fcall_init(struct p9_client *c, struct p9_fcall *fc,
@@ -968,7 +844,7 @@ static int p9_client_version(struct p9_client *c)
return err;
}
-struct p9_client *p9_client_create(const char *dev_name, char *options)
+struct p9_client *p9_client_create(struct fs_context *fc)
{
int err;
static atomic_t seqno = ATOMIC_INIT(0);
@@ -991,8 +867,8 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
idr_init(&clnt->fids);
idr_init(&clnt->reqs);
- err = parse_opts(options, clnt);
- if (err < 0)
+ err = apply_client_options(clnt, fc);
+ if (err)
goto free_client;
if (!clnt->trans_mod)
@@ -1008,7 +884,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n",
clnt, clnt->trans_mod, clnt->msize, clnt->proto_version);
- err = clnt->trans_mod->create(clnt, dev_name, options);
+ err = clnt->trans_mod->create(clnt, fc);
if (err)
goto put_trans;
diff --git a/net/9p/mod.c b/net/9p/mod.c
index 55576c1866fa..85160b52da55 100644
--- a/net/9p/mod.c
+++ b/net/9p/mod.c
@@ -16,7 +16,6 @@
#include <linux/moduleparam.h>
#include <net/9p/9p.h>
#include <linux/fs.h>
-#include <linux/parser.h>
#include <net/9p/client.h>
#include <net/9p/transport.h>
#include <linux/list.h>
@@ -171,6 +170,7 @@ void v9fs_put_trans(struct p9_trans_module *m)
if (m)
module_put(m->owner);
}
+EXPORT_SYMBOL(v9fs_put_trans);
/**
* init_p9 - Initialize module
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 9ef4f2e0db3c..cb4398d79b0a 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -22,7 +22,7 @@
#include <linux/uaccess.h>
#include <linux/inet.h>
#include <linux/file.h>
-#include <linux/parser.h>
+#include <linux/fs_context.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <net/9p/9p.h>
@@ -37,26 +37,6 @@
static struct p9_trans_module p9_tcp_trans;
static struct p9_trans_module p9_fd_trans;
-/*
- * Option Parsing (code inspired by NFS code)
- * - a little lazy - parse all fd-transport options
- */
-
-enum {
- /* Options that take integer arguments */
- Opt_port, Opt_rfdno, Opt_wfdno, Opt_err,
- /* Options that take no arguments */
- Opt_privport,
-};
-
-static const match_table_t tokens = {
- {Opt_port, "port=%u"},
- {Opt_rfdno, "rfdno=%u"},
- {Opt_wfdno, "wfdno=%u"},
- {Opt_privport, "privport"},
- {Opt_err, NULL},
-};
-
enum {
Rworksched = 1, /* read work scheduled or running */
Rpending = 2, /* can read */
@@ -744,73 +724,6 @@ static int p9_fd_show_options(struct seq_file *m, struct p9_client *clnt)
return 0;
}
-/**
- * parse_opts - parse mount options into p9_fd_opts structure
- * @params: options string passed from mount
- * @opts: fd transport-specific structure to parse options into
- *
- * Returns 0 upon success, -ERRNO upon failure
- */
-
-static int parse_opts(char *params, struct p9_fd_opts *opts)
-{
- char *p;
- substring_t args[MAX_OPT_ARGS];
- int option;
- char *options, *tmp_options;
-
- opts->port = P9_FD_PORT;
- opts->rfd = ~0;
- opts->wfd = ~0;
- opts->privport = false;
-
- if (!params)
- return 0;
-
- tmp_options = kstrdup(params, GFP_KERNEL);
- if (!tmp_options) {
- p9_debug(P9_DEBUG_ERROR,
- "failed to allocate copy of option string\n");
- return -ENOMEM;
- }
- options = tmp_options;
-
- while ((p = strsep(&options, ",")) != NULL) {
- int token;
- int r;
- if (!*p)
- continue;
- token = match_token(p, tokens, args);
- if ((token != Opt_err) && (token != Opt_privport)) {
- r = match_int(&args[0], &option);
- if (r < 0) {
- p9_debug(P9_DEBUG_ERROR,
- "integer field, but no integer?\n");
- continue;
- }
- }
- switch (token) {
- case Opt_port:
- opts->port = option;
- break;
- case Opt_rfdno:
- opts->rfd = option;
- break;
- case Opt_wfdno:
- opts->wfd = option;
- break;
- case Opt_privport:
- opts->privport = true;
- break;
- default:
- continue;
- }
- }
-
- kfree(tmp_options);
- return 0;
-}
-
static int p9_fd_open(struct p9_client *client, int rfd, int wfd)
{
struct p9_trans_fd *ts = kzalloc(sizeof(struct p9_trans_fd),
@@ -965,17 +878,18 @@ static int p9_bind_privport(struct socket *sock)
}
static int
-p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
+p9_fd_create_tcp(struct p9_client *client, struct fs_context *fc)
{
+ const char *addr = fc->source;
+ struct v9fs_context *ctx = fc->fs_private;
int err;
char port_str[6];
struct socket *csocket;
struct sockaddr_storage stor = { 0 };
struct p9_fd_opts opts;
- err = parse_opts(args, &opts);
- if (err < 0)
- return err;
+ /* opts are already parsed in context */
+ opts = ctx->fd_opts;
if (!addr)
return -EINVAL;
@@ -1022,8 +936,9 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
}
static int
-p9_fd_create_unix(struct p9_client *client, const char *addr, char *args)
+p9_fd_create_unix(struct p9_client *client, struct fs_context *fc)
{
+ const char *addr = fc->source;
int err;
struct socket *csocket;
struct sockaddr_un sun_server;
@@ -1062,14 +977,12 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args)
}
static int
-p9_fd_create(struct p9_client *client, const char *addr, char *args)
+p9_fd_create(struct p9_client *client, struct fs_context *fc)
{
+ struct v9fs_context *ctx = fc->fs_private;
+ struct p9_fd_opts opts = ctx->fd_opts;
int err;
- struct p9_fd_opts opts;
- err = parse_opts(args, &opts);
- if (err < 0)
- return err;
client->trans_opts.fd.rfd = opts.rfd;
client->trans_opts.fd.wfd = opts.wfd;
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
index 46ee37061faf..db4a18bb064e 100644
--- a/net/9p/trans_rdma.c
+++ b/net/9p/trans_rdma.c
@@ -22,7 +22,7 @@
#include <linux/uaccess.h>
#include <linux/inet.h>
#include <linux/file.h>
-#include <linux/parser.h>
+#include <linux/fs_context.h>
#include <linux/semaphore.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
@@ -106,26 +106,6 @@ struct p9_rdma_context {
};
};
-/*
- * Option Parsing (code inspired by NFS code)
- */
-enum {
- /* Options that take integer arguments */
- Opt_port, Opt_rq_depth, Opt_sq_depth, Opt_timeout,
- /* Options that take no argument */
- Opt_privport,
- Opt_err,
-};
-
-static match_table_t tokens = {
- {Opt_port, "port=%u"},
- {Opt_sq_depth, "sq=%u"},
- {Opt_rq_depth, "rq=%u"},
- {Opt_timeout, "timeout=%u"},
- {Opt_privport, "privport"},
- {Opt_err, NULL},
-};
-
static int p9_rdma_show_options(struct seq_file *m, struct p9_client *clnt)
{
struct p9_trans_rdma *rdma = clnt->trans;
@@ -143,77 +123,6 @@ static int p9_rdma_show_options(struct seq_file *m, struct p9_client *clnt)
return 0;
}
-/**
- * parse_opts - parse mount options into rdma options structure
- * @params: options string passed from mount
- * @opts: rdma transport-specific structure to parse options into
- *
- * Returns 0 upon success, -ERRNO upon failure
- */
-static int parse_opts(char *params, struct p9_rdma_opts *opts)
-{
- char *p;
- substring_t args[MAX_OPT_ARGS];
- int option;
- char *options, *tmp_options;
-
- opts->port = P9_RDMA_PORT;
- opts->sq_depth = P9_RDMA_SQ_DEPTH;
- opts->rq_depth = P9_RDMA_RQ_DEPTH;
- opts->timeout = P9_RDMA_TIMEOUT;
- opts->privport = false;
-
- if (!params)
- return 0;
-
- tmp_options = kstrdup(params, GFP_KERNEL);
- if (!tmp_options) {
- p9_debug(P9_DEBUG_ERROR,
- "failed to allocate copy of option string\n");
- return -ENOMEM;
- }
- options = tmp_options;
-
- while ((p = strsep(&options, ",")) != NULL) {
- int token;
- int r;
- if (!*p)
- continue;
- token = match_token(p, tokens, args);
- if ((token != Opt_err) && (token != Opt_privport)) {
- r = match_int(&args[0], &option);
- if (r < 0) {
- p9_debug(P9_DEBUG_ERROR,
- "integer field, but no integer?\n");
- continue;
- }
- }
- switch (token) {
- case Opt_port:
- opts->port = option;
- break;
- case Opt_sq_depth:
- opts->sq_depth = option;
- break;
- case Opt_rq_depth:
- opts->rq_depth = option;
- break;
- case Opt_timeout:
- opts->timeout = option;
- break;
- case Opt_privport:
- opts->privport = true;
- break;
- default:
- continue;
- }
- }
- /* RQ must be at least as large as the SQ */
- opts->rq_depth = max(opts->rq_depth, opts->sq_depth);
- kfree(tmp_options);
- return 0;
-}
-
static int
p9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
{
@@ -611,10 +520,12 @@ static int p9_rdma_bind_privport(struct p9_trans_rdma *rdma)
* @args: Mount options string
*/
static int
-rdma_create_trans(struct p9_client *client, const char *addr, char *args)
+rdma_create_trans(struct p9_client *client, struct fs_context *fc)
{
+ const char *addr = fc->source;
+ struct v9fs_context *ctx = fc->fs_private;
+ struct p9_rdma_opts opts = ctx->rdma_opts;
int err;
- struct p9_rdma_opts opts;
struct p9_trans_rdma *rdma;
struct rdma_conn_param conn_param;
struct ib_qp_init_attr qp_attr;
@@ -622,10 +533,8 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args)
if (addr == NULL)
return -EINVAL;
- /* Parse the transport specific mount options */
- err = parse_opts(args, &opts);
- if (err < 0)
- return err;
+ /* options are already parsed, in the fs context */
+ opts = ctx->rdma_opts;
/* Create and initialize the RDMA transport structure */
rdma = alloc_rdma(&opts);
diff --git a/net/9p/trans_usbg.c b/net/9p/trans_usbg.c
index 6b694f117aef..61197dae52cb 100644
--- a/net/9p/trans_usbg.c
+++ b/net/9p/trans_usbg.c
@@ -27,6 +27,7 @@
#include <linux/cleanup.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/fs_context.h>
#include <linux/usb/composite.h>
#include <linux/usb/func_utils.h>
@@ -366,8 +367,9 @@ enable_usb9pfs(struct usb_composite_dev *cdev, struct f_usb9pfs *usb9pfs)
return ret;
}
-static int p9_usbg_create(struct p9_client *client, const char *devname, char *args)
+static int p9_usbg_create(struct p9_client *client, struct fs_context *fc)
{
+ const char *devname = fc->source;
struct f_usb9pfs_dev *dev;
struct f_usb9pfs *usb9pfs;
int ret = -ENOENT;
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 0b8086f58ad5..5e4912e6b834 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -26,7 +26,7 @@
#include <linux/highmem.h>
#include <linux/slab.h>
#include <net/9p/9p.h>
-#include <linux/parser.h>
+#include <linux/fs_context.h>
#include <net/9p/client.h>
#include <net/9p/transport.h>
#include <linux/scatterlist.h>
@@ -691,8 +691,9 @@ static int p9_virtio_probe(struct virtio_device *vdev)
*/
static int
-p9_virtio_create(struct p9_client *client, const char *devname, char *args)
+p9_virtio_create(struct p9_client *client, struct fs_context *fc)
{
+ const char *devname = fc->source;
struct virtio_chan *chan;
int ret = -ENOENT;
int found = 0;
diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
index b9ff69c7522a..091a99eb51f4 100644
--- a/net/9p/trans_xen.c
+++ b/net/9p/trans_xen.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/fs_context.h>
#include <net/9p/9p.h>
#include <net/9p/client.h>
#include <net/9p/transport.h>
@@ -66,8 +67,9 @@ static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req)
return 1;
}
-static int p9_xen_create(struct p9_client *client, const char *addr, char *args)
+static int p9_xen_create(struct p9_client *client, struct fs_context *fc)
{
+ const char *addr = fc->source;
struct xen_9pfs_front_priv *priv;
if (addr == NULL)
--
2.48.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 4/4] 9p: convert to the new mount API
2025-07-24 2:23 [RFC PATCH 0/4] 9p: convert to the new mount API Eric Sandeen
` (3 preceding siblings ...)
2025-07-24 2:23 ` [RFC PATCH 4/4] 9p: convert to the new mount API Eric Sandeen
@ 2025-07-26 14:09 ` David Howells
2025-07-26 17:29 ` Eric Sandeen
4 siblings, 1 reply; 9+ messages in thread
From: David Howells @ 2025-07-26 14:09 UTC (permalink / raw)
To: Eric Sandeen; +Cc: dhowells, v9fs, ericvh, lucho, asmadeus, linux_oss
Eric Sandeen <sandeen@redhat.com> wrote:
> + case Opt_uname:
> + kfree(v9ses_opts->uname);
> + v9ses_opts->uname = param->string;
> + param->string = NULL;
I wonder if it's worth using swap() for that:
v9ses_opts->uname = swap(param->string, NULL);
> + if (strcmp(s, "user") == 0)
> + v9ses_opts->flags |= V9FS_ACCESS_USER;
> + else if (strcmp(s, "any") == 0)
> + v9ses_opts->flags |= V9FS_ACCESS_ANY;
> + else if (strcmp(s, "client") == 0) {
> + v9ses_opts->flags |= V9FS_ACCESS_CLIENT;
> + } else {
Maybe put braces on all the clauses in that?
> +static void v9fs_free_fc(struct fs_context *fc)
> +{
> + struct v9fs_context *ctx = fc->fs_private;
I would check that ctx isn't NULL.
> +static int v9fs_init_fs_context(struct fs_context *fc)
> +{
> + struct v9fs_context *ctx;
> +
> + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
> + if (!ctx)
> + return -ENOMEM;
> +
> + /* initialize core options */
> + ctx->v9ses.afid = ~0;
> + ctx->v9ses.debug = 0;
> + ctx->v9ses.cache = CACHE_NONE;
> +#ifdef CONFIG_9P_FSCACHE
> + ctx->v9ses.cachetag = NULL;
> +#endif
You used kzalloc... ;-).
> +err_names:
> + kfree(ctx->v9ses.uname);
> + kfree(ctx->v9ses.aname);
> + kfree(ctx);
> + return -ENOMEM;
> +}
Instead of doing the freeing, you could just set ->need_free and if
->init_fs_context() returns an error, the context will be put and that will
invoke ->free().
David
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 3/4] 9p: create a v9fs_context structure to hold parsed options
2025-07-24 2:23 ` [RFC PATCH 3/4] 9p: create a v9fs_context structure to hold parsed options Eric Sandeen
@ 2025-07-26 17:17 ` Eric Sandeen
2025-07-26 18:32 ` Eric Sandeen
0 siblings, 1 reply; 9+ messages in thread
From: Eric Sandeen @ 2025-07-26 17:17 UTC (permalink / raw)
To: v9fs; +Cc: ericvh, lucho, asmadeus, linux_oss, David Howells
On 7/23/25 9:23 PM, Eric Sandeen wrote:
> This patch creates a new v9fs_context structure which includes
> v9fs_session_info as well as p9_client, p9_fd_opts, and p9_rdma_opts
> to hold all parsed options. The new structure will be used in the next
> commit to pass all parsed options to the appropriate transports.
>
> Signed-off-by: Eric Sandeen <sandeen@redhat.com>
> ---
> fs/9p/v9fs.h | 49 ---------------------
> include/net/9p/client.h | 88 ++++++++++++++++++++++++++++++++++++++
> include/net/9p/transport.h | 32 --------------
> 3 files changed, 88 insertions(+), 81 deletions(-)
This was a last-minute refactoring that I did not properly build-test,
it seems, I'll get it fixed up in the next version. Sorry about that.
-Eric
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 4/4] 9p: convert to the new mount API
2025-07-26 14:09 ` David Howells
@ 2025-07-26 17:29 ` Eric Sandeen
0 siblings, 0 replies; 9+ messages in thread
From: Eric Sandeen @ 2025-07-26 17:29 UTC (permalink / raw)
To: David Howells; +Cc: v9fs, ericvh, lucho, asmadeus, linux_oss
On 7/26/25 9:09 AM, David Howells wrote:
> Eric Sandeen <sandeen@redhat.com> wrote:
>
>> + case Opt_uname:
>> + kfree(v9ses_opts->uname);
>> + v9ses_opts->uname = param->string;
>> + param->string = NULL;
>
> I wonder if it's worth using swap() for that:
ok. Sadly I've used the above pattern a lot in other patches ;)
> v9ses_opts->uname = swap(param->string, NULL);
>
>> + if (strcmp(s, "user") == 0)
>> + v9ses_opts->flags |= V9FS_ACCESS_USER;
>> + else if (strcmp(s, "any") == 0)
>> + v9ses_opts->flags |= V9FS_ACCESS_ANY;
>> + else if (strcmp(s, "client") == 0) {
>> + v9ses_opts->flags |= V9FS_ACCESS_CLIENT;
>> + } else {
>
> Maybe put braces on all the clauses in that?
Ah, sure.
>> +static void v9fs_free_fc(struct fs_context *fc)
>> +{
>> + struct v9fs_context *ctx = fc->fs_private;
>
> I would check that ctx isn't NULL.
ok.
>> +static int v9fs_init_fs_context(struct fs_context *fc)
>> +{
>> + struct v9fs_context *ctx;
>> +
>> + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
>> + if (!ctx)
>> + return -ENOMEM;
>> +
>> + /* initialize core options */
>> + ctx->v9ses.afid = ~0;
>> + ctx->v9ses.debug = 0;
>> + ctx->v9ses.cache = CACHE_NONE;
>> +#ifdef CONFIG_9P_FSCACHE
>> + ctx->v9ses.cachetag = NULL;
>> +#endif
>
> You used kzalloc... ;-).
Oh, fair enough.
>> +err_names:
>> + kfree(ctx->v9ses.uname);
>> + kfree(ctx->v9ses.aname);
>> + kfree(ctx);
>> + return -ENOMEM;
>> +}
>
> Instead of doing the freeing, you could just set ->need_free and if
> ->init_fs_context() returns an error, the context will be put and that will
> invoke ->free().
Ah ok, I don't think I knew that was an option. Will look.
The kernel test robot had a lot of complaints about this series, will dig
into those as well.
-Eric
> David
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 3/4] 9p: create a v9fs_context structure to hold parsed options
2025-07-26 17:17 ` Eric Sandeen
@ 2025-07-26 18:32 ` Eric Sandeen
0 siblings, 0 replies; 9+ messages in thread
From: Eric Sandeen @ 2025-07-26 18:32 UTC (permalink / raw)
To: v9fs; +Cc: ericvh, lucho, asmadeus, linux_oss, David Howells
On 7/26/25 12:17 PM, Eric Sandeen wrote:
> On 7/23/25 9:23 PM, Eric Sandeen wrote:
>> This patch creates a new v9fs_context structure which includes
>> v9fs_session_info as well as p9_client, p9_fd_opts, and p9_rdma_opts
>> to hold all parsed options. The new structure will be used in the next
>> commit to pass all parsed options to the appropriate transports.
>>
>> Signed-off-by: Eric Sandeen <sandeen@redhat.com>
>> ---
>> fs/9p/v9fs.h | 49 ---------------------
>> include/net/9p/client.h | 88 ++++++++++++++++++++++++++++++++++++++
>> include/net/9p/transport.h | 32 --------------
>> 3 files changed, 88 insertions(+), 81 deletions(-)
>
> This was a last-minute refactoring that I did not properly build-test,
> it seems, I'll get it fixed up in the next version. Sorry about that.
>
> -Eric
>
I just failed to build/test with fscache. This should fix it if anyone
wants to do early testing. Will clean this up in V2.
diff -Nurp korg/fs/9p/cache.c linux/fs/9p/cache.c
--- korg/fs/9p/cache.c 2025-07-26 13:25:29.082858321 -0500
+++ linux/fs/9p/cache.c 2025-07-26 12:48:13.518471053 -0500
@@ -12,6 +12,7 @@
#include <linux/sched.h>
#include <linux/fs.h>
#include <net/9p/9p.h>
+#include <net/9p/client.h>
#include "v9fs.h"
#include "cache.h"
diff -Nurp korg/fs/9p/v9fs.c linux/fs/9p/v9fs.c
--- korg/fs/9p/v9fs.c 2025-07-26 13:26:38.191669609 -0500
+++ linux/fs/9p/v9fs.c 2025-07-26 13:08:52.598712843 -0500
@@ -463,7 +462,7 @@ struct p9_fid *v9fs_session_init(struct
#ifdef CONFIG_9P_FSCACHE
/* register the session for caching */
if (v9ses->cache & CACHE_FSCACHE) {
- rc = v9fs_cache_session_get_cookie(v9ses, dev_name);
+ rc = v9fs_cache_session_get_cookie(v9ses, fc->source);
if (rc < 0)
goto err_clnt;
}
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-07-26 18:32 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-24 2:23 [RFC PATCH 0/4] 9p: convert to the new mount API Eric Sandeen
2025-07-24 2:23 ` [RFC PATCH 1/4] fs/fs_parse: add back fsparam_u32hex Eric Sandeen
2025-07-24 2:23 ` [RFC PATCH 2/4] net/9p: move structures and macros to header files Eric Sandeen
2025-07-24 2:23 ` [RFC PATCH 3/4] 9p: create a v9fs_context structure to hold parsed options Eric Sandeen
2025-07-26 17:17 ` Eric Sandeen
2025-07-26 18:32 ` Eric Sandeen
2025-07-24 2:23 ` [RFC PATCH 4/4] 9p: convert to the new mount API Eric Sandeen
2025-07-26 14:09 ` David Howells
2025-07-26 17:29 ` Eric Sandeen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).