diff options
Diffstat (limited to 'net/9p/client.c')
-rw-r--r-- | net/9p/client.c | 187 |
1 files changed, 140 insertions, 47 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 8af95b2dddd6..0aa79faa9850 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/poll.h> | 29 | #include <linux/poll.h> |
30 | #include <linux/idr.h> | 30 | #include <linux/idr.h> |
31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
32 | #include <linux/slab.h> | ||
32 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
33 | #include <linux/uaccess.h> | 34 | #include <linux/uaccess.h> |
34 | #include <net/9p/9p.h> | 35 | #include <net/9p/9p.h> |
@@ -46,6 +47,7 @@ enum { | |||
46 | Opt_msize, | 47 | Opt_msize, |
47 | Opt_trans, | 48 | Opt_trans, |
48 | Opt_legacy, | 49 | Opt_legacy, |
50 | Opt_version, | ||
49 | Opt_err, | 51 | Opt_err, |
50 | }; | 52 | }; |
51 | 53 | ||
@@ -53,9 +55,43 @@ static const match_table_t tokens = { | |||
53 | {Opt_msize, "msize=%u"}, | 55 | {Opt_msize, "msize=%u"}, |
54 | {Opt_legacy, "noextend"}, | 56 | {Opt_legacy, "noextend"}, |
55 | {Opt_trans, "trans=%s"}, | 57 | {Opt_trans, "trans=%s"}, |
58 | {Opt_version, "version=%s"}, | ||
56 | {Opt_err, NULL}, | 59 | {Opt_err, NULL}, |
57 | }; | 60 | }; |
58 | 61 | ||
62 | inline int p9_is_proto_dotl(struct p9_client *clnt) | ||
63 | { | ||
64 | return (clnt->proto_version == p9_proto_2000L); | ||
65 | } | ||
66 | EXPORT_SYMBOL(p9_is_proto_dotl); | ||
67 | |||
68 | inline int p9_is_proto_dotu(struct p9_client *clnt) | ||
69 | { | ||
70 | return (clnt->proto_version == p9_proto_2000u); | ||
71 | } | ||
72 | EXPORT_SYMBOL(p9_is_proto_dotu); | ||
73 | |||
74 | /* Interpret mount option for protocol version */ | ||
75 | static int get_protocol_version(const substring_t *name) | ||
76 | { | ||
77 | int version = -EINVAL; | ||
78 | |||
79 | if (!strncmp("9p2000", name->from, name->to-name->from)) { | ||
80 | version = p9_proto_legacy; | ||
81 | P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n"); | ||
82 | } else if (!strncmp("9p2000.u", name->from, name->to-name->from)) { | ||
83 | version = p9_proto_2000u; | ||
84 | P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n"); | ||
85 | } else if (!strncmp("9p2000.L", name->from, name->to-name->from)) { | ||
86 | version = p9_proto_2000L; | ||
87 | P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.L\n"); | ||
88 | } else { | ||
89 | P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ", | ||
90 | name->from); | ||
91 | } | ||
92 | return version; | ||
93 | } | ||
94 | |||
59 | static struct p9_req_t * | 95 | static struct p9_req_t * |
60 | p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); | 96 | p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); |
61 | 97 | ||
@@ -69,24 +105,25 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); | |||
69 | 105 | ||
70 | static int parse_opts(char *opts, struct p9_client *clnt) | 106 | static int parse_opts(char *opts, struct p9_client *clnt) |
71 | { | 107 | { |
72 | char *options; | 108 | char *options, *tmp_options; |
73 | char *p; | 109 | char *p; |
74 | substring_t args[MAX_OPT_ARGS]; | 110 | substring_t args[MAX_OPT_ARGS]; |
75 | int option; | 111 | int option; |
76 | int ret = 0; | 112 | int ret = 0; |
77 | 113 | ||
78 | clnt->dotu = 1; | 114 | clnt->proto_version = p9_proto_2000u; |
79 | clnt->msize = 8192; | 115 | clnt->msize = 8192; |
80 | 116 | ||
81 | if (!opts) | 117 | if (!opts) |
82 | return 0; | 118 | return 0; |
83 | 119 | ||
84 | options = kstrdup(opts, GFP_KERNEL); | 120 | tmp_options = kstrdup(opts, GFP_KERNEL); |
85 | if (!options) { | 121 | if (!tmp_options) { |
86 | P9_DPRINTK(P9_DEBUG_ERROR, | 122 | P9_DPRINTK(P9_DEBUG_ERROR, |
87 | "failed to allocate copy of option string\n"); | 123 | "failed to allocate copy of option string\n"); |
88 | return -ENOMEM; | 124 | return -ENOMEM; |
89 | } | 125 | } |
126 | options = tmp_options; | ||
90 | 127 | ||
91 | while ((p = strsep(&options, ",")) != NULL) { | 128 | while ((p = strsep(&options, ",")) != NULL) { |
92 | int token; | 129 | int token; |
@@ -108,16 +145,30 @@ static int parse_opts(char *opts, struct p9_client *clnt) | |||
108 | break; | 145 | break; |
109 | case Opt_trans: | 146 | case Opt_trans: |
110 | clnt->trans_mod = v9fs_get_trans_by_name(&args[0]); | 147 | clnt->trans_mod = v9fs_get_trans_by_name(&args[0]); |
148 | if(clnt->trans_mod == NULL) { | ||
149 | P9_DPRINTK(P9_DEBUG_ERROR, | ||
150 | "Could not find request transport: %s\n", | ||
151 | (char *) &args[0]); | ||
152 | ret = -EINVAL; | ||
153 | goto free_and_return; | ||
154 | } | ||
111 | break; | 155 | break; |
112 | case Opt_legacy: | 156 | case Opt_legacy: |
113 | clnt->dotu = 0; | 157 | clnt->proto_version = p9_proto_legacy; |
158 | break; | ||
159 | case Opt_version: | ||
160 | ret = get_protocol_version(&args[0]); | ||
161 | if (ret == -EINVAL) | ||
162 | goto free_and_return; | ||
163 | clnt->proto_version = ret; | ||
114 | break; | 164 | break; |
115 | default: | 165 | default: |
116 | continue; | 166 | continue; |
117 | } | 167 | } |
118 | } | 168 | } |
119 | 169 | ||
120 | kfree(options); | 170 | free_and_return: |
171 | kfree(tmp_options); | ||
121 | return ret; | 172 | return ret; |
122 | } | 173 | } |
123 | 174 | ||
@@ -401,14 +452,15 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) | |||
401 | int ecode; | 452 | int ecode; |
402 | char *ename; | 453 | char *ename; |
403 | 454 | ||
404 | err = p9pdu_readf(req->rc, c->dotu, "s?d", &ename, &ecode); | 455 | err = p9pdu_readf(req->rc, c->proto_version, "s?d", |
456 | &ename, &ecode); | ||
405 | if (err) { | 457 | if (err) { |
406 | P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", | 458 | P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", |
407 | err); | 459 | err); |
408 | return err; | 460 | return err; |
409 | } | 461 | } |
410 | 462 | ||
411 | if (c->dotu) | 463 | if (p9_is_proto_dotu(c)) |
412 | err = -ecode; | 464 | err = -ecode; |
413 | 465 | ||
414 | if (!err || !IS_ERR_VALUE(err)) | 466 | if (!err || !IS_ERR_VALUE(err)) |
@@ -483,7 +535,12 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
483 | 535 | ||
484 | P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); | 536 | P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); |
485 | 537 | ||
486 | if (c->status != Connected) | 538 | /* we allow for any status other than disconnected */ |
539 | if (c->status == Disconnected) | ||
540 | return ERR_PTR(-EIO); | ||
541 | |||
542 | /* if status is begin_disconnected we allow only clunk request */ | ||
543 | if ((c->status == BeginDisconnect) && (type != P9_TCLUNK)) | ||
487 | return ERR_PTR(-EIO); | 544 | return ERR_PTR(-EIO); |
488 | 545 | ||
489 | if (signal_pending(current)) { | 546 | if (signal_pending(current)) { |
@@ -506,7 +563,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
506 | /* marshall the data */ | 563 | /* marshall the data */ |
507 | p9pdu_prepare(req->tc, tag, type); | 564 | p9pdu_prepare(req->tc, tag, type); |
508 | va_start(ap, fmt); | 565 | va_start(ap, fmt); |
509 | err = p9pdu_vwritef(req->tc, c->dotu, fmt, ap); | 566 | err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); |
510 | va_end(ap); | 567 | va_end(ap); |
511 | p9pdu_finalize(req->tc); | 568 | p9pdu_finalize(req->tc); |
512 | 569 | ||
@@ -618,14 +675,31 @@ int p9_client_version(struct p9_client *c) | |||
618 | char *version; | 675 | char *version; |
619 | int msize; | 676 | int msize; |
620 | 677 | ||
621 | P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d extended %d\n", | 678 | P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n", |
622 | c->msize, c->dotu); | 679 | c->msize, c->proto_version); |
623 | req = p9_client_rpc(c, P9_TVERSION, "ds", c->msize, | 680 | |
624 | c->dotu ? "9P2000.u" : "9P2000"); | 681 | switch (c->proto_version) { |
682 | case p9_proto_2000L: | ||
683 | req = p9_client_rpc(c, P9_TVERSION, "ds", | ||
684 | c->msize, "9P2000.L"); | ||
685 | break; | ||
686 | case p9_proto_2000u: | ||
687 | req = p9_client_rpc(c, P9_TVERSION, "ds", | ||
688 | c->msize, "9P2000.u"); | ||
689 | break; | ||
690 | case p9_proto_legacy: | ||
691 | req = p9_client_rpc(c, P9_TVERSION, "ds", | ||
692 | c->msize, "9P2000"); | ||
693 | break; | ||
694 | default: | ||
695 | return -EINVAL; | ||
696 | break; | ||
697 | } | ||
698 | |||
625 | if (IS_ERR(req)) | 699 | if (IS_ERR(req)) |
626 | return PTR_ERR(req); | 700 | return PTR_ERR(req); |
627 | 701 | ||
628 | err = p9pdu_readf(req->rc, c->dotu, "ds", &msize, &version); | 702 | err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version); |
629 | if (err) { | 703 | if (err) { |
630 | P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err); | 704 | P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err); |
631 | p9pdu_dump(1, req->rc); | 705 | p9pdu_dump(1, req->rc); |
@@ -633,10 +707,12 @@ int p9_client_version(struct p9_client *c) | |||
633 | } | 707 | } |
634 | 708 | ||
635 | P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); | 709 | P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); |
636 | if (!memcmp(version, "9P2000.u", 8)) | 710 | if (!strncmp(version, "9P2000.L", 8)) |
637 | c->dotu = 1; | 711 | c->proto_version = p9_proto_2000L; |
638 | else if (!memcmp(version, "9P2000", 6)) | 712 | else if (!strncmp(version, "9P2000.u", 8)) |
639 | c->dotu = 0; | 713 | c->proto_version = p9_proto_2000u; |
714 | else if (!strncmp(version, "9P2000", 6)) | ||
715 | c->proto_version = p9_proto_legacy; | ||
640 | else { | 716 | else { |
641 | err = -EREMOTEIO; | 717 | err = -EREMOTEIO; |
642 | goto error; | 718 | goto error; |
@@ -667,18 +743,12 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
667 | clnt->trans = NULL; | 743 | clnt->trans = NULL; |
668 | spin_lock_init(&clnt->lock); | 744 | spin_lock_init(&clnt->lock); |
669 | INIT_LIST_HEAD(&clnt->fidlist); | 745 | INIT_LIST_HEAD(&clnt->fidlist); |
670 | clnt->fidpool = p9_idpool_create(); | ||
671 | if (IS_ERR(clnt->fidpool)) { | ||
672 | err = PTR_ERR(clnt->fidpool); | ||
673 | clnt->fidpool = NULL; | ||
674 | goto error; | ||
675 | } | ||
676 | 746 | ||
677 | p9_tag_init(clnt); | 747 | p9_tag_init(clnt); |
678 | 748 | ||
679 | err = parse_opts(options, clnt); | 749 | err = parse_opts(options, clnt); |
680 | if (err < 0) | 750 | if (err < 0) |
681 | goto error; | 751 | goto free_client; |
682 | 752 | ||
683 | if (!clnt->trans_mod) | 753 | if (!clnt->trans_mod) |
684 | clnt->trans_mod = v9fs_get_default_trans(); | 754 | clnt->trans_mod = v9fs_get_default_trans(); |
@@ -687,27 +757,40 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
687 | err = -EPROTONOSUPPORT; | 757 | err = -EPROTONOSUPPORT; |
688 | P9_DPRINTK(P9_DEBUG_ERROR, | 758 | P9_DPRINTK(P9_DEBUG_ERROR, |
689 | "No transport defined or default transport\n"); | 759 | "No transport defined or default transport\n"); |
690 | goto error; | 760 | goto free_client; |
761 | } | ||
762 | |||
763 | clnt->fidpool = p9_idpool_create(); | ||
764 | if (IS_ERR(clnt->fidpool)) { | ||
765 | err = PTR_ERR(clnt->fidpool); | ||
766 | clnt->fidpool = NULL; | ||
767 | goto put_trans; | ||
691 | } | 768 | } |
692 | 769 | ||
693 | P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n", | 770 | P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n", |
694 | clnt, clnt->trans_mod, clnt->msize, clnt->dotu); | 771 | clnt, clnt->trans_mod, clnt->msize, clnt->proto_version); |
695 | 772 | ||
696 | err = clnt->trans_mod->create(clnt, dev_name, options); | 773 | err = clnt->trans_mod->create(clnt, dev_name, options); |
697 | if (err) | 774 | if (err) |
698 | goto error; | 775 | goto destroy_fidpool; |
699 | 776 | ||
700 | if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize) | 777 | if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize) |
701 | clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ; | 778 | clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ; |
702 | 779 | ||
703 | err = p9_client_version(clnt); | 780 | err = p9_client_version(clnt); |
704 | if (err) | 781 | if (err) |
705 | goto error; | 782 | goto close_trans; |
706 | 783 | ||
707 | return clnt; | 784 | return clnt; |
708 | 785 | ||
709 | error: | 786 | close_trans: |
710 | p9_client_destroy(clnt); | 787 | clnt->trans_mod->close(clnt); |
788 | destroy_fidpool: | ||
789 | p9_idpool_destroy(clnt->fidpool); | ||
790 | put_trans: | ||
791 | v9fs_put_trans(clnt->trans_mod); | ||
792 | free_client: | ||
793 | kfree(clnt); | ||
711 | return ERR_PTR(err); | 794 | return ERR_PTR(err); |
712 | } | 795 | } |
713 | EXPORT_SYMBOL(p9_client_create); | 796 | EXPORT_SYMBOL(p9_client_create); |
@@ -723,8 +806,10 @@ void p9_client_destroy(struct p9_client *clnt) | |||
723 | 806 | ||
724 | v9fs_put_trans(clnt->trans_mod); | 807 | v9fs_put_trans(clnt->trans_mod); |
725 | 808 | ||
726 | list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) | 809 | list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) { |
810 | printk(KERN_INFO "Found fid %d not clunked\n", fid->fid); | ||
727 | p9_fid_destroy(fid); | 811 | p9_fid_destroy(fid); |
812 | } | ||
728 | 813 | ||
729 | if (clnt->fidpool) | 814 | if (clnt->fidpool) |
730 | p9_idpool_destroy(clnt->fidpool); | 815 | p9_idpool_destroy(clnt->fidpool); |
@@ -742,6 +827,13 @@ void p9_client_disconnect(struct p9_client *clnt) | |||
742 | } | 827 | } |
743 | EXPORT_SYMBOL(p9_client_disconnect); | 828 | EXPORT_SYMBOL(p9_client_disconnect); |
744 | 829 | ||
830 | void p9_client_begin_disconnect(struct p9_client *clnt) | ||
831 | { | ||
832 | P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); | ||
833 | clnt->status = BeginDisconnect; | ||
834 | } | ||
835 | EXPORT_SYMBOL(p9_client_begin_disconnect); | ||
836 | |||
745 | struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, | 837 | struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, |
746 | char *uname, u32 n_uname, char *aname) | 838 | char *uname, u32 n_uname, char *aname) |
747 | { | 839 | { |
@@ -768,7 +860,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, | |||
768 | goto error; | 860 | goto error; |
769 | } | 861 | } |
770 | 862 | ||
771 | err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid); | 863 | err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); |
772 | if (err) { | 864 | if (err) { |
773 | p9pdu_dump(1, req->rc); | 865 | p9pdu_dump(1, req->rc); |
774 | p9_free_req(clnt, req); | 866 | p9_free_req(clnt, req); |
@@ -817,7 +909,7 @@ p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname) | |||
817 | goto error; | 909 | goto error; |
818 | } | 910 | } |
819 | 911 | ||
820 | err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid); | 912 | err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); |
821 | if (err) { | 913 | if (err) { |
822 | p9pdu_dump(1, req->rc); | 914 | p9pdu_dump(1, req->rc); |
823 | p9_free_req(clnt, req); | 915 | p9_free_req(clnt, req); |
@@ -875,7 +967,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | |||
875 | goto error; | 967 | goto error; |
876 | } | 968 | } |
877 | 969 | ||
878 | err = p9pdu_readf(req->rc, clnt->dotu, "R", &nwqids, &wqids); | 970 | err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids); |
879 | if (err) { | 971 | if (err) { |
880 | p9pdu_dump(1, req->rc); | 972 | p9pdu_dump(1, req->rc); |
881 | p9_free_req(clnt, req); | 973 | p9_free_req(clnt, req); |
@@ -936,7 +1028,7 @@ int p9_client_open(struct p9_fid *fid, int mode) | |||
936 | goto error; | 1028 | goto error; |
937 | } | 1029 | } |
938 | 1030 | ||
939 | err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit); | 1031 | err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); |
940 | if (err) { | 1032 | if (err) { |
941 | p9pdu_dump(1, req->rc); | 1033 | p9pdu_dump(1, req->rc); |
942 | goto free_and_error; | 1034 | goto free_and_error; |
@@ -981,7 +1073,7 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, | |||
981 | goto error; | 1073 | goto error; |
982 | } | 1074 | } |
983 | 1075 | ||
984 | err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit); | 1076 | err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); |
985 | if (err) { | 1077 | if (err) { |
986 | p9pdu_dump(1, req->rc); | 1078 | p9pdu_dump(1, req->rc); |
987 | goto free_and_error; | 1079 | goto free_and_error; |
@@ -1082,7 +1174,7 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, | |||
1082 | goto error; | 1174 | goto error; |
1083 | } | 1175 | } |
1084 | 1176 | ||
1085 | err = p9pdu_readf(req->rc, clnt->dotu, "D", &count, &dataptr); | 1177 | err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); |
1086 | if (err) { | 1178 | if (err) { |
1087 | p9pdu_dump(1, req->rc); | 1179 | p9pdu_dump(1, req->rc); |
1088 | goto free_and_error; | 1180 | goto free_and_error; |
@@ -1143,7 +1235,7 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, | |||
1143 | goto error; | 1235 | goto error; |
1144 | } | 1236 | } |
1145 | 1237 | ||
1146 | err = p9pdu_readf(req->rc, clnt->dotu, "d", &count); | 1238 | err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count); |
1147 | if (err) { | 1239 | if (err) { |
1148 | p9pdu_dump(1, req->rc); | 1240 | p9pdu_dump(1, req->rc); |
1149 | goto free_and_error; | 1241 | goto free_and_error; |
@@ -1183,7 +1275,7 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) | |||
1183 | goto error; | 1275 | goto error; |
1184 | } | 1276 | } |
1185 | 1277 | ||
1186 | err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret); | 1278 | err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret); |
1187 | if (err) { | 1279 | if (err) { |
1188 | p9pdu_dump(1, req->rc); | 1280 | p9pdu_dump(1, req->rc); |
1189 | p9_free_req(clnt, req); | 1281 | p9_free_req(clnt, req); |
@@ -1210,14 +1302,15 @@ error: | |||
1210 | } | 1302 | } |
1211 | EXPORT_SYMBOL(p9_client_stat); | 1303 | EXPORT_SYMBOL(p9_client_stat); |
1212 | 1304 | ||
1213 | static int p9_client_statsize(struct p9_wstat *wst, int optional) | 1305 | static int p9_client_statsize(struct p9_wstat *wst, int proto_version) |
1214 | { | 1306 | { |
1215 | int ret; | 1307 | int ret; |
1216 | 1308 | ||
1309 | /* NOTE: size shouldn't include its own length */ | ||
1217 | /* size[2] type[2] dev[4] qid[13] */ | 1310 | /* size[2] type[2] dev[4] qid[13] */ |
1218 | /* mode[4] atime[4] mtime[4] length[8]*/ | 1311 | /* mode[4] atime[4] mtime[4] length[8]*/ |
1219 | /* name[s] uid[s] gid[s] muid[s] */ | 1312 | /* name[s] uid[s] gid[s] muid[s] */ |
1220 | ret = 2+2+4+13+4+4+4+8+2+2+2+2; | 1313 | ret = 2+4+13+4+4+4+8+2+2+2+2; |
1221 | 1314 | ||
1222 | if (wst->name) | 1315 | if (wst->name) |
1223 | ret += strlen(wst->name); | 1316 | ret += strlen(wst->name); |
@@ -1228,7 +1321,7 @@ static int p9_client_statsize(struct p9_wstat *wst, int optional) | |||
1228 | if (wst->muid) | 1321 | if (wst->muid) |
1229 | ret += strlen(wst->muid); | 1322 | ret += strlen(wst->muid); |
1230 | 1323 | ||
1231 | if (optional) { | 1324 | if (proto_version == p9_proto_2000u) { |
1232 | ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ | 1325 | ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ |
1233 | if (wst->extension) | 1326 | if (wst->extension) |
1234 | ret += strlen(wst->extension); | 1327 | ret += strlen(wst->extension); |
@@ -1245,7 +1338,7 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) | |||
1245 | 1338 | ||
1246 | err = 0; | 1339 | err = 0; |
1247 | clnt = fid->clnt; | 1340 | clnt = fid->clnt; |
1248 | wst->size = p9_client_statsize(wst, clnt->dotu); | 1341 | wst->size = p9_client_statsize(wst, clnt->proto_version); |
1249 | P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); | 1342 | P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); |
1250 | P9_DPRINTK(P9_DEBUG_9P, | 1343 | P9_DPRINTK(P9_DEBUG_9P, |
1251 | " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" | 1344 | " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" |
@@ -1258,7 +1351,7 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) | |||
1258 | wst->name, wst->uid, wst->gid, wst->muid, wst->extension, | 1351 | wst->name, wst->uid, wst->gid, wst->muid, wst->extension, |
1259 | wst->n_uid, wst->n_gid, wst->n_muid); | 1352 | wst->n_uid, wst->n_gid, wst->n_muid); |
1260 | 1353 | ||
1261 | req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size, wst); | 1354 | req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst); |
1262 | if (IS_ERR(req)) { | 1355 | if (IS_ERR(req)) { |
1263 | err = PTR_ERR(req); | 1356 | err = PTR_ERR(req); |
1264 | goto error; | 1357 | goto error; |