diff options
| -rw-r--r-- | include/net/9p/client.h | 1 | ||||
| -rw-r--r-- | net/9p/client.c | 74 | ||||
| -rw-r--r-- | net/9p/trans_fd.c | 14 | ||||
| -rw-r--r-- | net/9p/trans_rdma.c | 1 | ||||
| -rw-r--r-- | net/9p/trans_virtio.c | 1 |
5 files changed, 30 insertions, 61 deletions
diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 4012e07162e5..e26812274b75 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h | |||
| @@ -98,7 +98,6 @@ enum p9_req_status_t { | |||
| 98 | struct p9_req_t { | 98 | struct p9_req_t { |
| 99 | int status; | 99 | int status; |
| 100 | int t_err; | 100 | int t_err; |
| 101 | u16 flush_tag; | ||
| 102 | wait_queue_head_t *wq; | 101 | wait_queue_head_t *wq; |
| 103 | struct p9_fcall *tc; | 102 | struct p9_fcall *tc; |
| 104 | struct p9_fcall *rc; | 103 | struct p9_fcall *rc; |
diff --git a/net/9p/client.c b/net/9p/client.c index 781d89a952e4..dd43a8289b0d 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
| @@ -203,7 +203,6 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) | |||
| 203 | p9pdu_reset(req->tc); | 203 | p9pdu_reset(req->tc); |
| 204 | p9pdu_reset(req->rc); | 204 | p9pdu_reset(req->rc); |
| 205 | 205 | ||
| 206 | req->flush_tag = 0; | ||
| 207 | req->tc->tag = tag-1; | 206 | req->tc->tag = tag-1; |
| 208 | req->status = REQ_STATUS_ALLOC; | 207 | req->status = REQ_STATUS_ALLOC; |
| 209 | 208 | ||
| @@ -324,35 +323,9 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r) | |||
| 324 | */ | 323 | */ |
| 325 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req) | 324 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req) |
| 326 | { | 325 | { |
| 327 | struct p9_req_t *other_req; | ||
| 328 | unsigned long flags; | ||
| 329 | |||
| 330 | P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); | 326 | P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); |
| 331 | 327 | wake_up(req->wq); | |
| 332 | if (req->status == REQ_STATUS_ERROR) | 328 | P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); |
| 333 | wake_up(req->wq); | ||
| 334 | |||
| 335 | if (req->flush_tag) { /* flush receive path */ | ||
| 336 | P9_DPRINTK(P9_DEBUG_9P, "<<< RFLUSH %d\n", req->tc->tag); | ||
| 337 | spin_lock_irqsave(&c->lock, flags); | ||
| 338 | other_req = p9_tag_lookup(c, req->flush_tag); | ||
| 339 | if (other_req->status != REQ_STATUS_FLSH) /* stale flush */ | ||
| 340 | spin_unlock_irqrestore(&c->lock, flags); | ||
| 341 | else { | ||
| 342 | other_req->status = REQ_STATUS_FLSHD; | ||
| 343 | spin_unlock_irqrestore(&c->lock, flags); | ||
| 344 | wake_up(other_req->wq); | ||
| 345 | } | ||
| 346 | p9_free_req(c, req); | ||
| 347 | } else { /* normal receive path */ | ||
| 348 | P9_DPRINTK(P9_DEBUG_MUX, "normal: tag %d\n", req->tc->tag); | ||
| 349 | spin_lock_irqsave(&c->lock, flags); | ||
| 350 | if (req->status != REQ_STATUS_FLSHD) | ||
| 351 | req->status = REQ_STATUS_RCVD; | ||
| 352 | spin_unlock_irqrestore(&c->lock, flags); | ||
| 353 | wake_up(req->wq); | ||
| 354 | P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); | ||
| 355 | } | ||
| 356 | } | 329 | } |
| 357 | EXPORT_SYMBOL(p9_client_cb); | 330 | EXPORT_SYMBOL(p9_client_cb); |
| 358 | 331 | ||
| @@ -486,9 +459,15 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) | |||
| 486 | if (IS_ERR(req)) | 459 | if (IS_ERR(req)) |
| 487 | return PTR_ERR(req); | 460 | return PTR_ERR(req); |
| 488 | 461 | ||
| 489 | req->flush_tag = oldtag; | ||
| 490 | 462 | ||
| 491 | /* we don't free anything here because RPC isn't complete */ | 463 | /* if we haven't received a response for oldreq, |
| 464 | remove it from the list. */ | ||
| 465 | spin_lock(&c->lock); | ||
| 466 | if (oldreq->status == REQ_STATUS_FLSH) | ||
| 467 | list_del(&oldreq->req_list); | ||
| 468 | spin_unlock(&c->lock); | ||
| 469 | |||
| 470 | p9_free_req(c, req); | ||
| 492 | return 0; | 471 | return 0; |
| 493 | } | 472 | } |
| 494 | 473 | ||
| @@ -509,7 +488,6 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
| 509 | struct p9_req_t *req; | 488 | struct p9_req_t *req; |
| 510 | unsigned long flags; | 489 | unsigned long flags; |
| 511 | int sigpending; | 490 | int sigpending; |
| 512 | int flushed = 0; | ||
| 513 | 491 | ||
| 514 | P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); | 492 | P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); |
| 515 | 493 | ||
| @@ -546,42 +524,28 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
| 546 | goto reterr; | 524 | goto reterr; |
| 547 | } | 525 | } |
| 548 | 526 | ||
| 549 | /* if it was a flush we just transmitted, return our tag */ | ||
| 550 | if (type == P9_TFLUSH) | ||
| 551 | return req; | ||
| 552 | again: | ||
| 553 | P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag); | 527 | P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag); |
| 554 | err = wait_event_interruptible(*req->wq, | 528 | err = wait_event_interruptible(*req->wq, |
| 555 | req->status >= REQ_STATUS_RCVD); | 529 | req->status >= REQ_STATUS_RCVD); |
| 556 | P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d (flushed=%d)\n", | 530 | P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n", |
| 557 | req->wq, tag, err, flushed); | 531 | req->wq, tag, err); |
| 558 | 532 | ||
| 559 | if (req->status == REQ_STATUS_ERROR) { | 533 | if (req->status == REQ_STATUS_ERROR) { |
| 560 | P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); | 534 | P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); |
| 561 | err = req->t_err; | 535 | err = req->t_err; |
| 562 | } else if (err == -ERESTARTSYS && flushed) { | ||
| 563 | P9_DPRINTK(P9_DEBUG_MUX, "flushed - going again\n"); | ||
| 564 | goto again; | ||
| 565 | } else if (req->status == REQ_STATUS_FLSHD) { | ||
| 566 | P9_DPRINTK(P9_DEBUG_MUX, "flushed - erestartsys\n"); | ||
| 567 | err = -ERESTARTSYS; | ||
| 568 | } | 536 | } |
| 569 | 537 | ||
| 570 | if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) { | 538 | if ((err == -ERESTARTSYS) && (c->status == Connected)) { |
| 571 | P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); | 539 | P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); |
| 572 | spin_lock_irqsave(&c->lock, flags); | ||
| 573 | if (req->status == REQ_STATUS_SENT) | ||
| 574 | req->status = REQ_STATUS_FLSH; | ||
| 575 | spin_unlock_irqrestore(&c->lock, flags); | ||
| 576 | sigpending = 1; | 540 | sigpending = 1; |
| 577 | flushed = 1; | ||
| 578 | clear_thread_flag(TIF_SIGPENDING); | 541 | clear_thread_flag(TIF_SIGPENDING); |
| 579 | 542 | ||
| 580 | if (c->trans_mod->cancel(c, req)) { | 543 | if (c->trans_mod->cancel(c, req)) |
| 581 | err = p9_client_flush(c, req); | 544 | p9_client_flush(c, req); |
| 582 | if (err == 0) | 545 | |
| 583 | goto again; | 546 | /* if we received the response anyway, don't signal error */ |
| 584 | } | 547 | if (req->status == REQ_STATUS_RCVD) |
| 548 | err = 0; | ||
| 585 | } | 549 | } |
| 586 | 550 | ||
| 587 | if (sigpending) { | 551 | if (sigpending) { |
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index c613ed08a5ee..a2a1814c7a8d 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
| @@ -213,8 +213,8 @@ static void p9_conn_cancel(struct p9_conn *m, int err) | |||
| 213 | spin_unlock_irqrestore(&m->client->lock, flags); | 213 | spin_unlock_irqrestore(&m->client->lock, flags); |
| 214 | 214 | ||
| 215 | list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { | 215 | list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { |
| 216 | list_del(&req->req_list); | ||
| 217 | P9_DPRINTK(P9_DEBUG_ERROR, "call back req %p\n", req); | 216 | P9_DPRINTK(P9_DEBUG_ERROR, "call back req %p\n", req); |
| 217 | list_del(&req->req_list); | ||
| 218 | p9_client_cb(m->client, req); | 218 | p9_client_cb(m->client, req); |
| 219 | } | 219 | } |
| 220 | } | 220 | } |
| @@ -336,7 +336,8 @@ static void p9_read_work(struct work_struct *work) | |||
| 336 | "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); | 336 | "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); |
| 337 | 337 | ||
| 338 | m->req = p9_tag_lookup(m->client, tag); | 338 | m->req = p9_tag_lookup(m->client, tag); |
| 339 | if (!m->req) { | 339 | if (!m->req || (m->req->status != REQ_STATUS_SENT && |
| 340 | m->req->status != REQ_STATUS_FLSH)) { | ||
| 340 | P9_DPRINTK(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", | 341 | P9_DPRINTK(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", |
| 341 | tag); | 342 | tag); |
| 342 | err = -EIO; | 343 | err = -EIO; |
| @@ -361,10 +362,11 @@ static void p9_read_work(struct work_struct *work) | |||
| 361 | if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ | 362 | if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ |
| 362 | P9_DPRINTK(P9_DEBUG_TRANS, "got new packet\n"); | 363 | P9_DPRINTK(P9_DEBUG_TRANS, "got new packet\n"); |
| 363 | spin_lock(&m->client->lock); | 364 | spin_lock(&m->client->lock); |
| 365 | if (m->req->status != REQ_STATUS_ERROR) | ||
| 366 | m->req->status = REQ_STATUS_RCVD; | ||
| 364 | list_del(&m->req->req_list); | 367 | list_del(&m->req->req_list); |
| 365 | spin_unlock(&m->client->lock); | 368 | spin_unlock(&m->client->lock); |
| 366 | p9_client_cb(m->client, m->req); | 369 | p9_client_cb(m->client, m->req); |
| 367 | |||
| 368 | m->rbuf = NULL; | 370 | m->rbuf = NULL; |
| 369 | m->rpos = 0; | 371 | m->rpos = 0; |
| 370 | m->rsize = 0; | 372 | m->rsize = 0; |
| @@ -454,6 +456,7 @@ static void p9_write_work(struct work_struct *work) | |||
| 454 | req = list_entry(m->unsent_req_list.next, struct p9_req_t, | 456 | req = list_entry(m->unsent_req_list.next, struct p9_req_t, |
| 455 | req_list); | 457 | req_list); |
| 456 | req->status = REQ_STATUS_SENT; | 458 | req->status = REQ_STATUS_SENT; |
| 459 | P9_DPRINTK(P9_DEBUG_TRANS, "move req %p\n", req); | ||
| 457 | list_move_tail(&req->req_list, &m->req_list); | 460 | list_move_tail(&req->req_list, &m->req_list); |
| 458 | 461 | ||
| 459 | m->wbuf = req->tc->sdata; | 462 | m->wbuf = req->tc->sdata; |
| @@ -683,12 +686,13 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) | |||
| 683 | P9_DPRINTK(P9_DEBUG_TRANS, "client %p req %p\n", client, req); | 686 | P9_DPRINTK(P9_DEBUG_TRANS, "client %p req %p\n", client, req); |
| 684 | 687 | ||
| 685 | spin_lock(&client->lock); | 688 | spin_lock(&client->lock); |
| 686 | list_del(&req->req_list); | ||
| 687 | 689 | ||
| 688 | if (req->status == REQ_STATUS_UNSENT) { | 690 | if (req->status == REQ_STATUS_UNSENT) { |
| 691 | list_del(&req->req_list); | ||
| 689 | req->status = REQ_STATUS_FLSHD; | 692 | req->status = REQ_STATUS_FLSHD; |
| 690 | ret = 0; | 693 | ret = 0; |
| 691 | } | 694 | } else if (req->status == REQ_STATUS_SENT) |
| 695 | req->status = REQ_STATUS_FLSH; | ||
| 692 | 696 | ||
| 693 | spin_unlock(&client->lock); | 697 | spin_unlock(&client->lock); |
| 694 | 698 | ||
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 7fa0eb20b2f6..ac4990041ebb 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c | |||
| @@ -295,6 +295,7 @@ handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma, | |||
| 295 | goto err_out; | 295 | goto err_out; |
| 296 | 296 | ||
| 297 | req->rc = c->rc; | 297 | req->rc = c->rc; |
| 298 | req->status = REQ_STATUS_RCVD; | ||
| 298 | p9_client_cb(client, req); | 299 | p9_client_cb(client, req); |
| 299 | 300 | ||
| 300 | return; | 301 | return; |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 2d7781ec663b..bb8579a141a8 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
| @@ -134,6 +134,7 @@ static void req_done(struct virtqueue *vq) | |||
| 134 | P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); | 134 | P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); |
| 135 | P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); | 135 | P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); |
| 136 | req = p9_tag_lookup(chan->client, rc->tag); | 136 | req = p9_tag_lookup(chan->client, rc->tag); |
| 137 | req->status = REQ_STATUS_RCVD; | ||
| 137 | p9_client_cb(chan->client, req); | 138 | p9_client_cb(chan->client, req); |
| 138 | } | 139 | } |
| 139 | } | 140 | } |
