diff options
| -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); |
