aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/drbd')
-rw-r--r--drivers/block/drbd/drbd_int.h9
-rw-r--r--drivers/block/drbd/drbd_main.c36
-rw-r--r--drivers/block/drbd/drbd_nl.c20
-rw-r--r--drivers/block/drbd/drbd_proc.c2
-rw-r--r--drivers/block/drbd/drbd_receiver.c6
-rw-r--r--drivers/block/drbd/drbd_req.c6
6 files changed, 52 insertions, 27 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index eb1273d04caf..ff7fffa00dac 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1681,6 +1681,8 @@ void drbd_bcast_ee(struct drbd_conf *mdev,
1681#define susp_MASK 1 1681#define susp_MASK 1
1682#define user_isp_MASK 1 1682#define user_isp_MASK 1
1683#define aftr_isp_MASK 1 1683#define aftr_isp_MASK 1
1684#define susp_nod_MASK 1
1685#define susp_fen_MASK 1
1684 1686
1685#define NS(T, S) \ 1687#define NS(T, S) \
1686 ({ union drbd_state mask; mask.i = 0; mask.T = T##_MASK; mask; }), \ 1688 ({ union drbd_state mask; mask.i = 0; mask.T = T##_MASK; mask; }), \
@@ -2254,11 +2256,16 @@ static inline int drbd_state_is_stable(union drbd_state s)
2254 return 1; 2256 return 1;
2255} 2257}
2256 2258
2259static inline int is_susp(union drbd_state s)
2260{
2261 return s.susp || s.susp_nod || s.susp_fen;
2262}
2263
2257static inline int __inc_ap_bio_cond(struct drbd_conf *mdev) 2264static inline int __inc_ap_bio_cond(struct drbd_conf *mdev)
2258{ 2265{
2259 int mxb = drbd_get_max_buffers(mdev); 2266 int mxb = drbd_get_max_buffers(mdev);
2260 2267
2261 if (mdev->state.susp) 2268 if (is_susp(mdev->state))
2262 return 0; 2269 return 0;
2263 if (test_bit(SUSPEND_IO, &mdev->flags)) 2270 if (test_bit(SUSPEND_IO, &mdev->flags))
2264 return 0; 2271 return 0;
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 04c305d36f8e..4f33714fb3cd 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -654,7 +654,7 @@ static void print_st(struct drbd_conf *mdev, char *name, union drbd_state ns)
654 drbd_role_str(ns.peer), 654 drbd_role_str(ns.peer),
655 drbd_disk_str(ns.disk), 655 drbd_disk_str(ns.disk),
656 drbd_disk_str(ns.pdsk), 656 drbd_disk_str(ns.pdsk),
657 ns.susp ? 's' : 'r', 657 is_susp(ns) ? 's' : 'r',
658 ns.aftr_isp ? 'a' : '-', 658 ns.aftr_isp ? 'a' : '-',
659 ns.peer_isp ? 'p' : '-', 659 ns.peer_isp ? 'p' : '-',
660 ns.user_isp ? 'u' : '-' 660 ns.user_isp ? 'u' : '-'
@@ -925,12 +925,12 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
925 if (fp == FP_STONITH && 925 if (fp == FP_STONITH &&
926 (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED) && 926 (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED) &&
927 !(os.role == R_PRIMARY && os.conn < C_CONNECTED && os.pdsk > D_OUTDATED)) 927 !(os.role == R_PRIMARY && os.conn < C_CONNECTED && os.pdsk > D_OUTDATED))
928 ns.susp = 1; /* Suspend IO while fence-peer handler runs (peer lost) */ 928 ns.susp_fen = 1; /* Suspend IO while fence-peer handler runs (peer lost) */
929 929
930 if (mdev->sync_conf.on_no_data == OND_SUSPEND_IO && 930 if (mdev->sync_conf.on_no_data == OND_SUSPEND_IO &&
931 (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE) && 931 (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE) &&
932 !(os.role == R_PRIMARY && os.disk < D_UP_TO_DATE && os.pdsk < D_UP_TO_DATE)) 932 !(os.role == R_PRIMARY && os.disk < D_UP_TO_DATE && os.pdsk < D_UP_TO_DATE))
933 ns.susp = 1; /* Suspend IO while no data available (no accessible data available) */ 933 ns.susp_nod = 1; /* Suspend IO while no data available (no accessible data available) */
934 934
935 if (ns.aftr_isp || ns.peer_isp || ns.user_isp) { 935 if (ns.aftr_isp || ns.peer_isp || ns.user_isp) {
936 if (ns.conn == C_SYNC_SOURCE) 936 if (ns.conn == C_SYNC_SOURCE)
@@ -1030,7 +1030,10 @@ int __drbd_set_state(struct drbd_conf *mdev,
1030 PSC(conn); 1030 PSC(conn);
1031 PSC(disk); 1031 PSC(disk);
1032 PSC(pdsk); 1032 PSC(pdsk);
1033 PSC(susp); 1033 if (is_susp(ns) != is_susp(os))
1034 pbp += sprintf(pbp, "susp( %s -> %s ) ",
1035 drbd_susp_str(is_susp(os)),
1036 drbd_susp_str(is_susp(ns)));
1034 PSC(aftr_isp); 1037 PSC(aftr_isp);
1035 PSC(peer_isp); 1038 PSC(peer_isp);
1036 PSC(user_isp); 1039 PSC(user_isp);
@@ -1218,6 +1221,7 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
1218{ 1221{
1219 enum drbd_fencing_p fp; 1222 enum drbd_fencing_p fp;
1220 enum drbd_req_event what = nothing; 1223 enum drbd_req_event what = nothing;
1224 union drbd_state nsm = (union drbd_state){ .i = -1 };
1221 1225
1222 if (os.conn != C_CONNECTED && ns.conn == C_CONNECTED) { 1226 if (os.conn != C_CONNECTED && ns.conn == C_CONNECTED) {
1223 clear_bit(CRASHED_PRIMARY, &mdev->flags); 1227 clear_bit(CRASHED_PRIMARY, &mdev->flags);
@@ -1241,19 +1245,21 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
1241 /* Here we have the actions that are performed after a 1245 /* Here we have the actions that are performed after a
1242 state change. This function might sleep */ 1246 state change. This function might sleep */
1243 1247
1244 if (os.susp && ns.susp && mdev->sync_conf.on_no_data == OND_SUSPEND_IO) { 1248 nsm.i = -1;
1249 if (ns.susp_nod) {
1245 if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) { 1250 if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
1246 if (ns.conn == C_CONNECTED) 1251 if (ns.conn == C_CONNECTED)
1247 what = resend; 1252 what = resend, nsm.susp_nod = 0;
1248 else /* ns.conn > C_CONNECTED */ 1253 else /* ns.conn > C_CONNECTED */
1249 dev_err(DEV, "Unexpected Resynd going on!\n"); 1254 dev_err(DEV, "Unexpected Resynd going on!\n");
1250 } 1255 }
1251 1256
1252 if (os.disk == D_ATTACHING && ns.disk > D_ATTACHING) 1257 if (os.disk == D_ATTACHING && ns.disk > D_ATTACHING)
1253 what = restart_frozen_disk_io; 1258 what = restart_frozen_disk_io, nsm.susp_nod = 0;
1259
1254 } 1260 }
1255 1261
1256 if (fp == FP_STONITH && ns.susp) { 1262 if (ns.susp_fen) {
1257 /* case1: The outdate peer handler is successful: */ 1263 /* case1: The outdate peer handler is successful: */
1258 if (os.pdsk > D_OUTDATED && ns.pdsk <= D_OUTDATED) { 1264 if (os.pdsk > D_OUTDATED && ns.pdsk <= D_OUTDATED) {
1259 tl_clear(mdev); 1265 tl_clear(mdev);
@@ -1263,20 +1269,22 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
1263 drbd_md_sync(mdev); 1269 drbd_md_sync(mdev);
1264 } 1270 }
1265 spin_lock_irq(&mdev->req_lock); 1271 spin_lock_irq(&mdev->req_lock);
1266 _drbd_set_state(_NS(mdev, susp, 0), CS_VERBOSE, NULL); 1272 _drbd_set_state(_NS(mdev, susp_fen, 0), CS_VERBOSE, NULL);
1267 spin_unlock_irq(&mdev->req_lock); 1273 spin_unlock_irq(&mdev->req_lock);
1268 } 1274 }
1269 /* case2: The connection was established again: */ 1275 /* case2: The connection was established again: */
1270 if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) { 1276 if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
1271 clear_bit(NEW_CUR_UUID, &mdev->flags); 1277 clear_bit(NEW_CUR_UUID, &mdev->flags);
1272 what = resend; 1278 what = resend;
1279 nsm.susp_fen = 0;
1273 } 1280 }
1274 } 1281 }
1275 1282
1276 if (what != nothing) { 1283 if (what != nothing) {
1277 spin_lock_irq(&mdev->req_lock); 1284 spin_lock_irq(&mdev->req_lock);
1278 _tl_restart(mdev, what); 1285 _tl_restart(mdev, what);
1279 _drbd_set_state(_NS(mdev, susp, 0), CS_VERBOSE, NULL); 1286 nsm.i &= mdev->state.i;
1287 _drbd_set_state(mdev, nsm, CS_VERBOSE, NULL);
1280 spin_unlock_irq(&mdev->req_lock); 1288 spin_unlock_irq(&mdev->req_lock);
1281 } 1289 }
1282 1290
@@ -1298,7 +1306,7 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
1298 if (get_ldev(mdev)) { 1306 if (get_ldev(mdev)) {
1299 if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) && 1307 if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) &&
1300 mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) { 1308 mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
1301 if (mdev->state.susp) { 1309 if (is_susp(mdev->state)) {
1302 set_bit(NEW_CUR_UUID, &mdev->flags); 1310 set_bit(NEW_CUR_UUID, &mdev->flags);
1303 } else { 1311 } else {
1304 drbd_uuid_new_current(mdev); 1312 drbd_uuid_new_current(mdev);
@@ -1417,7 +1425,7 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
1417 resume_next_sg(mdev); 1425 resume_next_sg(mdev);
1418 1426
1419 /* free tl_hash if we Got thawed and are C_STANDALONE */ 1427 /* free tl_hash if we Got thawed and are C_STANDALONE */
1420 if (ns.conn == C_STANDALONE && ns.susp == 0 && mdev->tl_hash) 1428 if (ns.conn == C_STANDALONE && !is_susp(ns) && mdev->tl_hash)
1421 drbd_free_tl_hash(mdev); 1429 drbd_free_tl_hash(mdev);
1422 1430
1423 /* Upon network connection, we need to start the receiver */ 1431 /* Upon network connection, we need to start the receiver */
@@ -2732,7 +2740,9 @@ static void drbd_set_defaults(struct drbd_conf *mdev)
2732 .conn = C_STANDALONE, 2740 .conn = C_STANDALONE,
2733 .disk = D_DISKLESS, 2741 .disk = D_DISKLESS,
2734 .pdsk = D_UNKNOWN, 2742 .pdsk = D_UNKNOWN,
2735 .susp = 0 2743 .susp = 0,
2744 .susp_nod = 0,
2745 .susp_fen = 0
2736 } }; 2746 } };
2737} 2747}
2738 2748
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 5b30f90cab3e..9ee44568dce3 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -209,7 +209,8 @@ enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev)
209 put_ldev(mdev); 209 put_ldev(mdev);
210 } else { 210 } else {
211 dev_warn(DEV, "Not fencing peer, I'm not even Consistent myself.\n"); 211 dev_warn(DEV, "Not fencing peer, I'm not even Consistent myself.\n");
212 return mdev->state.pdsk; 212 nps = mdev->state.pdsk;
213 goto out;
213 } 214 }
214 215
215 r = drbd_khelper(mdev, "fence-peer"); 216 r = drbd_khelper(mdev, "fence-peer");
@@ -256,6 +257,14 @@ enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev)
256 257
257 dev_info(DEV, "fence-peer helper returned %d (%s)\n", 258 dev_info(DEV, "fence-peer helper returned %d (%s)\n",
258 (r>>8) & 0xff, ex_to_string); 259 (r>>8) & 0xff, ex_to_string);
260
261out:
262 if (mdev->state.susp_fen && nps >= D_UNKNOWN) {
263 /* The handler was not successful... unfreeze here, the
264 state engine can not unfreeze... */
265 _drbd_request_state(mdev, NS(susp_fen, 0), CS_VERBOSE);
266 }
267
259 return nps; 268 return nps;
260} 269}
261 270
@@ -550,7 +559,7 @@ char *ppsize(char *buf, unsigned long long size)
550void drbd_suspend_io(struct drbd_conf *mdev) 559void drbd_suspend_io(struct drbd_conf *mdev)
551{ 560{
552 set_bit(SUSPEND_IO, &mdev->flags); 561 set_bit(SUSPEND_IO, &mdev->flags);
553 if (mdev->state.susp) 562 if (is_susp(mdev->state))
554 return; 563 return;
555 wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt)); 564 wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
556} 565}
@@ -1016,7 +1025,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
1016 1025
1017 drbd_suspend_io(mdev); 1026 drbd_suspend_io(mdev);
1018 /* also wait for the last barrier ack. */ 1027 /* also wait for the last barrier ack. */
1019 wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_pending_cnt) || mdev->state.susp); 1028 wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_pending_cnt) || is_susp(mdev->state));
1020 /* and for any other previously queued work */ 1029 /* and for any other previously queued work */
1021 drbd_flush_workqueue(mdev); 1030 drbd_flush_workqueue(mdev);
1022 1031
@@ -1114,8 +1123,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
1114 clear_bit(CRASHED_PRIMARY, &mdev->flags); 1123 clear_bit(CRASHED_PRIMARY, &mdev->flags);
1115 1124
1116 if (drbd_md_test_flag(mdev->ldev, MDF_PRIMARY_IND) && 1125 if (drbd_md_test_flag(mdev->ldev, MDF_PRIMARY_IND) &&
1117 !(mdev->state.role == R_PRIMARY && mdev->state.susp && 1126 !(mdev->state.role == R_PRIMARY && mdev->state.susp_nod)) {
1118 mdev->sync_conf.on_no_data == OND_SUSPEND_IO)) {
1119 set_bit(CRASHED_PRIMARY, &mdev->flags); 1127 set_bit(CRASHED_PRIMARY, &mdev->flags);
1120 cp_discovered = 1; 1128 cp_discovered = 1;
1121 } 1129 }
@@ -1939,7 +1947,7 @@ static int drbd_nl_resume_io(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
1939 drbd_md_sync(mdev); 1947 drbd_md_sync(mdev);
1940 } 1948 }
1941 drbd_suspend_io(mdev); 1949 drbd_suspend_io(mdev);
1942 reply->ret_code = drbd_request_state(mdev, NS(susp, 0)); 1950 reply->ret_code = drbd_request_state(mdev, NS3(susp, 0, susp_nod, 0, susp_fen, 0));
1943 if (reply->ret_code == SS_SUCCESS) { 1951 if (reply->ret_code == SS_SUCCESS) {
1944 if (mdev->state.conn < C_CONNECTED) 1952 if (mdev->state.conn < C_CONNECTED)
1945 tl_clear(mdev); 1953 tl_clear(mdev);
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c
index a4a4a06908c5..aec8426c1bf6 100644
--- a/drivers/block/drbd/drbd_proc.c
+++ b/drivers/block/drbd/drbd_proc.c
@@ -213,7 +213,7 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
213 drbd_disk_str(mdev->state.pdsk), 213 drbd_disk_str(mdev->state.pdsk),
214 (mdev->net_conf == NULL ? ' ' : 214 (mdev->net_conf == NULL ? ' ' :
215 (mdev->net_conf->wire_protocol - DRBD_PROT_A+'A')), 215 (mdev->net_conf->wire_protocol - DRBD_PROT_A+'A')),
216 mdev->state.susp ? 's' : 'r', 216 is_susp(mdev->state) ? 's' : 'r',
217 mdev->state.aftr_isp ? 'a' : '-', 217 mdev->state.aftr_isp ? 'a' : '-',
218 mdev->state.peer_isp ? 'p' : '-', 218 mdev->state.peer_isp ? 'p' : '-',
219 mdev->state.user_isp ? 'u' : '-', 219 mdev->state.user_isp ? 'u' : '-',
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 983e49cbd233..6b69b2f734dc 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -3315,7 +3315,7 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
3315 if ((nconn == C_CONNECTED || nconn == C_WF_BITMAP_S) && ns.disk == D_NEGOTIATING) 3315 if ((nconn == C_CONNECTED || nconn == C_WF_BITMAP_S) && ns.disk == D_NEGOTIATING)
3316 ns.disk = mdev->new_state_tmp.disk; 3316 ns.disk = mdev->new_state_tmp.disk;
3317 cs_flags = CS_VERBOSE + (oconn < C_CONNECTED && nconn >= C_CONNECTED ? 0 : CS_HARD); 3317 cs_flags = CS_VERBOSE + (oconn < C_CONNECTED && nconn >= C_CONNECTED ? 0 : CS_HARD);
3318 if (ns.pdsk == D_CONSISTENT && ns.susp && nconn == C_CONNECTED && oconn < C_CONNECTED && 3318 if (ns.pdsk == D_CONSISTENT && is_susp(ns) && nconn == C_CONNECTED && oconn < C_CONNECTED &&
3319 test_bit(NEW_CUR_UUID, &mdev->flags)) { 3319 test_bit(NEW_CUR_UUID, &mdev->flags)) {
3320 /* Do not allow tl_restart(resend) for a rebooted peer. We can only allow this 3320 /* Do not allow tl_restart(resend) for a rebooted peer. We can only allow this
3321 for temporal network outages! */ 3321 for temporal network outages! */
@@ -3829,7 +3829,7 @@ static void drbd_disconnect(struct drbd_conf *mdev)
3829 kfree(mdev->p_uuid); 3829 kfree(mdev->p_uuid);
3830 mdev->p_uuid = NULL; 3830 mdev->p_uuid = NULL;
3831 3831
3832 if (!mdev->state.susp) 3832 if (!is_susp(mdev->state))
3833 tl_clear(mdev); 3833 tl_clear(mdev);
3834 3834
3835 dev_info(DEV, "Connection closed\n"); 3835 dev_info(DEV, "Connection closed\n");
@@ -3858,7 +3858,7 @@ static void drbd_disconnect(struct drbd_conf *mdev)
3858 if (os.conn == C_DISCONNECTING) { 3858 if (os.conn == C_DISCONNECTING) {
3859 wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0); 3859 wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0);
3860 3860
3861 if (!mdev->state.susp) { 3861 if (!is_susp(mdev->state)) {
3862 /* we must not free the tl_hash 3862 /* we must not free the tl_hash
3863 * while application io is still on the fly */ 3863 * while application io is still on the fly */
3864 wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt)); 3864 wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index af608b39c4e0..9e91a2545fc8 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -287,7 +287,7 @@ static void _req_may_be_done_not_susp(struct drbd_request *req, struct bio_and_e
287{ 287{
288 struct drbd_conf *mdev = req->mdev; 288 struct drbd_conf *mdev = req->mdev;
289 289
290 if (!mdev->state.susp) 290 if (!is_susp(mdev->state))
291 _req_may_be_done(req, m); 291 _req_may_be_done(req, m);
292} 292}
293 293
@@ -812,7 +812,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio)
812 (mdev->state.pdsk == D_INCONSISTENT && 812 (mdev->state.pdsk == D_INCONSISTENT &&
813 mdev->state.conn >= C_CONNECTED)); 813 mdev->state.conn >= C_CONNECTED));
814 814
815 if (!(local || remote) && !mdev->state.susp) { 815 if (!(local || remote) && !is_susp(mdev->state)) {
816 dev_err(DEV, "IO ERROR: neither local nor remote disk\n"); 816 dev_err(DEV, "IO ERROR: neither local nor remote disk\n");
817 goto fail_free_complete; 817 goto fail_free_complete;
818 } 818 }
@@ -838,7 +838,7 @@ allocate_barrier:
838 /* GOOD, everything prepared, grab the spin_lock */ 838 /* GOOD, everything prepared, grab the spin_lock */
839 spin_lock_irq(&mdev->req_lock); 839 spin_lock_irq(&mdev->req_lock);
840 840
841 if (mdev->state.susp) { 841 if (is_susp(mdev->state)) {
842 /* If we got suspended, use the retry mechanism of 842 /* If we got suspended, use the retry mechanism of
843 generic_make_request() to restart processing of this 843 generic_make_request() to restart processing of this
844 bio. In the next call to drbd_make_request_26 844 bio. In the next call to drbd_make_request_26