[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>
This commit is contained in:
parent
05818a004a
commit
034b91a3b6
1 changed files with 11 additions and 4 deletions
15
fs/9p/mux.c
15
fs/9p/mux.c
|
@ -471,10 +471,13 @@ static void v9fs_write_work(void *a)
|
|||
}
|
||||
|
||||
spin_lock(&m->lock);
|
||||
req =
|
||||
list_entry(m->unsent_req_list.next, struct v9fs_req,
|
||||
again:
|
||||
req = list_entry(m->unsent_req_list.next, struct v9fs_req,
|
||||
req_list);
|
||||
list_move_tail(&req->req_list, &m->req_list);
|
||||
if (req->err == ERREQFLUSH)
|
||||
goto again;
|
||||
|
||||
m->wbuf = req->tcall->sdata;
|
||||
m->wsize = req->tcall->size;
|
||||
m->wpos = 0;
|
||||
|
@ -525,7 +528,7 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
|
|||
struct v9fs_str *ename;
|
||||
|
||||
tag = req->tag;
|
||||
if (req->rcall->id == RERROR && !req->err) {
|
||||
if (!req->err && req->rcall->id == RERROR) {
|
||||
ecode = req->rcall->params.rerror.errno;
|
||||
ename = &req->rcall->params.rerror.error;
|
||||
|
||||
|
@ -551,7 +554,10 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
|
|||
req->err = -EIO;
|
||||
}
|
||||
|
||||
if (req->cb && req->err != ERREQFLUSH) {
|
||||
if (req->err == ERREQFLUSH)
|
||||
return;
|
||||
|
||||
if (req->cb) {
|
||||
dprintk(DEBUG_MUX, "calling callback tcall %p rcall %p\n",
|
||||
req->tcall, req->rcall);
|
||||
|
||||
|
@ -812,6 +818,7 @@ v9fs_mux_rpc_cb(void *a, struct v9fs_fcall *tc, struct v9fs_fcall *rc, int err)
|
|||
struct v9fs_mux_rpc *r;
|
||||
|
||||
if (err == ERREQFLUSH) {
|
||||
kfree(rc);
|
||||
dprintk(DEBUG_MUX, "err req flush\n");
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue