aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlya Dryomov <ilya.dryomov@inktank.com>2014-07-24 02:42:13 -0400
committerIlya Dryomov <ilya.dryomov@inktank.com>2014-07-25 05:16:14 -0400
commite8f59b595d05b7251a9a3054c14567fd8c8220ef (patch)
treeb5fdb58bfdd0436b498475adfa405a67f334f53b
parent5ff1108ccc10dbb07bf5875e38fee313844ccef6 (diff)
rbd: do not read in parent info before snap context
Currently rbd_dev_v2_header_info() reads in parent info before the snap context is read in. This is wrong, because we may need to look at the the parent_overlap value of the snapshot instead of that of the base image, for example when mapping a snapshot - see next commit. (When mapping a snapshot, all we got is its name and we need the snap context to translate that name into an id to know which parent info to look for.) The approach taken here is to make sure rbd_dev_v2_parent_info() is called after the snap context has been read in. The other approach would be to add a parent_overlap field to struct rbd_mapping and maintain it the same way rbd_mapping::size is maintained. The reason I chose the first approach is that the value of keeping around both base image values and the actual mapping values is unclear to me. Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com> Reviewed-by: Alex Elder <elder@linaro.org>
-rw-r--r--drivers/block/rbd.c60
1 files changed, 27 insertions, 33 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 92a9ce0a9e85..c4606987e9d1 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -515,6 +515,7 @@ static void rbd_dev_remove_parent(struct rbd_device *rbd_dev);
515static int rbd_dev_refresh(struct rbd_device *rbd_dev); 515static int rbd_dev_refresh(struct rbd_device *rbd_dev);
516static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev); 516static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev);
517static int rbd_dev_header_info(struct rbd_device *rbd_dev); 517static int rbd_dev_header_info(struct rbd_device *rbd_dev);
518static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev);
518static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, 519static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev,
519 u64 snap_id); 520 u64 snap_id);
520static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id, 521static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id,
@@ -3516,6 +3517,16 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev)
3516 if (ret) 3517 if (ret)
3517 return ret; 3518 return ret;
3518 3519
3520 /*
3521 * If there is a parent, see if it has disappeared due to the
3522 * mapped image getting flattened.
3523 */
3524 if (rbd_dev->parent) {
3525 ret = rbd_dev_v2_parent_info(rbd_dev);
3526 if (ret)
3527 return ret;
3528 }
3529
3519 if (rbd_dev->spec->snap_id == CEPH_NOSNAP) { 3530 if (rbd_dev->spec->snap_id == CEPH_NOSNAP) {
3520 if (rbd_dev->mapping.size != rbd_dev->header.image_size) 3531 if (rbd_dev->mapping.size != rbd_dev->header.image_size)
3521 rbd_dev->mapping.size = rbd_dev->header.image_size; 3532 rbd_dev->mapping.size = rbd_dev->header.image_size;
@@ -3526,9 +3537,8 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev)
3526 3537
3527 up_write(&rbd_dev->header_rwsem); 3538 up_write(&rbd_dev->header_rwsem);
3528 3539
3529 if (mapping_size != rbd_dev->mapping.size) { 3540 if (mapping_size != rbd_dev->mapping.size)
3530 rbd_dev_update_size(rbd_dev); 3541 rbd_dev_update_size(rbd_dev);
3531 }
3532 3542
3533 return 0; 3543 return 0;
3534} 3544}
@@ -4479,33 +4489,6 @@ static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev)
4479 return ret; 4489 return ret;
4480 } 4490 }
4481 4491
4482 /*
4483 * If the image supports layering, get the parent info. We
4484 * need to probe the first time regardless. Thereafter we
4485 * only need to if there's a parent, to see if it has
4486 * disappeared due to the mapped image getting flattened.
4487 */
4488 if (rbd_dev->header.features & RBD_FEATURE_LAYERING &&
4489 (first_time || rbd_dev->parent_spec)) {
4490 bool warn;
4491
4492 ret = rbd_dev_v2_parent_info(rbd_dev);
4493 if (ret)
4494 return ret;
4495
4496 /*
4497 * Print a warning if this is the initial probe and
4498 * the image has a parent. Don't print it if the
4499 * image now being probed is itself a parent. We
4500 * can tell at this point because we won't know its
4501 * pool name yet (just its pool id).
4502 */
4503 warn = rbd_dev->parent_spec && rbd_dev->spec->pool_name;
4504 if (first_time && warn)
4505 rbd_warn(rbd_dev, "WARNING: kernel layering "
4506 "is EXPERIMENTAL!");
4507 }
4508
4509 ret = rbd_dev_v2_snap_context(rbd_dev); 4492 ret = rbd_dev_v2_snap_context(rbd_dev);
4510 dout("rbd_dev_v2_snap_context returned %d\n", ret); 4493 dout("rbd_dev_v2_snap_context returned %d\n", ret);
4511 4494
@@ -5185,14 +5168,28 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
5185 if (ret) 5168 if (ret)
5186 goto err_out_probe; 5169 goto err_out_probe;
5187 5170
5171 if (rbd_dev->header.features & RBD_FEATURE_LAYERING) {
5172 ret = rbd_dev_v2_parent_info(rbd_dev);
5173 if (ret)
5174 goto err_out_probe;
5175
5176 /*
5177 * Need to warn users if this image is the one being
5178 * mapped and has a parent.
5179 */
5180 if (mapping && rbd_dev->parent_spec)
5181 rbd_warn(rbd_dev,
5182 "WARNING: kernel layering is EXPERIMENTAL!");
5183 }
5184
5188 ret = rbd_dev_probe_parent(rbd_dev); 5185 ret = rbd_dev_probe_parent(rbd_dev);
5189 if (ret) 5186 if (ret)
5190 goto err_out_probe; 5187 goto err_out_probe;
5191 5188
5192 dout("discovered format %u image, header name is %s\n", 5189 dout("discovered format %u image, header name is %s\n",
5193 rbd_dev->image_format, rbd_dev->header_name); 5190 rbd_dev->image_format, rbd_dev->header_name);
5194
5195 return 0; 5191 return 0;
5192
5196err_out_probe: 5193err_out_probe:
5197 rbd_dev_unprobe(rbd_dev); 5194 rbd_dev_unprobe(rbd_dev);
5198err_out_watch: 5195err_out_watch:
@@ -5205,9 +5202,6 @@ err_out_format:
5205 rbd_dev->image_format = 0; 5202 rbd_dev->image_format = 0;
5206 kfree(rbd_dev->spec->image_id); 5203 kfree(rbd_dev->spec->image_id);
5207 rbd_dev->spec->image_id = NULL; 5204 rbd_dev->spec->image_id = NULL;
5208
5209 dout("probe failed, returning %d\n", ret);
5210
5211 return ret; 5205 return ret;
5212} 5206}
5213 5207