aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/rbd.c
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-01-25 18:08:55 -0500
committerSage Weil <sage@inktank.com>2013-02-13 21:29:10 -0500
commit8eb87565306cf40a32f5d0883d008675cd2dd510 (patch)
treee999f857dbe1ccf18508590be9c818d7835b7201 /drivers/block/rbd.c
parent25dcf954c3230946b5f3e18db9f91d7640eff76e (diff)
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: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block/rbd.c')
-rw-r--r--drivers/block/rbd.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index d3d15d06abc0..fd9656b5fdb9 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1707,6 +1707,7 @@ static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, int start)
1707 &rbd_dev->watch_event); 1707 &rbd_dev->watch_event);
1708 if (ret < 0) 1708 if (ret < 0)
1709 return ret; 1709 return ret;
1710 rbd_assert(rbd_dev->watch_event != NULL);
1710 } 1711 }
1711 1712
1712 ret = -ENOMEM; 1713 ret = -ENOMEM;
@@ -1726,32 +1727,43 @@ static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, int start)
1726 if (!obj_request->osd_req) 1727 if (!obj_request->osd_req)
1727 goto out_cancel; 1728 goto out_cancel;
1728 1729
1729 if (start) { 1730 if (start)
1730 ceph_osdc_set_request_linger(osdc, obj_request->osd_req); 1731 ceph_osdc_set_request_linger(osdc, obj_request->osd_req);
1731 rbd_dev->watch_request = obj_request; 1732 else
1732 } else {
1733 ceph_osdc_unregister_linger_request(osdc, 1733 ceph_osdc_unregister_linger_request(osdc,
1734 rbd_dev->watch_request->osd_req); 1734 rbd_dev->watch_request->osd_req);
1735 rbd_dev->watch_request = NULL;
1736 }
1737 ret = rbd_obj_request_submit(osdc, obj_request); 1735 ret = rbd_obj_request_submit(osdc, obj_request);
1738 if (ret) 1736 if (ret)
1739 goto out_cancel; 1737 goto out_cancel;
1740 ret = rbd_obj_request_wait(obj_request); 1738 ret = rbd_obj_request_wait(obj_request);
1741 if (ret) 1739 if (ret)
1742 goto out_cancel; 1740 goto out_cancel;
1743
1744 ret = obj_request->result; 1741 ret = obj_request->result;
1745 if (ret) 1742 if (ret)
1746 goto out_cancel; 1743 goto out_cancel;
1747 1744
1748 if (start) 1745 /*
1749 goto done; /* Done if setting up the watch request */ 1746 * A watch request is set to linger, so the underlying osd
1747 * request won't go away until we unregister it. We retain
1748 * a pointer to the object request during that time (in
1749 * rbd_dev->watch_request), so we'll keep a reference to
1750 * it. We'll drop that reference (below) after we've
1751 * unregistered it.
1752 */
1753 if (start) {
1754 rbd_dev->watch_request = obj_request;
1755
1756 return 0;
1757 }
1758
1759 /* We have successfully torn down the watch request */
1760
1761 rbd_obj_request_put(rbd_dev->watch_request);
1762 rbd_dev->watch_request = NULL;
1750out_cancel: 1763out_cancel:
1751 /* Cancel the event if we're tearing down, or on error */ 1764 /* Cancel the event if we're tearing down, or on error */
1752 ceph_osdc_cancel_event(rbd_dev->watch_event); 1765 ceph_osdc_cancel_event(rbd_dev->watch_event);
1753 rbd_dev->watch_event = NULL; 1766 rbd_dev->watch_event = NULL;
1754done:
1755 if (obj_request) 1767 if (obj_request)
1756 rbd_obj_request_put(obj_request); 1768 rbd_obj_request_put(obj_request);
1757 1769