]> Pileus Git - ~andy/linux/blobdiff - drivers/block/rbd.c
rbd: set up watch in rbd_dev_image_probe()
[~andy/linux] / drivers / block / rbd.c
index 44739640d94f789e7ef8652ee8ee7273875136cc..ac94aa4b4d22c9db942d619910376973c6074278 100644 (file)
@@ -4024,20 +4024,12 @@ static char *rbd_dev_snap_info(struct rbd_device *rbd_dev, u32 which,
 static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev, u64 *hver)
 {
        int ret;
-       __u8 obj_order;
 
        down_write(&rbd_dev->header_rwsem);
 
-       /* Grab old order first, to see if it changes */
-
-       obj_order = rbd_dev->header.obj_order,
        ret = rbd_dev_v2_image_size(rbd_dev);
        if (ret)
                goto out;
-       if (rbd_dev->header.obj_order != obj_order) {
-               ret = -EIO;
-               goto out;
-       }
        rbd_update_mapping_size(rbd_dev);
 
        ret = rbd_dev_v2_snap_context(rbd_dev, hver);
@@ -4730,10 +4722,6 @@ static int rbd_dev_probe_finish(struct rbd_device *rbd_dev)
 {
        int ret;
 
-       ret = rbd_dev_header_watch_sync(rbd_dev, 1);
-       if (ret)
-               return ret;
-
        ret = rbd_dev_mapping_set(rbd_dev);
        if (ret)
                return ret;
@@ -4820,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
@@ -4836,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)
@@ -4865,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;
@@ -4975,9 +4972,6 @@ static void rbd_dev_release(struct device *dev)
 {
        struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 
-       if (rbd_dev->watch_event)
-               rbd_dev_header_watch_sync(rbd_dev, 0);
-
        /* clean up and free blkdev */
        rbd_free_disk(rbd_dev);
        unregister_blkdev(rbd_dev->major, rbd_dev->name);
@@ -5003,6 +4997,7 @@ static void rbd_dev_remove_parent(struct rbd_device *rbd_dev)
                struct rbd_device *first = rbd_dev;
                struct rbd_device *second = first->parent;
                struct rbd_device *third;
+               int ret;
 
                /*
                 * Follow to the parent with no grandparent and
@@ -5013,6 +5008,10 @@ static void rbd_dev_remove_parent(struct rbd_device *rbd_dev)
                        second = third;
                }
                rbd_assert(second);
+               ret = rbd_dev_header_watch_sync(rbd_dev, 0);
+               if (ret)
+                       rbd_warn(rbd_dev,
+                               "failed to cancel watch event (%d)\n", ret);
                rbd_remove_all_snaps(second);
                rbd_bus_del_dev(second);
                first->parent = NULL;
@@ -5029,13 +5028,13 @@ static ssize_t rbd_remove(struct bus_type *bus,
                          size_t count)
 {
        struct rbd_device *rbd_dev = NULL;
-       int target_id, rc;
+       int target_id;
        unsigned long ul;
-       int ret = count;
+       int ret;
 
-       rc = strict_strtoul(buf, 10, &ul);
-       if (rc)
-               return rc;
+       ret = strict_strtoul(buf, 10, &ul);
+       if (ret)
+               return ret;
 
        /* convert to int; abort if we lost anything in the conversion */
        target_id = (int) ul;
@@ -5059,6 +5058,15 @@ static ssize_t rbd_remove(struct bus_type *bus,
        if (ret < 0)
                goto done;
 
+       ret = rbd_dev_header_watch_sync(rbd_dev, 0);
+       if (ret) {
+               rbd_warn(rbd_dev, "failed to cancel watch event (%d)\n", ret);
+               clear_bit(RBD_DEV_FLAG_REMOVING, &rbd_dev->flags);
+               smp_mb();
+               return ret;
+       }
+       ret = count;
+
        rbd_dev_remove_parent(rbd_dev);
 
        rbd_remove_all_snaps(rbd_dev);