9p: Implement show_options
authorDavid Howells <dhowells@redhat.com>
Wed, 5 Jul 2017 15:25:37 +0000 (16:25 +0100)
committerAl Viro <viro@zeniv.linux.org.uk>
Tue, 11 Jul 2017 10:08:58 +0000 (06:08 -0400)
Implement the show_options superblock op for 9p as part of a bid to get
rid of s_options and generic_show_options() to make it easier to implement
a context-based mount where the mount options can be passed individually
over a file descriptor.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Eric Van Hensbergen <ericvh@gmail.com>
cc: Ron Minnich <rminnich@sandia.gov>
cc: Latchesar Ionkov <lucho@ionkov.net>
cc: v9fs-developer@lists.sourceforge.net
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/9p/v9fs.c
fs/9p/v9fs.h
fs/9p/vfs_super.c
include/net/9p/client.h
include/net/9p/transport.h
net/9p/client.c
net/9p/trans_fd.c
net/9p/trans_rdma.c

index c202930086edb6fd22e0645cdc5264071af28d1f..8fb89ddc6cc7ec3be59236cd5e493ffcc44719ae 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/parser.h>
 #include <linux/idr.h>
 #include <linux/slab.h>
+#include <linux/seq_file.h>
 #include <net/9p/9p.h>
 #include <net/9p/client.h>
 #include <net/9p/transport.h>
@@ -82,6 +83,13 @@ static const match_table_t tokens = {
        {Opt_err, NULL}
 };
 
+static const char *const v9fs_cache_modes[nr__p9_cache_modes] = {
+       [CACHE_NONE]    = "none",
+       [CACHE_MMAP]    = "mmap",
+       [CACHE_LOOSE]   = "loose",
+       [CACHE_FSCACHE] = "fscache",
+};
+
 /* Interpret mount options for cache mode */
 static int get_cache_mode(char *s)
 {
@@ -104,6 +112,58 @@ static int get_cache_mode(char *s)
        return version;
 }
 
