aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2012-09-27 09:07:11 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-09 08:11:40 -0500
commite34b677d09ce375a87acd0360537cbed33881b0c (patch)
tree6b8d1a2d6224f095c046bc0792d9288190253e19
parent8747d30af97232f9ff4cde78b8d259cc715a9b7a (diff)
drbd: wait for meta data IO completion even with failed disk, unless force-detached
The intention of force-detach is to be able to deal with a completely unresponsive lower level IO stack, which does not even deliver error completions anymore, but no completion at all. In all other cases, we must still wait for the meta data IO completion. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
-rw-r--r--drivers/block/drbd/drbd_actlog.c17
-rw-r--r--drivers/block/drbd/drbd_bitmap.c8
-rw-r--r--drivers/block/drbd/drbd_int.h4
3 files changed, 13 insertions, 16 deletions
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index e81085795ec4..bc6284ef21d5 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -123,13 +123,7 @@ void drbd_md_put_buffer(struct drbd_conf *mdev)
123 wake_up(&mdev->misc_wait); 123 wake_up(&mdev->misc_wait);
124} 124}
125 125
126static bool md_io_allowed(struct drbd_conf *mdev) 126void wait_until_done_or_force_detached(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
127{
128 enum drbd_disk_state ds = mdev->state.disk;
129 return ds >= D_NEGOTIATING || ds == D_ATTACHING;
130}
131
132void wait_until_done_or_disk_failure(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
133 unsigned int *done) 127 unsigned int *done)
134{ 128{
135 long dt; 129 long dt;
@@ -141,9 +135,12 @@ void wait_until_done_or_disk_failure(struct drbd_conf *mdev, struct drbd_backing
141 if (dt == 0) 135 if (dt == 0)
142 dt = MAX_SCHEDULE_TIMEOUT; 136 dt = MAX_SCHEDULE_TIMEOUT;
143 137
144 dt = wait_event_timeout(mdev->misc_wait, *done || !md_io_allowed(mdev), dt); 138 dt = wait_event_timeout(mdev->misc_wait,
145 if (dt == 0) 139 *done || test_bit(FORCE_DETACH, &mdev->flags), dt);
140 if (dt == 0) {
146 dev_err(DEV, "meta-data IO operation timed out\n"); 141 dev_err(DEV, "meta-data IO operation timed out\n");
142 drbd_chk_io_error(mdev, 1, DRBD_FORCE_DETACH);
143 }
147} 144}
148 145
149static int _drbd_md_sync_page_io(struct drbd_conf *mdev, 146static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
@@ -183,7 +180,7 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
183 bio_endio(bio, -EIO); 180 bio_endio(bio, -EIO);
184 else 181 else
185 submit_bio(rw, bio); 182 submit_bio(rw, bio);
186 wait_until_done_or_disk_failure(mdev, bdev, &mdev->md_io.done); 183 wait_until_done_or_force_detached(mdev, bdev, &mdev->md_io.done);
187 if (bio_flagged(bio, BIO_UPTODATE)) 184 if (bio_flagged(bio, BIO_UPTODATE))
188 err = mdev->md_io.error; 185 err = mdev->md_io.error;
189 186
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index e502535d2c4d..e30ff720894f 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -1128,7 +1128,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
1128 * "in_flight reached zero, all done" event. 1128 * "in_flight reached zero, all done" event.
1129 */ 1129 */
1130 if (!atomic_dec_and_test(&ctx->in_flight)) 1130 if (!atomic_dec_and_test(&ctx->in_flight))
1131 wait_until_done_or_disk_failure(mdev, mdev->ldev, &ctx->done); 1131 wait_until_done_or_force_detached(mdev, mdev->ldev, &ctx->done);
1132 else 1132 else
1133 kref_put(&ctx->kref, &bm_aio_ctx_destroy); 1133 kref_put(&ctx->kref, &bm_aio_ctx_destroy);
1134 1134
@@ -1145,7 +1145,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
1145 } 1145 }
1146 1146
1147 if (atomic_read(&ctx->in_flight)) 1147 if (atomic_read(&ctx->in_flight))
1148 err = -EIO; /* Disk failed during IO... */ 1148 err = -EIO; /* Disk timeout/force-detach during IO... */
1149 1149
1150 now = jiffies; 1150 now = jiffies;
1151 if (rw == WRITE) { 1151 if (rw == WRITE) {
@@ -1273,11 +1273,11 @@ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(loc
1273 } 1273 }
1274 1274
1275 bm_page_io_async(ctx, idx, WRITE_SYNC); 1275 bm_page_io_async(ctx, idx, WRITE_SYNC);
1276 wait_until_done_or_disk_failure(mdev, mdev->ldev, &ctx->done); 1276 wait_until_done_or_force_detached(mdev, mdev->ldev, &ctx->done);
1277 1277
1278 if (ctx->error) 1278 if (ctx->error)
1279 drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR); 1279 drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR);
1280 /* that should force detach, so the in memory bitmap will be 1280 /* that causes us to detach, so the in memory bitmap will be
1281 * gone in a moment as well. */ 1281 * gone in a moment as well. */
1282 1282
1283 mdev->bm_writ_cnt++; 1283 mdev->bm_writ_cnt++;
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 4aadd0818179..eeab868f056b 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1452,8 +1452,8 @@ extern void drbd_md_put_buffer(struct drbd_conf *mdev);
1452extern int drbd_md_sync_page_io(struct drbd_conf *mdev, 1452extern int drbd_md_sync_page_io(struct drbd_conf *mdev,
1453 struct drbd_backing_dev *bdev, sector_t sector, int rw); 1453 struct drbd_backing_dev *bdev, sector_t sector, int rw);
1454extern void drbd_ov_out_of_sync_found(struct drbd_conf *, sector_t, int); 1454extern void drbd_ov_out_of_sync_found(struct drbd_conf *, sector_t, int);
1455extern void wait_until_done_or_disk_failure(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, 1455extern void wait_until_done_or_force_detached(struct drbd_conf *mdev,
1456 unsigned int *done); 1456 struct drbd_backing_dev *bdev, unsigned int *done);
1457extern void drbd_rs_controller_reset(struct drbd_conf *mdev); 1457extern void drbd_rs_controller_reset(struct drbd_conf *mdev);
1458 1458
1459static inline void ov_out_of_sync_print(struct drbd_conf *mdev) 1459static inline void ov_out_of_sync_print(struct drbd_conf *mdev)