aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-06-27 09:29:16 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-05-09 09:10:33 -0400
commit9e58c4dad70bfba86f016bcc98fa19f468d0b777 (patch)
treec67117886829bfe77699498940c434a560fc4b64
parentd1f3779bbeae70b9552c9ac70d6ec8c4d3545615 (diff)
drbd: Bitmap IO functions can now return prematurely if the disk breaks
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_bitmap.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index a2c337b38d6e..e5e756dbc434 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -886,7 +886,7 @@ void drbd_bm_clear_all(struct drbd_conf *mdev)
886struct bm_aio_ctx { 886struct bm_aio_ctx {
887 struct drbd_conf *mdev; 887 struct drbd_conf *mdev;
888 atomic_t in_flight; 888 atomic_t in_flight;
889 struct completion done; 889 unsigned int done;
890 unsigned flags; 890 unsigned flags;
891#define BM_AIO_COPY_PAGES 1 891#define BM_AIO_COPY_PAGES 1
892 int error; 892 int error;
@@ -897,6 +897,7 @@ static void bm_aio_ctx_destroy(struct kref *kref)
897{ 897{
898 struct bm_aio_ctx *ctx = container_of(kref, struct bm_aio_ctx, kref); 898 struct bm_aio_ctx *ctx = container_of(kref, struct bm_aio_ctx, kref);
899 899
900 put_ldev(ctx->mdev);
900 kfree(ctx); 901 kfree(ctx);
901} 902}
902 903
@@ -945,7 +946,8 @@ static void bm_async_io_complete(struct bio *bio, int error)
945 bio_put(bio); 946 bio_put(bio);
946 947
947 if (atomic_dec_and_test(&ctx->in_flight)) { 948 if (atomic_dec_and_test(&ctx->in_flight)) {
948 complete(&ctx->done); 949 ctx->done = 1;
950 wake_up(&mdev->misc_wait);
949 kref_put(&ctx->kref, &bm_aio_ctx_destroy); 951 kref_put(&ctx->kref, &bm_aio_ctx_destroy);
950 } 952 }
951} 953}
@@ -1034,12 +1036,18 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id
1034 *ctx = (struct bm_aio_ctx) { 1036 *ctx = (struct bm_aio_ctx) {
1035 .mdev = mdev, 1037 .mdev = mdev,
1036 .in_flight = ATOMIC_INIT(1), 1038 .in_flight = ATOMIC_INIT(1),
1037 .done = COMPLETION_INITIALIZER(ctx->done), 1039 .done = 0,
1038 .flags = lazy_writeout_upper_idx ? BM_AIO_COPY_PAGES : 0, 1040 .flags = lazy_writeout_upper_idx ? BM_AIO_COPY_PAGES : 0,
1039 .error = 0, 1041 .error = 0,
1040 .kref = { ATOMIC_INIT(2) }, 1042 .kref = { ATOMIC_INIT(2) },
1041 }; 1043 };
1042 1044
1045 if (!get_ldev_if_state(mdev, D_ATTACHING)) { /* put is in bm_aio_ctx_destroy() */
1046 dev_err(DEV, "ASSERT FAILED: get_ldev_if_state() == 1 in bm_rw()\n");
1047 kfree(ctx);
1048 return -ENODEV;
1049 }
1050
1043 if (!ctx->flags) 1051 if (!ctx->flags)
1044 WARN_ON(!(BM_LOCKED_MASK & b->bm_flags)); 1052 WARN_ON(!(BM_LOCKED_MASK & b->bm_flags));
1045 1053
@@ -1073,11 +1081,16 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id
1073 1081
1074 /* 1082 /*
1075 * We initialize ctx->in_flight to one to make sure bm_async_io_complete 1083 * We initialize ctx->in_flight to one to make sure bm_async_io_complete
1076 * will not complete() early, and decrement / test it here. If there 1084 * will not set ctx->done early, and decrement / test it here. If there
1077 * are still some bios in flight, we need to wait for them here. 1085 * are still some bios in flight, we need to wait for them here.
1086 * If all IO is done already (or nothing had been submitted), there is
1087 * no need to wait. Still, we need to put the kref associated with the
1088 * "in_flight reached zero, all done" event.
1078 */ 1089 */
1079 if (!atomic_dec_and_test(&ctx->in_flight)) 1090 if (!atomic_dec_and_test(&ctx->in_flight))
1080 wait_for_completion(&ctx->done); 1091 wait_until_done_or_disk_failure(mdev, &ctx->done);
1092 else
1093 kref_put(&ctx->kref, &bm_aio_ctx_destroy);
1081 1094
1082 dev_info(DEV, "bitmap %s of %u pages took %lu jiffies\n", 1095 dev_info(DEV, "bitmap %s of %u pages took %lu jiffies\n",
1083 rw == WRITE ? "WRITE" : "READ", 1096 rw == WRITE ? "WRITE" : "READ",
@@ -1089,6 +1102,9 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id
1089 err = -EIO; /* ctx->error ? */ 1102 err = -EIO; /* ctx->error ? */
1090 } 1103 }
1091 1104
1105 if (atomic_read(&ctx->in_flight))
1106 err = -EIO; /* Disk failed during IO... */
1107
1092 now = jiffies; 1108 now = jiffies;
1093 if (rw == WRITE) { 1109 if (rw == WRITE) {
1094 drbd_md_flush(mdev); 1110 drbd_md_flush(mdev);
@@ -1103,7 +1119,6 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id
1103 ppsize(ppb, now << (BM_BLOCK_SHIFT-10)), now); 1119 ppsize(ppb, now << (BM_BLOCK_SHIFT-10)), now);
1104 1120
1105 kref_put(&ctx->kref, &bm_aio_ctx_destroy); 1121 kref_put(&ctx->kref, &bm_aio_ctx_destroy);
1106
1107 return err; 1122 return err;
1108} 1123}
1109 1124
@@ -1167,14 +1182,20 @@ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(loc
1167 *ctx = (struct bm_aio_ctx) { 1182 *ctx = (struct bm_aio_ctx) {
1168 .mdev = mdev, 1183 .mdev = mdev,
1169 .in_flight = ATOMIC_INIT(1), 1184 .in_flight = ATOMIC_INIT(1),
1170 .done = COMPLETION_INITIALIZER(ctx->done), 1185 .done = 0,
1171 .flags = BM_AIO_COPY_PAGES, 1186 .flags = BM_AIO_COPY_PAGES,
1172 .error = 0, 1187 .error = 0,
1173 .kref = { ATOMIC_INIT(2) }, 1188 .kref = { ATOMIC_INIT(2) },
1174 }; 1189 };
1175 1190
1191 if (!get_ldev_if_state(mdev, D_ATTACHING)) { /* put is in bm_aio_ctx_destroy() */
1192 dev_err(DEV, "ASSERT FAILED: get_ldev_if_state() == 1 in drbd_bm_write_page()\n");
1193 kfree(ctx);
1194 return -ENODEV;
1195 }
1196
1176 bm_page_io_async(ctx, idx, WRITE_SYNC); 1197 bm_page_io_async(ctx, idx, WRITE_SYNC);
1177 wait_for_completion(&ctx->done); 1198 wait_until_done_or_disk_failure(mdev, &ctx->done);
1178 1199
1179 if (ctx->error) 1200 if (ctx->error)
1180 drbd_chk_io_error(mdev, 1, true); 1201 drbd_chk_io_error(mdev, 1, true);
@@ -1182,9 +1203,8 @@ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(loc
1182 * gone in a moment as well. */ 1203 * gone in a moment as well. */
1183 1204
1184 mdev->bm_writ_cnt++; 1205 mdev->bm_writ_cnt++;
1185 err = ctx->error; 1206 err = atomic_read(&ctx->in_flight) ? -EIO : ctx->error;
1186 kref_put(&ctx->kref, &bm_aio_ctx_destroy); 1207 kref_put(&ctx->kref, &bm_aio_ctx_destroy);
1187
1188 return err; 1208 return err;
1189} 1209}
1190 1210