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>
This commit is contained in:
Родитель
3da54776e2
Коммит
35f9f8a09e
|
@ -841,6 +841,12 @@ static void register_request(struct ceph_osd_client *osdc,
|
||||||
static void __unregister_request(struct ceph_osd_client *osdc,
|
static void __unregister_request(struct ceph_osd_client *osdc,
|
||||||
struct ceph_osd_request *req)
|
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);
|
dout("__unregister_request %p tid %lld\n", req, req->r_tid);
|
||||||
rb_erase(&req->r_node, &osdc->requests);
|
rb_erase(&req->r_node, &osdc->requests);
|
||||||
osdc->num_requests--;
|
osdc->num_requests--;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче