aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/9p/client.c')
-rw-r--r--net/9p/client.c114
1 files changed, 87 insertions, 27 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index 09d4f1e2e4a8..bde9f3d38c57 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -46,6 +46,7 @@ enum {
46 Opt_msize, 46 Opt_msize,
47 Opt_trans, 47 Opt_trans,
48 Opt_legacy, 48 Opt_legacy,
49 Opt_version,
49 Opt_err, 50 Opt_err,
50}; 51};
51 52
@@ -53,9 +54,42 @@ static const match_table_t tokens = {
53 {Opt_msize, "msize=%u"}, 54 {Opt_msize, "msize=%u"},
54 {Opt_legacy, "noextend"}, 55 {Opt_legacy, "noextend"},
55 {Opt_trans, "trans=%s"}, 56 {Opt_trans, "trans=%s"},
57 {Opt_version, "version=%s"},
56 {Opt_err, NULL}, 58 {Opt_err, NULL},
57}; 59};
58 60
61inline int p9_is_proto_dotl(struct p9_client *clnt)
62{
63 return (clnt->proto_version == p9_proto_2010L);
64}
65EXPORT_SYMBOL(p9_is_proto_dotl);
66
67inline int p9_is_proto_dotu(struct p9_client *clnt)
68{
69 return (clnt->proto_version == p9_proto_2000u);
70}
71EXPORT_SYMBOL(p9_is_proto_dotu);
72
73/* Interpret mount option for protocol version */
74static unsigned char get_protocol_version(const substring_t *name)
75{
76 unsigned char version = -EINVAL;
77 if (!strncmp("9p2000", name->from, name->to-name->from)) {
78 version = p9_proto_legacy;
79 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n");
80 } else if (!strncmp("9p2000.u", name->from, name->to-name->from)) {
81 version = p9_proto_2000u;
82 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
83 } else if (!strncmp("9p2010.L", name->from, name->to-name->from)) {
84 version = p9_proto_2010L;
85 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2010.L\n");
86 } else {
87 P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ",
88 name->from);
89 }
90 return version;
91}
92
59static struct p9_req_t * 93static struct p9_req_t *
60p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); 94p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
61 95
@@ -75,7 +109,7 @@ static int parse_opts(char *opts, struct p9_client *clnt)
75 int option; 109 int option;
76 int ret = 0; 110 int ret = 0;
77 111
78 clnt->dotu = 1; 112 clnt->proto_version = p9_proto_2000u;
79 clnt->msize = 8192; 113 clnt->msize = 8192;
80 114
81 if (!opts) 115 if (!opts)
@@ -118,7 +152,13 @@ static int parse_opts(char *opts, struct p9_client *clnt)
118 } 152 }
119 break; 153 break;
120 case Opt_legacy: 154 case Opt_legacy:
121 clnt->dotu = 0; 155 clnt->proto_version = p9_proto_legacy;
156 break;
157 case Opt_version:
158 ret = get_protocol_version(&args[0]);
159 if (ret == -EINVAL)
160 goto free_and_return;
161 clnt->proto_version = ret;
122 break; 162 break;
123 default: 163 default:
124 continue; 164 continue;
@@ -410,14 +450,15 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
410 int ecode; 450 int ecode;
411 char *ename; 451 char *ename;
412 452
413 err = p9pdu_readf(req->rc, c->dotu, "s?d", &ename, &ecode); 453 err = p9pdu_readf(req->rc, c->proto_version, "s?d",
454 &ename, &ecode);
414 if (err) { 455 if (err) {
415 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", 456 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n",
416 err); 457 err);
417 return err; 458 return err;
418 } 459 }
419 460
420 if (c->dotu) 461 if (p9_is_proto_dotu(c))
421 err = -ecode; 462 err = -ecode;
422 463
423 if (!err || !IS_ERR_VALUE(err)) 464 if (!err || !IS_ERR_VALUE(err))
@@ -515,7 +556,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
515 /* marshall the data */ 556 /* marshall the data */
516 p9pdu_prepare(req->tc, tag, type); 557 p9pdu_prepare(req->tc, tag, type);
517 va_start(ap, fmt); 558 va_start(ap, fmt);
518 err = p9pdu_vwritef(req->tc, c->dotu, fmt, ap); 559 err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap);
519 va_end(ap); 560 va_end(ap);
520 p9pdu_finalize(req->tc); 561 p9pdu_finalize(req->tc);
521 562
@@ -627,14 +668,31 @@ int p9_client_version(struct p9_client *c)
627 char *version; 668 char *version;
628 int msize; 669 int msize;
629 670
630 P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d extended %d\n", 671 P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n",
631 c->msize, c->dotu); 672 c->msize, c->proto_version);
632 req = p9_client_rpc(c, P9_TVERSION, "ds", c->msize, 673
633 c->dotu ? "9P2000.u" : "9P2000"); 674 switch (c->proto_version) {
675 case p9_proto_2010L:
676 req = p9_client_rpc(c, P9_TVERSION, "ds",
677 c->msize, "9P2010.L");
678 break;
679 case p9_proto_2000u:
680 req = p9_client_rpc(c, P9_TVERSION, "ds",
681 c->msize, "9P2000.u");
682 break;
683 case p9_proto_legacy:
684 req = p9_client_rpc(c, P9_TVERSION, "ds",
685 c->msize, "9P2000");
686 break;
687 default:
688 return -EINVAL;
689 break;
690 }
691
634 if (IS_ERR(req)) 692 if (IS_ERR(req))
635 return PTR_ERR(req); 693 return PTR_ERR(req);
636 694
637 err = p9pdu_readf(req->rc, c->dotu, "ds", &msize, &version); 695 err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version);
638 if (err) { 696 if (err) {
639 P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err); 697 P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err);
640 p9pdu_dump(1, req->rc); 698 p9pdu_dump(1, req->rc);
@@ -642,10 +700,12 @@ int p9_client_version(struct p9_client *c)
642 } 700 }
643 701
644 P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); 702 P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
645 if (!memcmp(version, "9P2000.u", 8)) 703 if (!strncmp(version, "9P2010.L", 8))
646 c->dotu = 1; 704 c->proto_version = p9_proto_2010L;
647 else if (!memcmp(version, "9P2000", 6)) 705 else if (!strncmp(version, "9P2000.u", 8))
648 c->dotu = 0; 706 c->proto_version = p9_proto_2000u;
707 else if (!strncmp(version, "9P2000", 6))
708 c->proto_version = p9_proto_legacy;
649 else { 709 else {
650 err = -EREMOTEIO; 710 err = -EREMOTEIO;
651 goto error; 711 goto error;
@@ -700,8 +760,8 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
700 goto put_trans; 760 goto put_trans;
701 } 761 }
702 762
703 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n", 763 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n",
704 clnt, clnt->trans_mod, clnt->msize, clnt->dotu); 764 clnt, clnt->trans_mod, clnt->msize, clnt->proto_version);
705 765
706 err = clnt->trans_mod->create(clnt, dev_name, options); 766 err = clnt->trans_mod->create(clnt, dev_name, options);
707 if (err) 767 if (err)
@@ -784,7 +844,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
784 goto error; 844 goto error;
785 } 845 }
786 846
787 err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid); 847 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
788 if (err) { 848 if (err) {
789 p9pdu_dump(1, req->rc); 849 p9pdu_dump(1, req->rc);
790 p9_free_req(clnt, req); 850 p9_free_req(clnt, req);
@@ -833,7 +893,7 @@ p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname)
833 goto error; 893 goto error;
834 } 894 }
835 895
836 err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid); 896 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
837 if (err) { 897 if (err) {
838 p9pdu_dump(1, req->rc); 898 p9pdu_dump(1, req->rc);
839 p9_free_req(clnt, req); 899 p9_free_req(clnt, req);
@@ -891,7 +951,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
891 goto error; 951 goto error;
892 } 952 }
893 953
894 err = p9pdu_readf(req->rc, clnt->dotu, "R", &nwqids, &wqids); 954 err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids);
895 if (err) { 955 if (err) {
896 p9pdu_dump(1, req->rc); 956 p9pdu_dump(1, req->rc);
897 p9_free_req(clnt, req); 957 p9_free_req(clnt, req);
@@ -952,7 +1012,7 @@ int p9_client_open(struct p9_fid *fid, int mode)
952 goto error; 1012 goto error;
953 } 1013 }
954 1014
955 err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit); 1015 err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
956 if (err) { 1016 if (err) {
957 p9pdu_dump(1, req->rc); 1017 p9pdu_dump(1, req->rc);
958 goto free_and_error; 1018 goto free_and_error;
@@ -997,7 +1057,7 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
997 goto error; 1057 goto error;
998 } 1058 }
999 1059
1000 err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit); 1060 err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
1001 if (err) { 1061 if (err) {
1002 p9pdu_dump(1, req->rc); 1062 p9pdu_dump(1, req->rc);
1003 goto free_and_error; 1063 goto free_and_error;
@@ -1098,7 +1158,7 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1098 goto error; 1158 goto error;
1099 } 1159 }
1100 1160
1101 err = p9pdu_readf(req->rc, clnt->dotu, "D", &count, &dataptr); 1161 err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
1102 if (err) { 1162 if (err) {
1103 p9pdu_dump(1, req->rc); 1163 p9pdu_dump(1, req->rc);
1104 goto free_and_error; 1164 goto free_and_error;
@@ -1159,7 +1219,7 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1159 goto error; 1219 goto error;
1160 } 1220 }
1161 1221
1162 err = p9pdu_readf(req->rc, clnt->dotu, "d", &count); 1222 err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count);
1163 if (err) { 1223 if (err) {
1164 p9pdu_dump(1, req->rc); 1224 p9pdu_dump(1, req->rc);
1165 goto free_and_error; 1225 goto free_and_error;
@@ -1199,7 +1259,7 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
1199 goto error; 1259 goto error;
1200 } 1260 }
1201 1261
1202 err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret); 1262 err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret);
1203 if (err) { 1263 if (err) {
1204 p9pdu_dump(1, req->rc); 1264 p9pdu_dump(1, req->rc);
1205 p9_free_req(clnt, req); 1265 p9_free_req(clnt, req);
@@ -1226,7 +1286,7 @@ error:
1226} 1286}
1227EXPORT_SYMBOL(p9_client_stat); 1287EXPORT_SYMBOL(p9_client_stat);
1228 1288
1229static int p9_client_statsize(struct p9_wstat *wst, int optional) 1289static int p9_client_statsize(struct p9_wstat *wst, int proto_version)
1230{ 1290{
1231 int ret; 1291 int ret;
1232 1292
@@ -1245,7 +1305,7 @@ static int p9_client_statsize(struct p9_wstat *wst, int optional)
1245 if (wst->muid) 1305 if (wst->muid)
1246 ret += strlen(wst->muid); 1306 ret += strlen(wst->muid);
1247 1307
1248 if (optional) { 1308 if (proto_version == p9_proto_2000u) {
1249 ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ 1309 ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */
1250 if (wst->extension) 1310 if (wst->extension)
1251 ret += strlen(wst->extension); 1311 ret += strlen(wst->extension);
@@ -1262,7 +1322,7 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
1262 1322
1263 err = 0; 1323 err = 0;
1264 clnt = fid->clnt; 1324 clnt = fid->clnt;
1265 wst->size = p9_client_statsize(wst, clnt->dotu); 1325 wst->size = p9_client_statsize(wst, clnt->proto_version);
1266 P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); 1326 P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
1267 P9_DPRINTK(P9_DEBUG_9P, 1327 P9_DPRINTK(P9_DEBUG_9P,
1268 " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" 1328 " sz=%x type=%x dev=%x qid=%x.%llx.%x\n"