aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_int.h
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2012-07-30 03:07:28 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-08 10:58:39 -0500
commit0c849666016cbf541c1030eec55f5f8dd1fba513 (patch)
tree35a49ef17d65375947404bd81759fc815bf09d5d /drivers/block/drbd/drbd_int.h
parentbf709c8552bcbbbc66ecc11555a781e814a037d8 (diff)
drbd: differentiate between normal and forced detach
Aborting local requests (not waiting for completion from the lower level disk) is dangerous: if the master bio has been completed to upper layers, data pages may be re-used for other things already. If local IO is still pending and later completes, this may cause crashes or corrupt unrelated data. Only abort local IO if explicitly requested. Intended use case is a lower level device that turned into a tarpit, not completing io requests, not even doing error completion. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_int.h')
-rw-r--r--drivers/block/drbd/drbd_int.h17
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index b343875c9dee..963766bafab4 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -689,6 +689,7 @@ enum {
689 BITMAP_IO_QUEUED, /* Started bitmap IO */ 689 BITMAP_IO_QUEUED, /* Started bitmap IO */
690 GO_DISKLESS, /* Disk is being detached, on io-error or admin request. */ 690 GO_DISKLESS, /* Disk is being detached, on io-error or admin request. */
691 WAS_IO_ERROR, /* Local disk failed returned IO error */ 691 WAS_IO_ERROR, /* Local disk failed returned IO error */
692 FORCE_DETACH, /* Force-detach from local disk, aborting any pending local IO */
692 RESYNC_AFTER_NEG, /* Resync after online grow after the attach&negotiate finished. */ 693 RESYNC_AFTER_NEG, /* Resync after online grow after the attach&negotiate finished. */
693 RESIZE_PENDING, /* Size change detected locally, waiting for the response from 694 RESIZE_PENDING, /* Size change detected locally, waiting for the response from
694 * the peer, if it changed there as well. */ 695 * the peer, if it changed there as well. */
@@ -1653,8 +1654,16 @@ static inline union drbd_state drbd_read_state(struct drbd_conf *mdev)
1653 return rv; 1654 return rv;
1654} 1655}
1655 1656
1657enum drbd_force_detach_flags {
1658 DRBD_IO_ERROR,
1659 DRBD_META_IO_ERROR,
1660 DRBD_FORCE_DETACH,
1661};
1662
1656#define __drbd_chk_io_error(m,f) __drbd_chk_io_error_(m,f, __func__) 1663#define __drbd_chk_io_error(m,f) __drbd_chk_io_error_(m,f, __func__)
1657static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach, const char *where) 1664static inline void __drbd_chk_io_error_(struct drbd_conf *mdev,
1665 enum drbd_force_detach_flags forcedetach,
1666 const char *where)
1658{ 1667{
1659 enum drbd_io_error_p ep; 1668 enum drbd_io_error_p ep;
1660 1669
@@ -1663,7 +1672,7 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach,
1663 rcu_read_unlock(); 1672 rcu_read_unlock();
1664 switch (ep) { 1673 switch (ep) {
1665 case EP_PASS_ON: /* FIXME would this be better named "Ignore"? */ 1674 case EP_PASS_ON: /* FIXME would this be better named "Ignore"? */
1666 if (!forcedetach) { 1675 if (forcedetach == DRBD_IO_ERROR) {
1667 if (__ratelimit(&drbd_ratelimit_state)) 1676 if (__ratelimit(&drbd_ratelimit_state))
1668 dev_err(DEV, "Local IO failed in %s.\n", where); 1677 dev_err(DEV, "Local IO failed in %s.\n", where);
1669 if (mdev->state.disk > D_INCONSISTENT) 1678 if (mdev->state.disk > D_INCONSISTENT)
@@ -1674,6 +1683,8 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach,
1674 case EP_DETACH: 1683 case EP_DETACH:
1675 case EP_CALL_HELPER: 1684 case EP_CALL_HELPER:
1676 set_bit(WAS_IO_ERROR, &mdev->flags); 1685 set_bit(WAS_IO_ERROR, &mdev->flags);
1686 if (forcedetach == DRBD_FORCE_DETACH)
1687 set_bit(FORCE_DETACH, &mdev->flags);
1677 if (mdev->state.disk > D_FAILED) { 1688 if (mdev->state.disk > D_FAILED) {
1678 _drbd_set_state(_NS(mdev, disk, D_FAILED), CS_HARD, NULL); 1689 _drbd_set_state(_NS(mdev, disk, D_FAILED), CS_HARD, NULL);
1679 dev_err(DEV, 1690 dev_err(DEV,
@@ -1693,7 +1704,7 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach,
1693 */ 1704 */
1694#define drbd_chk_io_error(m,e,f) drbd_chk_io_error_(m,e,f, __func__) 1705#define drbd_chk_io_error(m,e,f) drbd_chk_io_error_(m,e,f, __func__)
1695static inline void drbd_chk_io_error_(struct drbd_conf *mdev, 1706static inline void drbd_chk_io_error_(struct drbd_conf *mdev,
1696 int error, int forcedetach, const char *where) 1707 int error, enum drbd_force_detach_flags forcedetach, const char *where)
1697{ 1708{
1698 if (error) { 1709 if (error) {
1699 unsigned long flags; 1710 unsigned long flags;