diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/drbd/drbd_actlog.c | 2 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_bitmap.c | 4 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 17 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 20 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 4 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 6 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 4 |
7 files changed, 42 insertions, 15 deletions
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index e54e31b02b88..6ace11e9e5a1 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c | |||
@@ -411,7 +411,7 @@ w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused) | |||
411 | + mdev->ldev->md.al_offset + mdev->al_tr_pos; | 411 | + mdev->ldev->md.al_offset + mdev->al_tr_pos; |
412 | 412 | ||
413 | if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) | 413 | if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) |
414 | drbd_chk_io_error(mdev, 1, true); | 414 | drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR); |
415 | 415 | ||
416 | if (++mdev->al_tr_pos > | 416 | if (++mdev->al_tr_pos > |
417 | div_ceil(mdev->act_log->nr_elements, AL_EXTENTS_PT)) | 417 | div_ceil(mdev->act_log->nr_elements, AL_EXTENTS_PT)) |
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index fcb956bb4b4c..ba91b408abad 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c | |||
@@ -1096,7 +1096,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w | |||
1096 | 1096 | ||
1097 | if (ctx->error) { | 1097 | if (ctx->error) { |
1098 | dev_alert(DEV, "we had at least one MD IO ERROR during bitmap IO\n"); | 1098 | dev_alert(DEV, "we had at least one MD IO ERROR during bitmap IO\n"); |
1099 | drbd_chk_io_error(mdev, 1, true); | 1099 | drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR); |
1100 | err = -EIO; /* ctx->error ? */ | 1100 | err = -EIO; /* ctx->error ? */ |
1101 | } | 1101 | } |
1102 | 1102 | ||
@@ -1212,7 +1212,7 @@ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(loc | |||
1212 | wait_until_done_or_disk_failure(mdev, mdev->ldev, &ctx->done); | 1212 | wait_until_done_or_disk_failure(mdev, mdev->ldev, &ctx->done); |
1213 | 1213 | ||
1214 | if (ctx->error) | 1214 | if (ctx->error) |
1215 | drbd_chk_io_error(mdev, 1, true); | 1215 | drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR); |
1216 | /* that should force detach, so the in memory bitmap will be | 1216 | /* that should force detach, so the in memory bitmap will be |
1217 | * gone in a moment as well. */ | 1217 | * gone in a moment as well. */ |
1218 | 1218 | ||
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 356a6e5b4415..79c69ebb0653 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -832,6 +832,7 @@ enum { | |||
832 | BITMAP_IO_QUEUED, /* Started bitmap IO */ | 832 | BITMAP_IO_QUEUED, /* Started bitmap IO */ |
833 | GO_DISKLESS, /* Disk is being detached, on io-error or admin request. */ | 833 | GO_DISKLESS, /* Disk is being detached, on io-error or admin request. */ |
834 | WAS_IO_ERROR, /* Local disk failed returned IO error */ | 834 | WAS_IO_ERROR, /* Local disk failed returned IO error */ |
835 | FORCE_DETACH, /* Force-detach from local disk, aborting any pending local IO */ | ||
835 | RESYNC_AFTER_NEG, /* Resync after online grow after the attach&negotiate finished. */ | 836 | RESYNC_AFTER_NEG, /* Resync after online grow after the attach&negotiate finished. */ |
836 | NET_CONGESTED, /* The data socket is congested */ | 837 | NET_CONGESTED, /* The data socket is congested */ |
837 | 838 | ||
@@ -1838,12 +1839,20 @@ static inline int drbd_request_state(struct drbd_conf *mdev, | |||
1838 | return _drbd_request_state(mdev, mask, val, CS_VERBOSE + CS_ORDERED); | 1839 | return _drbd_request_state(mdev, mask, val, CS_VERBOSE + CS_ORDERED); |
1839 | } | 1840 | } |
1840 | 1841 | ||
1842 | enum drbd_force_detach_flags { | ||
1843 | DRBD_IO_ERROR, | ||
1844 | DRBD_META_IO_ERROR, | ||
1845 | DRBD_FORCE_DETACH, | ||
1846 | }; | ||
1847 | |||
1841 | #define __drbd_chk_io_error(m,f) __drbd_chk_io_error_(m,f, __func__) | 1848 | #define __drbd_chk_io_error(m,f) __drbd_chk_io_error_(m,f, __func__) |
1842 | static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach, const char *where) | 1849 | static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, |
1850 | enum drbd_force_detach_flags forcedetach, | ||
1851 | const char *where) | ||
1843 | { | 1852 | { |
1844 | switch (mdev->ldev->dc.on_io_error) { | 1853 | switch (mdev->ldev->dc.on_io_error) { |
1845 | case EP_PASS_ON: | 1854 | case EP_PASS_ON: |
1846 | if (!forcedetach) { | 1855 | if (forcedetach == DRBD_IO_ERROR) { |
1847 | if (__ratelimit(&drbd_ratelimit_state)) | 1856 | if (__ratelimit(&drbd_ratelimit_state)) |
1848 | dev_err(DEV, "Local IO failed in %s.\n", where); | 1857 | dev_err(DEV, "Local IO failed in %s.\n", where); |
1849 | if (mdev->state.disk > D_INCONSISTENT) | 1858 | if (mdev->state.disk > D_INCONSISTENT) |
@@ -1854,6 +1863,8 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach, | |||
1854 | case EP_DETACH: | 1863 | case EP_DETACH: |
1855 | case EP_CALL_HELPER: | 1864 | case EP_CALL_HELPER: |
1856 | set_bit(WAS_IO_ERROR, &mdev->flags); | 1865 | set_bit(WAS_IO_ERROR, &mdev->flags); |
1866 | if (forcedetach == DRBD_FORCE_DETACH) | ||
1867 | set_bit(FORCE_DETACH, &mdev->flags); | ||
1857 | if (mdev->state.disk > D_FAILED) { | 1868 | if (mdev->state.disk > D_FAILED) { |
1858 | _drbd_set_state(_NS(mdev, disk, D_FAILED), CS_HARD, NULL); | 1869 | _drbd_set_state(_NS(mdev, disk, D_FAILED), CS_HARD, NULL); |
1859 | dev_err(DEV, | 1870 | dev_err(DEV, |
@@ -1873,7 +1884,7 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach, | |||
1873 | */ | 1884 | */ |
1874 | #define drbd_chk_io_error(m,e,f) drbd_chk_io_error_(m,e,f, __func__) | 1885 | #define drbd_chk_io_error(m,e,f) drbd_chk_io_error_(m,e,f, __func__) |
1875 | static inline void drbd_chk_io_error_(struct drbd_conf *mdev, | 1886 | static inline void drbd_chk_io_error_(struct drbd_conf *mdev, |
1876 | int error, int forcedetach, const char *where) | 1887 | int error, enum drbd_force_detach_flags forcedetach, const char *where) |
1877 | { | 1888 | { |
1878 | if (error) { | 1889 | if (error) { |
1879 | unsigned long flags; | 1890 | unsigned long flags; |
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 920ede2829d6..5bebe8d8ace3 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -1630,9 +1630,21 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, | |||
1630 | eh = mdev->ldev->dc.on_io_error; | 1630 | eh = mdev->ldev->dc.on_io_error; |
1631 | was_io_error = test_and_clear_bit(WAS_IO_ERROR, &mdev->flags); | 1631 | was_io_error = test_and_clear_bit(WAS_IO_ERROR, &mdev->flags); |
1632 | 1632 | ||
1633 | /* Immediately allow completion of all application IO, that waits | 1633 | /* Immediately allow completion of all application IO, |
1634 | for completion from the local disk. */ | 1634 | * that waits for completion from the local disk, |
1635 | tl_abort_disk_io(mdev); | 1635 | * if this was a force-detach due to disk_timeout |
1636 | * or administrator request (drbdsetup detach --force). | ||
1637 | * Do NOT abort otherwise. | ||
1638 | * Aborting local requests may cause serious problems, | ||
1639 | * if requests are completed to upper layers already, | ||
1640 | * and then later the already submitted local bio completes. | ||
1641 | * This can cause DMA into former bio pages that meanwhile | ||
1642 | * have been re-used for other things. | ||
1643 | * So aborting local requests may cause crashes, | ||
1644 | * or even worse, silent data corruption. | ||
1645 | */ | ||
1646 | if (test_and_clear_bit(FORCE_DETACH, &mdev->flags)) | ||
1647 | tl_abort_disk_io(mdev); | ||
1636 | 1648 | ||
1637 | /* current state still has to be D_FAILED, | 1649 | /* current state still has to be D_FAILED, |
1638 | * there is only one way out: to D_DISKLESS, | 1650 | * there is only one way out: to D_DISKLESS, |
@@ -3870,7 +3882,7 @@ void drbd_md_sync(struct drbd_conf *mdev) | |||
3870 | if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) { | 3882 | if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) { |
3871 | /* this was a try anyways ... */ | 3883 | /* this was a try anyways ... */ |
3872 | dev_err(DEV, "meta data update failed!\n"); | 3884 | dev_err(DEV, "meta data update failed!\n"); |
3873 | drbd_chk_io_error(mdev, 1, true); | 3885 | drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR); |
3874 | } | 3886 | } |
3875 | 3887 | ||
3876 | /* Update mdev->ldev->md.la_size_sect, | 3888 | /* Update mdev->ldev->md.la_size_sect, |
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 6d4de6a72e80..40a1c4f07190 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -950,6 +950,9 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp | |||
950 | * to realize a "hot spare" feature (not that I'd recommend that) */ | 950 | * to realize a "hot spare" feature (not that I'd recommend that) */ |
951 | wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt)); | 951 | wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt)); |
952 | 952 | ||
953 | /* make sure there is no leftover from previous force-detach attempts */ | ||
954 | clear_bit(FORCE_DETACH, &mdev->flags); | ||
955 | |||
953 | /* allocation not in the IO path, cqueue thread context */ | 956 | /* allocation not in the IO path, cqueue thread context */ |
954 | nbc = kzalloc(sizeof(struct drbd_backing_dev), GFP_KERNEL); | 957 | nbc = kzalloc(sizeof(struct drbd_backing_dev), GFP_KERNEL); |
955 | if (!nbc) { | 958 | if (!nbc) { |
@@ -1345,6 +1348,7 @@ static int drbd_nl_detach(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, | |||
1345 | } | 1348 | } |
1346 | 1349 | ||
1347 | if (dt.detach_force) { | 1350 | if (dt.detach_force) { |
1351 | set_bit(FORCE_DETACH, &mdev->flags); | ||
1348 | drbd_force_state(mdev, NS(disk, D_FAILED)); | 1352 | drbd_force_state(mdev, NS(disk, D_FAILED)); |
1349 | reply->ret_code = SS_SUCCESS; | 1353 | reply->ret_code = SS_SUCCESS; |
1350 | goto out; | 1354 | goto out; |
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 8e93a6ac9bb6..1f4b2dbb7d4a 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
@@ -455,7 +455,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
455 | req->rq_state |= RQ_LOCAL_COMPLETED; | 455 | req->rq_state |= RQ_LOCAL_COMPLETED; |
456 | req->rq_state &= ~RQ_LOCAL_PENDING; | 456 | req->rq_state &= ~RQ_LOCAL_PENDING; |
457 | 457 | ||
458 | __drbd_chk_io_error(mdev, false); | 458 | __drbd_chk_io_error(mdev, DRBD_IO_ERROR); |
459 | _req_may_be_done_not_susp(req, m); | 459 | _req_may_be_done_not_susp(req, m); |
460 | break; | 460 | break; |
461 | 461 | ||
@@ -477,7 +477,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
477 | break; | 477 | break; |
478 | } | 478 | } |
479 | 479 | ||
480 | __drbd_chk_io_error(mdev, false); | 480 | __drbd_chk_io_error(mdev, DRBD_IO_ERROR); |
481 | 481 | ||
482 | goto_queue_for_net_read: | 482 | goto_queue_for_net_read: |
483 | 483 | ||
@@ -1275,7 +1275,7 @@ void request_timer_fn(unsigned long data) | |||
1275 | time_after(now, req->start_time + dt) && | 1275 | time_after(now, req->start_time + dt) && |
1276 | !time_in_range(now, mdev->last_reattach_jif, mdev->last_reattach_jif + dt)) { | 1276 | !time_in_range(now, mdev->last_reattach_jif, mdev->last_reattach_jif + dt)) { |
1277 | dev_warn(DEV, "Local backing device failed to meet the disk-timeout\n"); | 1277 | dev_warn(DEV, "Local backing device failed to meet the disk-timeout\n"); |
1278 | __drbd_chk_io_error(mdev, 1); | 1278 | __drbd_chk_io_error(mdev, DRBD_FORCE_DETACH); |
1279 | } | 1279 | } |
1280 | nt = (time_after(now, req->start_time + et) ? now : req->start_time) + et; | 1280 | nt = (time_after(now, req->start_time + et) ? now : req->start_time) + et; |
1281 | spin_unlock_irq(&mdev->req_lock); | 1281 | spin_unlock_irq(&mdev->req_lock); |
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 620c70ff2231..a35393f2fd1b 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c | |||
@@ -111,7 +111,7 @@ void drbd_endio_read_sec_final(struct drbd_epoch_entry *e) __releases(local) | |||
111 | if (list_empty(&mdev->read_ee)) | 111 | if (list_empty(&mdev->read_ee)) |
112 | wake_up(&mdev->ee_wait); | 112 | wake_up(&mdev->ee_wait); |
113 | if (test_bit(__EE_WAS_ERROR, &e->flags)) | 113 | if (test_bit(__EE_WAS_ERROR, &e->flags)) |
114 | __drbd_chk_io_error(mdev, false); | 114 | __drbd_chk_io_error(mdev, DRBD_IO_ERROR); |
115 | spin_unlock_irqrestore(&mdev->req_lock, flags); | 115 | spin_unlock_irqrestore(&mdev->req_lock, flags); |
116 | 116 | ||
117 | drbd_queue_work(&mdev->data.work, &e->w); | 117 | drbd_queue_work(&mdev->data.work, &e->w); |
@@ -154,7 +154,7 @@ static void drbd_endio_write_sec_final(struct drbd_epoch_entry *e) __releases(lo | |||
154 | : list_empty(&mdev->active_ee); | 154 | : list_empty(&mdev->active_ee); |
155 | 155 | ||
156 | if (test_bit(__EE_WAS_ERROR, &e->flags)) | 156 | if (test_bit(__EE_WAS_ERROR, &e->flags)) |
157 | __drbd_chk_io_error(mdev, false); | 157 | __drbd_chk_io_error(mdev, DRBD_IO_ERROR); |
158 | spin_unlock_irqrestore(&mdev->req_lock, flags); | 158 | spin_unlock_irqrestore(&mdev->req_lock, flags); |
159 | 159 | ||
160 | if (is_syncer_req) | 160 | if (is_syncer_req) |