summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2012-06-20 21:53:53 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-11-26 11:38:27 -0800
commit8a62c3339d5455c46c1da1e9fb9b60df20e59905 (patch)
tree8cabebaa63de6c8f237cd7edc50ab813912571ad
parent70b06043cd9aebf15319ce3917196ff032dc20dd (diff)
downloadlinux-3.10-8a62c3339d5455c46c1da1e9fb9b60df20e59905.tar.gz
linux-3.10-8a62c3339d5455c46c1da1e9fb9b60df20e59905.tar.bz2
linux-3.10-8a62c3339d5455c46c1da1e9fb9b60df20e59905.zip
libceph: don't touch con state in con_close_socket()
(cherry picked from commit 456ea46865787283088b23a8a7f69244513b95f0) In con_close_socket(), a connection's SOCK_CLOSED flag gets set and then cleared while its shutdown method is called and its reference gets dropped. Previously, that flag got set only if it had not already been set, so setting it in con_close_socket() might have prevented additional processing being done on a socket being shut down. We no longer set SOCK_CLOSED in the socket event routine conditionally, so setting that bit here no longer provides whatever benefit it might have provided before. A race condition could still leave the SOCK_CLOSED bit set even after we've issued the call to con_close_socket(), so we still clear that bit after shutting the socket down. Add a comment explaining the reason for this. Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Sage Weil <sage@inktank.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/ceph/messenger.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index f8ca57805b1..8edd3052d34 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -392,10 +392,16 @@ static int con_close_socket(struct ceph_connection *con)
dout("con_close_socket on %p sock %p\n", con, con->sock);
if (!con->sock)
return 0;
- set_bit(SOCK_CLOSED, &con->flags);
rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR);
sock_release(con->sock);
con->sock = NULL;
+
+ /*
+ * Forcibly clear the SOCK_CLOSE flag. It gets set
+ * independent of the connection mutex, and we could have
+ * received a socket close event before we had the chance to
+ * shut the socket down.
+ */
clear_bit(SOCK_CLOSED, &con->flags);
con_sock_state_closed(con);
return rc;