Commit 034b91a3b66cf9d2983ac45f73162395c0936c36

Authored by Latchesar Ionkov
Committed by Linus Torvalds
1 parent 05818a004a

[PATCH] v9fs: fix corner cases when flushing request

When v9fs_mux_rpc sends a 9P message, it may be put in the queue of unsent
request.  If the user process receives a signal, v9fs_mux_rpc sets the
request error to ERREQFLUSH and assigns NULL to request's send message.  If
the message was still in the unsent queue, v9fs_write_work would produce an
oops while processing it.

The patch makes sure that requests that are being flushed are moved to the
pending requests queue safely.

If a request is being flushed, don't remove it from the list of pending
requests even if it receives a reply before the flush is acknoledged.  The
request will be removed during from the Rflush handler (v9fs_mux_flush_cb).

Signed-off-by: Latchesar Ionkov <lucho@ionkov.net>
Cc: Eric Van Hensbergen <ericvh@ericvh.myip.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 1 changed file with 11 additions and 4 deletions Side-by-side Diff

... ... @@ -471,10 +471,13 @@
471 471 }
472 472  
473 473 spin_lock(&m->lock);
474   - req =
475   - list_entry(m->unsent_req_list.next, struct v9fs_req,
  474 +again:
  475 + req = list_entry(m->unsent_req_list.next, struct v9fs_req,
476 476 req_list);
477 477 list_move_tail(&req->req_list, &m->req_list);
  478 + if (req->err == ERREQFLUSH)
  479 + goto again;
  480 +
478 481 m->wbuf = req->tcall->sdata;
479 482 m->wsize = req->tcall->size;
480 483 m->wpos = 0;
... ... @@ -525,7 +528,7 @@
525 528 struct v9fs_str *ename;
526 529  
527 530 tag = req->tag;
528   - if (req->rcall->id == RERROR && !req->err) {
  531 + if (!req->err && req->rcall->id == RERROR) {
529 532 ecode = req->rcall->params.rerror.errno;
530 533 ename = &req->rcall->params.rerror.error;
531 534  
... ... @@ -551,7 +554,10 @@
551 554 req->err = -EIO;
552 555 }
553 556  
554   - if (req->cb && req->err != ERREQFLUSH) {
  557 + if (req->err == ERREQFLUSH)
  558 + return;
  559 +
  560 + if (req->cb) {
555 561 dprintk(DEBUG_MUX, "calling callback tcall %p rcall %p\n",
556 562 req->tcall, req->rcall);
557 563  
... ... @@ -812,6 +818,7 @@
812 818 struct v9fs_mux_rpc *r;
813 819  
814 820 if (err == ERREQFLUSH) {
  821 + kfree(rc);
815 822 dprintk(DEBUG_MUX, "err req flush\n");
816 823 return;
817 824 }