diff options
author | Eric Van Hensbergen <ericvh@gmail.com> | 2005-09-09 16:04:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-09 16:57:58 -0400 |
commit | cb2e87a65d6cd735eb06fa595bf90497af28c37b (patch) | |
tree | ba4a261d67eb3c4830fe307ea2b97b51f0bc6fdf /fs/9p/mux.c | |
parent | b501611a6f78558eafcf09b228abd866d4ea5d9f (diff) |
[PATCH] v9fs: fix handling of malformed 9P messages
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 <lucho@ionkov.net>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/9p/mux.c')
-rw-r--r-- | fs/9p/mux.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/fs/9p/mux.c b/fs/9p/mux.c index 0854bef58c16..8835b576f744 100644 --- a/fs/9p/mux.c +++ b/fs/9p/mux.c | |||
@@ -162,18 +162,21 @@ static int v9fs_recv(struct v9fs_session_info *v9ses, struct v9fs_rpcreq *req) | |||
162 | dprintk(DEBUG_MUX, "waiting for response: %d\n", req->tcall->tag); | 162 | dprintk(DEBUG_MUX, "waiting for response: %d\n", req->tcall->tag); |
163 | ret = wait_event_interruptible(v9ses->read_wait, | 163 | ret = wait_event_interruptible(v9ses->read_wait, |
164 | ((v9ses->transport->status != Connected) || | 164 | ((v9ses->transport->status != Connected) || |
165 | (req->rcall != 0) || dprintcond(v9ses, req))); | 165 | (req->rcall != 0) || (req->err < 0) || |
166 | dprintcond(v9ses, req))); | ||
166 | 167 | ||
167 | dprintk(DEBUG_MUX, "got it: rcall %p\n", req->rcall); | 168 | dprintk(DEBUG_MUX, "got it: rcall %p\n", req->rcall); |
169 | |||
170 | spin_lock(&v9ses->muxlock); | ||
171 | list_del(&req->next); | ||
172 | spin_unlock(&v9ses->muxlock); | ||
173 | |||
174 | if (req->err < 0) | ||
175 | return req->err; | ||
176 | |||
168 | if (v9ses->transport->status == Disconnected) | 177 | if (v9ses->transport->status == Disconnected) |
169 | return -ECONNRESET; | 178 | return -ECONNRESET; |
170 | 179 | ||
171 | if (ret == 0) { | ||
172 | spin_lock(&v9ses->muxlock); | ||
173 | list_del(&req->next); | ||
174 | spin_unlock(&v9ses->muxlock); | ||
175 | } | ||
176 | |||
177 | return ret; | 180 | return ret; |
178 | } | 181 | } |
179 | 182 | ||
@@ -245,6 +248,9 @@ v9fs_mux_rpc(struct v9fs_session_info *v9ses, struct v9fs_fcall *tcall, | |||
245 | if (!v9ses) | 248 | if (!v9ses) |
246 | return -EINVAL; | 249 | return -EINVAL; |
247 | 250 | ||
251 | if (!v9ses->transport || v9ses->transport->status != Connected) | ||
252 | return -EIO; | ||
253 | |||
248 | if (rcall) | 254 | if (rcall) |
249 | *rcall = NULL; | 255 | *rcall = NULL; |
250 | 256 | ||
@@ -257,6 +263,7 @@ v9fs_mux_rpc(struct v9fs_session_info *v9ses, struct v9fs_fcall *tcall, | |||
257 | tcall->tag = tid; | 263 | tcall->tag = tid; |
258 | 264 | ||
259 | req.tcall = tcall; | 265 | req.tcall = tcall; |
266 | req.err = 0; | ||
260 | req.rcall = NULL; | 267 | req.rcall = NULL; |
261 | 268 | ||
262 | ret = v9fs_send(v9ses, &req); | 269 | ret = v9fs_send(v9ses, &req); |
@@ -371,16 +378,21 @@ static int v9fs_recvproc(void *data) | |||
371 | } | 378 | } |
372 | 379 | ||
373 | err = read_message(v9ses, rcall, v9ses->maxdata + V9FS_IOHDRSZ); | 380 | err = read_message(v9ses, rcall, v9ses->maxdata + V9FS_IOHDRSZ); |
374 | if (err < 0) { | ||
375 | kfree(rcall); | ||
376 | break; | ||
377 | } | ||
378 | spin_lock(&v9ses->muxlock); | 381 | spin_lock(&v9ses->muxlock); |
379 | list_for_each_entry_safe(rreq, rptr, &v9ses->mux_fcalls, next) { | 382 | if (err < 0) { |
380 | if (rreq->tcall->tag == rcall->tag) { | 383 | list_for_each_entry_safe(rreq, rptr, &v9ses->mux_fcalls, next) { |
381 | req = rreq; | 384 | rreq->err = err; |
382 | req->rcall = rcall; | 385 | } |
383 | break; | 386 | if(err != -ERESTARTSYS) |
387 | eprintk(KERN_ERR, | ||
388 | "Transport error while reading message %d\n", err); | ||
389 | } else { | ||
390 | list_for_each_entry_safe(rreq, rptr, &v9ses->mux_fcalls, next) { | ||
391 | if (rreq->tcall->tag == rcall->tag) { | ||
392 | req = rreq; | ||
393 | req->rcall = rcall; | ||
394 | break; | ||
395 | } | ||
384 | } | 396 | } |
385 | } | 397 | } |
386 | 398 | ||
@@ -399,9 +411,10 @@ static int v9fs_recvproc(void *data) | |||
399 | spin_unlock(&v9ses->muxlock); | 411 | spin_unlock(&v9ses->muxlock); |
400 | 412 | ||
401 | if (!req) { | 413 | if (!req) { |
402 | dprintk(DEBUG_ERROR, | 414 | if (err >= 0) |
403 | "unexpected response: id %d tag %d\n", | 415 | dprintk(DEBUG_ERROR, |
404 | rcall->id, rcall->tag); | 416 | "unexpected response: id %d tag %d\n", |
417 | rcall->id, rcall->tag); | ||
405 | 418 | ||
406 | kfree(rcall); | 419 | kfree(rcall); |
407 | } | 420 | } |
@@ -410,6 +423,8 @@ static int v9fs_recvproc(void *data) | |||
410 | set_current_state(TASK_INTERRUPTIBLE); | 423 | set_current_state(TASK_INTERRUPTIBLE); |
411 | } | 424 | } |
412 | 425 | ||
426 | v9ses->transport->close(v9ses->transport); | ||
427 | |||
413 | /* Inform all pending processes about the failure */ | 428 | /* Inform all pending processes about the failure */ |
414 | wake_up_all(&v9ses->read_wait); | 429 | wake_up_all(&v9ses->read_wait); |
415 | 430 | ||