aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-05-31 18:40:45 -0400
committerSage Weil <sage@inktank.com>2013-07-03 18:32:43 -0400
commitcfbf6377b696d88461eef6966bef9e6184111183 (patch)
tree6da8c0cfcd4aeb02a738a6c552f9a5f429139164
parent1ba0f1e7975ad07557f7a931522bdcd813ae35f6 (diff)
rbd: use rwsem to protect header updates
Updating an image header needs to be protected to ensure it's done consistently. However distinct headers can be updated concurrently without a problem. Instead of using the global control lock to serialize headder updates, just rely on the header semaphore. (It's already used, this just moves it out to cover a broader section of the code.) That leaves the control mutex protecting only the creation of rbd clients, so rename it. This resolves: http://tracker.ceph.com/issues/5222 Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
-rw-r--r--drivers/block/rbd.c26
1 files changed, 10 insertions, 16 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index d735eb13847d..44c44c6071ed 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -372,7 +372,7 @@ enum rbd_dev_flags {
372 RBD_DEV_FLAG_REMOVING, /* this mapping is being removed */ 372 RBD_DEV_FLAG_REMOVING, /* this mapping is being removed */
373}; 373};
374 374
375static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */ 375static DEFINE_MUTEX(client_mutex); /* Serialize client creation */
376 376
377static LIST_HEAD(rbd_dev_list); /* devices */ 377static LIST_HEAD(rbd_dev_list); /* devices */
378static DEFINE_SPINLOCK(rbd_dev_list_lock); 378static DEFINE_SPINLOCK(rbd_dev_list_lock);
@@ -516,7 +516,7 @@ static const struct block_device_operations rbd_bd_ops = {
516 516
517/* 517/*
518 * Initialize an rbd client instance. Success or not, this function 518 * Initialize an rbd client instance. Success or not, this function
519 * consumes ceph_opts. Caller holds ctl_mutex. 519 * consumes ceph_opts. Caller holds client_mutex.
520 */ 520 */
521static struct rbd_client *rbd_client_create(struct ceph_options *ceph_opts) 521static struct rbd_client *rbd_client_create(struct ceph_options *ceph_opts)
522{ 522{
@@ -673,13 +673,13 @@ static struct rbd_client *rbd_get_client(struct ceph_options *ceph_opts)
673{ 673{
674 struct rbd_client *rbdc; 674 struct rbd_client *rbdc;
675 675
676 mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); 676 mutex_lock_nested(&client_mutex, SINGLE_DEPTH_NESTING);
677 rbdc = rbd_client_find(ceph_opts); 677 rbdc = rbd_client_find(ceph_opts);
678 if (rbdc) /* using an existing client */ 678 if (rbdc) /* using an existing client */
679 ceph_destroy_options(ceph_opts); 679 ceph_destroy_options(ceph_opts);
680 else 680 else
681 rbdc = rbd_client_create(ceph_opts); 681 rbdc = rbd_client_create(ceph_opts);
682 mutex_unlock(&ctl_mutex); 682 mutex_unlock(&client_mutex);
683 683
684 return rbdc; 684 return rbdc;
685} 685}
@@ -833,7 +833,6 @@ static int rbd_header_from_disk(struct rbd_device *rbd_dev,
833 833
834 /* We won't fail any more, fill in the header */ 834 /* We won't fail any more, fill in the header */
835 835
836 down_write(&rbd_dev->header_rwsem);
837 if (first_time) { 836 if (first_time) {
838 header->object_prefix = object_prefix; 837 header->object_prefix = object_prefix;
839 header->obj_order = ondisk->options.order; 838 header->obj_order = ondisk->options.order;
@@ -862,8 +861,6 @@ static int rbd_header_from_disk(struct rbd_device *rbd_dev,
862 if (rbd_dev->mapping.size != header->image_size) 861 if (rbd_dev->mapping.size != header->image_size)
863 rbd_dev->mapping.size = header->image_size; 862 rbd_dev->mapping.size = header->image_size;
864 863
865 up_write(&rbd_dev->header_rwsem);
866
867 return 0; 864 return 0;
868out_2big: 865out_2big:
869 ret = -EIO; 866 ret = -EIO;
@@ -3333,7 +3330,7 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev)
3333 int ret; 3330 int ret;
3334 3331
3335 rbd_assert(rbd_image_format_valid(rbd_dev->image_format)); 3332 rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
3336 mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); 3333 down_write(&rbd_dev->header_rwsem);
3337 mapping_size = rbd_dev->mapping.size; 3334 mapping_size = rbd_dev->mapping.size;
3338 if (rbd_dev->image_format == 1) 3335 if (rbd_dev->image_format == 1)
3339 ret = rbd_dev_v1_header_info(rbd_dev); 3336 ret = rbd_dev_v1_header_info(rbd_dev);
@@ -3343,7 +3340,8 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev)
3343 /* If it's a mapped snapshot, validate its EXISTS flag */ 3340 /* If it's a mapped snapshot, validate its EXISTS flag */
3344 3341
3345 rbd_exists_validate(rbd_dev); 3342 rbd_exists_validate(rbd_dev);
3346 mutex_unlock(&ctl_mutex); 3343 up_write(&rbd_dev->header_rwsem);
3344
3347 if (mapping_size != rbd_dev->mapping.size) { 3345 if (mapping_size != rbd_dev->mapping.size) {
3348 sector_t size; 3346 sector_t size;
3349 3347
@@ -4272,16 +4270,14 @@ static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev)
4272 bool first_time = rbd_dev->header.object_prefix == NULL; 4270 bool first_time = rbd_dev->header.object_prefix == NULL;
4273 int ret; 4271 int ret;
4274 4272
4275 down_write(&rbd_dev->header_rwsem);
4276
4277 ret = rbd_dev_v2_image_size(rbd_dev); 4273 ret = rbd_dev_v2_image_size(rbd_dev);
4278 if (ret) 4274 if (ret)
4279 goto out; 4275 return ret;
4280 4276
4281 if (first_time) { 4277 if (first_time) {
4282 ret = rbd_dev_v2_header_onetime(rbd_dev); 4278 ret = rbd_dev_v2_header_onetime(rbd_dev);
4283 if (ret) 4279 if (ret)
4284 goto out; 4280 return ret;
4285 } 4281 }
4286 4282
4287 /* 4283 /*
@@ -4296,7 +4292,7 @@ static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev)
4296 4292
4297 ret = rbd_dev_v2_parent_info(rbd_dev); 4293 ret = rbd_dev_v2_parent_info(rbd_dev);
4298 if (ret) 4294 if (ret)
4299 goto out; 4295 return ret;
4300 4296
4301 /* 4297 /*
4302 * Print a warning if this is the initial probe and 4298 * Print a warning if this is the initial probe and
@@ -4317,8 +4313,6 @@ static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev)
4317 4313
4318 ret = rbd_dev_v2_snap_context(rbd_dev); 4314 ret = rbd_dev_v2_snap_context(rbd_dev);
4319 dout("rbd_dev_v2_snap_context returned %d\n", ret); 4315 dout("rbd_dev_v2_snap_context returned %d\n", ret);
4320out:
4321 up_write(&rbd_dev->header_rwsem);
4322 4316
4323 return ret; 4317 return ret;
4324} 4318}