diff options
author | Alex Elder <elder@inktank.com> | 2012-07-10 21:30:11 -0400 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2012-10-01 15:30:53 -0400 |
commit | a30b71b999c92071befec73434f4e67fd4b4734b (patch) | |
tree | fc48430344eb6904fa59c9f7a2a121add329ebba /drivers/block | |
parent | cd892126c617b3837b6088bf6c097ad2def4de83 (diff) |
rbd: lay out header probe infrastructure
This defines a new function rbd_dev_probe() as a top-level
function for populating detailed information about an rbd device.
It first checks for the existence of a format 2 rbd image id object.
If it exists, the image is assumed to be a format 2 rbd image, and
another function rbd_dev_v2() is called to finish populating
header data for that image. If it does not exist, it is assumed to
be an old (format 1) rbd image, and calls a similar function
rbd_dev_v1() to populate its header information.
A new field, rbd_dev->format, is defined to record which version
of the rbd image format the device represents. For a valid mapped
rbd device it will have one of two values, 1 or 2.
So far, the format 2 images are not really supported; this is
laying out the infrastructure for fleshing out that support.
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.c | 127 |
1 files changed, 99 insertions, 28 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 366a3a1f2aac..3b284d53a566 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -170,6 +170,7 @@ struct rbd_device { | |||
170 | int major; /* blkdev assigned major */ | 170 | int major; /* blkdev assigned major */ |
171 | struct gendisk *disk; /* blkdev's gendisk and rq */ | 171 | struct gendisk *disk; /* blkdev's gendisk and rq */ |
172 | 172 | ||
173 | u32 image_format; /* Either 1 or 2 */ | ||
173 | struct rbd_options rbd_opts; | 174 | struct rbd_options rbd_opts; |
174 | struct rbd_client *rbd_client; | 175 | struct rbd_client *rbd_client; |
175 | 176 | ||
@@ -507,6 +508,11 @@ static void rbd_coll_release(struct kref *kref) | |||
507 | kfree(coll); | 508 | kfree(coll); |
508 | } | 509 | } |
509 | 510 | ||
511 | static bool rbd_image_format_valid(u32 image_format) | ||
512 | { | ||
513 | return image_format == 1 || image_format == 2; | ||
514 | } | ||
515 | |||
510 | static bool rbd_dev_ondisk_valid(struct rbd_image_header_ondisk *ondisk) | 516 | static bool rbd_dev_ondisk_valid(struct rbd_image_header_ondisk *ondisk) |
511 | { | 517 | { |
512 | size_t size; | 518 | size_t size; |
@@ -2584,6 +2590,96 @@ out: | |||
2584 | return ret; | 2590 | return ret; |
2585 | } | 2591 | } |
2586 | 2592 | ||
2593 | static int rbd_dev_v1_probe(struct rbd_device *rbd_dev) | ||
2594 | { | ||
2595 | int ret; | ||
2596 | size_t size; | ||
2597 | |||
2598 | /* Version 1 images have no id; empty string is used */ | ||
2599 | |||
2600 | rbd_dev->image_id = kstrdup("", GFP_KERNEL); | ||
2601 | if (!rbd_dev->image_id) | ||
2602 | return -ENOMEM; | ||
2603 | rbd_dev->image_id_len = 0; | ||
2604 | |||
2605 | /* Record the header object name for this rbd image. */ | ||
2606 | |||
2607 | size = rbd_dev->image_name_len + sizeof (RBD_SUFFIX); | ||
2608 | rbd_dev->header_name = kmalloc(size, GFP_KERNEL); | ||
2609 | if (!rbd_dev->header_name) { | ||
2610 | ret = -ENOMEM; | ||
2611 | goto out_err; | ||
2612 | } | ||
2613 | sprintf(rbd_dev->header_name, "%s%s", rbd_dev->image_name, RBD_SUFFIX); | ||
2614 | |||
2615 | /* Populate rbd image metadata */ | ||
2616 | |||
2617 | ret = rbd_read_header(rbd_dev, &rbd_dev->header); | ||
2618 | if (ret < 0) | ||
2619 | goto out_err; | ||
2620 | rbd_dev->image_format = 1; | ||
2621 | |||
2622 | dout("discovered version 1 image, header name is %s\n", | ||
2623 | rbd_dev->header_name); | ||
2624 | |||
2625 | return 0; | ||
2626 | |||
2627 | out_err: | ||
2628 | kfree(rbd_dev->header_name); | ||
2629 | rbd_dev->header_name = NULL; | ||
2630 | kfree(rbd_dev->image_id); | ||
2631 | rbd_dev->image_id = NULL; | ||
2632 | |||
2633 | return ret; | ||
2634 | } | ||
2635 | |||
2636 | static int rbd_dev_v2_probe(struct rbd_device *rbd_dev) | ||
2637 | { | ||
2638 | size_t size; | ||
2639 | |||
2640 | /* | ||
2641 | * Image id was filled in by the caller. Record the header | ||
2642 | * object name for this rbd image. | ||
2643 | */ | ||
2644 | size = sizeof (RBD_HEADER_PREFIX) + rbd_dev->image_id_len; | ||
2645 | rbd_dev->header_name = kmalloc(size, GFP_KERNEL); | ||
2646 | if (!rbd_dev->header_name) | ||
2647 | return -ENOMEM; | ||
2648 | sprintf(rbd_dev->header_name, "%s%s", | ||
2649 | RBD_HEADER_PREFIX, rbd_dev->image_id); | ||
2650 | rbd_dev->image_format = 2; | ||
2651 | |||
2652 | dout("discovered version 2 image, header name is %s\n", | ||
2653 | rbd_dev->header_name); | ||
2654 | |||
2655 | return -ENOTSUPP; | ||
2656 | } | ||
2657 | |||
2658 | /* | ||
2659 | * Probe for the existence of the header object for the given rbd | ||
2660 | * device. For format 2 images this includes determining the image | ||
2661 | * id. | ||
2662 | */ | ||
2663 | static int rbd_dev_probe(struct rbd_device *rbd_dev) | ||
2664 | { | ||
2665 | int ret; | ||
2666 | |||
2667 | /* | ||
2668 | * Get the id from the image id object. If it's not a | ||
2669 | * format 2 image, we'll get ENOENT back, and we'll assume | ||
2670 | * it's a format 1 image. | ||
2671 | */ | ||
2672 | ret = rbd_dev_image_id(rbd_dev); | ||
2673 | if (ret) | ||
2674 | ret = rbd_dev_v1_probe(rbd_dev); | ||
2675 | else | ||
2676 | ret = rbd_dev_v2_probe(rbd_dev); | ||
2677 | if (ret) | ||
2678 | dout("probe failed, returning %d\n", ret); | ||
2679 | |||
2680 | return ret; | ||
2681 | } | ||
2682 | |||
2587 | static ssize_t rbd_add(struct bus_type *bus, | 2683 | static ssize_t rbd_add(struct bus_type *bus, |
2588 | const char *buf, | 2684 | const char *buf, |
2589 | size_t count) | 2685 | size_t count) |
@@ -2631,35 +2727,10 @@ static ssize_t rbd_add(struct bus_type *bus, | |||
2631 | goto err_out_client; | 2727 | goto err_out_client; |
2632 | rbd_dev->pool_id = rc; | 2728 | rbd_dev->pool_id = rc; |
2633 | 2729 | ||
2634 | rc = rbd_dev_image_id(rbd_dev); | 2730 | rc = rbd_dev_probe(rbd_dev); |
2635 | if (!rc) { | 2731 | if (rc < 0) |
2636 | rc = -ENOTSUPP; /* Not actually supporting format 2 yet */ | ||
2637 | goto err_out_client; | ||
2638 | } | ||
2639 | |||
2640 | /* Version 1 images have no id; empty string is used */ | ||
2641 | |||
2642 | rbd_dev->image_id = kstrdup("", GFP_KERNEL); | ||
2643 | if (!rbd_dev->image_id) { | ||
2644 | rc = -ENOMEM; | ||
2645 | goto err_out_client; | ||
2646 | } | ||
2647 | rbd_dev->image_id_len = 0; | ||
2648 | |||
2649 | /* Create the name of the header object */ | ||
2650 | |||
2651 | rbd_dev->header_name = kmalloc(rbd_dev->image_name_len | ||
2652 | + sizeof (RBD_SUFFIX), | ||
2653 | GFP_KERNEL); | ||
2654 | if (!rbd_dev->header_name) | ||
2655 | goto err_out_client; | ||
2656 | sprintf(rbd_dev->header_name, "%s%s", rbd_dev->image_name, RBD_SUFFIX); | ||
2657 | |||
2658 | /* Get information about the image being mapped */ | ||
2659 | |||
2660 | rc = rbd_read_header(rbd_dev, &rbd_dev->header); | ||
2661 | if (rc) | ||
2662 | goto err_out_client; | 2732 | goto err_out_client; |
2733 | rbd_assert(rbd_image_format_valid(rbd_dev->image_format)); | ||
2663 | 2734 | ||
2664 | /* no need to lock here, as rbd_dev is not registered yet */ | 2735 | /* no need to lock here, as rbd_dev is not registered yet */ |
2665 | rc = rbd_dev_snaps_update(rbd_dev); | 2736 | rc = rbd_dev_snaps_update(rbd_dev); |