diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2011-06-27 05:51:46 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-05-09 04:22:31 -0400 |
commit | e17117310b73ce6d2340ad46a539d3896a2d6de8 (patch) | |
tree | 66fed6cc939a402f70a51fdebb3b27f1f629b0ea /drivers/block | |
parent | cc94c65015022e7329e80e057e20848581d3f2a5 (diff) |
drbd: Replaced md_io_mutex by an atomic: md_io_in_use
The new function drbd_md_get_buffer() aborts waiting for the buffer
in case the disk failes in the meantime.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/drbd/drbd_actlog.c | 44 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 6 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 19 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 1 |
4 files changed, 51 insertions, 19 deletions
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index c64ca6b956cf..4271352dd72b 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c | |||
@@ -65,6 +65,23 @@ struct drbd_atodb_wait { | |||
65 | 65 | ||
66 | int w_al_write_transaction(struct drbd_conf *, struct drbd_work *, int); | 66 | int w_al_write_transaction(struct drbd_conf *, struct drbd_work *, int); |
67 | 67 | ||
68 | void *drbd_md_get_buffer(struct drbd_conf *mdev) | ||
69 | { | ||
70 | int r; | ||
71 | |||
72 | wait_event(mdev->misc_wait, | ||
73 | (r = atomic_cmpxchg(&mdev->md_io_in_use, 0, 1)) == 0 || | ||
74 | mdev->state.disk <= D_FAILED); | ||
75 | |||
76 | return r ? NULL : page_address(mdev->md_io_page); | ||
77 | } | ||
78 | |||
79 | void drbd_md_put_buffer(struct drbd_conf *mdev) | ||
80 | { | ||
81 | if (atomic_dec_and_test(&mdev->md_io_in_use)) | ||
82 | wake_up(&mdev->misc_wait); | ||
83 | } | ||
84 | |||
68 | static int _drbd_md_sync_page_io(struct drbd_conf *mdev, | 85 | static int _drbd_md_sync_page_io(struct drbd_conf *mdev, |
69 | struct drbd_backing_dev *bdev, | 86 | struct drbd_backing_dev *bdev, |
70 | struct page *page, sector_t sector, | 87 | struct page *page, sector_t sector, |
@@ -90,6 +107,7 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev, | |||
90 | bio->bi_end_io = drbd_md_io_complete; | 107 | bio->bi_end_io = drbd_md_io_complete; |
91 | bio->bi_rw = rw; | 108 | bio->bi_rw = rw; |
92 | 109 | ||
110 | atomic_inc(&mdev->md_io_in_use); /* drbd_md_put_buffer() is in the completion handler */ | ||
93 | if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) | 111 | if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) |
94 | bio_endio(bio, -EIO); | 112 | bio_endio(bio, -EIO); |
95 | else | 113 | else |
@@ -109,7 +127,7 @@ int drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, | |||
109 | int offset = 0; | 127 | int offset = 0; |
110 | struct page *iop = mdev->md_io_page; | 128 | struct page *iop = mdev->md_io_page; |
111 | 129 | ||
112 | D_ASSERT(mutex_is_locked(&mdev->md_io_mutex)); | 130 | D_ASSERT(atomic_read(&mdev->md_io_in_use) == 1); |
113 | 131 | ||
114 | BUG_ON(!bdev->md_bdev); | 132 | BUG_ON(!bdev->md_bdev); |
115 | 133 | ||
@@ -326,8 +344,13 @@ w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused) | |||
326 | return 1; | 344 | return 1; |
327 | } | 345 | } |
328 | 346 | ||
329 | mutex_lock(&mdev->md_io_mutex); /* protects md_io_buffer, al_tr_cycle, ... */ | 347 | buffer = drbd_md_get_buffer(mdev); /* protects md_io_buffer, al_tr_cycle, ... */ |
330 | buffer = (struct al_transaction *)page_address(mdev->md_io_page); | 348 | if (!buffer) { |
349 | dev_err(DEV, "disk failed while waiting for md_io buffer\n"); | ||
350 | complete(&((struct update_al_work *)w)->event); | ||
351 | put_ldev(mdev); | ||
352 | return 1; | ||
353 | } | ||
331 | 354 | ||
332 | buffer->magic = __constant_cpu_to_be32(DRBD_MAGIC); | 355 | buffer->magic = __constant_cpu_to_be32(DRBD_MAGIC); |
333 | buffer->tr_number = cpu_to_be32(mdev->al_tr_number); | 356 | buffer->tr_number = cpu_to_be32(mdev->al_tr_number); |
@@ -372,7 +395,7 @@ w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused) | |||
372 | D_ASSERT(mdev->al_tr_pos < MD_AL_MAX_SIZE); | 395 | D_ASSERT(mdev->al_tr_pos < MD_AL_MAX_SIZE); |
373 | mdev->al_tr_number++; | 396 | mdev->al_tr_number++; |
374 | 397 | ||
375 | mutex_unlock(&mdev->md_io_mutex); | 398 | drbd_md_put_buffer(mdev); |
376 | 399 | ||
377 | complete(&((struct update_al_work *)w)->event); | 400 | complete(&((struct update_al_work *)w)->event); |
378 | put_ldev(mdev); | 401 | put_ldev(mdev); |
@@ -441,8 +464,9 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) | |||
441 | /* lock out all other meta data io for now, | 464 | /* lock out all other meta data io for now, |
442 | * and make sure the page is mapped. | 465 | * and make sure the page is mapped. |
443 | */ | 466 | */ |
444 | mutex_lock(&mdev->md_io_mutex); | 467 | buffer = drbd_md_get_buffer(mdev); |
445 | buffer = page_address(mdev->md_io_page); | 468 | if (!buffer) |
469 | return 0; | ||
446 | 470 | ||
447 | /* Find the valid transaction in the log */ | 471 | /* Find the valid transaction in the log */ |
448 | for (i = 0; i <= mx; i++) { | 472 | for (i = 0; i <= mx; i++) { |
@@ -450,7 +474,7 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) | |||
450 | if (rv == 0) | 474 | if (rv == 0) |
451 | continue; | 475 | continue; |
452 | if (rv == -1) { | 476 | if (rv == -1) { |
453 | mutex_unlock(&mdev->md_io_mutex); | 477 | drbd_md_put_buffer(mdev); |
454 | return 0; | 478 | return 0; |
455 | } | 479 | } |
456 | cnr = be32_to_cpu(buffer->tr_number); | 480 | cnr = be32_to_cpu(buffer->tr_number); |
@@ -476,7 +500,7 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) | |||
476 | 500 | ||
477 | if (!found_valid) { | 501 | if (!found_valid) { |
478 | dev_warn(DEV, "No usable activity log found.\n"); | 502 | dev_warn(DEV, "No usable activity log found.\n"); |
479 | mutex_unlock(&mdev->md_io_mutex); | 503 | drbd_md_put_buffer(mdev); |
480 | return 1; | 504 | return 1; |
481 | } | 505 | } |
482 | 506 | ||
@@ -491,7 +515,7 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) | |||
491 | rv = drbd_al_read_tr(mdev, bdev, buffer, i); | 515 | rv = drbd_al_read_tr(mdev, bdev, buffer, i); |
492 | ERR_IF(rv == 0) goto cancel; | 516 | ERR_IF(rv == 0) goto cancel; |
493 | if (rv == -1) { | 517 | if (rv == -1) { |
494 | mutex_unlock(&mdev->md_io_mutex); | 518 | drbd_md_put_buffer(mdev); |
495 | return 0; | 519 | return 0; |
496 | } | 520 | } |
497 | 521 | ||
@@ -532,7 +556,7 @@ cancel: | |||
532 | mdev->al_tr_pos = 0; | 556 | mdev->al_tr_pos = 0; |
533 | 557 | ||
534 | /* ok, we are done with it */ | 558 | /* ok, we are done with it */ |
535 | mutex_unlock(&mdev->md_io_mutex); | 559 | drbd_md_put_buffer(mdev); |
536 | 560 | ||
537 | dev_info(DEV, "Found %d transactions (%d active extents) in activity log.\n", | 561 | dev_info(DEV, "Found %d transactions (%d active extents) in activity log.\n", |
538 | transactions, active_extents); | 562 | transactions, active_extents); |
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 91e69ffd5566..55cae74911e8 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -1095,7 +1095,7 @@ struct drbd_conf { | |||
1095 | struct page *md_io_page; /* one page buffer for md_io */ | 1095 | struct page *md_io_page; /* one page buffer for md_io */ |
1096 | struct page *md_io_tmpp; /* for logical_block_size != 512 */ | 1096 | struct page *md_io_tmpp; /* for logical_block_size != 512 */ |
1097 | struct drbd_md_io md_io; | 1097 | struct drbd_md_io md_io; |
1098 | struct mutex md_io_mutex; /* protects the md_io, md_io_page and md_io_tmpp */ | 1098 | atomic_t md_io_in_use; /* protects the md_io, md_io_page and md_io_tmpp */ |
1099 | spinlock_t al_lock; | 1099 | spinlock_t al_lock; |
1100 | wait_queue_head_t al_wait; | 1100 | wait_queue_head_t al_wait; |
1101 | struct lru_cache *act_log; /* activity log */ | 1101 | struct lru_cache *act_log; /* activity log */ |
@@ -1537,8 +1537,10 @@ extern void resume_next_sg(struct drbd_conf *mdev); | |||
1537 | extern void suspend_other_sg(struct drbd_conf *mdev); | 1537 | extern void suspend_other_sg(struct drbd_conf *mdev); |
1538 | extern int drbd_resync_finished(struct drbd_conf *mdev); | 1538 | extern int drbd_resync_finished(struct drbd_conf *mdev); |
1539 | /* maybe rather drbd_main.c ? */ | 1539 | /* maybe rather drbd_main.c ? */ |
1540 | extern void *drbd_md_get_buffer(struct drbd_conf *mdev); | ||
1541 | extern void drbd_md_put_buffer(struct drbd_conf *mdev); | ||
1540 | extern int drbd_md_sync_page_io(struct drbd_conf *mdev, | 1542 | extern int drbd_md_sync_page_io(struct drbd_conf *mdev, |
1541 | struct drbd_backing_dev *bdev, sector_t sector, int rw); | 1543 | struct drbd_backing_dev *bdev, sector_t sector, int rw); |
1542 | extern void drbd_ov_oos_found(struct drbd_conf*, sector_t, int); | 1544 | extern void drbd_ov_oos_found(struct drbd_conf*, sector_t, int); |
1543 | extern void drbd_rs_controller_reset(struct drbd_conf *mdev); | 1545 | extern void drbd_rs_controller_reset(struct drbd_conf *mdev); |
1544 | 1546 | ||
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 16969c2b96cd..1b59ab3ab9c7 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -3043,8 +3043,8 @@ void drbd_init_set_defaults(struct drbd_conf *mdev) | |||
3043 | atomic_set(&mdev->rs_sect_in, 0); | 3043 | atomic_set(&mdev->rs_sect_in, 0); |
3044 | atomic_set(&mdev->rs_sect_ev, 0); | 3044 | atomic_set(&mdev->rs_sect_ev, 0); |
3045 | atomic_set(&mdev->ap_in_flight, 0); | 3045 | atomic_set(&mdev->ap_in_flight, 0); |
3046 | atomic_set(&mdev->md_io_in_use, 0); | ||
3046 | 3047 | ||
3047 | mutex_init(&mdev->md_io_mutex); | ||
3048 | mutex_init(&mdev->data.mutex); | 3048 | mutex_init(&mdev->data.mutex); |
3049 | mutex_init(&mdev->meta.mutex); | 3049 | mutex_init(&mdev->meta.mutex); |
3050 | sema_init(&mdev->data.work.s, 0); | 3050 | sema_init(&mdev->data.work.s, 0); |
@@ -3722,8 +3722,10 @@ void drbd_md_sync(struct drbd_conf *mdev) | |||
3722 | if (!get_ldev_if_state(mdev, D_FAILED)) | 3722 | if (!get_ldev_if_state(mdev, D_FAILED)) |
3723 | return; | 3723 | return; |
3724 | 3724 | ||
3725 | mutex_lock(&mdev->md_io_mutex); | 3725 | buffer = drbd_md_get_buffer(mdev); |
3726 | buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page); | 3726 | if (!buffer) |
3727 | goto out; | ||
3728 | |||
3727 | memset(buffer, 0, 512); | 3729 | memset(buffer, 0, 512); |
3728 | 3730 | ||
3729 | buffer->la_size = cpu_to_be64(drbd_get_capacity(mdev->this_bdev)); | 3731 | buffer->la_size = cpu_to_be64(drbd_get_capacity(mdev->this_bdev)); |
@@ -3754,7 +3756,8 @@ void drbd_md_sync(struct drbd_conf *mdev) | |||
3754 | * since we updated it on metadata. */ | 3756 | * since we updated it on metadata. */ |
3755 | mdev->ldev->md.la_size_sect = drbd_get_capacity(mdev->this_bdev); | 3757 | mdev->ldev->md.la_size_sect = drbd_get_capacity(mdev->this_bdev); |
3756 | 3758 | ||
3757 | mutex_unlock(&mdev->md_io_mutex); | 3759 | drbd_md_put_buffer(mdev); |
3760 | out: | ||
3758 | put_ldev(mdev); | 3761 | put_ldev(mdev); |
3759 | } | 3762 | } |
3760 | 3763 | ||
@@ -3774,8 +3777,9 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) | |||
3774 | if (!get_ldev_if_state(mdev, D_ATTACHING)) | 3777 | if (!get_ldev_if_state(mdev, D_ATTACHING)) |
3775 | return ERR_IO_MD_DISK; | 3778 | return ERR_IO_MD_DISK; |
3776 | 3779 | ||
3777 | mutex_lock(&mdev->md_io_mutex); | 3780 | buffer = drbd_md_get_buffer(mdev); |
3778 | buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page); | 3781 | if (!buffer) |
3782 | goto out; | ||
3779 | 3783 | ||
3780 | if (!drbd_md_sync_page_io(mdev, bdev, bdev->md.md_offset, READ)) { | 3784 | if (!drbd_md_sync_page_io(mdev, bdev, bdev->md.md_offset, READ)) { |
3781 | /* NOTE: can't do normal error processing here as this is | 3785 | /* NOTE: can't do normal error processing here as this is |
@@ -3836,7 +3840,8 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) | |||
3836 | mdev->sync_conf.al_extents = 127; | 3840 | mdev->sync_conf.al_extents = 127; |
3837 | 3841 | ||
3838 | err: | 3842 | err: |
3839 | mutex_unlock(&mdev->md_io_mutex); | 3843 | drbd_md_put_buffer(mdev); |
3844 | out: | ||
3840 | put_ldev(mdev); | 3845 | put_ldev(mdev); |
3841 | 3846 | ||
3842 | return rv; | 3847 | return rv; |
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index eedfe311c403..94a128b49f4f 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c | |||
@@ -78,6 +78,7 @@ void drbd_md_io_complete(struct bio *bio, int error) | |||
78 | md_io->error = error; | 78 | md_io->error = error; |
79 | 79 | ||
80 | complete(&md_io->event); | 80 | complete(&md_io->event); |
81 | drbd_md_put_buffer(mdev); | ||
81 | } | 82 | } |
82 | 83 | ||
83 | /* reads on behalf of the partner, | 84 | /* reads on behalf of the partner, |