diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2012-08-22 10:15:26 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-09 08:08:21 -0500 |
commit | c02abda2b28734a7e97e15db866507b3cb92b7d0 (patch) | |
tree | c85af57b2f3e9689d4374895c125da37d7ae7fad /drivers/block/drbd | |
parent | c1fd29a11f433ca8ae37723768016ffe6cdd487b (diff) |
drbd: mutex_unlock "... must no be used in interrupt context"
Documentation of mutex_unlock says
we must not use it in interrupt context.
So do not call it while holding the spin_lock_irq,
but give up the spinlock temporarily.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd')
-rw-r--r-- | drivers/block/drbd/drbd_state.c | 74 |
1 files changed, 39 insertions, 35 deletions
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c index ce1495187f02..755425a7a99b 100644 --- a/drivers/block/drbd/drbd_state.c +++ b/drivers/block/drbd/drbd_state.c | |||
@@ -1721,38 +1721,6 @@ _conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state | |||
1721 | return rv; | 1721 | return rv; |
1722 | } | 1722 | } |
1723 | 1723 | ||
1724 | static enum drbd_state_rv | ||
1725 | conn_cl_wide(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val, | ||
1726 | enum chg_state_flags f) | ||
1727 | { | ||
1728 | enum drbd_state_rv rv; | ||
1729 | |||
1730 | spin_unlock_irq(&tconn->req_lock); | ||
1731 | mutex_lock(&tconn->cstate_mutex); | ||
1732 | |||
1733 | set_bit(CONN_WD_ST_CHG_REQ, &tconn->flags); | ||
1734 | if (conn_send_state_req(tconn, mask, val)) { | ||
1735 | clear_bit(CONN_WD_ST_CHG_REQ, &tconn->flags); | ||
1736 | /* if (f & CS_VERBOSE) | ||
1737 | print_st_err(mdev, os, ns, rv); */ | ||
1738 | mutex_unlock(&tconn->cstate_mutex); | ||
1739 | spin_lock_irq(&tconn->req_lock); | ||
1740 | return SS_CW_FAILED_BY_PEER; | ||
1741 | } | ||
1742 | |||
1743 | if (val.conn == C_DISCONNECTING) | ||
1744 | set_bit(DISCONNECT_SENT, &tconn->flags); | ||
1745 | |||
1746 | spin_lock_irq(&tconn->req_lock); | ||
1747 | |||
1748 | wait_event_lock_irq(tconn->ping_wait, (rv = _conn_rq_cond(tconn, mask, val)), tconn->req_lock,); | ||
1749 | clear_bit(CONN_WD_ST_CHG_REQ, &tconn->flags); | ||
1750 | |||
1751 | mutex_unlock(&tconn->cstate_mutex); | ||
1752 | |||
1753 | return rv; | ||
1754 | } | ||
1755 | |||
1756 | enum drbd_state_rv | 1724 | enum drbd_state_rv |
1757 | _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val, | 1725 | _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val, |
1758 | enum chg_state_flags flags) | 1726 | enum chg_state_flags flags) |
@@ -1761,6 +1729,7 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_ | |||
1761 | struct after_conn_state_chg_work *acscw; | 1729 | struct after_conn_state_chg_work *acscw; |
1762 | enum drbd_conns oc = tconn->cstate; | 1730 | enum drbd_conns oc = tconn->cstate; |
1763 | union drbd_state ns_max, ns_min, os; | 1731 | union drbd_state ns_max, ns_min, os; |
1732 | bool have_mutex = false; | ||
1764 | 1733 | ||
1765 | rv = is_valid_conn_transition(oc, val.conn); | 1734 | rv = is_valid_conn_transition(oc, val.conn); |
1766 | if (rv < SS_SUCCESS) | 1735 | if (rv < SS_SUCCESS) |
@@ -1772,7 +1741,35 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_ | |||
1772 | 1741 | ||
1773 | if (oc == C_WF_REPORT_PARAMS && val.conn == C_DISCONNECTING && | 1742 | if (oc == C_WF_REPORT_PARAMS && val.conn == C_DISCONNECTING && |
1774 | !(flags & (CS_LOCAL_ONLY | CS_HARD))) { | 1743 | !(flags & (CS_LOCAL_ONLY | CS_HARD))) { |
1775 | rv = conn_cl_wide(tconn, mask, val, flags); | 1744 | |
1745 | /* This will be a cluster-wide state change. | ||
1746 | * Need to give up the spinlock, grab the mutex, | ||
1747 | * then send the state change request, ... */ | ||
1748 | spin_unlock_irq(&tconn->req_lock); | ||
1749 | mutex_lock(&tconn->cstate_mutex); | ||
1750 | have_mutex = true; | ||
1751 | |||
1752 | set_bit(CONN_WD_ST_CHG_REQ, &tconn->flags); | ||
1753 | if (conn_send_state_req(tconn, mask, val)) { | ||
1754 | /* sending failed. */ | ||
1755 | clear_bit(CONN_WD_ST_CHG_REQ, &tconn->flags); | ||
1756 | rv = SS_CW_FAILED_BY_PEER; | ||
1757 | /* need to re-aquire the spin lock, though */ | ||
1758 | goto abort_unlocked; | ||
1759 | } | ||
1760 | |||
1761 | if (val.conn == C_DISCONNECTING) | ||
1762 | set_bit(DISCONNECT_SENT, &tconn->flags); | ||
1763 | |||
1764 | /* ... and re-aquire the spinlock. | ||
1765 | * If _conn_rq_cond() returned >= SS_SUCCESS, we must call | ||
1766 | * conn_set_state() within the same spinlock. */ | ||
1767 | spin_lock_irq(&tconn->req_lock); | ||
1768 | wait_event_lock_irq(tconn->ping_wait, | ||
1769 | (rv = _conn_rq_cond(tconn, mask, val)), | ||
1770 | tconn->req_lock, | ||
1771 | ); | ||
1772 | clear_bit(CONN_WD_ST_CHG_REQ, &tconn->flags); | ||
1776 | if (rv < SS_SUCCESS) | 1773 | if (rv < SS_SUCCESS) |
1777 | goto abort; | 1774 | goto abort; |
1778 | } | 1775 | } |
@@ -1796,9 +1793,16 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_ | |||
1796 | conn_err(tconn, "Could not kmalloc an acscw\n"); | 1793 | conn_err(tconn, "Could not kmalloc an acscw\n"); |
1797 | } | 1794 | } |
1798 | 1795 | ||
1799 | return rv; | ||
1800 | abort: | 1796 | abort: |
1801 | if (flags & CS_VERBOSE) { | 1797 | if (have_mutex) { |
1798 | /* mutex_unlock() "... must not be used in interrupt context.", | ||
1799 | * so give up the spinlock, then re-aquire it */ | ||
1800 | spin_unlock_irq(&tconn->req_lock); | ||
1801 | abort_unlocked: | ||
1802 | mutex_unlock(&tconn->cstate_mutex); | ||
1803 | spin_lock_irq(&tconn->req_lock); | ||
1804 | } | ||
1805 | if (rv < SS_SUCCESS && flags & CS_VERBOSE) { | ||
1802 | conn_err(tconn, "State change failed: %s\n", drbd_set_st_err_str(rv)); | 1806 | conn_err(tconn, "State change failed: %s\n", drbd_set_st_err_str(rv)); |
1803 | conn_err(tconn, " state = { cs:%s }\n", drbd_conn_str(oc)); | 1807 | conn_err(tconn, " state = { cs:%s }\n", drbd_conn_str(oc)); |
1804 | conn_err(tconn, "wanted = { cs:%s }\n", drbd_conn_str(val.conn)); | 1808 | conn_err(tconn, "wanted = { cs:%s }\n", drbd_conn_str(val.conn)); |