提交 8eb87565 编写于 作者: A Alex Elder 提交者: Sage Weil

rbd: don't drop watch requests on completion

When we register an osd request to linger, it means that request
will stay around (under control of the osd client) until we've
unregistered it.  We do that for an rbd image's header object, and
we keep a pointer to the object request associated with it.

Keep a reference to the watch object request for as long as it is
registered to linger.  Drop it again after we've removed the linger
registration.

This resolves:
    http://tracker.ceph.com/issues/3937

(Note: this originally came about because the osd client was
issuing a callback more than once.  But that behavior will be
changing soon, documented in tracker issue 3967.)
Signed-off-by: NAlex Elder <elder@inktank.com>
Reviewed-by: NJosh Durgin <josh.durgin@inktank.com>
上级 25dcf954
...@@ -1707,6 +1707,7 @@ static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, int start) ...@@ -1707,6 +1707,7 @@ static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, int start)
&rbd_dev->watch_event); &rbd_dev->watch_event);
if (ret < 0) if (ret < 0)
return ret; return ret;
rbd_assert(rbd_dev->watch_event != NULL);
} }
ret = -ENOMEM; ret = -ENOMEM;
...@@ -1726,32 +1727,43 @@ static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, int start) ...@@ -1726,32 +1727,43 @@ static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, int start)
if (!obj_request->osd_req) if (!obj_request->osd_req)
goto out_cancel; goto out_cancel;
if (start) { if (start)
ceph_osdc_set_request_linger(osdc, obj_request->osd_req); ceph_osdc_set_request_linger(osdc, obj_request->osd_req);
rbd_dev->watch_request = obj_request; else
} else {
ceph_osdc_unregister_linger_request(osdc, ceph_osdc_unregister_linger_request(osdc,
rbd_dev->watch_request->osd_req); rbd_dev->watch_request->osd_req);
rbd_dev->watch_request = NULL;
}
ret = rbd_obj_request_submit(osdc, obj_request); ret = rbd_obj_request_submit(osdc, obj_request);
if (ret) if (ret)
goto out_cancel; goto out_cancel;
ret = rbd_obj_request_wait(obj_request); ret = rbd_obj_request_wait(obj_request);
if (ret) if (ret)
goto out_cancel; goto out_cancel;
ret = obj_request->result; ret = obj_request->result;
if (ret) if (ret)
goto out_cancel; goto out_cancel;
if (start) /*
goto done; /* Done if setting up the watch request */ * A watch request is set to linger, so the underlying osd
* request won't go away until we unregister it. We retain
* a pointer to the object request during that time (in
* rbd_dev->watch_request), so we'll keep a reference to
* it. We'll drop that reference (below) after we've
* unregistered it.
*/
if (start) {
rbd_dev->watch_request = obj_request;
return 0;
}
/* We have successfully torn down the watch request */
rbd_obj_request_put(rbd_dev->watch_request);
rbd_dev->watch_request = NULL;
out_cancel: out_cancel:
/* Cancel the event if we're tearing down, or on error */ /* Cancel the event if we're tearing down, or on error */
ceph_osdc_cancel_event(rbd_dev->watch_event); ceph_osdc_cancel_event(rbd_dev->watch_event);
rbd_dev->watch_event = NULL; rbd_dev->watch_event = NULL;
done:
if (obj_request) if (obj_request)
rbd_obj_request_put(obj_request); rbd_obj_request_put(obj_request);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册