diff options
Diffstat (limited to 'net/9p/client.c')
-rw-r--r-- | net/9p/client.c | 115 |
1 files changed, 94 insertions, 21 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 433b30713ef6..84e087e24146 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * 9P Client | 4 | * 9P Client |
5 | * | 5 | * |
6 | * Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com> | ||
6 | * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> | 7 | * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> |
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
@@ -25,6 +26,7 @@ | |||
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
26 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
27 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | #include <linux/poll.h> | ||
28 | #include <linux/idr.h> | 30 | #include <linux/idr.h> |
29 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
30 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
@@ -32,13 +34,82 @@ | |||
32 | #include <net/9p/9p.h> | 34 | #include <net/9p/9p.h> |
33 | #include <linux/parser.h> | 35 | #include <linux/parser.h> |
34 | #include <net/9p/transport.h> | 36 | #include <net/9p/transport.h> |
35 | #include <net/9p/conn.h> | ||
36 | #include <net/9p/client.h> | 37 | #include <net/9p/client.h> |
37 | 38 | ||
38 | static struct p9_fid *p9_fid_create(struct p9_client *clnt); | 39 | static struct p9_fid *p9_fid_create(struct p9_client *clnt); |
39 | static void p9_fid_destroy(struct p9_fid *fid); | 40 | static void p9_fid_destroy(struct p9_fid *fid); |
40 | static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu); | 41 | static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu); |
41 | 42 | ||
43 | /* | ||
44 | * Client Option Parsing (code inspired by NFS code) | ||
45 | * - a little lazy - parse all client options | ||
46 | */ | ||
47 | |||
48 | enum { | ||
49 | Opt_msize, | ||
50 | Opt_trans, | ||
51 | Opt_legacy, | ||
52 | Opt_err, | ||
53 | }; | ||
54 | |||
55 | static match_table_t tokens = { | ||
56 | {Opt_msize, "msize=%u"}, | ||
57 | {Opt_legacy, "noextend"}, | ||
58 | {Opt_trans, "trans=%s"}, | ||
59 | {Opt_err, NULL}, | ||
60 | }; | ||
61 | |||
62 | /** | ||
63 | * v9fs_parse_options - parse mount options into session structure | ||
64 | * @options: options string passed from mount | ||
65 | * @v9ses: existing v9fs session information | ||
66 | * | ||
67 | */ | ||
68 | |||
69 | static void parse_opts(char *options, struct p9_client *clnt) | ||
70 | { | ||
71 | char *p; | ||
72 | substring_t args[MAX_OPT_ARGS]; | ||
73 | int option; | ||
74 | int ret; | ||
75 | |||
76 | clnt->trans_mod = v9fs_default_trans(); | ||
77 | clnt->dotu = 1; | ||
78 | clnt->msize = 8192; | ||
79 | |||
80 | if (!options) | ||
81 | return; | ||
82 | |||
83 | while ((p = strsep(&options, ",")) != NULL) { | ||
84 | int token; | ||
85 | if (!*p) | ||
86 | continue; | ||
87 | token = match_token(p, tokens, args); | ||
88 | if (token < Opt_trans) { | ||
89 | ret = match_int(&args[0], &option); | ||
90 | if (ret < 0) { | ||
91 | P9_DPRINTK(P9_DEBUG_ERROR, | ||
92 | "integer field, but no integer?\n"); | ||
93 | continue; | ||
94 | } | ||
95 | } | ||
96 | switch (token) { | ||
97 | case Opt_msize: | ||
98 | clnt->msize = option; | ||
99 | break; | ||
100 | case Opt_trans: | ||
101 | clnt->trans_mod = v9fs_match_trans(&args[0]); | ||
102 | break; | ||
103 | case Opt_legacy: | ||
104 | clnt->dotu = 0; | ||
105 | break; | ||
106 | default: | ||
107 | continue; | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | |||
112 | |||
42 | /** | 113 | /** |
43 | * p9_client_rpc - sends 9P request and waits until a response is available. | 114 | * p9_client_rpc - sends 9P request and waits until a response is available. |
44 | * The function can be interrupted. | 115 | * The function can be interrupted. |
@@ -50,14 +121,10 @@ int | |||
50 | p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, | 121 | p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, |
51 | struct p9_fcall **rc) | 122 | struct p9_fcall **rc) |
52 | { | 123 | { |
53 | if (c->trans->rpc) | 124 | return c->trans->rpc(c->trans, tc, rc); |
54 | return c->trans->rpc(c->trans, tc, rc, c->msize, c->dotu); | ||
55 | else | ||
56 | return p9_conn_rpc(c->conn, tc, rc); | ||
57 | } | 125 | } |
58 | 126 | ||
59 | struct p9_client *p9_client_create(struct p9_trans *trans, int msize, | 127 | struct p9_client *p9_client_create(const char *dev_name, char *options) |
60 | int dotu) | ||
61 | { | 128 | { |
62 | int err, n; | 129 | int err, n; |
63 | struct p9_client *clnt; | 130 | struct p9_client *clnt; |
@@ -71,12 +138,7 @@ struct p9_client *p9_client_create(struct p9_trans *trans, int msize, | |||
71 | if (!clnt) | 138 | if (!clnt) |
72 | return ERR_PTR(-ENOMEM); | 139 | return ERR_PTR(-ENOMEM); |
73 | 140 | ||
74 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n", | ||
75 | clnt, trans, msize, dotu); | ||
76 | spin_lock_init(&clnt->lock); | 141 | spin_lock_init(&clnt->lock); |
77 | clnt->trans = trans; | ||
78 | clnt->msize = msize; | ||
79 | clnt->dotu = dotu; | ||
80 | INIT_LIST_HEAD(&clnt->fidlist); | 142 | INIT_LIST_HEAD(&clnt->fidlist); |
81 | clnt->fidpool = p9_idpool_create(); | 143 | clnt->fidpool = p9_idpool_create(); |
82 | if (!clnt->fidpool) { | 144 | if (!clnt->fidpool) { |
@@ -85,13 +147,29 @@ struct p9_client *p9_client_create(struct p9_trans *trans, int msize, | |||
85 | goto error; | 147 | goto error; |
86 | } | 148 | } |
87 | 149 | ||
88 | clnt->conn = p9_conn_create(clnt->trans, clnt->msize, &clnt->dotu); | 150 | parse_opts(options, clnt); |
89 | if (IS_ERR(clnt->conn)) { | 151 | if (clnt->trans_mod == NULL) { |
90 | err = PTR_ERR(clnt->conn); | 152 | err = -EPROTONOSUPPORT; |
91 | clnt->conn = NULL; | 153 | P9_DPRINTK(P9_DEBUG_ERROR, |
154 | "No transport defined or default transport\n"); | ||
155 | goto error; | ||
156 | } | ||
157 | |||
158 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n", | ||
159 | clnt, clnt->trans_mod, clnt->msize, clnt->dotu); | ||
160 | |||
161 | |||
162 | clnt->trans = clnt->trans_mod->create(dev_name, options, clnt->msize, | ||
163 | clnt->dotu); | ||
164 | if (IS_ERR(clnt->trans)) { | ||
165 | err = PTR_ERR(clnt->trans); | ||
166 | clnt->trans = NULL; | ||
92 | goto error; | 167 | goto error; |
93 | } | 168 | } |
94 | 169 | ||
170 | if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize) | ||
171 | clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ; | ||
172 | |||
95 | tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000"); | 173 | tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000"); |
96 | if (IS_ERR(tc)) { | 174 | if (IS_ERR(tc)) { |
97 | err = PTR_ERR(tc); | 175 | err = PTR_ERR(tc); |
@@ -134,10 +212,6 @@ void p9_client_destroy(struct p9_client *clnt) | |||
134 | struct p9_fid *fid, *fidptr; | 212 | struct p9_fid *fid, *fidptr; |
135 | 213 | ||
136 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); | 214 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); |
137 | if (clnt->conn) { | ||
138 | p9_conn_destroy(clnt->conn); | ||
139 | clnt->conn = NULL; | ||
140 | } | ||
141 | 215 | ||
142 | if (clnt->trans) { | 216 | if (clnt->trans) { |
143 | clnt->trans->close(clnt->trans); | 217 | clnt->trans->close(clnt->trans); |
@@ -159,7 +233,6 @@ void p9_client_disconnect(struct p9_client *clnt) | |||
159 | { | 233 | { |
160 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); | 234 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); |
161 | clnt->trans->status = Disconnected; | 235 | clnt->trans->status = Disconnected; |
162 | p9_conn_cancel(clnt->conn, -EIO); | ||
163 | } | 236 | } |
164 | EXPORT_SYMBOL(p9_client_disconnect); | 237 | EXPORT_SYMBOL(p9_client_disconnect); |
165 | 238 | ||