diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2012-09-27 09:07:11 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-09 08:11:40 -0500 |
commit | e34b677d09ce375a87acd0360537cbed33881b0c (patch) | |
tree | 6b8d1a2d6224f095c046bc0792d9288190253e19 | |
parent | 8747d30af97232f9ff4cde78b8d259cc715a9b7a (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.c | 17 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_bitmap.c | 8 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 4 |
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 | ||
126 | static bool md_io_allowed(struct drbd_conf *mdev) | 126 | void 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 | |||
132 | void 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 | ||
149 | static int _drbd_md_sync_page_io(struct drbd_conf *mdev, | 146 | static 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); | |||
1452 | extern int drbd_md_sync_page_io(struct drbd_conf *mdev, | 1452 | extern 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); |
1454 | extern void drbd_ov_out_of_sync_found(struct drbd_conf *, sector_t, int); | 1454 | extern void drbd_ov_out_of_sync_found(struct drbd_conf *, sector_t, int); |
1455 | extern void wait_until_done_or_disk_failure(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, | 1455 | extern void wait_until_done_or_force_detached(struct drbd_conf *mdev, |
1456 | unsigned int *done); | 1456 | struct drbd_backing_dev *bdev, unsigned int *done); |
1457 | extern void drbd_rs_controller_reset(struct drbd_conf *mdev); | 1457 | extern void drbd_rs_controller_reset(struct drbd_conf *mdev); |
1458 | 1458 | ||
1459 | static inline void ov_out_of_sync_print(struct drbd_conf *mdev) | 1459 | static inline void ov_out_of_sync_print(struct drbd_conf *mdev) |