diff options
Diffstat (limited to 'net/9p/client.c')
-rw-r--r-- | net/9p/client.c | 161 |
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 @@ | |||
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,15 +34,97 @@ | |||
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 | ||
42 | struct p9_client *p9_client_create(struct p9_trans *trans, int msize, | 43 | /* |
43 | int dotu) | 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 | |||
113 | /** | ||
114 | * p9_client_rpc - sends 9P request and waits until a response is available. | ||
115 | * The function can be interrupted. | ||
116 | * @c: client data | ||
117 | * @tc: request to be sent | ||
118 | * @rc: pointer where a pointer to the response is stored | ||
119 | */ | ||
120 | int | ||
121 | p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, | ||
122 | struct p9_fcall **rc) | ||
123 | { | ||
124 | return c->trans->rpc(c->trans, tc, rc); | ||
125 | } | ||
126 | |||
127 | struct p9_client *p9_client_create(const char *dev_name, char *options) | ||
44 | { | 128 | { |
45 | int err, n; | 129 | int err, n; |
46 | struct p9_client *clnt; | 130 | struct p9_client *clnt; |
@@ -54,12 +138,7 @@ struct p9_client *p9_client_create(struct p9_trans *trans, int msize, | |||
54 | if (!clnt) | 138 | if (!clnt) |
55 | return ERR_PTR(-ENOMEM); | 139 | return ERR_PTR(-ENOMEM); |
56 | 140 | ||
57 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n", | ||
58 | clnt, trans, msize, dotu); | ||
59 | spin_lock_init(&clnt->lock); | 141 | spin_lock_init(&clnt->lock); |
60 | clnt->trans = trans; | ||
61 | clnt->msize = msize; | ||
62 | clnt->dotu = dotu; | ||
63 | INIT_LIST_HEAD(&clnt->fidlist); | 142 | INIT_LIST_HEAD(&clnt->fidlist); |
64 | clnt->fidpool = p9_idpool_create(); | 143 | clnt->fidpool = p9_idpool_create(); |
65 | if (!clnt->fidpool) { | 144 | if (!clnt->fidpool) { |
@@ -68,13 +147,29 @@ struct p9_client *p9_client_create(struct p9_trans *trans, int msize, | |||
68 | goto error; | 147 | goto error; |
69 | } | 148 | } |
70 | 149 | ||
71 | clnt->conn = p9_conn_create(clnt->trans, clnt->msize, &clnt->dotu); | 150 | parse_opts(options, clnt); |
72 | if (IS_ERR(clnt->conn)) { | 151 | if (clnt->trans_mod == NULL) { |
73 | err = PTR_ERR(clnt->conn); | 152 | err = -EPROTONOSUPPORT; |
74 | clnt->conn = NULL; | 153 | P9_DPRINTK(P9_DEBUG_ERROR, |
154 | "No transport defined or default transport\n"); | ||
75 | goto error; | 155 | goto error; |
76 | } | 156 | } |
77 | 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; | ||
167 | goto error; | ||
168 | } | ||
169 | |||
170 | if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize) | ||
171 | clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ; | ||
172 | |||
78 | tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000"); | 173 | tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000"); |
79 | if (IS_ERR(tc)) { | 174 | if (IS_ERR(tc)) { |
80 | err = PTR_ERR(tc); | 175 | err = PTR_ERR(tc); |
@@ -82,7 +177,7 @@ struct p9_client *p9_client_create(struct p9_trans *trans, int msize, | |||
82 | goto error; | 177 | goto error; |
83 | } | 178 | } |
84 | 179 | ||
85 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 180 | err = p9_client_rpc(clnt, tc, &rc); |
86 | if (err) | 181 | if (err) |
87 | goto error; | 182 | goto error; |
88 | 183 | ||
@@ -117,10 +212,6 @@ void p9_client_destroy(struct p9_client *clnt) | |||
117 | struct p9_fid *fid, *fidptr; | 212 | struct p9_fid *fid, *fidptr; |
118 | 213 | ||
119 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); | 214 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); |
120 | if (clnt->conn) { | ||
121 | p9_conn_destroy(clnt->conn); | ||
122 | clnt->conn = NULL; | ||
123 | } | ||
124 | 215 | ||
125 | if (clnt->trans) { | 216 | if (clnt->trans) { |
126 | clnt->trans->close(clnt->trans); | 217 | clnt->trans->close(clnt->trans); |
@@ -142,7 +233,6 @@ void p9_client_disconnect(struct p9_client *clnt) | |||
142 | { | 233 | { |
143 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); | 234 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); |
144 | clnt->trans->status = Disconnected; | 235 | clnt->trans->status = Disconnected; |
145 | p9_conn_cancel(clnt->conn, -EIO); | ||
146 | } | 236 | } |
147 | EXPORT_SYMBOL(p9_client_disconnect); | 237 | EXPORT_SYMBOL(p9_client_disconnect); |
148 | 238 | ||
@@ -174,7 +264,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, | |||
174 | goto error; | 264 | goto error; |
175 | } | 265 | } |
176 | 266 | ||
177 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 267 | err = p9_client_rpc(clnt, tc, &rc); |
178 | if (err) | 268 | if (err) |
179 | goto error; | 269 | goto error; |
180 | 270 | ||
@@ -219,7 +309,7 @@ struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, | |||
219 | goto error; | 309 | goto error; |
220 | } | 310 | } |
221 | 311 | ||
222 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 312 | err = p9_client_rpc(clnt, tc, &rc); |
223 | if (err) | 313 | if (err) |
224 | goto error; | 314 | goto error; |
225 | 315 | ||
@@ -270,7 +360,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | |||
270 | goto error; | 360 | goto error; |
271 | } | 361 | } |
272 | 362 | ||
273 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 363 | err = p9_client_rpc(clnt, tc, &rc); |
274 | if (err) { | 364 | if (err) { |
275 | if (rc && rc->id == P9_RWALK) | 365 | if (rc && rc->id == P9_RWALK) |
276 | goto clunk_fid; | 366 | goto clunk_fid; |
@@ -305,7 +395,7 @@ clunk_fid: | |||
305 | goto error; | 395 | goto error; |
306 | } | 396 | } |
307 | 397 | ||
308 | p9_conn_rpc(clnt->conn, tc, &rc); | 398 | p9_client_rpc(clnt, tc, &rc); |
309 | 399 | ||
310 | error: | 400 | error: |
311 | kfree(tc); | 401 | kfree(tc); |
@@ -339,7 +429,7 @@ int p9_client_open(struct p9_fid *fid, int mode) | |||
339 | goto done; | 429 | goto done; |
340 | } | 430 | } |
341 | 431 | ||
342 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 432 | err = p9_client_rpc(clnt, tc, &rc); |
343 | if (err) | 433 | if (err) |
344 | goto done; | 434 | goto done; |
345 | 435 | ||
@@ -378,7 +468,7 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, | |||
378 | goto done; | 468 | goto done; |
379 | } | 469 | } |
380 | 470 | ||
381 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 471 | err = p9_client_rpc(clnt, tc, &rc); |
382 | if (err) | 472 | if (err) |
383 | goto done; | 473 | goto done; |
384 | 474 | ||
@@ -411,7 +501,7 @@ int p9_client_clunk(struct p9_fid *fid) | |||
411 | goto done; | 501 | goto done; |
412 | } | 502 | } |
413 | 503 | ||
414 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 504 | err = p9_client_rpc(clnt, tc, &rc); |
415 | if (err) | 505 | if (err) |
416 | goto done; | 506 | goto done; |
417 | 507 | ||
@@ -443,7 +533,7 @@ int p9_client_remove(struct p9_fid *fid) | |||
443 | goto done; | 533 | goto done; |
444 | } | 534 | } |
445 | 535 | ||
446 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 536 | err = p9_client_rpc(clnt, tc, &rc); |
447 | if (err) | 537 | if (err) |
448 | goto done; | 538 | goto done; |
449 | 539 | ||
@@ -485,7 +575,7 @@ int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count) | |||
485 | goto error; | 575 | goto error; |
486 | } | 576 | } |
487 | 577 | ||
488 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 578 | err = p9_client_rpc(clnt, tc, &rc); |
489 | if (err) | 579 | if (err) |
490 | goto error; | 580 | goto error; |
491 | 581 | ||
@@ -542,7 +632,7 @@ int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count) | |||
542 | goto error; | 632 | goto error; |
543 | } | 633 | } |
544 | 634 | ||
545 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 635 | err = p9_client_rpc(clnt, tc, &rc); |
546 | if (err) | 636 | if (err) |
547 | goto error; | 637 | goto error; |
548 | 638 | ||
@@ -596,7 +686,7 @@ p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, u32 count) | |||
596 | goto error; | 686 | goto error; |
597 | } | 687 | } |
598 | 688 | ||
599 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 689 | err = p9_client_rpc(clnt, tc, &rc); |
600 | if (err) | 690 | if (err) |
601 | goto error; | 691 | goto error; |
602 | 692 | ||
@@ -660,7 +750,7 @@ p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset, | |||
660 | goto error; | 750 | goto error; |
661 | } | 751 | } |
662 | 752 | ||
663 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 753 | err = p9_client_rpc(clnt, tc, &rc); |
664 | if (err) | 754 | if (err) |
665 | goto error; | 755 | goto error; |
666 | 756 | ||
@@ -731,7 +821,7 @@ struct p9_stat *p9_client_stat(struct p9_fid *fid) | |||
731 | goto error; | 821 | goto error; |
732 | } | 822 | } |
733 | 823 | ||
734 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 824 | err = p9_client_rpc(clnt, tc, &rc); |
735 | if (err) | 825 | if (err) |
736 | goto error; | 826 | goto error; |
737 | 827 | ||
@@ -773,7 +863,7 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) | |||
773 | goto done; | 863 | goto done; |
774 | } | 864 | } |
775 | 865 | ||
776 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 866 | err = p9_client_rpc(clnt, tc, &rc); |
777 | 867 | ||
778 | done: | 868 | done: |
779 | kfree(tc); | 869 | kfree(tc); |
@@ -830,7 +920,7 @@ struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset) | |||
830 | goto error; | 920 | goto error; |
831 | } | 921 | } |
832 | 922 | ||
833 | err = p9_conn_rpc(clnt->conn, tc, &rc); | 923 | err = p9_client_rpc(clnt, tc, &rc); |
834 | if (err) | 924 | if (err) |
835 | goto error; | 925 | goto error; |
836 | 926 | ||
@@ -901,16 +991,21 @@ static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu) | |||
901 | memmove(ret, st, sizeof(struct p9_stat)); | 991 | memmove(ret, st, sizeof(struct p9_stat)); |
902 | p = ((char *) ret) + sizeof(struct p9_stat); | 992 | p = ((char *) ret) + sizeof(struct p9_stat); |
903 | memmove(p, st->name.str, st->name.len); | 993 | memmove(p, st->name.str, st->name.len); |
994 | ret->name.str = p; | ||
904 | p += st->name.len; | 995 | p += st->name.len; |
905 | memmove(p, st->uid.str, st->uid.len); | 996 | memmove(p, st->uid.str, st->uid.len); |
997 | ret->uid.str = p; | ||
906 | p += st->uid.len; | 998 | p += st->uid.len; |
907 | memmove(p, st->gid.str, st->gid.len); | 999 | memmove(p, st->gid.str, st->gid.len); |
1000 | ret->gid.str = p; | ||
908 | p += st->gid.len; | 1001 | p += st->gid.len; |
909 | memmove(p, st->muid.str, st->muid.len); | 1002 | memmove(p, st->muid.str, st->muid.len); |
1003 | ret->muid.str = p; | ||
910 | p += st->muid.len; | 1004 | p += st->muid.len; |
911 | 1005 | ||
912 | if (dotu) { | 1006 | if (dotu) { |
913 | memmove(p, st->extension.str, st->extension.len); | 1007 | memmove(p, st->extension.str, st->extension.len); |
1008 | ret->extension.str = p; | ||
914 | p += st->extension.len; | 1009 | p += st->extension.len; |
915 | } | 1010 | } |
916 | 1011 | ||