summaryrefslogtreecommitdiff
path: root/drivers/block
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-04-27 18:59:31 +0400
committerSage Weil <sage@inktank.com>2013-05-02 08:20:01 +0400
commitb644de2ba0c5b590db9195c03358ccd0f061daa6 (patch)
tree85bfa5ab49b5a3617b04d8c4c3dab1750550f3dd /drivers/block
parent96f03e08f9f27cf72d2c24b4e75ade81d2df3c75 (diff)
downloadlinux-b644de2ba0c5b590db9195c03358ccd0f061daa6.tar.xz
rbd: set up watch in rbd_dev_image_probe()
Move setting up the watch request for an image so it's done in rbd_dev_image_probe() rather than rbd_dev_probe_finish(). Move it all the way up to before doing the initial probe. This avoids a potential race condition, in which we get (and use) the initial snapshot context for an image, and it gets changed between that time and the time we get the watch set up. This resolves: http://tracker.ceph.com/issues/3871 Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/rbd.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 52c722b471e4..ac94aa4b4d22 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -4721,11 +4721,6 @@ out_err:
static int rbd_dev_probe_finish(struct rbd_device *rbd_dev)
{
int ret;
- int tmp;
-
- ret = rbd_dev_header_watch_sync(rbd_dev, 1);
- if (ret)
- return ret;
ret = rbd_dev_mapping_set(rbd_dev);
if (ret)
@@ -4773,9 +4768,6 @@ err_out_blkdev:
unregister_blkdev(rbd_dev->major, rbd_dev->name);
err_out_id:
rbd_dev_id_put(rbd_dev);
- tmp = rbd_dev_header_watch_sync(rbd_dev, 0);
- if (tmp)
- rbd_warn(rbd_dev, "failed to cancel watch event (%d)\n", ret);
rbd_dev_mapping_clear(rbd_dev);
return ret;
@@ -4816,6 +4808,7 @@ static int rbd_dev_header_name(struct rbd_device *rbd_dev)
static int rbd_dev_image_probe(struct rbd_device *rbd_dev)
{
int ret;
+ int tmp;
/*
* Get the id from the image id object. If it's not a
@@ -4832,16 +4825,20 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev)
if (ret)
goto err_out_format;
+ ret = rbd_dev_header_watch_sync(rbd_dev, 1);
+ if (ret)
+ goto out_header_name;
+
if (rbd_dev->image_format == 1)
ret = rbd_dev_v1_probe(rbd_dev);
else
ret = rbd_dev_v2_probe(rbd_dev);
if (ret)
- goto out_header_name;
+ goto err_out_watch;
ret = rbd_dev_snaps_update(rbd_dev);
if (ret)
- goto out_header_name;
+ goto err_out_watch;
ret = rbd_dev_spec_update(rbd_dev);
if (ret)
@@ -4861,6 +4858,10 @@ err_out_parent:
rbd_header_free(&rbd_dev->header);
err_out_snaps:
rbd_remove_all_snaps(rbd_dev);
+err_out_watch:
+ tmp = rbd_dev_header_watch_sync(rbd_dev, 0);
+ if (tmp)
+ rbd_warn(rbd_dev, "unable to tear down watch request\n");
out_header_name:
kfree(rbd_dev->header_name);
rbd_dev->header_name = NULL;