diff options
Diffstat (limited to 'net/9p/trans_fd.c')
-rw-r--r-- | net/9p/trans_fd.c | 268 |
1 files changed, 36 insertions, 232 deletions
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 627e3f097fc5..6bfc013f8b6f 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
@@ -174,44 +174,6 @@ static void p9_mux_poll_stop(struct p9_conn *m) | |||
174 | spin_unlock_irqrestore(&p9_poll_lock, flags); | 174 | spin_unlock_irqrestore(&p9_poll_lock, flags); |
175 | } | 175 | } |
176 | 176 | ||
177 | static void p9_conn_rpc_cb(struct p9_client *, struct p9_req_t *); | ||
178 | |||
179 | static void p9_mux_flush_cb(struct p9_client *client, struct p9_req_t *freq) | ||
180 | { | ||
181 | struct p9_conn *m = client->trans; | ||
182 | struct p9_req_t *req; | ||
183 | |||
184 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, | ||
185 | freq->tc, freq->rc, freq->t_err, | ||
186 | freq->tc->params.tflush.oldtag); | ||
187 | |||
188 | req = p9_tag_lookup(client, freq->tc->params.tflush.oldtag); | ||
189 | if (req) { | ||
190 | req->status = REQ_STATUS_FLSHD; | ||
191 | list_del(&req->req_list); | ||
192 | p9_conn_rpc_cb(client, req); | ||
193 | } | ||
194 | |||
195 | p9_free_req(client, freq); | ||
196 | } | ||
197 | |||
198 | static void p9_conn_rpc_cb(struct p9_client *client, struct p9_req_t *req) | ||
199 | { | ||
200 | P9_DPRINTK(P9_DEBUG_MUX, "req %p\n", req); | ||
201 | |||
202 | if (req->tc->id == P9_TFLUSH) { /* flush callback */ | ||
203 | P9_DPRINTK(P9_DEBUG_MUX, "flush req %p\n", req); | ||
204 | p9_mux_flush_cb(client, req); | ||
205 | } else { /* normal wakeup path */ | ||
206 | P9_DPRINTK(P9_DEBUG_MUX, "normal req %p\n", req); | ||
207 | if (!req->t_err && (req->status == REQ_STATUS_FLSHD || | ||
208 | req->status == REQ_STATUS_FLSH)) | ||
209 | req->t_err = -ERESTARTSYS; | ||
210 | |||
211 | wake_up(req->wq); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | /** | 177 | /** |
216 | * p9_conn_cancel - cancel all pending requests with error | 178 | * p9_conn_cancel - cancel all pending requests with error |
217 | * @m: mux data | 179 | * @m: mux data |
@@ -222,11 +184,12 @@ static void p9_conn_rpc_cb(struct p9_client *client, struct p9_req_t *req) | |||
222 | void p9_conn_cancel(struct p9_conn *m, int err) | 184 | void p9_conn_cancel(struct p9_conn *m, int err) |
223 | { | 185 | { |
224 | struct p9_req_t *req, *rtmp; | 186 | struct p9_req_t *req, *rtmp; |
187 | unsigned long flags; | ||
225 | LIST_HEAD(cancel_list); | 188 | LIST_HEAD(cancel_list); |
226 | 189 | ||
227 | P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err); | 190 | P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err); |
228 | m->err = err; | 191 | m->err = err; |
229 | spin_lock(&m->client->lock); | 192 | spin_lock_irqsave(&m->client->lock, flags); |
230 | list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { | 193 | list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { |
231 | req->status = REQ_STATUS_ERROR; | 194 | req->status = REQ_STATUS_ERROR; |
232 | if (!req->t_err) | 195 | if (!req->t_err) |
@@ -239,44 +202,12 @@ void p9_conn_cancel(struct p9_conn *m, int err) | |||
239 | req->t_err = err; | 202 | req->t_err = err; |
240 | list_move(&req->req_list, &cancel_list); | 203 | list_move(&req->req_list, &cancel_list); |
241 | } | 204 | } |
242 | spin_unlock(&m->client->lock); | 205 | spin_unlock_irqrestore(&m->client->lock, flags); |
243 | 206 | ||
244 | list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { | 207 | list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { |
245 | list_del(&req->req_list); | 208 | list_del(&req->req_list); |
246 | p9_conn_rpc_cb(m->client, req); | 209 | P9_DPRINTK(P9_DEBUG_ERROR, "call back req %p\n", req); |
247 | } | 210 | p9_client_cb(m->client, req); |
248 | } | ||
249 | |||
250 | static void process_request(struct p9_conn *m, struct p9_req_t *req) | ||
251 | { | ||
252 | int ecode; | ||
253 | struct p9_str *ename; | ||
254 | |||
255 | if (!req->t_err && req->rc->id == P9_RERROR) { | ||
256 | ecode = req->rc->params.rerror.errno; | ||
257 | ename = &req->rc->params.rerror.error; | ||
258 | |||
259 | P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len, | ||
260 | ename->str); | ||
261 | |||
262 | if (m->client->dotu) | ||
263 | req->t_err = -ecode; | ||
264 | |||
265 | if (!req->t_err) { | ||
266 | req->t_err = p9_errstr2errno(ename->str, ename->len); | ||
267 | |||
268 | /* string match failed */ | ||
269 | if (!req->t_err) { | ||
270 | PRINT_FCALL_ERROR("unknown error", req->rc); | ||
271 | req->t_err = -ESERVERFAULT; | ||
272 | } | ||
273 | } | ||
274 | } else if (req->tc && req->rc->id != req->tc->id + 1) { | ||
275 | P9_DPRINTK(P9_DEBUG_ERROR, | ||
276 | "fcall mismatch: expected %d, got %d\n", | ||
277 | req->tc->id + 1, req->rc->id); | ||
278 | if (!req->t_err) | ||
279 | req->t_err = -EIO; | ||
280 | } | 211 | } |
281 | } | 212 | } |
282 | 213 | ||
@@ -421,41 +352,13 @@ static void p9_read_work(struct work_struct *work) | |||
421 | /* not an else because some packets (like clunk) have no payload */ | 352 | /* not an else because some packets (like clunk) have no payload */ |
422 | if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ | 353 | if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ |
423 | P9_DPRINTK(P9_DEBUG_MUX, "got new packet\n"); | 354 | P9_DPRINTK(P9_DEBUG_MUX, "got new packet\n"); |
424 | m->rbuf = (char *)m->req->rc + sizeof(struct p9_fcall); | ||
425 | err = p9_deserialize_fcall(m->rbuf, m->rsize, m->req->rc, | ||
426 | m->client->dotu); | ||
427 | if (err < 0) { | ||
428 | m->req = NULL; | ||
429 | goto error; | ||
430 | } | ||
431 | |||
432 | #ifdef CONFIG_NET_9P_DEBUG | ||
433 | if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { | ||
434 | char buf[150]; | ||
435 | |||
436 | p9_printfcall(buf, sizeof(buf), m->req->rc, | ||
437 | m->client->dotu); | ||
438 | printk(KERN_NOTICE ">>> %p %s\n", m, buf); | ||
439 | } | ||
440 | #endif | ||
441 | 355 | ||
442 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, | 356 | list_del(&m->req->req_list); |
443 | m->req->rc->id, m->req->rc->tag); | 357 | p9_client_cb(m->client, m->req); |
444 | 358 | ||
445 | m->rbuf = NULL; | 359 | m->rbuf = NULL; |
446 | m->rpos = 0; | 360 | m->rpos = 0; |
447 | m->rsize = 0; | 361 | m->rsize = 0; |
448 | |||
449 | if (m->req->status != REQ_STATUS_FLSH) { | ||
450 | list_del(&m->req->req_list); | ||
451 | m->req->status = REQ_STATUS_RCVD; | ||
452 | } | ||
453 | |||
454 | process_request(m, m->req); | ||
455 | |||
456 | if (m->req->status != REQ_STATUS_FLSH) | ||
457 | p9_conn_rpc_cb(m->client, m->req); | ||
458 | |||
459 | m->req = NULL; | 362 | m->req = NULL; |
460 | } | 363 | } |
461 | 364 | ||
@@ -741,57 +644,41 @@ static void p9_poll_mux(struct p9_conn *m) | |||
741 | } | 644 | } |
742 | 645 | ||
743 | /** | 646 | /** |
744 | * p9_send_request - send 9P request | 647 | * p9_fd_request - send 9P request |
745 | * The function can sleep until the request is scheduled for sending. | 648 | * The function can sleep until the request is scheduled for sending. |
746 | * The function can be interrupted. Return from the function is not | 649 | * The function can be interrupted. Return from the function is not |
747 | * a guarantee that the request is sent successfully. Can return errors | 650 | * a guarantee that the request is sent successfully. |
748 | * that can be retrieved by PTR_ERR macros. | ||
749 | * | 651 | * |
750 | * @m: mux data | 652 | * @client: client instance |
751 | * @tc: request to be sent | 653 | * @req: request to be sent |
752 | * | 654 | * |
753 | */ | 655 | */ |
754 | 656 | ||
755 | static struct p9_req_t *p9_send_request(struct p9_conn *m, struct p9_fcall *tc) | 657 | static int p9_fd_request(struct p9_client *client, struct p9_req_t *req) |
756 | { | 658 | { |
757 | int tag; | ||
758 | int n; | 659 | int n; |
759 | struct p9_req_t *req; | 660 | struct p9_trans_fd *ts = client->trans; |
661 | struct p9_conn *m = ts->conn; | ||
760 | 662 | ||
761 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current, | 663 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current, |
762 | tc, tc->id); | 664 | req->tc, req->tc->id); |
763 | if (m->err < 0) | 665 | if (m->err < 0) |
764 | return ERR_PTR(m->err); | 666 | return m->err; |
765 | |||
766 | tag = P9_NOTAG; | ||
767 | if (tc->id != P9_TVERSION) { | ||
768 | tag = p9_idpool_get(m->client->tagpool); | ||
769 | if (tag < 0) | ||
770 | return ERR_PTR(-ENOMEM); | ||
771 | } | ||
772 | |||
773 | p9_set_tag(tc, tag); | ||
774 | |||
775 | req = p9_tag_alloc(m->client, tag); | ||
776 | 667 | ||
777 | #ifdef CONFIG_NET_9P_DEBUG | 668 | #ifdef CONFIG_NET_9P_DEBUG |
778 | if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { | 669 | if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { |
779 | char buf[150]; | 670 | char buf[150]; |
780 | 671 | ||
781 | p9_printfcall(buf, sizeof(buf), tc, m->client->dotu); | 672 | p9_printfcall(buf, sizeof(buf), req->tc, client->dotu); |
782 | printk(KERN_NOTICE "<<< %p %s\n", m, buf); | 673 | printk(KERN_NOTICE "<<< %p %s\n", m, buf); |
783 | } | 674 | } |
784 | #endif | 675 | #endif |
785 | 676 | ||
786 | req->tag = tag; | ||
787 | req->tc = tc; | ||
788 | req->rc = NULL; | ||
789 | req->t_err = 0; | ||
790 | req->status = REQ_STATUS_UNSENT; | 677 | req->status = REQ_STATUS_UNSENT; |
791 | 678 | ||
792 | spin_lock(&m->client->lock); | 679 | spin_lock(&client->lock); |
793 | list_add_tail(&req->req_list, &m->unsent_req_list); | 680 | list_add_tail(&req->req_list, &m->unsent_req_list); |
794 | spin_unlock(&m->client->lock); | 681 | spin_unlock(&client->lock); |
795 | 682 | ||
796 | if (test_and_clear_bit(Wpending, &m->wsched)) | 683 | if (test_and_clear_bit(Wpending, &m->wsched)) |
797 | n = POLLOUT; | 684 | n = POLLOUT; |
@@ -801,17 +688,20 @@ static struct p9_req_t *p9_send_request(struct p9_conn *m, struct p9_fcall *tc) | |||
801 | if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched)) | 688 | if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched)) |
802 | queue_work(p9_mux_wq, &m->wq); | 689 | queue_work(p9_mux_wq, &m->wq); |
803 | 690 | ||
804 | return req; | 691 | return 0; |
805 | } | 692 | } |
806 | 693 | ||
807 | static int | 694 | static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) |
808 | p9_mux_flush_request(struct p9_conn *m, struct p9_req_t *req) | ||
809 | { | 695 | { |
810 | struct p9_fcall *fc; | 696 | struct p9_trans_fd *ts = client->trans; |
811 | struct p9_req_t *rreq, *rptr; | 697 | struct p9_conn *m = ts->conn; |
812 | 698 | ||
813 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); | 699 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); |
814 | 700 | ||
701 | spin_lock(&client->lock); | ||
702 | list_del(&req->req_list); | ||
703 | spin_unlock(&client->lock); | ||
704 | |||
815 | /* if a response was received for a request, do nothing */ | 705 | /* if a response was received for a request, do nothing */ |
816 | if (req->rc || req->t_err) { | 706 | if (req->rc || req->t_err) { |
817 | P9_DPRINTK(P9_DEBUG_MUX, | 707 | P9_DPRINTK(P9_DEBUG_MUX, |
@@ -819,104 +709,15 @@ p9_mux_flush_request(struct p9_conn *m, struct p9_req_t *req) | |||
819 | return 0; | 709 | return 0; |
820 | } | 710 | } |
821 | 711 | ||
822 | req->status = REQ_STATUS_FLSH; | 712 | if (req->status == REQ_STATUS_UNSENT) { |
823 | 713 | req->status = REQ_STATUS_FLSHD; | |
824 | spin_lock(&m->client->lock); | 714 | return 0; |
825 | /* if the request is not sent yet, just remove it from the list */ | ||
826 | list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) { | ||
827 | if (rreq->tag == req->tag) { | ||
828 | P9_DPRINTK(P9_DEBUG_MUX, | ||
829 | "mux %p req %p request is not sent yet\n", m, req); | ||
830 | list_del(&rreq->req_list); | ||
831 | req->status = REQ_STATUS_FLSHD; | ||
832 | spin_unlock(&m->client->lock); | ||
833 | p9_conn_rpc_cb(m->client, req); | ||
834 | return 0; | ||
835 | } | ||
836 | } | 715 | } |
837 | spin_unlock(&m->client->lock); | ||
838 | 716 | ||
839 | clear_thread_flag(TIF_SIGPENDING); | ||
840 | fc = p9_create_tflush(req->tag); | ||
841 | p9_send_request(m, fc); | ||
842 | return 1; | 717 | return 1; |
843 | } | 718 | } |
844 | 719 | ||
845 | /** | 720 | /** |
846 | * p9_fd_rpc- sends 9P request and waits until a response is available. | ||
847 | * The function can be interrupted. | ||
848 | * @client: client instance | ||
849 | * @tc: request to be sent | ||
850 | * @rc: pointer where a pointer to the response is stored | ||
851 | * | ||
852 | */ | ||
853 | |||
854 | int | ||
855 | p9_fd_rpc(struct p9_client *client, struct p9_fcall *tc, struct p9_fcall **rc) | ||
856 | { | ||
857 | struct p9_trans_fd *p = client->trans; | ||
858 | struct p9_conn *m = p->conn; | ||
859 | int err, sigpending; | ||
860 | unsigned long flags; | ||
861 | struct p9_req_t *req; | ||
862 | |||
863 | if (rc) | ||
864 | *rc = NULL; | ||
865 | |||
866 | sigpending = 0; | ||
867 | if (signal_pending(current)) { | ||
868 | sigpending = 1; | ||
869 | clear_thread_flag(TIF_SIGPENDING); | ||
870 | } | ||
871 | |||
872 | req = p9_send_request(m, tc); | ||
873 | if (IS_ERR(req)) { | ||
874 | err = PTR_ERR(req); | ||
875 | P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err); | ||
876 | return err; | ||
877 | } | ||
878 | |||
879 | err = wait_event_interruptible(*req->wq, req->rc != NULL || | ||
880 | req->t_err < 0); | ||
881 | if (req->t_err < 0) | ||
882 | err = req->t_err; | ||
883 | |||
884 | if (err == -ERESTARTSYS && client->status == Connected | ||
885 | && m->err == 0) { | ||
886 | if (p9_mux_flush_request(m, req)) { | ||
887 | /* wait until we get response of the flush message */ | ||
888 | do { | ||
889 | clear_thread_flag(TIF_SIGPENDING); | ||
890 | err = wait_event_interruptible(*req->wq, | ||
891 | req->rc || req->t_err); | ||
892 | } while (!req->rc && !req->t_err && | ||
893 | err == -ERESTARTSYS && | ||
894 | client->status == Connected && !m->err); | ||
895 | |||
896 | err = -ERESTARTSYS; | ||
897 | } | ||
898 | sigpending = 1; | ||
899 | } | ||
900 | |||
901 | if (sigpending) { | ||
902 | spin_lock_irqsave(¤t->sighand->siglock, flags); | ||
903 | recalc_sigpending(); | ||
904 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | ||
905 | } | ||
906 | |||
907 | if (rc) | ||
908 | *rc = req->rc; | ||
909 | else | ||
910 | kfree(req->rc); | ||
911 | |||
912 | p9_free_req(client, req); | ||
913 | if (err > 0) | ||
914 | err = -EIO; | ||
915 | |||
916 | return err; | ||
917 | } | ||
918 | |||
919 | /** | ||
920 | * parse_options - parse mount options into session structure | 721 | * parse_options - parse mount options into session structure |
921 | * @options: options string passed from mount | 722 | * @options: options string passed from mount |
922 | * @opts: transport-specific structure to parse options into | 723 | * @opts: transport-specific structure to parse options into |
@@ -1243,7 +1044,8 @@ static struct p9_trans_module p9_tcp_trans = { | |||
1243 | .def = 1, | 1044 | .def = 1, |
1244 | .create = p9_fd_create_tcp, | 1045 | .create = p9_fd_create_tcp, |
1245 | .close = p9_fd_close, | 1046 | .close = p9_fd_close, |
1246 | .rpc = p9_fd_rpc, | 1047 | .request = p9_fd_request, |
1048 | .cancel = p9_fd_cancel, | ||
1247 | .owner = THIS_MODULE, | 1049 | .owner = THIS_MODULE, |
1248 | }; | 1050 | }; |
1249 | 1051 | ||
@@ -1253,7 +1055,8 @@ static struct p9_trans_module p9_unix_trans = { | |||
1253 | .def = 0, | 1055 | .def = 0, |
1254 | .create = p9_fd_create_unix, | 1056 | .create = p9_fd_create_unix, |
1255 | .close = p9_fd_close, | 1057 | .close = p9_fd_close, |
1256 | .rpc = p9_fd_rpc, | 1058 | .request = p9_fd_request, |
1059 | .cancel = p9_fd_cancel, | ||
1257 | .owner = THIS_MODULE, | 1060 | .owner = THIS_MODULE, |
1258 | }; | 1061 | }; |
1259 | 1062 | ||
@@ -1263,7 +1066,8 @@ static struct p9_trans_module p9_fd_trans = { | |||
1263 | .def = 0, | 1066 | .def = 0, |
1264 | .create = p9_fd_create, | 1067 | .create = p9_fd_create, |
1265 | .close = p9_fd_close, | 1068 | .close = p9_fd_close, |
1266 | .rpc = p9_fd_rpc, | 1069 | .request = p9_fd_request, |
1070 | .cancel = p9_fd_cancel, | ||
1267 | .owner = THIS_MODULE, | 1071 | .owner = THIS_MODULE, |
1268 | }; | 1072 | }; |
1269 | 1073 | ||