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 | ||