aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/trans_fd.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/9p/trans_fd.c')
-rw-r--r--net/9p/trans_fd.c262
1 files changed, 95 insertions, 167 deletions
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 6243093934b2..cc9bc739e9d3 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -44,7 +44,6 @@
44 44
45#define P9_PORT 564 45#define P9_PORT 564
46#define MAX_SOCK_BUF (64*1024) 46#define MAX_SOCK_BUF (64*1024)
47#define ERREQFLUSH 1
48#define MAXPOLLWADDR 2 47#define MAXPOLLWADDR 2
49 48
50/** 49/**
@@ -99,38 +98,6 @@ enum {
99 Wpending = 8, /* can write */ 98 Wpending = 8, /* can write */
100}; 99};
101 100
102enum {
103 None,
104 Flushing,
105 Flushed,
106};
107
108/**
109 * struct p9_req - fd mux encoding of an rpc transaction
110 * @lock: protects req_list
111 * @tag: numeric tag for rpc transaction
112 * @tcall: request &p9_fcall structure
113 * @rcall: response &p9_fcall structure
114 * @err: error state
115 * @flush: flag to indicate RPC has been flushed
116 * @req_list: list link for higher level objects to chain requests
117 * @m: connection this request was issued on
118 * @wqueue: wait queue that client is blocked on for this rpc
119 *
120 */
121
122struct p9_req {
123 spinlock_t lock;
124 int tag;
125 struct p9_fcall *tcall;
126 struct p9_fcall *rcall;
127 int err;
128 int flush;
129 struct list_head req_list;
130 struct p9_conn *m;
131 wait_queue_head_t wqueue;
132};
133
134struct p9_poll_wait { 101struct p9_poll_wait {
135 struct p9_conn *conn; 102 struct p9_conn *conn;
136 wait_queue_t wait; 103 wait_queue_t wait;
@@ -139,7 +106,6 @@ struct p9_poll_wait {
139 106
140/** 107/**
141 * struct p9_conn - fd mux connection state information 108 * struct p9_conn - fd mux connection state information
142 * @lock: protects mux_list (?)
143 * @mux_list: list link for mux to manage multiple connections (?) 109 * @mux_list: list link for mux to manage multiple connections (?)
144 * @client: reference to client instance for this connection 110 * @client: reference to client instance for this connection
145 * @err: error state 111 * @err: error state
@@ -161,7 +127,6 @@ struct p9_poll_wait {
161 */ 127 */
162 128
163struct p9_conn { 129struct p9_conn {
164 spinlock_t lock; /* protect lock structure */
165 struct list_head mux_list; 130 struct list_head mux_list;
166 struct p9_client *client; 131 struct p9_client *client;
167 int err; 132 int err;
@@ -205,64 +170,41 @@ static void p9_mux_poll_stop(struct p9_conn *m)
205 spin_unlock_irqrestore(&p9_poll_lock, flags); 170 spin_unlock_irqrestore(&p9_poll_lock, flags);
206} 171}
207 172
208static void p9_mux_free_request(struct p9_conn *m, struct p9_req *req) 173static void p9_conn_rpc_cb(struct p9_client *, struct p9_req_t *);
209{
210 if (req->tag != P9_NOTAG &&
211 p9_idpool_check(req->tag, m->client->tagpool))
212 p9_idpool_put(req->tag, m->client->tagpool);
213 kfree(req);
214}
215
216static void p9_conn_rpc_cb(struct p9_req *req);
217 174
218static void p9_mux_flush_cb(struct p9_req *freq) 175static void p9_mux_flush_cb(struct p9_client *client, struct p9_req_t *freq)
219{ 176{
220 int tag; 177 struct p9_conn *m = client->trans;
221 struct p9_conn *m = freq->m; 178 struct p9_req_t *req;
222 struct p9_req *req, *rreq, *rptr;
223 179
224 P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, 180 P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m,
225 freq->tcall, freq->rcall, freq->err, 181 freq->tc, freq->rc, freq->t_err,
226 freq->tcall->params.tflush.oldtag); 182 freq->tc->params.tflush.oldtag);
227
228 spin_lock(&m->lock);
229 tag = freq->tcall->params.tflush.oldtag;
230 req = NULL;
231 list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
232 if (rreq->tag == tag) {
233 req = rreq;
234 list_del(&req->req_list);
235 break;
236 }
237 }
238 spin_unlock(&m->lock);
239 183
184 req = p9_tag_lookup(client, freq->tc->params.tflush.oldtag);
240 if (req) { 185 if (req) {
241 spin_lock(&req->lock); 186 req->status = REQ_STATUS_FLSHD;
242 req->flush = Flushed; 187 list_del(&req->req_list);
243 spin_unlock(&req->lock); 188 p9_conn_rpc_cb(client, req);
244
245 p9_conn_rpc_cb(req);
246 } 189 }
247 190
248 kfree(freq->tcall); 191 p9_free_req(client, freq);
249 kfree(freq->rcall);
250 p9_mux_free_request(m, freq);
251} 192}
252 193
253static void p9_conn_rpc_cb(struct p9_req *req) 194static void p9_conn_rpc_cb(struct p9_client *client, struct p9_req_t *req)
254{ 195{
255 P9_DPRINTK(P9_DEBUG_MUX, "req %p\n", req); 196 P9_DPRINTK(P9_DEBUG_MUX, "req %p\n", req);
256 197
257 if (req->tcall->id == P9_TFLUSH) { /* flush callback */ 198 if (req->tc->id == P9_TFLUSH) { /* flush callback */
258 P9_DPRINTK(P9_DEBUG_MUX, "flush req %p\n", req); 199 P9_DPRINTK(P9_DEBUG_MUX, "flush req %p\n", req);
259 p9_mux_flush_cb(req); 200 p9_mux_flush_cb(client, req);
260 } else { /* normal wakeup path */ 201 } else { /* normal wakeup path */
261 P9_DPRINTK(P9_DEBUG_MUX, "normal req %p\n", req); 202 P9_DPRINTK(P9_DEBUG_MUX, "normal req %p\n", req);
262 if (req->flush != None && !req->err) 203 if (!req->t_err && (req->status == REQ_STATUS_FLSHD ||
263 req->err = -ERESTARTSYS; 204 req->status == REQ_STATUS_FLSH))
205 req->t_err = -ERESTARTSYS;
264 206
265 wake_up(&req->wqueue); 207 wake_up(req->wq);
266 } 208 }
267} 209}
268 210
@@ -275,59 +217,62 @@ static void p9_conn_rpc_cb(struct p9_req *req)
275 217
276void p9_conn_cancel(struct p9_conn *m, int err) 218void p9_conn_cancel(struct p9_conn *m, int err)
277{ 219{
278 struct p9_req *req, *rtmp; 220 struct p9_req_t *req, *rtmp;
279 LIST_HEAD(cancel_list); 221 LIST_HEAD(cancel_list);
280 222
281 P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err); 223 P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err);
282 m->err = err; 224 m->err = err;
283 spin_lock(&m->lock); 225 spin_lock(&m->client->lock);
284 list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { 226 list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
227 req->status = REQ_STATUS_ERROR;
228 if (!req->t_err)
229 req->t_err = err;
285 list_move(&req->req_list, &cancel_list); 230 list_move(&req->req_list, &cancel_list);
286 } 231 }
287 list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { 232 list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
233 req->status = REQ_STATUS_ERROR;
234 if (!req->t_err)
235 req->t_err = err;
288 list_move(&req->req_list, &cancel_list); 236 list_move(&req->req_list, &cancel_list);
289 } 237 }
290 spin_unlock(&m->lock); 238 spin_unlock(&m->client->lock);
291 239
292 list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { 240 list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
293 list_del(&req->req_list); 241 list_del(&req->req_list);
294 if (!req->err) 242 p9_conn_rpc_cb(m->client, req);
295 req->err = err;
296
297 p9_conn_rpc_cb(req);
298 } 243 }
299} 244}
300 245
301static void process_request(struct p9_conn *m, struct p9_req *req) 246static void process_request(struct p9_conn *m, struct p9_req_t *req)
302{ 247{
303 int ecode; 248 int ecode;
304 struct p9_str *ename; 249 struct p9_str *ename;
305 250
306 if (!req->err && req->rcall->id == P9_RERROR) { 251 if (!req->t_err && req->rc->id == P9_RERROR) {
307 ecode = req->rcall->params.rerror.errno; 252 ecode = req->rc->params.rerror.errno;
308 ename = &req->rcall->params.rerror.error; 253 ename = &req->rc->params.rerror.error;
309 254
310 P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len, 255 P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len,
311 ename->str); 256 ename->str);
312 257
313 if (m->client->dotu) 258 if (m->client->dotu)
314 req->err = -ecode; 259 req->t_err = -ecode;
315 260
316 if (!req->err) { 261 if (!req->t_err) {
317 req->err = p9_errstr2errno(ename->str, ename->len); 262 req->t_err = p9_errstr2errno(ename->str, ename->len);
318 263
319 /* string match failed */ 264 /* string match failed */
320 if (!req->err) { 265 if (!req->t_err) {
321 PRINT_FCALL_ERROR("unknown error", req->rcall); 266 PRINT_FCALL_ERROR("unknown error", req->rc);
322 req->err = -ESERVERFAULT; 267 req->t_err = -ESERVERFAULT;
323 } 268 }
324 } 269 }
325 } else if (req->tcall && req->rcall->id != req->tcall->id + 1) { 270 } else if (req->tc && req->rc->id != req->tc->id + 1) {
326 P9_DPRINTK(P9_DEBUG_ERROR, 271 P9_DPRINTK(P9_DEBUG_ERROR,
327 "fcall mismatch: expected %d, got %d\n", 272 "fcall mismatch: expected %d, got %d\n",
328 req->tcall->id + 1, req->rcall->id); 273 req->tc->id + 1, req->rc->id);
329 if (!req->err) 274 if (!req->t_err)
330 req->err = -EIO; 275 req->t_err = -EIO;
331 } 276 }
332} 277}
333 278
@@ -401,7 +346,7 @@ static void p9_read_work(struct work_struct *work)
401{ 346{
402 int n, err; 347 int n, err;
403 struct p9_conn *m; 348 struct p9_conn *m;
404 struct p9_req *req, *rptr, *rreq; 349 struct p9_req_t *req;
405 struct p9_fcall *rcall; 350 struct p9_fcall *rcall;
406 char *rbuf; 351 char *rbuf;
407 352
@@ -488,24 +433,19 @@ static void p9_read_work(struct work_struct *work)
488 P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, 433 P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m,
489 rcall->id, rcall->tag); 434 rcall->id, rcall->tag);
490 435
491 req = NULL; 436 req = p9_tag_lookup(m->client, rcall->tag);
492 spin_lock(&m->lock);
493 list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
494 if (rreq->tag == rcall->tag) {
495 req = rreq;
496 if (req->flush != Flushing)
497 list_del(&req->req_list);
498 break;
499 }
500 }
501 spin_unlock(&m->lock);
502 437
503 if (req) { 438 if (req) {
504 req->rcall = rcall; 439 if (req->status != REQ_STATUS_FLSH) {
440 list_del(&req->req_list);
441 req->status = REQ_STATUS_RCVD;
442 }
443
444 req->rc = rcall;
505 process_request(m, req); 445 process_request(m, req);
506 446
507 if (req->flush != Flushing) 447 if (req->status != REQ_STATUS_FLSH)
508 p9_conn_rpc_cb(req); 448 p9_conn_rpc_cb(m->client, req);
509 } else { 449 } else {
510 if (err >= 0 && rcall->id != P9_RFLUSH) 450 if (err >= 0 && rcall->id != P9_RFLUSH)
511 P9_DPRINTK(P9_DEBUG_ERROR, 451 P9_DPRINTK(P9_DEBUG_ERROR,
@@ -580,7 +520,7 @@ static void p9_write_work(struct work_struct *work)
580{ 520{
581 int n, err; 521 int n, err;
582 struct p9_conn *m; 522 struct p9_conn *m;
583 struct p9_req *req; 523 struct p9_req_t *req;
584 524
585 m = container_of(work, struct p9_conn, wq); 525 m = container_of(work, struct p9_conn, wq);
586 526
@@ -595,18 +535,16 @@ static void p9_write_work(struct work_struct *work)
595 return; 535 return;
596 } 536 }
597 537
598 spin_lock(&m->lock); 538 spin_lock(&m->client->lock);
599again: 539 req = list_entry(m->unsent_req_list.next, struct p9_req_t,
600 req = list_entry(m->unsent_req_list.next, struct p9_req,
601 req_list); 540 req_list);
541 req->status = REQ_STATUS_SENT;
602 list_move_tail(&req->req_list, &m->req_list); 542 list_move_tail(&req->req_list, &m->req_list);
603 if (req->err == ERREQFLUSH)
604 goto again;
605 543
606 m->wbuf = req->tcall->sdata; 544 m->wbuf = req->tc->sdata;
607 m->wsize = req->tcall->size; 545 m->wsize = req->tc->size;
608 m->wpos = 0; 546 m->wpos = 0;
609 spin_unlock(&m->lock); 547 spin_unlock(&m->client->lock);
610 } 548 }
611 549
612 P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, 550 P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos,
@@ -725,7 +663,6 @@ static struct p9_conn *p9_conn_create(struct p9_client *client)
725 if (!m) 663 if (!m)
726 return ERR_PTR(-ENOMEM); 664 return ERR_PTR(-ENOMEM);
727 665
728 spin_lock_init(&m->lock);
729 INIT_LIST_HEAD(&m->mux_list); 666 INIT_LIST_HEAD(&m->mux_list);
730 m->client = client; 667 m->client = client;
731 668
@@ -812,30 +749,27 @@ static void p9_poll_mux(struct p9_conn *m)
812 * 749 *
813 */ 750 */
814 751
815static struct p9_req *p9_send_request(struct p9_conn *m, struct p9_fcall *tc) 752static struct p9_req_t *p9_send_request(struct p9_conn *m, struct p9_fcall *tc)
816{ 753{
754 int tag;
817 int n; 755 int n;
818 struct p9_req *req; 756 struct p9_req_t *req;
819 757
820 P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current, 758 P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current,
821 tc, tc->id); 759 tc, tc->id);
822 if (m->err < 0) 760 if (m->err < 0)
823 return ERR_PTR(m->err); 761 return ERR_PTR(m->err);
824 762
825 req = kmalloc(sizeof(struct p9_req), GFP_KERNEL); 763 tag = P9_NOTAG;
826 if (!req)
827 return ERR_PTR(-ENOMEM);
828
829 n = P9_NOTAG;
830 if (tc->id != P9_TVERSION) { 764 if (tc->id != P9_TVERSION) {
831 n = p9_idpool_get(m->client->tagpool); 765 tag = p9_idpool_get(m->client->tagpool);
832 if (n < 0) { 766 if (tag < 0)
833 kfree(req);
834 return ERR_PTR(-ENOMEM); 767 return ERR_PTR(-ENOMEM);
835 }
836 } 768 }
837 769
838 p9_set_tag(tc, n); 770 p9_set_tag(tc, tag);
771
772 req = p9_tag_alloc(m->client, tag);
839 773
840#ifdef CONFIG_NET_9P_DEBUG 774#ifdef CONFIG_NET_9P_DEBUG
841 if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { 775 if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
@@ -846,18 +780,15 @@ static struct p9_req *p9_send_request(struct p9_conn *m, struct p9_fcall *tc)
846 } 780 }
847#endif 781#endif
848 782
849 spin_lock_init(&req->lock); 783 req->tag = tag;
850 req->m = m; 784 req->tc = tc;
851 init_waitqueue_head(&req->wqueue); 785 req->rc = NULL;
852 req->tag = n; 786 req->t_err = 0;
853 req->tcall = tc; 787 req->status = REQ_STATUS_UNSENT;
854 req->rcall = NULL;
855 req->err = 0;
856 req->flush = None;
857 788
858 spin_lock(&m->lock); 789 spin_lock(&m->client->lock);
859 list_add_tail(&req->req_list, &m->unsent_req_list); 790 list_add_tail(&req->req_list, &m->unsent_req_list);
860 spin_unlock(&m->lock); 791 spin_unlock(&m->client->lock);
861 792
862 if (test_and_clear_bit(Wpending, &m->wsched)) 793 if (test_and_clear_bit(Wpending, &m->wsched))
863 n = POLLOUT; 794 n = POLLOUT;
@@ -871,39 +802,36 @@ static struct p9_req *p9_send_request(struct p9_conn *m, struct p9_fcall *tc)
871} 802}
872 803
873static int 804static int
874p9_mux_flush_request(struct p9_conn *m, struct p9_req *req) 805p9_mux_flush_request(struct p9_conn *m, struct p9_req_t *req)
875{ 806{
876 struct p9_fcall *fc; 807 struct p9_fcall *fc;
877 struct p9_req *rreq, *rptr; 808 struct p9_req_t *rreq, *rptr;
878 809
879 P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); 810 P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag);
880 811
881 /* if a response was received for a request, do nothing */ 812 /* if a response was received for a request, do nothing */
882 spin_lock(&req->lock); 813 if (req->rc || req->t_err) {
883 if (req->rcall || req->err) {
884 spin_unlock(&req->lock);
885 P9_DPRINTK(P9_DEBUG_MUX, 814 P9_DPRINTK(P9_DEBUG_MUX,
886 "mux %p req %p response already received\n", m, req); 815 "mux %p req %p response already received\n", m, req);
887 return 0; 816 return 0;
888 } 817 }
889 818
890 req->flush = Flushing; 819 req->status = REQ_STATUS_FLSH;
891 spin_unlock(&req->lock);
892 820
893 spin_lock(&m->lock); 821 spin_lock(&m->client->lock);
894 /* if the request is not sent yet, just remove it from the list */ 822 /* if the request is not sent yet, just remove it from the list */
895 list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) { 823 list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) {
896 if (rreq->tag == req->tag) { 824 if (rreq->tag == req->tag) {
897 P9_DPRINTK(P9_DEBUG_MUX, 825 P9_DPRINTK(P9_DEBUG_MUX,
898 "mux %p req %p request is not sent yet\n", m, req); 826 "mux %p req %p request is not sent yet\n", m, req);
899 list_del(&rreq->req_list); 827 list_del(&rreq->req_list);
900 req->flush = Flushed; 828 req->status = REQ_STATUS_FLSHD;
901 spin_unlock(&m->lock); 829 spin_unlock(&m->client->lock);
902 p9_conn_rpc_cb(req); 830 p9_conn_rpc_cb(m->client, req);
903 return 0; 831 return 0;
904 } 832 }
905 } 833 }
906 spin_unlock(&m->lock); 834 spin_unlock(&m->client->lock);
907 835
908 clear_thread_flag(TIF_SIGPENDING); 836 clear_thread_flag(TIF_SIGPENDING);
909 fc = p9_create_tflush(req->tag); 837 fc = p9_create_tflush(req->tag);
@@ -927,7 +855,7 @@ p9_fd_rpc(struct p9_client *client, struct p9_fcall *tc, struct p9_fcall **rc)
927 struct p9_conn *m = p->conn; 855 struct p9_conn *m = p->conn;
928 int err, sigpending; 856 int err, sigpending;
929 unsigned long flags; 857 unsigned long flags;
930 struct p9_req *req; 858 struct p9_req_t *req;
931 859
932 if (rc) 860 if (rc)
933 *rc = NULL; 861 *rc = NULL;
@@ -945,10 +873,10 @@ p9_fd_rpc(struct p9_client *client, struct p9_fcall *tc, struct p9_fcall **rc)
945 return err; 873 return err;
946 } 874 }
947 875
948 err = wait_event_interruptible(req->wqueue, req->rcall != NULL || 876 err = wait_event_interruptible(*req->wq, req->rc != NULL ||
949 req->err < 0); 877 req->t_err < 0);
950 if (req->err < 0) 878 if (req->t_err < 0)
951 err = req->err; 879 err = req->t_err;
952 880
953 if (err == -ERESTARTSYS && client->status == Connected 881 if (err == -ERESTARTSYS && client->status == Connected
954 && m->err == 0) { 882 && m->err == 0) {
@@ -956,9 +884,9 @@ p9_fd_rpc(struct p9_client *client, struct p9_fcall *tc, struct p9_fcall **rc)
956 /* wait until we get response of the flush message */ 884 /* wait until we get response of the flush message */
957 do { 885 do {
958 clear_thread_flag(TIF_SIGPENDING); 886 clear_thread_flag(TIF_SIGPENDING);
959 err = wait_event_interruptible(req->wqueue, 887 err = wait_event_interruptible(*req->wq,
960 req->rcall || req->err); 888 req->rc || req->t_err);
961 } while (!req->rcall && !req->err && 889 } while (!req->rc && !req->t_err &&
962 err == -ERESTARTSYS && 890 err == -ERESTARTSYS &&
963 client->status == Connected && !m->err); 891 client->status == Connected && !m->err);
964 892
@@ -974,11 +902,11 @@ p9_fd_rpc(struct p9_client *client, struct p9_fcall *tc, struct p9_fcall **rc)
974 } 902 }
975 903
976 if (rc) 904 if (rc)
977 *rc = req->rcall; 905 *rc = req->rc;
978 else 906 else
979 kfree(req->rcall); 907 kfree(req->rc);
980 908
981 p9_mux_free_request(m, req); 909 p9_free_req(client, req);
982 if (err > 0) 910 if (err > 0)
983 err = -EIO; 911 err = -EIO;
984 912