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 | |
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')
-rw-r--r-- | fs/9p/error.h | 1 | ||||
-rw-r--r-- | fs/9p/mux.c | 53 | ||||
-rw-r--r-- | fs/9p/mux.h | 1 | ||||
-rw-r--r-- | fs/9p/trans_sock.c | 12 |
4 files changed, 46 insertions, 21 deletions
diff --git a/fs/9p/error.h b/fs/9p/error.h index 2eb5927d589e..78f89acf7c9a 100644 --- a/fs/9p/error.h +++ b/fs/9p/error.h | |||
@@ -47,6 +47,7 @@ static struct errormap errmap[] = { | |||
47 | {"Operation not permitted", EPERM}, | 47 | {"Operation not permitted", EPERM}, |
48 | {"wstat prohibited", EPERM}, | 48 | {"wstat prohibited", EPERM}, |
49 | {"No such file or directory", ENOENT}, | 49 | {"No such file or directory", ENOENT}, |
50 | {"directory entry not found", ENOENT}, | ||
50 | {"file not found", ENOENT}, | 51 | {"file not found", ENOENT}, |
51 | {"Interrupted system call", EINTR}, | 52 | {"Interrupted system call", EINTR}, |
52 | {"Input/output error", EIO}, | 53 | {"Input/output error", EIO}, |
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 | ||
diff --git a/fs/9p/mux.h b/fs/9p/mux.h index 82ce793af1b5..4994cb10badf 100644 --- a/fs/9p/mux.h +++ b/fs/9p/mux.h | |||
@@ -28,6 +28,7 @@ | |||
28 | struct v9fs_rpcreq { | 28 | struct v9fs_rpcreq { |
29 | struct v9fs_fcall *tcall; | 29 | struct v9fs_fcall *tcall; |
30 | struct v9fs_fcall *rcall; | 30 | struct v9fs_fcall *rcall; |
31 | int err; /* error code if response failed */ | ||
31 | 32 | ||
32 | /* XXX - could we put scatter/gather buffers here? */ | 33 | /* XXX - could we put scatter/gather buffers here? */ |
33 | 34 | ||
diff --git a/fs/9p/trans_sock.c b/fs/9p/trans_sock.c index 081d1c847803..01e26f0013ac 100644 --- a/fs/9p/trans_sock.c +++ b/fs/9p/trans_sock.c | |||
@@ -254,7 +254,12 @@ v9fs_unix_init(struct v9fs_session_info *v9ses, const char *dev_name, | |||
254 | 254 | ||
255 | static void v9fs_sock_close(struct v9fs_transport *trans) | 255 | static void v9fs_sock_close(struct v9fs_transport *trans) |
256 | { | 256 | { |
257 | struct v9fs_trans_sock *ts = trans ? trans->priv : NULL; | 257 | struct v9fs_trans_sock *ts; |
258 | |||
259 | if (!trans) | ||
260 | return; | ||
261 | |||
262 | ts = trans->priv; | ||
258 | 263 | ||
259 | if ((ts) && (ts->s)) { | 264 | if ((ts) && (ts->s)) { |
260 | dprintk(DEBUG_TRANS, "closing the socket %p\n", ts->s); | 265 | dprintk(DEBUG_TRANS, "closing the socket %p\n", ts->s); |
@@ -264,7 +269,10 @@ static void v9fs_sock_close(struct v9fs_transport *trans) | |||
264 | dprintk(DEBUG_TRANS, "socket closed\n"); | 269 | dprintk(DEBUG_TRANS, "socket closed\n"); |
265 | } | 270 | } |
266 | 271 | ||
267 | kfree(ts); | 272 | if (ts) |
273 | kfree(ts); | ||
274 | |||
275 | trans->priv = NULL; | ||
268 | } | 276 | } |
269 | 277 | ||
270 | struct v9fs_transport v9fs_trans_tcp = { | 278 | struct v9fs_transport v9fs_trans_tcp = { |