aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2012-05-18 10:20:06 -0400
committerJens Axboe <axboe@kernel.dk>2012-05-18 10:20:06 -0400
commit4fd1ffaa122cf66bfb710ced43679413df4f3605 (patch)
tree27bf967e16c4dcc34877e6d33672fb635a7926a2
parent13828dec457270b48f433142fce0efd1e85f2c5d (diff)
parent92b4ca291f8676c9f323166a65fb7447774b2a46 (diff)
Merge branch 'for-jens' of git://git.drbd.org/linux-drbd into for-3.5/drivers
Philipp writes: This are the updates we have in the drbd-8.3 tree. They are intended for your "for-3.5/drivers" drivers branch. These changes include one new feature: * Allow detach from frozen backing devices with the new --force option; configurable timeout for backing devices by the new disk-timeout option And huge number of bug fixes: * Fixed a write ordering problem on SyncTarget nodes for a write to a block that gets resynced at the same time. The bug can only be triggered with a device that has a firmware that actually reorders writes to the same block * Fixed a race between disconnect and receive_state, that could cause a IO lockup * Fixed resend/resubmit for requests with disk or network timeout * Make sure that hard state changed do not disturb the connection establishing process (I.e. detach due to an IO error). When the bug was triggered it caused a retry in the connect process * Postpone soft state changes to no disturb the connection establishing process (I.e. becoming primary). When the bug was triggered it could cause both nodes going into SyncSource state * Fixed a refcount leak that could cause failures when trying to unload a protocol family modules, that was used by DRBD * Dedicated page pool for meta data IOs * Deny normal detach (as opposed to --forced) if the user tries to detach from the last UpToDate disk in the resource * Fixed a possible protocol error that could be caused by "unusual" BIOs. * Enforce the disk-timeout option also on meta-data IO operations * Implemented stable bitmap pages when we do a full write out of the bitmap * Fixed a rare compatibility issue with DRBD's older than 8.3.7 when negotiating the bio_size * Fixed a rare race condition where an empty resync could stall with if pause/unpause events happen in parallel * Made the re-establishing of connections quicker, if it got a broken pipe once. Previously there was a bug in the code caused it to waste the first successful established connection after a broken pipe event. PS: I am postponing the drbd-8.4 for mainline for one or two kernel development cycles more (the ~400 patchets set).
-rw-r--r--drivers/block/drbd/drbd_actlog.c104
-rw-r--r--drivers/block/drbd/drbd_bitmap.c146
-rw-r--r--drivers/block/drbd/drbd_int.h90
-rw-r--r--drivers/block/drbd/drbd_main.c357
-rw-r--r--drivers/block/drbd/drbd_nl.c48
-rw-r--r--drivers/block/drbd/drbd_proc.c2
-rw-r--r--drivers/block/drbd/drbd_receiver.c95
-rw-r--r--drivers/block/drbd/drbd_req.c132
-rw-r--r--drivers/block/drbd/drbd_req.h19
-rw-r--r--drivers/block/drbd/drbd_worker.c31
-rw-r--r--include/linux/drbd.h6
-rw-r--r--include/linux/drbd_limits.h7
-rw-r--r--include/linux/drbd_nl.h5
13 files changed, 754 insertions, 288 deletions
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index cf0e63dd97da..e54e31b02b88 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -65,39 +65,80 @@ 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
85static bool md_io_allowed(struct drbd_conf *mdev)
86{
87 enum drbd_disk_state ds = mdev->state.disk;
88 return ds >= D_NEGOTIATING || ds == D_ATTACHING;
89}
90
91void wait_until_done_or_disk_failure(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
92 unsigned int *done)
93{
94 long dt = bdev->dc.disk_timeout * HZ / 10;
95 if (dt == 0)
96 dt = MAX_SCHEDULE_TIMEOUT;
97
98 dt = wait_event_timeout(mdev->misc_wait, *done || !md_io_allowed(mdev), dt);
99 if (dt == 0)
100 dev_err(DEV, "meta-data IO operation timed out\n");
101}
102
68static int _drbd_md_sync_page_io(struct drbd_conf *mdev, 103static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
69 struct drbd_backing_dev *bdev, 104 struct drbd_backing_dev *bdev,
70 struct page *page, sector_t sector, 105 struct page *page, sector_t sector,
71 int rw, int size) 106 int rw, int size)
72{ 107{
73 struct bio *bio; 108 struct bio *bio;
74 struct drbd_md_io md_io;
75 int ok; 109 int ok;
76 110
77 md_io.mdev = mdev; 111 mdev->md_io.done = 0;
78 init_completion(&md_io.event); 112 mdev->md_io.error = -ENODEV;
79 md_io.error = 0;
80 113
81 if ((rw & WRITE) && !test_bit(MD_NO_FUA, &mdev->flags)) 114 if ((rw & WRITE) && !test_bit(MD_NO_FUA, &mdev->flags))
82 rw |= REQ_FUA | REQ_FLUSH; 115 rw |= REQ_FUA | REQ_FLUSH;
83 rw |= REQ_SYNC; 116 rw |= REQ_SYNC;
84 117
85 bio = bio_alloc(GFP_NOIO, 1); 118 bio = bio_alloc_drbd(GFP_NOIO);
86 bio->bi_bdev = bdev->md_bdev; 119 bio->bi_bdev = bdev->md_bdev;
87 bio->bi_sector = sector; 120 bio->bi_sector = sector;
88 ok = (bio_add_page(bio, page, size, 0) == size); 121 ok = (bio_add_page(bio, page, size, 0) == size);
89 if (!ok) 122 if (!ok)
90 goto out; 123 goto out;
91 bio->bi_private = &md_io; 124 bio->bi_private = &mdev->md_io;
92 bio->bi_end_io = drbd_md_io_complete; 125 bio->bi_end_io = drbd_md_io_complete;
93 bio->bi_rw = rw; 126 bio->bi_rw = rw;
94 127
128 if (!get_ldev_if_state(mdev, D_ATTACHING)) { /* Corresponding put_ldev in drbd_md_io_complete() */
129 dev_err(DEV, "ASSERT FAILED: get_ldev_if_state() == 1 in _drbd_md_sync_page_io()\n");
130 ok = 0;
131 goto out;
132 }
133
134 bio_get(bio); /* one bio_put() is in the completion handler */
135 atomic_inc(&mdev->md_io_in_use); /* drbd_md_put_buffer() is in the completion handler */
95 if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) 136 if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD))
96 bio_endio(bio, -EIO); 137 bio_endio(bio, -EIO);
97 else 138 else
98 submit_bio(rw, bio); 139 submit_bio(rw, bio);
99 wait_for_completion(&md_io.event); 140 wait_until_done_or_disk_failure(mdev, bdev, &mdev->md_io.done);
100 ok = bio_flagged(bio, BIO_UPTODATE) && md_io.error == 0; 141 ok = bio_flagged(bio, BIO_UPTODATE) && mdev->md_io.error == 0;
101 142
102 out: 143 out:
103 bio_put(bio); 144 bio_put(bio);
@@ -111,7 +152,7 @@ int drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
111 int offset = 0; 152 int offset = 0;
112 struct page *iop = mdev->md_io_page; 153 struct page *iop = mdev->md_io_page;
113 154
114 D_ASSERT(mutex_is_locked(&mdev->md_io_mutex)); 155 D_ASSERT(atomic_read(&mdev->md_io_in_use) == 1);
115 156
116 BUG_ON(!bdev->md_bdev); 157 BUG_ON(!bdev->md_bdev);
117 158
@@ -328,8 +369,13 @@ w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused)
328 return 1; 369 return 1;
329 } 370 }
330 371
331 mutex_lock(&mdev->md_io_mutex); /* protects md_io_buffer, al_tr_cycle, ... */ 372 buffer = drbd_md_get_buffer(mdev); /* protects md_io_buffer, al_tr_cycle, ... */
332 buffer = (struct al_transaction *)page_address(mdev->md_io_page); 373 if (!buffer) {
374 dev_err(DEV, "disk failed while waiting for md_io buffer\n");
375 complete(&((struct update_al_work *)w)->event);
376 put_ldev(mdev);
377 return 1;
378 }
333 379
334 buffer->magic = __constant_cpu_to_be32(DRBD_MAGIC); 380 buffer->magic = __constant_cpu_to_be32(DRBD_MAGIC);
335 buffer->tr_number = cpu_to_be32(mdev->al_tr_number); 381 buffer->tr_number = cpu_to_be32(mdev->al_tr_number);
@@ -374,7 +420,7 @@ w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused)
374 D_ASSERT(mdev->al_tr_pos < MD_AL_MAX_SIZE); 420 D_ASSERT(mdev->al_tr_pos < MD_AL_MAX_SIZE);
375 mdev->al_tr_number++; 421 mdev->al_tr_number++;
376 422
377 mutex_unlock(&mdev->md_io_mutex); 423 drbd_md_put_buffer(mdev);
378 424
379 complete(&((struct update_al_work *)w)->event); 425 complete(&((struct update_al_work *)w)->event);
380 put_ldev(mdev); 426 put_ldev(mdev);
@@ -443,8 +489,9 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
443 /* lock out all other meta data io for now, 489 /* lock out all other meta data io for now,
444 * and make sure the page is mapped. 490 * and make sure the page is mapped.
445 */ 491 */
446 mutex_lock(&mdev->md_io_mutex); 492 buffer = drbd_md_get_buffer(mdev);
447 buffer = page_address(mdev->md_io_page); 493 if (!buffer)
494 return 0;
448 495
449 /* Find the valid transaction in the log */ 496 /* Find the valid transaction in the log */
450 for (i = 0; i <= mx; i++) { 497 for (i = 0; i <= mx; i++) {
@@ -452,7 +499,7 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
452