+/*
+ * Display the mount options in /proc/mounts.
+ */
+int v9fs_show_options(struct seq_file *m, struct dentry *root)
+{
+       struct v9fs_session_info *v9ses = root->d_sb->s_fs_info;
+
+       if (v9ses->debug)
+               seq_printf(m, ",debug=%x", v9ses->debug);
+       if (!uid_eq(v9ses->dfltuid, V9FS_DEFUID))
+               seq_printf(m, ",dfltuid=%u",
+                          from_kuid_munged(&init_user_ns, v9ses->dfltuid));
+       if (!gid_eq(v9ses->dfltgid, V9FS_DEFGID))
+               seq_printf(m, ",dfltgid=%u",
+                          from_kgid_munged(&init_user_ns, v9ses->dfltgid));
+       if (v9ses->afid != ~0)
+               seq_printf(m, ",afid=%u", v9ses->afid);
+       if (strcmp(v9ses->uname, V9FS_DEFUSER) != 0)
+               seq_printf(m, ",uname=%s", v9ses->uname);
+       if (strcmp(v9ses->aname, V9FS_DEFANAME) != 0)
+               seq_printf(m, ",aname=%s", v9ses->aname);
+       if (v9ses->nodev)
+               seq_puts(m, ",nodevmap");
+       if (v9ses->cache)
+               seq_printf(m, ",%s", v9fs_cache_modes[v9ses->cache]);
+#ifdef CONFIG_9P_FSCACHE
+       if (v9ses->cachetag && v9ses->cache == CACHE_FSCACHE)
+               seq_printf(m, ",cachetag=%s", v9ses->cachetag);
+#endif
+
+       switch (v9ses->flags & V9FS_ACCESS_MASK) {
+       case V9FS_ACCESS_USER:
+               seq_puts(m, ",access=user");
+               break;
+       case V9FS_ACCESS_ANY:
+               seq_puts(m, ",access=any");
+               break;
+       case V9FS_ACCESS_CLIENT:
+               seq_puts(m, ",access=client");
+               break;
+       case V9FS_ACCESS_SINGLE:
+               seq_printf(m, ",access=%u",
+                          from_kuid_munged(&init_user_ns, v9ses->uid));
+               break;
+       }
+
+       if (v9ses->flags & V9FS_POSIX_ACL)
+               seq_puts(m, ",posixacl");
+
+       return p9_show_client_options(m, v9ses->clnt);
+}
+
 /**
  * v9fs_parse_options - parse mount options into session structure
  * @v9ses: existing v9fs session information
@@ -230,6 +290,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
                        break;
                case Opt_cachetag:
 #ifdef CONFIG_9P_FSCACHE
+                       kfree(v9ses->cachetag);
                        v9ses->cachetag = match_strdup(&args[0]);
 #endif
                        break;
index 76eaf49abd3aea3b56644f3a025ccbc48b89bae8..982e017acadbc7f9efccf445876959e811d85aa4 100644 (file)
@@ -67,6 +67,7 @@ enum p9_cache_modes {
        CACHE_MMAP,
        CACHE_LOOSE,
        CACHE_FSCACHE,
+       nr__p9_cache_modes
 };
 
 /**
@@ -137,6 +138,8 @@ static inline struct v9fs_inode *V9FS_I(const struct inode *inode)
        return container_of(inode, struct v9fs_inode, vfs_inode);
 }
 
+extern int v9fs_show_options(struct seq_file *m, struct dentry *root);
+
 struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
                                                                        char *);
 extern void v9fs_session_close(struct v9fs_session_info *v9ses);
index a0965fb587a5f7321b7f428b018d88307d471163..8b75463cb2116895b4a44b28bf1faab7f1db8f71 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/string.h>
 #include <linux/inet.h>
 #include <linux/pagemap.h>
-#include <linux/seq_file.h>
 #include <linux/mount.h>
 #include <linux/idr.h>
 #include <linux/sched.h>
@@ -104,7 +103,6 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
                sb->s_flags |= MS_POSIXACL;
 #endif
 
-       save_mount_options(sb, data);
        return 0;
 }
 
@@ -349,7 +347,7 @@ static const struct super_operations v9fs_super_ops = {
        .destroy_inode = v9fs_destroy_inode,
        .statfs = simple_statfs,
        .evict_inode = v9fs_evict_inode,
-       .show_options = generic_show_options,
+       .show_options = v9fs_show_options,
        .umount_begin = v9fs_umount_begin,
        .write_inode = v9fs_write_inode,
 };
@@ -360,7 +358,7 @@ static const struct super_operations v9fs_super_ops_dotl = {
        .statfs = v9fs_statfs,
        .drop_inode = v9fs_drop_inode,
        .evict_inode = v9fs_evict_inode,
-       .show_options = generic_show_options,
+       .show_options = v9fs_show_options,
        .umount_begin = v9fs_umount_begin,
        .write_inode = v9fs_write_inode_dotl,
 };
index b582339ccef5c6f075eab1485a1cff37bf6cacc3..7af9d769b97d80d8417d6cf500923d583a498fca 100644 (file)
@@ -157,6 +157,18 @@ struct p9_client {
        enum p9_trans_status status;
        void *trans;
 
+       union {
+               struct {
+                       int rfd;
+                       int wfd;
+               } fd;
+               struct {
+                       u16 port;
+                       bool privport;
+
+               } tcp;
+       } trans_opts;
+
        struct p9_idpool *fidpool;
        struct list_head fidlist;
 
@@ -213,6 +225,7 @@ struct p9_dirent {
 
 struct iov_iter;
 
+int p9_show_client_options(struct seq_file *m, struct p9_client *clnt);
 int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb);
 int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid,
                     const char *name);
index 5122b5e40f78f1aec1b30aa17d13dd68558d9f4f..1625fb842ac478d139151ce31d3c9e8ddbbf10c4 100644 (file)
@@ -62,6 +62,7 @@ struct p9_trans_module {
        int (*cancelled)(struct p9_client *, struct p9_req_t *req);
        int (*zc_request)(struct p9_client *, struct p9_req_t *,
                          struct iov_iter *, struct iov_iter *, int , int, int);
+       int (*show_options)(struct seq_file *, struct p9_client *);
 };
 
 void v9fs_register_trans(struct p9_trans_module *m);
index 1218fb3b52dad115e4343c465ea891aed38d34c0..4674235b0d9b1f77dae3736fd08b1a6a2a417eeb 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/uio.h>
 #include <net/9p/9p.h>
 #include <linux/parser.h>
+#include <linux/seq_file.h>
 #include <net/9p/client.h>
 #include <net/9p/transport.h>
 #include "protocol.h"
@@ -77,6 +78,30 @@ inline int p9_is_proto_dotu(struct p9_client *clnt)
 }
 EXPORT_SYMBOL(p9_is_proto_dotu);
 
+int p9_show_client_options(struct seq_file *m, struct p9_client *clnt)
+{
+       if (clnt->msize != 8192)
+               seq_printf(m, ",msize=%u", clnt->msize);
+       seq_printf(m, "trans=%s", clnt->trans_mod->name);
+
+       switch (clnt->proto_version) {
+       case p9_proto_legacy:
+               seq_puts(m, ",noextend");
+               break;
+       case p9_proto_2000u:
+               seq_puts(m, ",version=9p2000.u");
+               break;
+       case p9_proto_2000L:
+               /* Default */
+               break;
+       }
+
+       if (clnt->trans_mod->show_options)
+               return clnt->trans_mod->show_options(m, clnt);
+       return 0;
+}
+EXPORT_SYMBOL(p9_show_client_options);
+
 /*
  * Some error codes are taken directly from the server replies,
  * make sure they are valid.
index 7bc2208b6cc4c445286c20e01d9911ac9e75b9b2..f2e0eaf58018efd8e7c7e461491af56e1739a77f 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/file.h>
 #include <linux/parser.h>
 #include <linux/slab.h>
+#include <linux/seq_file.h>
 #include <net/9p/9p.h>
 #include <net/9p/client.h>
 #include <net/9p/transport.h>
@@ -51,6 +52,9 @@
 #define MAX_SOCK_BUF (64*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)
@@ -63,7 +67,7 @@ struct p9_fd_opts {
        int rfd;
        int wfd;
        u16 port;
-       int privport;
+       bool privport;
 };
 
 /*
@@ -720,6 +724,20 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
        return 0;
 }
 
+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)
+                       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)
+                       seq_printf(m, "rfd=%u", clnt->trans_opts.fd.rfd);
+               if (clnt->trans_opts.fd.wfd != ~0)
+                       seq_printf(m, "wfd=%u", clnt->trans_opts.fd.wfd);
+       }
+       return 0;
+}
+
 /**
  * parse_opts - parse mount options into p9_fd_opts structure
  * @params: options string passed from mount
@@ -738,7 +756,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
        opts->port = P9_PORT;
        opts->rfd = ~0;
        opts->wfd = ~0;
-       opts->privport = 0;
+       opts->privport = false;
 
        if (!params)
                return 0;
@@ -776,7 +794,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
                        opts->wfd = option;
                        break;
                case Opt_privport:
-                       opts->privport = 1;
+                       opts->privport = true;
                        break;
                default:
                        continue;
@@ -942,6 +960,8 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
 
        csocket = NULL;
 
+       client->trans_opts.tcp.port = opts.port;
+       client->trans_opts.tcp.privport = opts.privport;
        sin_server.sin_family = AF_INET;
        sin_server.sin_addr.s_addr = in_aton(addr);
        sin_server.sin_port = htons(opts.port);
@@ -1020,6 +1040,8 @@ p9_fd_create(struct p9_client *client, const char *addr, char *args)
        struct p9_fd_opts opts;
 
        parse_opts(args, &opts);
+       client->trans_opts.fd.rfd = opts.rfd;
+       client->trans_opts.fd.wfd = opts.wfd;
 
        if (opts.rfd == ~0 || opts.wfd == ~0) {
                pr_err("Insufficient options for proto=fd\n");
@@ -1044,6 +1066,7 @@ static struct p9_trans_module p9_tcp_trans = {
        .request = p9_fd_request,
        .cancel = p9_fd_cancel,
        .cancelled = p9_fd_cancelled,
+       .show_options = p9_fd_show_options,
        .owner = THIS_MODULE,
 };
 
@@ -1056,6 +1079,7 @@ static struct p9_trans_module p9_unix_trans = {
        .request = p9_fd_request,
        .cancel = p9_fd_cancel,
        .cancelled = p9_fd_cancelled,
+       .show_options = p9_fd_show_options,
        .owner = THIS_MODULE,
 };
 
@@ -1068,6 +1092,7 @@ static struct p9_trans_module p9_fd_trans = {
        .request = p9_fd_request,
        .cancel = p9_fd_cancel,
        .cancelled = p9_fd_cancelled,
+       .show_options = p9_fd_show_options,
        .owner = THIS_MODULE,
 };
 
index 553ed4ecb6a0ec6527ca6171e3493f97ac8a8e0d..6d8e3031978f3493edb123a51b58b30b1c2807c5 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/parser.h>
 #include <linux/semaphore.h>
 #include <linux/slab.h>
+#include <linux/seq_file.h>
 #include <net/9p/9p.h>
 #include <net/9p/client.h>
 #include <net/9p/transport.h>
@@ -70,6 +71,8 @@
  * @dm_mr: DMA Memory Region pointer
  * @lkey: The local access only memory region key
  * @timeout: Number of uSecs to wait for connection management events
+ * @privport: Whether a privileged port may be used
+ * @port: The port to use
  * @sq_depth: The depth of the Send Queue
  * @sq_sem: Semaphore for the SQ
  * @rq_depth: The depth of the Receive Queue.
@@ -95,6 +98,8 @@ struct p9_trans_rdma {
        struct ib_qp *qp;
        struct ib_cq *cq;
        long timeout;
+       bool privport;
+       u16 port;
        int sq_depth;
        struct semaphore sq_sem;
        int rq_depth;
@@ -133,10 +138,10 @@ struct p9_rdma_context {
  */
 struct p9_rdma_opts {
        short port;
+       bool privport;
        int sq_depth;
        int rq_depth;
        long timeout;
-       int privport;
 };
 
 /*
@@ -159,6 +164,23 @@ static match_table_t tokens = {
        {Opt_err, NULL},
 };
 
+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)
+               seq_printf(m, ",port=%u", rdma->port);
+       if (rdma->sq_depth != P9_RDMA_SQ_DEPTH)
+               seq_printf(m, ",sq=%u", rdma->sq_depth);
+       if (rdma->rq_depth != P9_RDMA_RQ_DEPTH)
+               seq_printf(m, ",rq=%u", rdma->rq_depth);
+       if (rdma->timeout != P9_RDMA_TIMEOUT)
+               seq_printf(m, ",timeout=%lu", rdma->timeout);
+       if (rdma->privport)
+               seq_puts(m, ",privport");
+       return 0;
+}
+
 /**
  * parse_opts - parse mount options into rdma options structure
  * @params: options string passed from mount
@@ -177,7 +199,7 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts)
        opts->sq_depth = P9_RDMA_SQ_DEPTH;
        opts->rq_depth = P9_RDMA_RQ_DEPTH;
        opts->timeout = P9_RDMA_TIMEOUT;
-       opts->privport = 0;
+       opts->privport = false;
 
        if (!params)
                return 0;
@@ -218,7 +240,7 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts)
                        opts->timeout = option;
                        break;
                case Opt_privport:
-                       opts->privport = 1;
+                       opts->privport = true;
                        break;
                default:
                        continue;
@@ -560,6 +582,8 @@ static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts)
        if (!rdma)
                return NULL;
 
+       rdma->port = opts->port;
+       rdma->privport = opts->privport;
        rdma->sq_depth = opts->sq_depth;
        rdma->rq_depth = opts->rq_depth;
        rdma->timeout = opts->timeout;
@@ -733,6 +757,7 @@ static struct p9_trans_module p9_rdma_trans = {
        .request = rdma_request,
        .cancel = rdma_cancel,
        .cancelled = rdma_cancelled,
+       .show_options = p9_rdma_show_options,
 };
 
 /**