aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2012-10-26 00:34:42 -0400
committerAlex Elder <elder@inktank.com>2012-11-01 08:55:42 -0400
commit86b00e0da6be7bbc16412f126c5b548ac5d91d50 (patch)
tree466c0dcecd75ca707f33b18265be969e385f366c /drivers/block
parenta92ffdf8a9b09f8fae9a8f418f87f30a5e459570 (diff)
rbd: get parent spec for version 2 images
Add support for getting the the information identifying the parent image for rbd images that have them. The child image holds a reference to its parent image specification structure. Create a new entry "parent" in /sys/bus/rbd/image/N/ to report the identifying information for the parent image, if any. 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.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 28052ff679ca..bce1fcfb5185 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -217,6 +217,9 @@ struct rbd_device {
217 struct ceph_osd_event *watch_event; 217 struct ceph_osd_event *watch_event;
218 struct ceph_osd_request *watch_request; 218 struct ceph_osd_request *watch_request;
219 219
220 struct rbd_spec *parent_spec;
221 u64 parent_overlap;
222
220 /* protects updating the header */ 223 /* protects updating the header */
221 struct rw_semaphore header_rwsem; 224 struct rw_semaphore header_rwsem;
222 225
@@ -2009,6 +2012,49 @@ static ssize_t rbd_snap_show(struct device *dev,
2009 return sprintf(buf, "%s\n", rbd_dev->spec->snap_name); 2012 return sprintf(buf, "%s\n", rbd_dev->spec->snap_name);
2010} 2013}
2011 2014
2015/*
2016 * For an rbd v2 image, shows the pool id, image id, and snapshot id
2017 * for the parent image. If there is no parent, simply shows
2018 * "(no parent image)".
2019 */
2020static ssize_t rbd_parent_show(struct device *dev,
2021 struct device_attribute *attr,
2022 char *buf)
2023{
2024 struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
2025 struct rbd_spec *spec = rbd_dev->parent_spec;
2026 int count;
2027 char *bufp = buf;
2028
2029 if (!spec)
2030 return sprintf(buf, "(no parent image)\n");
2031
2032 count = sprintf(bufp, "pool_id %llu\npool_name %s\n",
2033 (unsigned long long) spec->pool_id, spec->pool_name);
2034 if (count < 0)
2035 return count;
2036 bufp += count;
2037
2038 count = sprintf(bufp, "image_id %s\nimage_name %s\n", spec->image_id,
2039 spec->image_name ? spec->image_name : "(unknown)");
2040 if (count < 0)
2041 return count;
2042 bufp += count;
2043
2044 count = sprintf(bufp, "snap_id %llu\nsnap_name %s\n",
2045 (unsigned long long) spec->snap_id, spec->snap_name);
2046 if (count < 0)
2047 return count;
2048 bufp += count;
2049
2050 count = sprintf(bufp, "overlap %llu\n", rbd_dev->parent_overlap);
2051 if (count < 0)
2052 return count;
2053 bufp += count;
2054
2055 return (ssize_t) (bufp - buf);
2056}
2057
2012static ssize_t rbd_image_refresh(struct device *dev, 2058static ssize_t rbd_image_refresh(struct device *dev,
2013 struct device_attribute *attr, 2059 struct device_attribute *attr,
2014 const char *buf, 2060 const char *buf,
@@ -2032,6 +2078,7 @@ static DEVICE_ATTR(name, S_IRUGO, rbd_name_show, NULL);
2032static DEVICE_ATTR(image_id, S_IRUGO, rbd_image_id_show, NULL); 2078static DEVICE_ATTR(image_id, S_IRUGO, rbd_image_id_show, NULL);
2033static DEVICE_ATTR(refresh, S_IWUSR, NULL, rbd_image_refresh); 2079static DEVICE_ATTR(refresh, S_IWUSR, NULL, rbd_image_refresh);
2034static DEVICE_ATTR(current_snap, S_IRUGO, rbd_snap_show, NULL); 2080static DEVICE_ATTR(current_snap, S_IRUGO, rbd_snap_show, NULL);
2081static DEVICE_ATTR(parent, S_IRUGO, rbd_parent_show, NULL);
2035 2082
2036static struct attribute *rbd_attrs[] = { 2083static struct attribute *rbd_attrs[] = {
2037 &dev_attr_size.attr, 2084 &dev_attr_size.attr,
@@ -2043,6 +2090,7 @@ static struct attribute *rbd_attrs[] = {
2043 &dev_attr_name.attr, 2090 &dev_attr_name.attr,
2044 &dev_attr_image_id.attr, 2091 &dev_attr_image_id.attr,
2045 &dev_attr_current_snap.attr, 2092 &dev_attr_current_snap.attr,
2093 &dev_attr_parent.attr,
2046 &dev_attr_refresh.attr, 2094 &dev_attr_refresh.attr,
2047 NULL 2095 NULL
2048}; 2096};
@@ -2192,6 +2240,7 @@ struct rbd_device *rbd_dev_create(struct rbd_client *rbdc,
2192 2240
2193static void rbd_dev_destroy(struct rbd_device *rbd_dev) 2241static void rbd_dev_destroy(struct rbd_device *rbd_dev)
2194{ 2242{
2243 rbd_spec_put(rbd_dev->parent_spec);
2195 kfree(rbd_dev->header_name); 2244 kfree(rbd_dev->header_name);
2196 rbd_put_client(rbd_dev->rbd_client); 2245 rbd_put_client(rbd_dev->rbd_client);
2197 rbd_spec_put(rbd_dev->spec); 2246 rbd_spec_put(rbd_dev->spec);
@@ -2400,6 +2449,71 @@ static int rbd_dev_v2_features(struct rbd_device *rbd_dev)
2400 &rbd_dev->header.features); 2449 &rbd_dev->header.features);
2401} 2450}
2402 2451
2452static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
2453{
2454 struct rbd_spec *parent_spec;
2455 size_t size;
2456 void *reply_buf = NULL;
2457 __le64 snapid;
2458 void *p;
2459 void *end;
2460 char *image_id;
2461 u64 overlap;
2462 size_t len = 0;
2463 int ret;
2464
2465 parent_spec = rbd_spec_alloc();
2466 if (!parent_spec)
2467 return -ENOMEM;
2468
2469 size = sizeof (__le64) + /* pool_id */
2470 sizeof (__le32) + RBD_IMAGE_ID_LEN_MAX + /* image_id */
2471 sizeof (__le64) + /* snap_id */
2472 sizeof (__le64); /* overlap */
2473 reply_buf = kmalloc(size, GFP_KERNEL);
2474 if (!reply_buf) {
2475 ret = -ENOMEM;
2476 goto out_err;
2477 }
2478
2479 snapid = cpu_to_le64(CEPH_NOSNAP);
2480 ret = rbd_req_sync_exec(rbd_dev, rbd_dev->header_name,
2481 "rbd", "get_parent",
2482 (char *) &snapid, sizeof (snapid),
2483 (char *) reply_buf, size,
2484 CEPH_OSD_FLAG_READ, NULL);
2485 dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret);
2486 if (ret < 0)
2487 goto out_err;
2488
2489 ret = -ERANGE;
2490 p = reply_buf;
2491 end = (char *) reply_buf + size;
2492 ceph_decode_64_safe(&p, end, parent_spec->pool_id, out_err);
2493 if (parent_spec->pool_id == CEPH_NOPOOL)
2494 goto out; /* No parent? No problem. */
2495
2496 image_id = ceph_extract_encoded_string(&p, end, &len, GFP_KERNEL);
2497 if (IS_ERR(image_id)) {
2498 ret = PTR_ERR(image_id);
2499 goto out_err;
2500 }
2501 parent_spec->image_id = image_id;
2502 ceph_decode_64_safe(&p, end, parent_spec->snap_id, out_err);
2503 ceph_decode_64_safe(&p, end, overlap, out_err);
2504
2505 rbd_dev->parent_overlap = overlap;
2506 rbd_dev->parent_spec = parent_spec;
2507 parent_spec = NULL; /* rbd_dev now owns this */
2508out:
2509 ret = 0;
2510out_err:
2511 kfree(reply_buf);
2512 rbd_spec_put(parent_spec);
2513
2514 return ret;
2515}
2516
2403static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev, u64 *ver) 2517static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev, u64 *ver)
2404{ 2518{
2405 size_t size; 2519 size_t size;
@@ -3154,6 +3268,12 @@ static int rbd_dev_v1_probe(struct rbd_device *rbd_dev)
3154 ret = rbd_read_header(rbd_dev, &rbd_dev->header); 3268 ret = rbd_read_header(rbd_dev, &rbd_dev->header);
3155 if (ret < 0) 3269 if (ret < 0)
3156 goto out_err; 3270 goto out_err;
3271
3272 /* Version 1 images have no parent (no layering) */
3273
3274 rbd_dev->parent_spec = NULL;
3275 rbd_dev->parent_overlap = 0;
3276
3157 rbd_dev->image_format = 1; 3277 rbd_dev->image_format = 1;
3158 3278
3159 dout("discovered version 1 image, header name is %s\n", 3279 dout("discovered version 1 image, header name is %s\n",
@@ -3205,6 +3325,14 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
3205 if (ret < 0) 3325 if (ret < 0)
3206 goto out_err; 3326 goto out_err;
3207 3327
3328 /* If the image supports layering, get the parent info */
3329
3330 if (rbd_dev->header.features & RBD_FEATURE_LAYERING) {
3331 ret = rbd_dev_v2_parent_info(rbd_dev);
3332 if (ret < 0)
3333 goto out_err;
3334 }
3335
3208 /* crypto and compression type aren't (yet) supported for v2 images */ 3336 /* crypto and compression type aren't (yet) supported for v2 images */
3209 3337
3210 rbd_dev->header.crypt_type = 0; 3338 rbd_dev->header.crypt_type = 0;
@@ -3224,6 +3352,9 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
3224 3352
3225 return 0; 3353 return 0;
3226out_err: 3354out_err:
3355 rbd_dev->parent_overlap = 0;
3356 rbd_spec_put(rbd_dev->parent_spec);
3357 rbd_dev->parent_spec = NULL;
3227 kfree(rbd_dev->header_name); 3358 kfree(rbd_dev->header_name);
3228 rbd_dev->header_name = NULL; 3359 rbd_dev->header_name = NULL;
3229 kfree(rbd_dev->header.object_prefix); 3360 kfree(rbd_dev->header.object_prefix);