libceph: avoid unregistering osd request when not registered
authorSage Weil <sage@inktank.com>
Wed, 16 May 2012 20:16:38 +0000 (15:16 -0500)
committerSage Weil <sage@inktank.com>
Sat, 19 May 2012 00:36:00 +0000 (17:36 -0700)
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>
net/ceph/osd_client.c

index b7d633cc96a67555165d500e197f0794b8e12e89..b098e7b591f0f2f9e8e647be37073e2e3b3e64cf 100644 (file)
@@ -841,6 +841,12 @@ static void register_request(struct ceph_osd_client *osdc,
 static void __unregister_request(struct ceph_osd_client *osdc,
                                 struct ceph_osd_request *req)
 {
+       if (RB_EMPTY_NODE(&req->r_node)) {
+               dout("__unregister_request %p tid %lld not registered\n",
+                       req, req->r_tid);
+               return;
+       }
+
        dout("__unregister_request %p tid %lld\n", req, req->r_tid);
        rb_erase(&req->r_node, &osdc->requests);
        osdc->num_requests--;