From: Eric Van Hensbergen This patch attempts to do a better job of cleaning up after detecting errors on the transport. This should also improve error reporting on broken connections to servers. Signed-off-by: Latchesar Ionkov Signed-off-by: Eric Van Hensbergen Signed-off-by: Andrew Morton --- fs/9p/error.h | 1 + fs/9p/mux.c | 53 ++++++++++++++++++++++++++++++++++------------------- fs/9p/mux.h | 1 + fs/9p/trans_sock.c | 12 ++++++++++-- 4 files changed, 46 insertions(+), 21 deletions(-) diff -puN fs/9p/error.h~v9fs-fix-handling-of-malformed-9p-messages fs/9p/error.h --- devel/fs/9p/error.h~v9fs-fix-handling-of-malformed-9p-messages 2005-09-03 16:20:08.000000000 -0700 +++ devel-akpm/fs/9p/error.h 2005-09-03 16:20:08.000000000 -0700 @@ -47,6 +47,7 @@ static struct errormap errmap[] = { {"Operation not permitted", EPERM}, {"wstat prohibited", EPERM}, {"No such file or directory", ENOENT}, + {"directory entry not found", ENOENT}, {"file not found", ENOENT}, {"Interrupted system call", EINTR}, {"Input/output error", EIO}, diff -puN fs/9p/mux.c~v9fs-fix-handling-of-malformed-9p-messages fs/9p/mux.c --- devel/fs/9p/mux.c~v9fs-fix-handling-of-malformed-9p-messages 2005-09-03 16:20:08.000000000 -0700 +++ devel-akpm/fs/9p/mux.c 2005-09-03 16:20:08.000000000 -0700 @@ -162,18 +162,21 @@ static int v9fs_recv(struct v9fs_session dprintk(DEBUG_MUX, "waiting for response: %d\n", req->tcall->tag); ret = wait_event_interruptible(v9ses->read_wait, ((v9ses->transport->status != Connected) || - (req->rcall != 0) || dprintcond(v9ses, req))); + (req->rcall != 0) || (req->err < 0) || + dprintcond(v9ses, req))); dprintk(DEBUG_MUX, "got it: rcall %p\n", req->rcall); + + spin_lock(&v9ses->muxlock); + list_del(&req->next); + spin_unlock(&v9ses->muxlock); + + if (req->err < 0) + return req->err; + if (v9ses->transport->status == Disconnected) return -ECONNRESET; - if (ret == 0) { - spin_lock(&v9ses->muxlock); - list_del(&req->next); - spin_unlock(&v9ses->muxlock); - } - return ret; } @@ -245,6 +248,9 @@ v9fs_mux_rpc(struct v9fs_session_info *v if (!v9ses) return -EINVAL; + if (!v9ses->transport || v9ses->transport->status != Connected) + return -EIO; + if (rcall) *rcall = NULL; @@ -257,6 +263,7 @@ v9fs_mux_rpc(struct v9fs_session_info *v tcall->tag = tid; req.tcall = tcall; + req.err = 0; req.rcall = NULL; ret = v9fs_send(v9ses, &req); @@ -371,16 +378,21 @@ static int v9fs_recvproc(void *data) } err = read_message(v9ses, rcall, v9ses->maxdata + V9FS_IOHDRSZ); - if (err < 0) { - kfree(rcall); - break; - } spin_lock(&v9ses->muxlock); - list_for_each_entry_safe(rreq, rptr, &v9ses->mux_fcalls, next) { - if (rreq->tcall->tag == rcall->tag) { - req = rreq; - req->rcall = rcall; - break; + if (err < 0) { + list_for_each_entry_safe(rreq, rptr, &v9ses->mux_fcalls, next) { + rreq->err = err; + } + if(err != -ERESTARTSYS) + eprintk(KERN_ERR, + "Transport error while reading message %d\n", err); + } else { + list_for_each_entry_safe(rreq, rptr, &v9ses->mux_fcalls, next) { + if (rreq->tcall->tag == rcall->tag) { + req = rreq; + req->rcall = rcall; + break; + } } } @@ -399,9 +411,10 @@ static int v9fs_recvproc(void *data) spin_unlock(&v9ses->muxlock); if (!req) { - dprintk(DEBUG_ERROR, - "unexpected response: id %d tag %d\n", - rcall->id, rcall->tag); + if (err >= 0) + dprintk(DEBUG_ERROR, + "unexpected response: id %d tag %d\n", + rcall->id, rcall->tag); kfree(rcall); } @@ -410,6 +423,8 @@ static int v9fs_recvproc(void *data) set_current_state(TASK_INTERRUPTIBLE); } + v9ses->transport->close(v9ses->transport); + /* Inform all pending processes about the failure */ wake_up_all(&v9ses->read_wait); diff -puN fs/9p/mux.h~v9fs-fix-handling-of-malformed-9p-messages fs/9p/mux.h --- devel/fs/9p/mux.h~v9fs-fix-handling-of-malformed-9p-messages 2005-09-03 16:20:08.000000000 -0700 +++ devel-akpm/fs/9p/mux.h 2005-09-03 16:20:08.000000000 -0700 @@ -28,6 +28,7 @@ struct v9fs_rpcreq { struct v9fs_fcall *tcall; struct v9fs_fcall *rcall; + int err; /* error code if response failed */ /* XXX - could we put scatter/gather buffers here? */ diff -puN fs/9p/trans_sock.c~v9fs-fix-handling-of-malformed-9p-messages fs/9p/trans_sock.c --- devel/fs/9p/trans_sock.c~v9fs-fix-handling-of-malformed-9p-messages 2005-09-03 16:20:08.000000000 -0700 +++ devel-akpm/fs/9p/trans_sock.c 2005-09-03 16:20:08.000000000 -0700 @@ -254,7 +254,12 @@ v9fs_unix_init(struct v9fs_session_info static void v9fs_sock_close(struct v9fs_transport *trans) { - struct v9fs_trans_sock *ts = trans ? trans->priv : NULL; + struct v9fs_trans_sock *ts; + + if (!trans) + return; + + ts = trans->priv; if ((ts) && (ts->s)) { dprintk(DEBUG_TRANS, "closing the socket %p\n", ts->s); @@ -264,7 +269,10 @@ static void v9fs_sock_close(struct v9fs_ dprintk(DEBUG_TRANS, "socket closed\n"); } - kfree(ts); + if (ts) + kfree(ts); + + trans->priv = NULL; } struct v9fs_transport v9fs_trans_tcp = { _