aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/rbd.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index bce1fcfb5185..842caf4aab47 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -70,7 +70,10 @@
70 70
71#define RBD_SNAP_HEAD_NAME "-" 71#define RBD_SNAP_HEAD_NAME "-"
72 72
73/* This allows a single page to hold an image name sent by OSD */
74#define RBD_IMAGE_NAME_LEN_MAX (PAGE_SIZE - sizeof (__le32) - 1)
73#define RBD_IMAGE_ID_LEN_MAX 64 75#define RBD_IMAGE_ID_LEN_MAX 64
76
74#define RBD_OBJ_PREFIX_LEN_MAX 64 77#define RBD_OBJ_PREFIX_LEN_MAX 64
75 78
76/* Feature bits */ 79/* Feature bits */
@@ -658,6 +661,20 @@ out_err:
658 return -ENOMEM; 661 return -ENOMEM;
659} 662}
660 663
664static const char *rbd_snap_name(struct rbd_device *rbd_dev, u64 snap_id)
665{
666 struct rbd_snap *snap;
667
668 if (snap_id == CEPH_NOSNAP)
669 return RBD_SNAP_HEAD_NAME;
670
671 list_for_each_entry(snap, &rbd_dev->snaps, node)
672 if (snap_id == snap->id)
673 return snap->name;
674
675 return NULL;
676}
677
661static int snap_by_name(struct rbd_device *rbd_dev, const char *snap_name) 678static int snap_by_name(struct rbd_device *rbd_dev, const char *snap_name)
662{ 679{
663 680
@@ -2499,6 +2516,7 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
2499 goto out_err; 2516 goto out_err;
2500 } 2517 }
2501 parent_spec->image_id = image_id; 2518 parent_spec->image_id = image_id;
2519 parent_spec->image_id_len = len;
2502 ceph_decode_64_safe(&p, end, parent_spec->snap_id, out_err); 2520 ceph_decode_64_safe(&p, end, parent_spec->snap_id, out_err);
2503 ceph_decode_64_safe(&p, end, overlap, out_err); 2521 ceph_decode_64_safe(&p, end, overlap, out_err);
2504 2522
@@ -2514,6 +2532,117 @@ out_err:
2514 return ret; 2532 return ret;
2515} 2533}
2516 2534
2535static char *rbd_dev_image_name(struct rbd_device *rbd_dev)
2536{
2537 size_t image_id_size;
2538 char *image_id;
2539 void *p;
2540 void *end;
2541 size_t size;
2542 void *reply_buf = NULL;
2543 size_t len = 0;
2544 char *image_name = NULL;
2545 int ret;
2546
2547 rbd_assert(!rbd_dev->spec->image_name);
2548
2549 image_id_size = sizeof (__le32) + rbd_dev->spec->image_id_len;
2550 image_id = kmalloc(image_id_size, GFP_KERNEL);
2551 if (!image_id)
2552 return NULL;
2553
2554 p = image_id;
2555 end = (char *) image_id + image_id_size;
2556 ceph_encode_string(&p, end, rbd_dev->spec->image_id,
2557 (u32) rbd_dev->spec->image_id_len);
2558
2559 size = sizeof (__le32) + RBD_IMAGE_NAME_LEN_MAX;
2560 reply_buf = kmalloc(size, GFP_KERNEL);
2561 if (!reply_buf)
2562 goto out;
2563
2564 ret = rbd_req_sync_exec(rbd_dev, RBD_DIRECTORY,
2565 "rbd", "dir_get_name",
2566 image_id, image_id_size,
2567 (char *) reply_buf, size,
2568 CEPH_OSD_FLAG_READ, NULL);
2569 if (ret < 0)
2570 goto out;
2571 p = reply_buf;
2572 end = (char *) reply_buf + size;
2573 image_name = ceph_extract_encoded_string(&p, end, &len, GFP_KERNEL);
2574 if (IS_ERR(image_name))
2575 image_name = NULL;
2576 else
2577 dout("%s: name is %s len is %zd\n", __func__, image_name, len);
2578out:
2579 kfree(reply_buf);
2580 kfree(image_id);
2581
2582 return image_name;
2583}
2584
2585/*
2586 * When a parent image gets probed, we only have the pool, image,
2587 * and snapshot ids but not the names of any of them. This call
2588 * is made later to fill in those names. It has to be done after
2589 * rbd_dev_snaps_update() has completed because some of the
2590 * information (in particular, snapshot name) is not available
2591 * until then.
2592 */
2593static int rbd_dev_probe_update_spec(struct rbd_device *rbd_dev)
2594{
2595 struct ceph_osd_client *osdc;
2596 const char *name;
2597 void *reply_buf = NULL;
2598 int ret;
2599
2600 if (rbd_dev->spec->pool_name)
2601 return 0; /* Already have the names */
2602
2603 /* Look up the pool name */
2604
2605 osdc = &rbd_dev->rbd_client->client->osdc;
2606 name = ceph_pg_pool_name_by_id(osdc->osdmap, rbd_dev->spec->pool_id);
2607 if (!name)
2608 return -EIO; /* pool id too large (>= 2^31) */
2609
2610 rbd_dev->spec->pool_name = kstrdup(name, GFP_KERNEL);
2611 if (!rbd_dev->spec->pool_name)
2612 return -ENOMEM;
2613
2614 /* Fetch the image name; tolerate failure here */
2615
2616 name = rbd_dev_image_name(rbd_dev);
2617 if (name) {
2618 rbd_dev->spec->image_name_len = strlen(name);
2619 rbd_dev->spec->image_name = (char *) name;
2620 } else {
2621 pr_warning(RBD_DRV_NAME "%d "
2622 "unable to get image name for image id %s\n",
2623 rbd_dev->major, rbd_dev->spec->image_id);
2624 }
2625
2626 /* Look up the snapshot name. */
2627
2628 name = rbd_snap_name(rbd_dev, rbd_dev->spec->snap_id);
2629 if (!name) {
2630 ret = -EIO;
2631 goto out_err;
2632 }
2633 rbd_dev->spec->snap_name = kstrdup(name, GFP_KERNEL);
2634 if(!rbd_dev->spec->snap_name)
2635 goto out_err;
2636
2637 return 0;
2638out_err:
2639 kfree(reply_buf);
2640 kfree(rbd_dev->spec->pool_name);
2641 rbd_dev->spec->pool_name = NULL;
2642
2643 return ret;
2644}
2645
2517static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev, u64 *ver) 2646static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev, u64 *ver)
2518{ 2647{
2519 size_t size; 2648 size_t size;
@@ -3372,6 +3501,10 @@ static int rbd_dev_probe_finish(struct rbd_device *rbd_dev)
3372 if (ret) 3501 if (ret)
3373 return ret; 3502 return ret;
3374 3503
3504 ret = rbd_dev_probe_update_spec(rbd_dev);
3505 if (ret)
3506 goto err_out_snaps;
3507
3375 ret = rbd_dev_set_mapping(rbd_dev); 3508 ret = rbd_dev_set_mapping(rbd_dev);
3376 if (ret) 3509 if (ret)
3377 goto err_out_snaps; 3510 goto err_out_snaps;