aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/trans_fd.c
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@gmail.com>2008-10-13 19:45:21 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2008-10-17 12:04:42 -0400
commit91b8534fa8f5e01f249b1bf8df0a2540053549ad (patch)
treefde6b3b63dad229108106553106995889b4f0fa7 /net/9p/trans_fd.c
parent1b0a763bdd5ed467d0e03b88e045000c749303fb (diff)
9p: make rpc code common and rework flush code
This code moves the rpc function to the common client base, reorganizes the flush code to be more simple and stable, and makes the necessary adjustments to the underlying transports to adapt to the new structure. This reduces the overall amount of code duplication between the transports and should make adding new transports more straightforward. Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'net/9p/trans_fd.c')
-rw-r--r--net/9p/trans_fd.c268
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
177static void p9_conn_rpc_cb(struct p9_client *, struct p9_req_t *);
178
179static 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
198static 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)
222void p9_conn_cancel(struct p9_conn *m, int err) 184void 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
250static 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
755static struct p9_req_t *p9_send_request(struct p9_conn *m, struct p9_fcall *tc) 657static 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
807static int 694static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
808p9_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
854int
855p9_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(&current->sighand->siglock, flags);
903 recalc_sigpending();
904 spin_unlock_irqrestore(&current->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