Commit 034b91a3b66cf9d2983ac45f73162395c0936c36
Committed by
Linus Torvalds
1 parent
05818a004a
Exists in
master
and in
7 other branches
[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
fs/9p/mux.c
... | ... | @@ -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 | } |