aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLinus Torvalds2014-04-11 16:14:57 -0500
committerLinus Torvalds2014-04-11 16:14:57 -0500
commit582076ab16779208e7eb6ce712a9c0a6cc5bafe4 (patch)
tree6841c02fa19dba9c4a8299592a7f14344f8944f7 /net
parent79d2d21ee06f3634423d1a45fb6ddfcae59061fd (diff)
parent8a5daf1e2c199746767d94b4036638ba11d528b3 (diff)
downloadlinux-phy-582076ab16779208e7eb6ce712a9c0a6cc5bafe4.tar.gz
linux-phy-582076ab16779208e7eb6ce712a9c0a6cc5bafe4.tar.xz
linux-phy-582076ab16779208e7eb6ce712a9c0a6cc5bafe4.zip
Merge tag 'for-linus-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs
Pull 9p changes from Eric Van Hensbergen: "A bunch of updates and cleanup within the transport layer, particularly with a focus on RDMA" * tag 'for-linus-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs: 9pnet_rdma: check token type before int conversion 9pnet: trans_fd : allocate struct p9_trans_fd and struct p9_conn together. 9pnet: p9_client->conn field is unused. Remove it. 9P: Get rid of REQ_STATUS_FLSH 9pnet_rdma: add cancelled() 9pnet_rdma: update request status during send 9P: Add cancelled() to the transport functions. net: Mark function as static in 9p/client.c 9P: Add memory barriers to protect request fields over cb/rpc threads handoff
Diffstat (limited to 'net')
-rw-r--r--net/9p/client.c25
-rw-r--r--net/9p/trans_fd.c110
-rw-r--r--net/9p/trans_rdma.c26
-rw-r--r--net/9p/trans_virtio.c3
4 files changed, 92 insertions, 72 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index 9186550d77a6..0004cbaac4a4 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -415,9 +415,17 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
415 * req: request received 415 * req: request received
416 * 416 *
417 */ 417 */
418void p9_client_cb(struct p9_client *c, struct p9_req_t *req) 418void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status)
419{ 419{
420 p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); 420 p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
421
422 /*
423 * This barrier is needed to make sure any change made to req before
424 * the other thread wakes up will indeed be seen by the waiting side.
425 */
426 smp_wmb();
427 req->status = status;
428
421 wake_up(req->wq); 429 wake_up(req->wq);
422 p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); 430 p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
423} 431}
@@ -655,16 +663,13 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
655 if (IS_ERR(req)) 663 if (IS_ERR(req))
656 return PTR_ERR(req); 664 return PTR_ERR(req);
657 665
658
659 /* 666 /*
660 * if we haven't received a response for oldreq, 667 * if we haven't received a response for oldreq,
661 * remove it from the list 668 * remove it from the list
662 */ 669 */
663 if (oldreq->status == REQ_STATUS_FLSH) { 670 if (oldreq->status == REQ_STATUS_SENT)
664 spin_lock(&c->lock); 671 if (c->trans_mod->cancelled)
665 list_del(&oldreq->req_list); 672 c->trans_mod->cancelled(c, oldreq);
666 spin_unlock(&c->lock);
667 }
668 673
669 p9_free_req(c, req); 674 p9_free_req(c, req);
670 return 0; 675 return 0;
@@ -751,6 +756,12 @@ again:
751 err = wait_event_interruptible(*req->wq, 756 err = wait_event_interruptible(*req->wq,
752 req->status >= REQ_STATUS_RCVD); 757 req->status >= REQ_STATUS_RCVD);
753 758
759 /*
760 * Make sure our req is coherent with regard to updates in other
761 * threads - echoes to wmb() in the callback
762 */
763 smp_rmb();
764
754 if ((err == -ERESTARTSYS) && (c->status == Connected) 765 if ((err == -ERESTARTSYS) && (c->status == Connected)
755 && (type == P9_TFLUSH)) { 766 && (type == P9_TFLUSH)) {
756 sigpending = 1; 767 sigpending = 1;
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index b7bd7f2961bf..80d08f6664cb 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -66,20 +66,6 @@ struct p9_fd_opts {
66 int privport; 66 int privport;
67}; 67};
68 68
69/**
70 * struct p9_trans_fd - transport state
71 * @rd: reference to file to read from
72 * @wr: reference of file to write to
73 * @conn: connection state reference
74 *
75 */
76
77struct p9_trans_fd {
78 struct file *rd;
79 struct file *wr;
80 struct p9_conn *conn;
81};
82
83/* 69/*
84 * Option Parsing (code inspired by NFS code) 70 * Option Parsing (code inspired by NFS code)
85 * - a little lazy - parse all fd-transport options 71 * - a little lazy - parse all fd-transport options
@@ -159,6 +145,20 @@ struct p9_conn {
159 unsigned long wsched; 145 unsigned long wsched;
160}; 146};
161 147
148/**
149 * struct p9_trans_fd - transport state
150 * @rd: reference to file to read from
151 * @wr: reference of file to write to
152 * @conn: connection state reference
153 *
154 */
155
156struct p9_trans_fd {
157 struct file *rd;
158 struct file *wr;
159 struct p9_conn conn;
160};
161
162static void p9_poll_workfn(struct work_struct *work); 162static void p9_poll_workfn(struct work_struct *work);
163 163
164static DEFINE_SPINLOCK(p9_poll_lock); 164static DEFINE_SPINLOCK(p9_poll_lock);
@@ -212,15 +212,9 @@ static void p9_conn_cancel(struct p9_conn *m, int err)
212 m->err = err; 212 m->err = err;
213 213
214 list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { 214 list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
215 req->status = REQ_STATUS_ERROR;
216 if (!req->t_err)
217 req->t_err = err;
218 list_move(&req->req_list, &cancel_list); 215 list_move(&req->req_list, &cancel_list);
219 } 216 }
220 list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { 217 list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
221 req->status = REQ_STATUS_ERROR;
222 if (!req->t_err)
223 req->t_err = err;
224 list_move(&req->req_list, &cancel_list); 218 list_move(&req->req_list, &cancel_list);
225 } 219 }
226 spin_unlock_irqrestore(&m->client->lock, flags); 220 spin_unlock_irqrestore(&m->client->lock, flags);
@@ -228,7 +222,9 @@ static void p9_conn_cancel(struct p9_conn *m, int err)
228 list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { 222 list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
229 p9_debug(P9_DEBUG_ERROR, "call back req %p\n", req); 223 p9_debug(P9_DEBUG_ERROR, "call back req %p\n", req);
230 list_del(&req->req_list); 224 list_del(&req->req_list);
231 p9_client_cb(m->client, req); 225 if (!req->t_err)
226 req->t_err = err;
227 p9_client_cb(m->client, req, REQ_STATUS_ERROR);
232 } 228 }
233} 229}
234 230
@@ -302,6 +298,7 @@ static void p9_read_work(struct work_struct *work)
302{ 298{
303 int n, err; 299 int n, err;
304 struct p9_conn *m; 300 struct p9_conn *m;
301 int status = REQ_STATUS_ERROR;
305 302
306 m = container_of(work, struct p9_conn, rq); 303 m = container_of(work, struct p9_conn, rq);
307 304
@@ -348,8 +345,7 @@ static void p9_read_work(struct work_struct *work)
348 "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); 345 "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag);
349 346
350 m->req = p9_tag_lookup(m->client, tag); 347 m->req = p9_tag_lookup(m->client, tag);
351 if (!m->req || (m->req->status != REQ_STATUS_SENT && 348 if (!m->req || (m->req->status != REQ_STATUS_SENT)) {
352 m->req->status != REQ_STATUS_FLSH)) {
353 p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", 349 p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n",
354 tag); 350 tag);
355 err = -EIO; 351 err = -EIO;
@@ -375,10 +371,10 @@ static void p9_read_work(struct work_struct *work)
375 p9_debug(P9_DEBUG_TRANS, "got new packet\n"); 371 p9_debug(P9_DEBUG_TRANS, "got new packet\n");
376 spin_lock(&m->client->lock); 372 spin_lock(&m->client->lock);
377 if (m->req->status != REQ_STATUS_ERROR) 373 if (m->req->status != REQ_STATUS_ERROR)
378 m->req->status = REQ_STATUS_RCVD; 374 status = REQ_STATUS_RCVD;
379 list_del(&m->req->req_list); 375 list_del(&m->req->req_list);
380 spin_unlock(&m->client->lock); 376 spin_unlock(&m->client->lock);
381 p9_client_cb(m->client, m->req); 377 p9_client_cb(m->client, m->req, status);
382 m->rbuf = NULL; 378 m->rbuf = NULL;
383 m->rpos = 0; 379 m->rpos = 0;
384 m->rsize = 0; 380 m->rsize = 0;
@@ -573,21 +569,19 @@ p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
573} 569}
574 570
575/** 571/**
576 * p9_conn_create - allocate and initialize the per-session mux data 572 * p9_conn_create - initialize the per-session mux data
577 * @client: client instance 573 * @client: client instance
578 * 574 *
579 * Note: Creates the polling task if this is the first session. 575 * Note: Creates the polling task if this is the first session.
580 */ 576 */
581 577
582static struct p9_conn *p9_conn_create(struct p9_client *client) 578static void p9_conn_create(struct p9_client *client)
583{ 579{
584 int n; 580 int n;
585 struct p9_conn *m; 581 struct p9_trans_fd *ts = client->trans;
582 struct p9_conn *m = &ts->conn;
586 583
587 p9_debug(P9_DEBUG_TRANS, "client %p msize %d\n", client, client->msize); 584 p9_debug(P9_DEBUG_TRANS, "client %p msize %d\n", client, client->msize);
588 m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL);
589 if (!m)
590 return ERR_PTR(-ENOMEM);
591 585
592 INIT_LIST_HEAD(&m->mux_list); 586 INIT_LIST_HEAD(&m->mux_list);
593 m->client = client; 587 m->client = client;
@@ -609,8 +603,6 @@ static struct p9_conn *p9_conn_create(struct p9_client *client)
609 p9_debug(P9_DEBUG_TRANS, "mux %p can write\n", m); 603 p9_debug(P9_DEBUG_TRANS, "mux %p can write\n", m);
610 set_bit(Wpending, &m->wsched); 604 set_bit(Wpending, &m->wsched);
611 } 605 }
612
613 return m;
614} 606}
615 607
616/** 608/**
@@ -669,7 +661,7 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
669{ 661{
670 int n; 662 int n;
671 struct p9_trans_fd *ts = client->trans; 663 struct p9_trans_fd *ts = client->trans;
672 struct p9_conn *m = ts->conn; 664 struct p9_conn *m = &ts->conn;
673 665
674 p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n", 666 p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n",
675 m, current, req->tc, req->tc->id); 667 m, current, req->tc, req->tc->id);
@@ -704,14 +696,26 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
704 list_del(&req->req_list); 696 list_del(&req->req_list);
705 req->status = REQ_STATUS_FLSHD; 697 req->status = REQ_STATUS_FLSHD;
706 ret = 0; 698 ret = 0;
707 } else if (req->status == REQ_STATUS_SENT) 699 }
708 req->status = REQ_STATUS_FLSH;
709
710 spin_unlock(&client->lock); 700 spin_unlock(&client->lock);
711 701
712 return ret; 702 return ret;
713} 703}
714 704
705static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
706{
707 p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
708
709 /* we haven't received a response for oldreq,
710 * remove it from the list.
711 */
712 spin_lock(&client->lock);
713 list_del(&req->req_list);
714 spin_unlock(&client->lock);
715
716 return 0;
717}
718
715/** 719/**
716 * parse_opts - parse mount options into p9_fd_opts structure 720 * parse_opts - parse mount options into p9_fd_opts structure
717 * @params: options string passed from mount 721 * @params: options string passed from mount
@@ -780,7 +784,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
780 784
781static int p9_fd_open(struct p9_client *client, int rfd, int wfd) 785static int p9_fd_open(struct p9_client *client, int rfd, int wfd)
782{ 786{
783 struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd), 787 struct p9_trans_fd *ts = kzalloc(sizeof(struct p9_trans_fd),
784 GFP_KERNEL); 788 GFP_KERNEL);
785 if (!ts) 789 if (!ts)
786 return -ENOMEM; 790 return -ENOMEM;
@@ -806,9 +810,8 @@ static int p9_socket_open(struct p9_client *client, struct socket *csocket)
806{ 810{
807 struct p9_trans_fd *p; 811 struct p9_trans_fd *p;
808 struct file *file; 812 struct file *file;
809 int ret;
810 813
811 p = kmalloc(sizeof(struct p9_trans_fd), GFP_KERNEL); 814 p = kzalloc(sizeof(struct p9_trans_fd), GFP_KERNEL);
812 if (!p) 815 if (!p)
813 return -ENOMEM; 816 return -ENOMEM;
814 817
@@ -829,20 +832,12 @@ static int p9_socket_open(struct p9_client *client, struct socket *csocket)
829 832
830 p->rd->f_flags |= O_NONBLOCK; 833 p->rd->f_flags |= O_NONBLOCK;
831 834
832 p->conn = p9_conn_create(client); 835 p9_conn_create(client);
833 if (IS_ERR(p->conn)) {
834 ret = PTR_ERR(p->conn);
835 p->conn = NULL;
836 kfree(p);
837 sockfd_put(csocket);
838 sockfd_put(csocket);
839 return ret;
840 }
841 return 0; 836 return 0;
842} 837}
843 838
844/** 839/**
845 * p9_mux_destroy - cancels all pending requests and frees mux resources 840 * p9_mux_destroy - cancels all pending requests of mux
846 * @m: mux to destroy 841 * @m: mux to destroy
847 * 842 *
848 */ 843 */
@@ -859,7 +854,6 @@ static void p9_conn_destroy(struct p9_conn *m)
859 p9_conn_cancel(m, -ECONNRESET); 854 p9_conn_cancel(m, -ECONNRESET);
860 855
861 m->client = NULL; 856 m->client = NULL;
862 kfree(m);
863} 857}
864 858
865/** 859/**
@@ -881,7 +875,7 @@ static void p9_fd_close(struct p9_client *client)
881 875
882 client->status = Disconnected; 876 client->status = Disconnected;
883 877
884 p9_conn_destroy(ts->conn); 878 p9_conn_destroy(&ts->conn);
885 879
886 if (ts->rd) 880 if (ts->rd)
887 fput(ts->rd); 881 fput(ts->rd);
@@ -1033,14 +1027,7 @@ p9_fd_create(struct p9_client *client, const char *addr, char *args)
1033 return err; 1027 return err;
1034 1028
1035 p = (struct p9_trans_fd *) client->trans; 1029 p = (struct p9_trans_fd *) client->trans;
1036 p->conn = p9_conn_create(client); 1030 p9_conn_create(client);
1037 if (IS_ERR(p->conn)) {
1038 err = PTR_ERR(p->conn);
1039 p->conn = NULL;
1040 fput(p->rd);
1041 fput(p->wr);
1042 return err;
1043 }
1044 1031
1045 return 0; 1032 return 0;
1046} 1033}
@@ -1053,6 +1040,7 @@ static struct p9_trans_module p9_tcp_trans = {
1053 .close = p9_fd_close, 1040 .close = p9_fd_close,
1054 .request = p9_fd_request, 1041 .request = p9_fd_request,
1055 .cancel = p9_fd_cancel, 1042 .cancel = p9_fd_cancel,
1043 .cancelled = p9_fd_cancelled,
1056 .owner = THIS_MODULE, 1044 .owner = THIS_MODULE,
1057}; 1045};
1058 1046
@@ -1064,6 +1052,7 @@ static struct p9_trans_module p9_unix_trans = {
1064 .close = p9_fd_close, 1052 .close = p9_fd_close,
1065 .request = p9_fd_request, 1053 .request = p9_fd_request,
1066 .cancel = p9_fd_cancel, 1054 .cancel = p9_fd_cancel,
1055 .cancelled = p9_fd_cancelled,
1067 .owner = THIS_MODULE, 1056 .owner = THIS_MODULE,
1068}; 1057};
1069 1058
@@ -1075,6 +1064,7 @@ static struct p9_trans_module p9_fd_trans = {
1075 .close = p9_fd_close, 1064 .close = p9_fd_close,
1076 .request = p9_fd_request, 1065 .request = p9_fd_request,
1077 .cancel = p9_fd_cancel, 1066 .cancel = p9_fd_cancel,
1067 .cancelled = p9_fd_cancelled,
1078 .owner = THIS_MODULE, 1068 .owner = THIS_MODULE,
1079}; 1069};
1080 1070
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
index 8f68df5d2973..14ad43b5cf89 100644
--- a/net/9p/trans_rdma.c
+++ b/net/9p/trans_rdma.c
@@ -193,6 +193,8 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts)
193 if (!*p) 193 if (!*p)
194 continue; 194 continue;
195 token = match_token(p, tokens, args); 195 token = match_token(p, tokens, args);
196 if (token == Opt_err)
197 continue;
196 r = match_int(&args[0], &option); 198 r = match_int(&args[0], &option);
197 if (r < 0) { 199 if (r < 0) {
198 p9_debug(P9_DEBUG_ERROR, 200 p9_debug(P9_DEBUG_ERROR,
@@ -305,8 +307,7 @@ handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma,
305 } 307 }
306 308
307 req->rc = c->rc; 309 req->rc = c->rc;
308 req->status = REQ_STATUS_RCVD; 310 p9_client_cb(client, req, REQ_STATUS_RCVD);
309 p9_client_cb(client, req);
310 311
311 return; 312 return;
312 313
@@ -511,6 +512,11 @@ dont_need_post_recv:
511 goto send_error; 512 goto send_error;
512 } 513 }
513 514
515 /* Mark request as `sent' *before* we actually send it,
516 * because doing if after could erase the REQ_STATUS_RCVD
517 * status in case of a very fast reply.
518 */
519 req->status = REQ_STATUS_SENT;
514 err = ib_post_send(rdma->qp, &wr, &bad_wr); 520 err = ib_post_send(rdma->qp, &wr, &bad_wr);
515 if (err) 521 if (err)
516 goto send_error; 522 goto send_error;
@@ -520,6 +526,7 @@ dont_need_post_recv:
520 526
521 /* Handle errors that happened during or while preparing the send: */ 527 /* Handle errors that happened during or while preparing the send: */
522 send_error: 528 send_error:
529 req->status = REQ_STATUS_ERROR;
523 kfree(c); 530 kfree(c);
524 p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err); 531 p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err);
525 532
@@ -582,12 +589,24 @@ static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts)
582 return rdma; 589 return rdma;
583} 590}
584 591
585/* its not clear to me we can do anything after send has been posted */
586static int rdma_cancel(struct p9_client *client, struct p9_req_t *req) 592static int rdma_cancel(struct p9_client *client, struct p9_req_t *req)
587{ 593{
594 /* Nothing to do here.
595 * We will take care of it (if we have to) in rdma_cancelled()
596 */
588 return 1; 597 return 1;
589} 598}
590 599
600/* A request has been fully flushed without a reply.
601 * That means we have posted one buffer in excess.
602 */
603static int rdma_cancelled(struct p9_client *client, struct p9_req_t *req)
604{
605 struct p9_trans_rdma *rdma = client->trans;
606 atomic_inc(&rdma->excess_rc);
607 return 0;
608}
609
591/** 610/**
592 * trans_create_rdma - Transport method for creating atransport instance 611 * trans_create_rdma - Transport method for creating atransport instance
593 * @client: client instance 612 * @client: client instance
@@ -721,6 +740,7 @@ static struct p9_trans_module p9_rdma_trans = {
721 .close = rdma_close, 740 .close = rdma_close,
722 .request = rdma_request, 741 .request = rdma_request,
723 .cancel = rdma_cancel, 742 .cancel = rdma_cancel,
743 .cancelled = rdma_cancelled,
724}; 744};
725 745
726/** 746/**
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index ac2666c1d011..6940d8fe8971 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -164,8 +164,7 @@ static void req_done(struct virtqueue *vq)
164 p9_debug(P9_DEBUG_TRANS, ": rc %p\n", rc); 164 p9_debug(P9_DEBUG_TRANS, ": rc %p\n", rc);
165 p9_debug(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); 165 p9_debug(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag);
166 req = p9_tag_lookup(chan->client, rc->tag); 166 req = p9_tag_lookup(chan->client, rc->tag);
167 req->status = REQ_STATUS_RCVD; 167 p9_client_cb(chan->client, req, REQ_STATUS_RCVD);
168 p9_client_cb(chan->client, req);
169 } 168 }
170} 169}
171 170