aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-06-27 05:51:46 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-05-09 04:22:31 -0400
commite17117310b73ce6d2340ad46a539d3896a2d6de8 (patch)
tree66fed6cc939a402f70a51fdebb3b27f1f629b0ea /drivers/block
parentcc94c65015022e7329e80e057e20848581d3f2a5 (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.c44
-rw-r--r--drivers/block/drbd/drbd_int.h6
-rw-r--r--drivers/block/drbd/drbd_main.c19
-rw-r--r--drivers/block/drbd/drbd_worker.c1
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
66int w_al_write_transaction(struct drbd_conf *, struct drbd_work *, int); 66int w_al_write_transaction(struct drbd_conf *, struct drbd_work *, int);
67 67
68void *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
79void 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
68static int _drbd_md_sync_page_io(struct drbd_conf *mdev, 85static 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);
1537extern void suspend_other_sg(struct drbd_conf *mdev); 1537extern void suspend_other_sg(struct drbd_conf *mdev);
1538extern int drbd_resync_finished(struct drbd_conf *mdev); 1538extern int drbd_resync_finished(struct drbd_conf *mdev);
1539/* maybe rather drbd_main.c ? */ 1539/* maybe rather drbd_main.c ? */
1540extern void *drbd_md_get_buffer(struct drbd_conf *mdev);
1541extern void drbd_md_put_buffer(struct drbd_conf *mdev);
1540extern int drbd_md_sync_page_io(struct drbd_conf *mdev, 1542extern 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);
1542extern void drbd_ov_oos_found(struct drbd_conf*, sector_t, int); 1544extern void drbd_ov_oos_found(struct drbd_conf*, sector_t, int);
1543extern void drbd_rs_controller_reset(struct drbd_conf *mdev); 1545extern 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);
3760out:
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,