diff options
Diffstat (limited to 'drivers/block/drbd/drbd_state.c')
-rw-r--r-- | drivers/block/drbd/drbd_state.c | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c index 1a84345a3868..a5d8aae00e04 100644 --- a/drivers/block/drbd/drbd_state.c +++ b/drivers/block/drbd/drbd_state.c | |||
@@ -54,8 +54,8 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os, | |||
54 | static enum drbd_state_rv is_valid_state(struct drbd_device *, union drbd_state); | 54 | static enum drbd_state_rv is_valid_state(struct drbd_device *, union drbd_state); |
55 | static enum drbd_state_rv is_valid_soft_transition(union drbd_state, union drbd_state, struct drbd_connection *); | 55 | static enum drbd_state_rv is_valid_soft_transition(union drbd_state, union drbd_state, struct drbd_connection *); |
56 | static enum drbd_state_rv is_valid_transition(union drbd_state os, union drbd_state ns); | 56 | static enum drbd_state_rv is_valid_transition(union drbd_state os, union drbd_state ns); |
57 | static union drbd_state sanitize_state(struct drbd_device *device, union drbd_state ns, | 57 | static union drbd_state sanitize_state(struct drbd_device *device, union drbd_state os, |
58 | enum sanitize_state_warnings *warn); | 58 | union drbd_state ns, enum sanitize_state_warnings *warn); |
59 | 59 | ||
60 | static inline bool is_susp(union drbd_state s) | 60 | static inline bool is_susp(union drbd_state s) |
61 | { | 61 | { |
@@ -287,7 +287,7 @@ _req_st_cond(struct drbd_device *device, union drbd_state mask, | |||
287 | 287 | ||
288 | spin_lock_irqsave(&device->resource->req_lock, flags); | 288 | spin_lock_irqsave(&device->resource->req_lock, flags); |
289 | os = drbd_read_state(device); | 289 | os = drbd_read_state(device); |
290 | ns = sanitize_state(device, apply_mask_val(os, mask, val), NULL); | 290 | ns = sanitize_state(device, os, apply_mask_val(os, mask, val), NULL); |
291 | rv = is_valid_transition(os, ns); | 291 | rv = is_valid_transition(os, ns); |
292 | if (rv >= SS_SUCCESS) | 292 | if (rv >= SS_SUCCESS) |
293 | rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */ | 293 | rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */ |
@@ -333,7 +333,7 @@ drbd_req_state(struct drbd_device *device, union drbd_state mask, | |||
333 | 333 | ||
334 | spin_lock_irqsave(&device->resource->req_lock, flags); | 334 | spin_lock_irqsave(&device->resource->req_lock, flags); |
335 | os = drbd_read_state(device); | 335 | os = drbd_read_state(device); |
336 | ns = sanitize_state(device, apply_mask_val(os, mask, val), NULL); | 336 | ns = sanitize_state(device, os, apply_mask_val(os, mask, val), NULL); |
337 | rv = is_valid_transition(os, ns); | 337 | rv = is_valid_transition(os, ns); |
338 | if (rv < SS_SUCCESS) { | 338 | if (rv < SS_SUCCESS) { |
339 | spin_unlock_irqrestore(&device->resource->req_lock, flags); | 339 | spin_unlock_irqrestore(&device->resource->req_lock, flags); |
@@ -740,8 +740,8 @@ static void print_sanitize_warnings(struct drbd_device *device, enum sanitize_st | |||
740 | * When we loose connection, we have to set the state of the peers disk (pdsk) | 740 | * When we loose connection, we have to set the state of the peers disk (pdsk) |
741 | * to D_UNKNOWN. This rule and many more along those lines are in this function. | 741 | * to D_UNKNOWN. This rule and many more along those lines are in this function. |
742 | */ | 742 | */ |
743 | static union drbd_state sanitize_state(struct drbd_device *device, union drbd_state ns, | 743 | static union drbd_state sanitize_state(struct drbd_device *device, union drbd_state os, |
744 | enum sanitize_state_warnings *warn) | 744 | union drbd_state ns, enum sanitize_state_warnings *warn) |
745 | { | 745 | { |
746 | enum drbd_fencing_p fp; | 746 | enum drbd_fencing_p fp; |
747 | enum drbd_disk_state disk_min, disk_max, pdsk_min, pdsk_max; | 747 | enum drbd_disk_state disk_min, disk_max, pdsk_min, pdsk_max; |
@@ -882,11 +882,13 @@ static union drbd_state sanitize_state(struct drbd_device *device, union drbd_st | |||
882 | } | 882 | } |
883 | 883 | ||
884 | if (fp == FP_STONITH && | 884 | if (fp == FP_STONITH && |
885 | (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED)) | 885 | (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED) && |
886 | !(os.role == R_PRIMARY && os.conn < C_CONNECTED && os.pdsk > D_OUTDATED)) | ||
886 | ns.susp_fen = 1; /* Suspend IO while fence-peer handler runs (peer lost) */ | 887 | ns.susp_fen = 1; /* Suspend IO while fence-peer handler runs (peer lost) */ |
887 | 888 | ||
888 | if (device->resource->res_opts.on_no_data == OND_SUSPEND_IO && | 889 | if (device->resource->res_opts.on_no_data == OND_SUSPEND_IO && |
889 | (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE)) | 890 | (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE) && |
891 | !(os.role == R_PRIMARY && os.disk < D_UP_TO_DATE && os.pdsk < D_UP_TO_DATE)) | ||
890 | ns.susp_nod = 1; /* Suspend IO while no data available (no accessible data available) */ | 892 | ns.susp_nod = 1; /* Suspend IO while no data available (no accessible data available) */ |
891 | 893 | ||
892 | if (ns.aftr_isp || ns.peer_isp || ns.user_isp) { | 894 | if (ns.aftr_isp || ns.peer_isp || ns.user_isp) { |
@@ -958,7 +960,7 @@ __drbd_set_state(struct drbd_device *device, union drbd_state ns, | |||
958 | 960 | ||
959 | os = drbd_read_state(device); | 961 | os = drbd_read_state(device); |
960 | 962 | ||
961 | ns = sanitize_state(device, ns, &ssw); | 963 | ns = sanitize_state(device, os, ns, &ssw); |
962 | if (ns.i == os.i) | 964 | if (ns.i == os.i) |
963 | return SS_NOTHING_TO_DO; | 965 | return SS_NOTHING_TO_DO; |
964 | 966 | ||
@@ -1656,7 +1658,7 @@ conn_is_valid_transition(struct drbd_connection *connection, union drbd_state ma | |||
1656 | idr_for_each_entry(&connection->peer_devices, peer_device, vnr) { | 1658 | idr_for_each_entry(&connection->peer_devices, peer_device, vnr) { |
1657 | struct drbd_device *device = peer_device->device; | 1659 | struct drbd_device *device = peer_device->device; |
1658 | os = drbd_read_state(device); | 1660 | os = drbd_read_state(device); |
1659 | ns = sanitize_state(device, apply_mask_val(os, mask, val), NULL); | 1661 | ns = sanitize_state(device, os, apply_mask_val(os, mask, val), NULL); |
1660 | 1662 | ||
1661 | if (flags & CS_IGN_OUTD_FAIL && ns.disk == D_OUTDATED && os.disk < D_OUTDATED) | 1663 | if (flags & CS_IGN_OUTD_FAIL && ns.disk == D_OUTDATED && os.disk < D_OUTDATED) |
1662 | ns.disk = os.disk; | 1664 | ns.disk = os.disk; |
@@ -1718,7 +1720,7 @@ conn_set_state(struct drbd_connection *connection, union drbd_state mask, union | |||
1718 | number_of_volumes++; | 1720 | number_of_volumes++; |
1719 | os = drbd_read_state(device); | 1721 | os = drbd_read_state(device); |
1720 | ns = apply_mask_val(os, mask, val); | 1722 | ns = apply_mask_val(os, mask, val); |
1721 | ns = sanitize_state(device, ns, NULL); | 1723 | ns = sanitize_state(device, os, ns, NULL); |
1722 | 1724 | ||
1723 | if (flags & CS_IGN_OUTD_FAIL && ns.disk == D_OUTDATED && os.disk < D_OUTDATED) | 1725 | if (flags & CS_IGN_OUTD_FAIL && ns.disk == D_OUTDATED && os.disk < D_OUTDATED) |
1724 | ns.disk = os.disk; | 1726 | ns.disk = os.disk; |
@@ -1763,19 +1765,19 @@ conn_set_state(struct drbd_connection *connection, union drbd_state mask, union | |||
1763 | static enum drbd_state_rv | 1765 | static enum drbd_state_rv |
1764 | _conn_rq_cond(struct drbd_connection *connection, union drbd_state mask, union drbd_state val) | 1766 | _conn_rq_cond(struct drbd_connection *connection, union drbd_state mask, union drbd_state val) |
1765 | { | 1767 | { |
1766 | enum drbd_state_rv rv; | 1768 | enum drbd_state_rv err, rv = SS_UNKNOWN_ERROR; /* continue waiting */; |
1767 | 1769 | ||
1768 | if (test_and_clear_bit(CONN_WD_ST_CHG_OKAY, &connection->flags)) | 1770 | if (test_and_clear_bit(CONN_WD_ST_CHG_OKAY, &connection->flags)) |
1769 | return SS_CW_SUCCESS; | 1771 | rv = SS_CW_SUCCESS; |
1770 | 1772 | ||
1771 | if (test_and_clear_bit(CONN_WD_ST_CHG_FAIL, &connection->flags)) | 1773 | if (test_and_clear_bit(CONN_WD_ST_CHG_FAIL, &connection->flags)) |
1772 | return SS_CW_FAILED_BY_PEER; | 1774 | rv = SS_CW_FAILED_BY_PEER; |
1773 | 1775 | ||
1774 | rv = conn_is_valid_transition(connection, mask, val, 0); | 1776 | err = conn_is_valid_transition(connection, mask, val, 0); |
1775 | if (rv == SS_SUCCESS && connection->cstate == C_WF_REPORT_PARAMS) | 1777 | if (err == SS_SUCCESS && connection->cstate == C_WF_REPORT_PARAMS) |
1776 | rv = SS_UNKNOWN_ERROR; /* continue waiting */ | 1778 | return rv; |
1777 | 1779 | ||
1778 | return rv; | 1780 | return err; |
1779 | } | 1781 | } |
1780 | 1782 | ||
1781 | enum drbd_state_rv | 1783 | enum drbd_state_rv |