aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svc.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2007-02-08 17:20:30 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-09 12:25:47 -0500
commitaaf68cfbf2241d24d46583423f6bff5c47e088b3 (patch)
tree65ca14b85d28b12da097d7d187cebfef88b5ba3a /net/sunrpc/svc.c
parent387bb17374c5fa057462d00d4ba941d49f45de4d (diff)
[PATCH] knfsd: fix a race in closing NFSd connections
If you lose this race, it can iput a socket inode twice and you get a BUG in fs/inode.c When I added the option for user-space to close a socket, I added some cruft to svc_delete_socket so that I could call that function when closing a socket per user-space request. This was the wrong thing to do. I should have just set SK_CLOSE and let normal mechanisms do the work. Not only wrong, but buggy. The locking is all wrong and it openned up a race where-by a socket could be closed twice. So this patch: Introduces svc_close_socket which sets SK_CLOSE then either leave the close up to a thread, or calls svc_delete_socket if it can get SK_BUSY. Adds a bias to sk_busy which is removed when SK_DEAD is set, This avoid races around shutting down the socket. Changes several 'spin_lock' to 'spin_lock_bh' where the _bh was missing. Bugzilla-url: http://bugzilla.kernel.org/show_bug.cgi?id=7916 Signed-off-by: Neil Brown <neilb@suse.de> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'net/sunrpc/svc.c')
-rw-r--r--net/sunrpc/svc.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 4c1611211119..c1f878131ac6 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -386,7 +386,7 @@ svc_destroy(struct svc_serv *serv)
386 svsk = list_entry(serv->sv_tempsocks.next, 386 svsk = list_entry(serv->sv_tempsocks.next,
387 struct svc_sock, 387 struct svc_sock,
388 sk_list); 388 sk_list);
389 svc_delete_socket(svsk); 389 svc_close_socket(svsk);
390 } 390 }
391 if (serv->sv_shutdown) 391 if (serv->sv_shutdown)
392 serv->sv_shutdown(serv); 392 serv->sv_shutdown(serv);
@@ -395,7 +395,7 @@ svc_destroy(struct svc_serv *serv)
395 svsk = list_entry(serv->sv_permsocks.next, 395 svsk = list_entry(serv->sv_permsocks.next,
396 struct svc_sock, 396 struct svc_sock,
397 sk_list); 397 sk_list);
398 svc_delete_socket(svsk); 398 svc_close_socket(svsk);
399 } 399 }
400 400
401 cache_clean_deferred(serv); 401 cache_clean_deferred(serv);