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.c161
1 files changed, 128 insertions, 33 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index af9199364049..84e087e24146 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -3,6 +3,7 @@
*
* 9P Client
*
+ * Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
* Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
*
* This program is free software; you can redistribute it and/or modify
@@ -25,6 +26,7 @@
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fs.h>
+#include <linux/poll.h>
#include <linux/idr.h>
#include <linux/mutex.h>
#include <linux/sched.h>
@@ -32,15 +34,97 @@
#include <net/9p/9p.h>
#include <linux/parser.h>
#include <net/9p/transport.h>
-#include <net/9p/conn.h>
#include <net/9p/client.h>
static struct p9_fid *p9_fid_create(struct p9_client *clnt);
static void p9_fid_destroy(struct p9_fid *fid);
static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu);
-struct p9_client *p9_client_create(struct p9_trans *trans, int msize,
- int dotu)
+/*
+ * Client Option Parsing (code inspired by NFS code)
+ * - a little lazy - parse all client options
+ */
+
+enum {
+ Opt_msize,
+ Opt_trans,
+ Opt_legacy,
+ Opt_err,
+};
+
+static match_table_t tokens = {
+ {Opt_msize, "msize=%u"},
+ {Opt_legacy, "noextend"},
+ {Opt_trans, "trans=%s"},
+ {Opt_err, NULL},
+};
+
+/**
+ * v9fs_parse_options - parse mount options into session structure
+ * @options: options string passed from mount
+ * @v9ses: existing v9fs session information
+ *
+ */
+
+static void parse_opts(char *options, struct p9_client *clnt)
+{
+ char *p;
+ substring_t args[MAX_OPT_ARGS];
+ int option;
+ int ret;
+
+ clnt->trans_mod = v9fs_default_trans();
+ clnt->dotu = 1;
+ clnt->msize = 8192;
+
+ if (!options)
+ return;
+
+ while ((p = strsep(&options, ",")) != NULL) {
+ int token;
+ if (!*p)
+ continue;
+ token = match_token(p, tokens, args);
+ if (token < Opt_trans) {
+ ret = match_int(&args[0], &option);
+ if (ret < 0) {
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "integer field, but no integer?\n");
+ continue;
+ }
+ }
+ switch (token) {
+ case Opt_msize:
+ clnt->msize = option;
+ break;
+ case Opt_trans:
+ clnt->trans_mod = v9fs_match_trans(&args[0]);
+ break;
+ case Opt_legacy:
+ clnt->dotu = 0;
+ break;
+ default:
+ continue;
+ }
+ }
+}
+
+
+/**
+ * p9_client_rpc - sends 9P request and waits until a response is available.
+ * The function can be interrupted.
+ * @c: client data
+ * @tc: request to be sent
+ * @rc: pointer where a pointer to the response is stored
+ */
+int
+p9_client_rpc(struct p9_client *c, struct p9_fcall *tc,
+ struct p9_fcall **rc)
+{
+ return c->trans->rpc(c->trans, tc, rc);
+}
+
+struct p9_client *p9_client_create(const char *dev_name, char *options)
{
int err, n;
struct p9_client *clnt;
@@ -54,12 +138,7 @@ struct p9_client *p9_client_create(struct p9_trans *trans, int msize,
if (!clnt)
return ERR_PTR(-ENOMEM);
- P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n",
- clnt, trans, msize, dotu);
spin_lock_init(&clnt->lock);
- clnt->trans = trans;
- clnt->msize = msize;
- clnt->dotu = dotu;
INIT_LIST_HEAD(&clnt->fidlist);
clnt->fidpool = p9_idpool_create();
if (!clnt->fidpool) {
@@ -68,13 +147,29 @@ struct p9_client *p9_client_create(struct p9_trans *trans, int msize,
goto error;
}
- clnt->conn = p9_conn_create(clnt->trans, clnt->msize, &clnt->dotu);
- if (IS_ERR(clnt->conn)) {
- err = PTR_ERR(clnt->conn);
- clnt->conn = NULL;
+ parse_opts(options, clnt);
+ if (clnt->trans_mod == NULL) {
+ err = -EPROTONOSUPPORT;
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "No transport defined or default transport\n");
goto error;
}
+ P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n",
+ clnt, clnt->trans_mod, clnt->msize, clnt->dotu);
+
+
+ clnt->trans = clnt->trans_mod->create(dev_name, options, clnt->msize,
+ clnt->dotu);
+ if (IS_ERR(clnt->trans)) {
+ err = PTR_ERR(clnt->trans);
+ clnt->trans = NULL;
+ goto error;
+ }
+
+ if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize)
+ clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ;
+
tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000");
if (IS_ERR(tc)) {
err = PTR_ERR(tc);
@@ -82,7 +177,7 @@ struct p9_client *p9_client_create(struct p9_trans *trans, int msize,
goto error;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto error;
@@ -117,10 +212,6 @@ void p9_client_destroy(struct p9_client *clnt)
struct p9_fid *fid, *fidptr;
P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
- if (clnt->conn) {
- p9_conn_destroy(clnt->conn);
- clnt->conn = NULL;
- }
if (clnt->trans) {
clnt->trans->close(clnt->trans);
@@ -142,7 +233,6 @@ void p9_client_disconnect(struct p9_client *clnt)
{
P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
clnt->trans->status = Disconnected;
- p9_conn_cancel(clnt->conn, -EIO);
}
EXPORT_SYMBOL(p9_client_disconnect);
@@ -174,7 +264,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
goto error;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto error;
@@ -219,7 +309,7 @@ struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname,
goto error;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto error;
@@ -270,7 +360,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
goto error;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err) {
if (rc && rc->id == P9_RWALK)
goto clunk_fid;
@@ -305,7 +395,7 @@ clunk_fid:
goto error;
}
- p9_conn_rpc(clnt->conn, tc, &rc);
+ p9_client_rpc(clnt, tc, &rc);
error:
kfree(tc);
@@ -339,7 +429,7 @@ int p9_client_open(struct p9_fid *fid, int mode)
goto done;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto done;
@@ -378,7 +468,7 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
goto done;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto done;
@@ -411,7 +501,7 @@ int p9_client_clunk(struct p9_fid *fid)
goto done;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto done;
@@ -443,7 +533,7 @@ int p9_client_remove(struct p9_fid *fid)
goto done;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto done;
@@ -485,7 +575,7 @@ int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count)
goto error;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto error;
@@ -542,7 +632,7 @@ int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count)
goto error;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto error;
@@ -596,7 +686,7 @@ p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, u32 count)
goto error;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto error;
@@ -660,7 +750,7 @@ p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
goto error;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto error;
@@ -731,7 +821,7 @@ struct p9_stat *p9_client_stat(struct p9_fid *fid)
goto error;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto error;
@@ -773,7 +863,7 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
goto done;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
done:
kfree(tc);
@@ -830,7 +920,7 @@ struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset)
goto error;
}
- err = p9_conn_rpc(clnt->conn, tc, &rc);
+ err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto error;
@@ -901,16 +991,21 @@ static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu)
memmove(ret, st, sizeof(struct p9_stat));
p = ((char *) ret) + sizeof(struct p9_stat);
memmove(p, st->name.str, st->name.len);
+ ret->name.str = p;
p += st->name.len;
memmove(p, st->uid.str, st->uid.len);
+ ret->uid.str = p;
p += st->uid.len;
memmove(p, st->gid.str, st->gid.len);
+ ret->gid.str = p;
p += st->gid.len;
memmove(p, st->muid.str, st->muid.len);
+ ret->muid.str = p;
p += st->muid.len;
if (dotu) {
memmove(p, st->extension.str, st->extension.len);
+ ret->extension.str = p;
p += st->extension.len;
}