summaryrefslogtreecommitdiff
path: root/net/9p/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/9p/client.c')
-rw-r--r--net/9p/client.c165
1 files changed, 21 insertions, 144 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index 5c1ca57ccd28..f60d1d041adb 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"
@@ -29,32 +29,10 @@
#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
*/
-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;
@@ -103,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;
-}
+ 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;
-/**
- * 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;
-
- 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,
@@ -229,8 +99,15 @@ static int p9_fcall_init(struct p9_client *c, struct p9_fcall *fc,
if (likely(c->fcall_cache) && alloc_msize == c->msize) {
fc->sdata = kmem_cache_alloc(c->fcall_cache, GFP_NOFS);
fc->cache = c->fcall_cache;
+ if (!fc->sdata && c->trans_mod->supports_vmalloc) {
+ fc->sdata = kvmalloc(alloc_msize, GFP_NOFS);
+ fc->cache = NULL;
+ }
} else {
- fc->sdata = kmalloc(alloc_msize, GFP_NOFS);
+ if (c->trans_mod->supports_vmalloc)
+ fc->sdata = kvmalloc(alloc_msize, GFP_NOFS);
+ else
+ fc->sdata = kmalloc(alloc_msize, GFP_NOFS);
fc->cache = NULL;
}
if (!fc->sdata)
@@ -252,7 +129,7 @@ void p9_fcall_fini(struct p9_fcall *fc)
if (fc->cache)
kmem_cache_free(fc->cache, fc->sdata);
else
- kfree(fc->sdata);
+ kvfree(fc->sdata);
}
EXPORT_SYMBOL(p9_fcall_fini);
@@ -974,7 +851,7 @@ error:
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);
@@ -997,8 +874,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)
@@ -1014,7 +891,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;