diff options
| -rw-r--r-- | include/net/9p/client.h | 6 | ||||
| -rw-r--r-- | include/net/9p/transport.h | 3 | ||||
| -rw-r--r-- | net/9p/client.c | 25 | ||||
| -rw-r--r-- | net/9p/trans_fd.c | 110 | ||||
| -rw-r--r-- | net/9p/trans_rdma.c | 26 | ||||
| -rw-r--r-- | net/9p/trans_virtio.c | 3 |
6 files changed, 96 insertions, 77 deletions
diff --git a/include/net/9p/client.h b/include/net/9p/client.h index c38a005bd0cf..6fab66c5c5af 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h | |||
| @@ -67,7 +67,6 @@ enum p9_trans_status { | |||
| 67 | * @REQ_STATUS_ALLOC: request has been allocated but not sent | 67 | * @REQ_STATUS_ALLOC: request has been allocated but not sent |
| 68 | * @REQ_STATUS_UNSENT: request waiting to be sent | 68 | * @REQ_STATUS_UNSENT: request waiting to be sent |
| 69 | * @REQ_STATUS_SENT: request sent to server | 69 | * @REQ_STATUS_SENT: request sent to server |
| 70 | * @REQ_STATUS_FLSH: a flush has been sent for this request | ||
| 71 | * @REQ_STATUS_RCVD: response received from server | 70 | * @REQ_STATUS_RCVD: response received from server |
| 72 | * @REQ_STATUS_FLSHD: request has been flushed | 71 | * @REQ_STATUS_FLSHD: request has been flushed |
| 73 | * @REQ_STATUS_ERROR: request encountered an error on the client side | 72 | * @REQ_STATUS_ERROR: request encountered an error on the client side |
| @@ -83,7 +82,6 @@ enum p9_req_status_t { | |||
| 83 | REQ_STATUS_ALLOC, | 82 | REQ_STATUS_ALLOC, |
| 84 | REQ_STATUS_UNSENT, | 83 | REQ_STATUS_UNSENT, |
| 85 | REQ_STATUS_SENT, | 84 | REQ_STATUS_SENT, |
| 86 | REQ_STATUS_FLSH, | ||
| 87 | REQ_STATUS_RCVD, | 85 | REQ_STATUS_RCVD, |
| 88 | REQ_STATUS_FLSHD, | 86 | REQ_STATUS_FLSHD, |
| 89 | REQ_STATUS_ERROR, | 87 | REQ_STATUS_ERROR, |
| @@ -130,7 +128,6 @@ struct p9_req_t { | |||
| 130 | * @proto_version: 9P protocol version to use | 128 | * @proto_version: 9P protocol version to use |
| 131 | * @trans_mod: module API instantiated with this client | 129 | * @trans_mod: module API instantiated with this client |
| 132 | * @trans: tranport instance state and API | 130 | * @trans: tranport instance state and API |
| 133 | * @conn: connection state information used by trans_fd | ||
| 134 | * @fidpool: fid handle accounting for session | 131 | * @fidpool: fid handle accounting for session |
| 135 | * @fidlist: List of active fid handles | 132 | * @fidlist: List of active fid handles |
| 136 | * @tagpool - transaction id accounting for session | 133 | * @tagpool - transaction id accounting for session |
| @@ -159,7 +156,6 @@ struct p9_client { | |||
| 159 | struct p9_trans_module *trans_mod; | 156 | struct p9_trans_module *trans_mod; |
| 160 | enum p9_trans_status status; | 157 | enum p9_trans_status status; |
| 161 | void *trans; | 158 | void *trans; |
| 162 | struct p9_conn *conn; | ||
| 163 | 159 | ||
| 164 | struct p9_idpool *fidpool; | 160 | struct p9_idpool *fidpool; |
| 165 | struct list_head fidlist; | 161 | struct list_head fidlist; |
| @@ -261,7 +257,7 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode, | |||
| 261 | int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status); | 257 | int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status); |
| 262 | int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl); | 258 | int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl); |
| 263 | struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); | 259 | struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); |
| 264 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req); | 260 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status); |
| 265 | 261 | ||
| 266 | int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int); | 262 | int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int); |
| 267 | int p9stat_read(struct p9_client *, char *, int, struct p9_wstat *); | 263 | int p9stat_read(struct p9_client *, char *, int, struct p9_wstat *); |
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 9a36d9297114..d9fa68f26c41 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h | |||
| @@ -40,6 +40,8 @@ | |||
| 40 | * @close: member function to discard a connection on this transport | 40 | * @close: member function to discard a connection on this transport |
| 41 | * @request: member function to issue a request to the transport | 41 | * @request: member function to issue a request to the transport |
| 42 | * @cancel: member function to cancel a request (if it hasn't been sent) | 42 | * @cancel: member function to cancel a request (if it hasn't been sent) |
| 43 | * @cancelled: member function to notify that a cancelled request will not | ||
| 44 | * not receive a reply | ||
| 43 | * | 45 | * |
| 44 | * This is the basic API for a transport module which is registered by the | 46 | * This is the basic API for a transport module which is registered by the |
| 45 | * transport module with the 9P core network module and used by the client | 47 | * transport module with the 9P core network module and used by the client |
| @@ -58,6 +60,7 @@ struct p9_trans_module { | |||
| 58 | void (*close) (struct p9_client *); | 60 | void (*close) (struct p9_client *); |
| 59 | int (*request) (struct p9_client *, struct p9_req_t *req); | 61 | int (*request) (struct p9_client *, struct p9_req_t *req); |
| 60 | int (*cancel) (struct p9_client *, struct p9_req_t *req); | 62 | int (*cancel) (struct p9_client *, struct p9_req_t *req); |
| 63 | int (*cancelled)(struct p9_client *, struct p9_req_t *req); | ||
| 61 | int (*zc_request)(struct p9_client *, struct p9_req_t *, | 64 | int (*zc_request)(struct p9_client *, struct p9_req_t *, |
| 62 | char *, char *, int , int, int, int); | 65 | char *, char *, int , int, int, int); |
| 63 | }; | 66 | }; |
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 | */ |
| 418 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req) | 418 | void 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 | |||
| 77 | struct 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 | |||
| 156 | struct p9_trans_fd { | ||
| 157 | struct file *rd; | ||
| 158 | struct file *wr; | ||
| 159 | struct p9_conn conn; | ||
| 160 | }; | ||
| 161 | |||
| 162 | static void p9_poll_workfn(struct work_struct *work); | 162 | static void p9_poll_workfn(struct work_struct *work); |
| 163 | 163 | ||
| 164 | static DEFINE_SPINLOCK(p9_poll_lock); | 164 | static 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 | ||
| 582 | static struct p9_conn *p9_conn_create(struct p9_client *client) | 578 | static 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 | ||
| 705 | static 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 | ||
| 781 | static int p9_fd_open(struct p9_client *client, int rfd, int wfd) | 785 | static 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 */ | ||
| 586 | static int rdma_cancel(struct p9_client *client, struct p9_req_t *req) | 592 | static 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 | */ | ||
| 603 | static 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 | ||
