aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-04-27 10:59:31 -0400
committerSage Weil <sage@inktank.com>2013-05-02 00:20:01 -0400
commitb644de2ba0c5b590db9195c03358ccd0f061daa6 (patch)
tree85bfa5ab49b5a3617b04d8c4c3dab1750550f3dd /drivers/block
parent96f03e08f9f27cf72d2c24b4e75ade81d2df3c75 (diff)
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:
4721static int rbd_dev_probe_finish(struct rbd_device *rbd_dev) 4721static int rbd_dev_probe_finish(struct rbd_device *rbd_dev)
4722{ 4722{
4723 int ret; 4723 int ret;
4724 int tmp;
4725
4726 ret = rbd_dev_header_watch_sync(rbd_dev, 1);
4727 if (ret)
4728 return ret;
4729 4724
4730 ret = rbd_dev_mapping_set(rbd_dev); 4725 ret = rbd_dev_mapping_set(rbd_dev);
4731 if (ret) 4726 if (ret)
@@ -4773,9 +4768,6 @@ err_out_blkdev:
4773 unregister_blkdev(rbd_dev->major, rbd_dev->name); 4768 unregister_blkdev(rbd_dev->major, rbd_dev->name);
4774err_out_id: 4769err_out_id:
4775 rbd_dev_id_put(rbd_dev); 4770 rbd_dev_id_put(rbd_dev);
4776 tmp = rbd_dev_header_watch_sync(rbd_dev, 0);
4777 if (tmp)
4778 rbd_warn(rbd_dev, "failed to cancel watch event (%d)\n", ret);
4779 rbd_dev_mapping_clear(rbd_dev); 4771 rbd_dev_mapping_clear(rbd_dev);
4780 4772
4781 return ret; 4773 return ret;
@@ -4816,6 +4808,7 @@ static int rbd_dev_header_name(struct rbd_device *rbd_dev)
4816static int rbd_dev_image_probe(struct rbd_device *rbd_dev) 4808static int rbd_dev_image_probe(struct rbd_device *rbd_dev)
4817{ 4809{
4818 int ret; 4810 int ret;
4811 int tmp;
4819 4812
4820 /* 4813 /*
4821 * Get the id from the image id object. If it's not a 4814 * 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)
4832 if (ret) 4825 if (ret)
4833 goto err_out_format; 4826 goto err_out_format;
4834 4827
4828 ret = rbd_dev_header_watch_sync(rbd_dev, 1);
4829 if (ret)
4830 goto out_header_name;
4831
4835 if (rbd_dev->image_format == 1) 4832 if (rbd_dev->image_format == 1)
4836 ret = rbd_dev_v1_probe(rbd_dev); 4833 ret = rbd_dev_v1_probe(rbd_dev);
4837 else 4834 else
4838 ret = rbd_dev_v2_probe(rbd_dev); 4835 ret = rbd_dev_v2_probe(rbd_dev);
4839 if (ret) 4836 if (ret)
4840 goto out_header_name; 4837 goto err_out_watch;
4841 4838
4842 ret = rbd_dev_snaps_update(rbd_dev); 4839 ret = rbd_dev_snaps_update(rbd_dev);
4843 if (ret) 4840 if (ret)
4844 goto out_header_name; 4841 goto err_out_watch;
4845 4842
4846 ret = rbd_dev_spec_update(rbd_dev); 4843 ret = rbd_dev_spec_update(rbd_dev);
4847 if (ret) 4844 if (ret)
@@ -4861,6 +4858,10 @@ err_out_parent:
4861 rbd_header_free(&rbd_dev->header); 4858 rbd_header_free(&rbd_dev->header);
4862err_out_snaps: 4859err_out_snaps:
4863 rbd_remove_all_snaps(rbd_dev); 4860 rbd_remove_all_snaps(rbd_dev);
4861err_out_watch:
4862 tmp = rbd_dev_header_watch_sync(rbd_dev, 0);
4863 if (tmp)
4864 rbd_warn(rbd_dev, "unable to tear down watch request\n");
4864out_header_name: 4865out_header_name:
4865 kfree(rbd_dev->header_name); 4866 kfree(rbd_dev->header_name);
4866 rbd_dev->header_name = NULL; 4867 rbd_dev->header_name = NULL;