aboutsummaryrefslogtreecommitdiffstats
path: root/net/ceph/osd_client.c
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2012-05-16 16:16:38 -0400
committerSage Weil <sage@inktank.com>2012-05-18 20:36:00 -0400
commit35f9f8a09e1e88e31bd34a1e645ca0e5f070dd5c (patch)
treec7bc4a1dba445ea2e250decbf9b88282ee37cb3f /net/ceph/osd_client.c
parent3da54776e2c0385c32d143fd497a7f40a88e29dd (diff)
libceph: avoid unregistering osd request when not registered
There is a race between two __unregister_request() callers: the reply path and the ceph_osdc_wait_request(). If we get a reply *and* the timeout expires at roughly the same time, both callers will try to unregister the request, and the second one will do bad things. Simply check if the request is still already unregistered; if so, return immediately and do nothing. Fixes http://tracker.newdream.net/issues/2420 Signed-off-by: Sage Weil <sage@inktank.com> Reviewed-by: Alex Elder <elder@inktank.com>
Diffstat (limited to 'net/ceph/osd_client.c')
-rw-r--r--net/ceph/osd_client.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index b7d633cc96a6..b098e7b591f0 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -841,6 +841,12 @@ static void register_request(struct ceph_osd_client *osdc,
841static void __unregister_request(struct ceph_osd_client *osdc, 841static void __unregister_request(struct ceph_osd_client *osdc,
842 struct ceph_osd_request *req) 842 struct ceph_osd_request *req)
843{ 843{
844 if (RB_EMPTY_NODE(&req->r_node)) {
845 dout("__unregister_request %p tid %lld not registered\n",
846 req, req->r_tid);
847 return;
848 }
849
844 dout("__unregister_request %p tid %lld\n", req, req->r_tid); 850 dout("__unregister_request %p tid %lld\n", req, req->r_tid);
845 rb_erase(&req->r_node, &osdc->requests); 851 rb_erase(&req->r_node, &osdc->requests);
846 osdc->num_requests--; 852 osdc->num_requests--;