diff options
| author | Alex Elder <elder@inktank.com> | 2013-05-06 10:51:29 -0400 |
|---|---|---|
| committer | Alex Elder <elder@inktank.com> | 2013-05-08 18:00:37 -0400 |
| commit | 662518b128c27def65e9af4bea2b56a1e04b3251 (patch) | |
| tree | 195365fca5ff452ad5364fb876f2b9a720e8ee5a /drivers/block/rbd.c | |
| parent | bb23e37acb2ae9604130c4819fb8ae0f784a3a2b (diff) | |
rbd: update in-core header directly
Now that rbd_header_from_disk() only fills in one-time fields once,
we can extend it slightly so it releases the other fields before
replacing their values. This way there's no need to pass a
temporary buffer and then copy all the results in. Just use the rbd
device header structure in rbd_header_from_disk() so its values get
updated directly.
Note that this means we need to take the header semaphore at the
point we update things. So pass the rbd_dev rather than the address
of its header as its first argument to rbd_header_from_disk(), and
have it return an error code.
As a result, rbd_dev_v1_header_read() does all the work,
rbd_read_header() becomes unnecessary, and rbd_dev_v1_refresh()
becomes a very simple wrapper.
Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block/rbd.c')
| -rw-r--r-- | drivers/block/rbd.c | 98 |
1 files changed, 27 insertions, 71 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index a3b6bf5e9ae8..e4586f2e04c2 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
| @@ -730,9 +730,10 @@ static bool rbd_dev_ondisk_valid(struct rbd_image_header_ondisk *ondisk) | |||
| 730 | * Fill an rbd image header with information from the given format 1 | 730 | * Fill an rbd image header with information from the given format 1 |
| 731 | * on-disk header. | 731 | * on-disk header. |
| 732 | */ | 732 | */ |
| 733 | static int rbd_header_from_disk(struct rbd_image_header *header, | 733 | static int rbd_header_from_disk(struct rbd_device *rbd_dev, |
| 734 | struct rbd_image_header_ondisk *ondisk) | 734 | struct rbd_image_header_ondisk *ondisk) |
| 735 | { | 735 | { |
| 736 | struct rbd_image_header *header = &rbd_dev->header; | ||
| 736 | bool first_time = header->object_prefix == NULL; | 737 | bool first_time = header->object_prefix == NULL; |
| 737 | struct ceph_snap_context *snapc; | 738 | struct ceph_snap_context *snapc; |
| 738 | char *object_prefix = NULL; | 739 | char *object_prefix = NULL; |
| @@ -802,6 +803,7 @@ static int rbd_header_from_disk(struct rbd_image_header *header, | |||
| 802 | 803 | ||
| 803 | /* We won't fail any more, fill in the header */ | 804 | /* We won't fail any more, fill in the header */ |
| 804 | 805 | ||
| 806 | down_write(&rbd_dev->header_rwsem); | ||
| 805 | if (first_time) { | 807 | if (first_time) { |
| 806 | header->object_prefix = object_prefix; | 808 | header->object_prefix = object_prefix; |
| 807 | header->obj_order = ondisk->options.order; | 809 | header->obj_order = ondisk->options.order; |
| @@ -811,6 +813,10 @@ static int rbd_header_from_disk(struct rbd_image_header *header, | |||
| 811 | header->stripe_unit = 0; | 813 | header->stripe_unit = 0; |
| 812 | header->stripe_count = 0; | 814 | header->stripe_count = 0; |
| 813 | header->features = 0; | 815 | header->features = 0; |
| 816 | } else { | ||
| 817 | ceph_put_snap_context(header->snapc); | ||
| 818 | kfree(header->snap_names); | ||
| 819 | kfree(header->snap_sizes); | ||
| 814 | } | 820 | } |
| 815 | 821 | ||
| 816 | /* The remaining fields always get updated (when we refresh) */ | 822 | /* The remaining fields always get updated (when we refresh) */ |
| @@ -820,6 +826,14 @@ static int rbd_header_from_disk(struct rbd_image_header *header, | |||
| 820 | header->snap_names = snap_names; | 826 | header->snap_names = snap_names; |
| 821 | header->snap_sizes = snap_sizes; | 827 | header->snap_sizes = snap_sizes; |
| 822 | 828 | ||
| 829 | /* Make sure mapping size is consistent with header info */ | ||
| 830 | |||
| 831 | if (rbd_dev->spec->snap_id == CEPH_NOSNAP || first_time) | ||
| 832 | if (rbd_dev->mapping.size != header->image_size) | ||
| 833 | rbd_dev->mapping.size = header->image_size; | ||
| 834 | |||
| 835 | up_write(&rbd_dev->header_rwsem); | ||
| 836 | |||
| 823 | return 0; | 837 | return 0; |
| 824 | out_2big: | 838 | out_2big: |
| 825 | ret = -EIO; | 839 | ret = -EIO; |
| @@ -3032,17 +3046,11 @@ out: | |||
| 3032 | } | 3046 | } |
| 3033 | 3047 | ||
| 3034 | /* | 3048 | /* |
| 3035 | * Read the complete header for the given rbd device. | 3049 | * Read the complete header for the given rbd device. On successful |
| 3036 | * | 3050 | * return, the rbd_dev->header field will contain up-to-date |
| 3037 | * Returns a pointer to a dynamically-allocated buffer containing | 3051 | * information about the image. |
| 3038 | * the complete and validated header. Caller can pass the address | ||
| 3039 | * of a variable that will be filled in with the version of the | ||
| 3040 | * header object at the time it was read. | ||
| 3041 | * | ||
| 3042 | * Returns a pointer-coded errno if a failure occurs. | ||
| 3043 | */ | 3052 | */ |
| 3044 | static struct rbd_image_header_ondisk * | 3053 | static int rbd_dev_v1_header_read(struct rbd_device *rbd_dev) |
| 3045 | rbd_dev_v1_header_read(struct rbd_device *rbd_dev) | ||
| 3046 | { | 3054 | { |
| 3047 | struct rbd_image_header_ondisk *ondisk = NULL; | 3055 | struct rbd_image_header_ondisk *ondisk = NULL; |
| 3048 | u32 snap_count = 0; | 3056 | u32 snap_count = 0; |
| @@ -3067,22 +3075,22 @@ rbd_dev_v1_header_read(struct rbd_device *rbd_dev) | |||
| 3067 | size += names_size; | 3075 | size += names_size; |
| 3068 | ondisk = kmalloc(size, GFP_KERNEL); | 3076 | ondisk = kmalloc(size, GFP_KERNEL); |
| 3069 | if (!ondisk) | 3077 | if (!ondisk) |
| 3070 | return ERR_PTR(-ENOMEM); | 3078 | return -ENOMEM; |
| 3071 | 3079 | ||
| 3072 | ret = rbd_obj_read_sync(rbd_dev, rbd_dev->header_name, | 3080 | ret = rbd_obj_read_sync(rbd_dev, rbd_dev->header_name, |
| 3073 | 0, size, ondisk); | 3081 | 0, size, ondisk); |
| 3074 | if (ret < 0) | 3082 | if (ret < 0) |
| 3075 | goto out_err; | 3083 | goto out; |
| 3076 | if ((size_t)ret < size) { | 3084 | if ((size_t)ret < size) { |
| 3077 | ret = -ENXIO; | 3085 | ret = -ENXIO; |
| 3078 | rbd_warn(rbd_dev, "short header read (want %zd got %d)", | 3086 | rbd_warn(rbd_dev, "short header read (want %zd got %d)", |
| 3079 | size, ret); | 3087 | size, ret); |
| 3080 | goto out_err; | 3088 | goto out; |
| 3081 | } | 3089 | } |
| 3082 | if (!rbd_dev_ondisk_valid(ondisk)) { | 3090 | if (!rbd_dev_ondisk_valid(ondisk)) { |
| 3083 | ret = -ENXIO; | 3091 | ret = -ENXIO; |
| 3084 | rbd_warn(rbd_dev, "invalid header"); | 3092 | rbd_warn(rbd_dev, "invalid header"); |
| 3085 | goto out_err; | 3093 | goto out; |
| 3086 | } | 3094 | } |
| 3087 | 3095 | ||
| 3088 | names_size = le64_to_cpu(ondisk->snap_names_len); | 3096 | names_size = le64_to_cpu(ondisk->snap_names_len); |
| @@ -3090,27 +3098,8 @@ rbd_dev_v1_header_read(struct rbd_device *rbd_dev) | |||
| 3090 | snap_count = le32_to_cpu(ondisk->snap_count); | 3098 | snap_count = le32_to_cpu(ondisk->snap_count); |
| 3091 | } while (snap_count != want_count); | 3099 | } while (snap_count != want_count); |
| 3092 | 3100 | ||
| 3093 | return ondisk; | 3101 | ret = rbd_header_from_disk(rbd_dev, ondisk); |
| 3094 | 3102 | out: | |
| 3095 | out_err: | ||
| 3096 | kfree(ondisk); | ||
| 3097 | |||
| 3098 | return ERR_PTR(ret); | ||
| 3099 | } | ||
| 3100 | |||
| 3101 | /* | ||
| 3102 | * reload the ondisk the header | ||
| 3103 | */ | ||
| 3104 | static int rbd_read_header(struct rbd_device *rbd_dev, | ||
| 3105 | struct rbd_image_header *header) | ||
| 3106 | { | ||
| 3107 | struct rbd_image_header_ondisk *ondisk; | ||
| 3108 | int ret; | ||
| 3109 | |||
| 3110 | ondisk = rbd_dev_v1_header_read(rbd_dev); | ||
| 3111 | if (IS_ERR(ondisk)) | ||
| 3112 | return PTR_ERR(ondisk); | ||
| 3113 | ret = rbd_header_from_disk(header, ondisk); | ||
| 3114 | kfree(ondisk); | 3103 | kfree(ondisk); |
| 3115 | 3104 | ||
| 3116 | return ret; | 3105 | return ret; |
| @@ -3121,40 +3110,7 @@ static int rbd_read_header(struct rbd_device *rbd_dev, | |||
| 3121 | */ | 3110 | */ |
| 3122 | static int rbd_dev_v1_refresh(struct rbd_device *rbd_dev) | 3111 | static int rbd_dev_v1_refresh(struct rbd_device *rbd_dev) |
| 3123 | { | 3112 | { |
| 3124 | int ret; | 3113 | return rbd_dev_v1_header_read(rbd_dev); |
| 3125 | struct rbd_image_header h; | ||
| 3126 | |||
| 3127 | memset(&h, 0, sizeof (h)); | ||
| 3128 | ret = rbd_read_header(rbd_dev, &h); | ||
| 3129 | if (ret < 0) | ||
| 3130 | return ret; | ||
| 3131 | |||
| 3132 | down_write(&rbd_dev->header_rwsem); | ||
| 3133 | |||
| 3134 | /* Update image size, and check for resize of mapped image */ | ||
| 3135 | rbd_dev->header.image_size = h.image_size; | ||
| 3136 | if (rbd_dev->spec->snap_id == CEPH_NOSNAP) | ||
| 3137 | if (rbd_dev->mapping.size != rbd_dev->header.image_size) | ||
| 3138 | rbd_dev->mapping.size = rbd_dev->header.image_size; | ||
| 3139 | |||
| 3140 | /* rbd_dev->header.object_prefix shouldn't change */ | ||
| 3141 | kfree(rbd_dev->header.snap_sizes); | ||
| 3142 | kfree(rbd_dev->header.snap_names); | ||
| 3143 | /* osd requests may still refer to snapc */ | ||
| 3144 | ceph_put_snap_context(rbd_dev->header.snapc); | ||
| 3145 | |||
| 3146 | rbd_dev->header.image_size = h.image_size; | ||
| 3147 | rbd_dev->header.snapc = h.snapc; | ||
| 3148 | rbd_dev->header.snap_names = h.snap_names; | ||
| 3149 | rbd_dev->header.snap_sizes = h.snap_sizes; | ||
| 3150 | /* Free the extra copy of the object prefix */ | ||
| 3151 | if (strcmp(rbd_dev->header.object_prefix, h.object_prefix)) | ||
| 3152 | rbd_warn(rbd_dev, "object prefix changed (ignoring)"); | ||
| 3153 | kfree(h.object_prefix); | ||
| 3154 | |||
| 3155 | up_write(&rbd_dev->header_rwsem); | ||
| 3156 | |||
| 3157 | return ret; | ||
| 3158 | } | 3114 | } |
| 3159 | 3115 | ||
| 3160 | /* | 3116 | /* |
| @@ -4517,7 +4473,7 @@ static int rbd_dev_v1_probe(struct rbd_device *rbd_dev) | |||
| 4517 | 4473 | ||
| 4518 | /* Populate rbd image metadata */ | 4474 | /* Populate rbd image metadata */ |
| 4519 | 4475 | ||
| 4520 | ret = rbd_read_header(rbd_dev, &rbd_dev->header); | 4476 | ret = rbd_dev_v1_header_read(rbd_dev); |
| 4521 | if (ret < 0) | 4477 | if (ret < 0) |
| 4522 | goto out_err; | 4478 | goto out_err; |
| 4523 | 4479 | ||
