diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2010-10-27 06:21:30 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2011-03-10 05:34:46 -0500 |
commit | 67531718d8f1259f01ab84c2aa25f7b03c7afd46 (patch) | |
tree | 6f76323440f8ce3793b5d5f1a19808207f38db5b | |
parent | 422028b1ca4c07995af82a18abced022ff4c296c (diff) |
drbd: Implemented two new connection states Ahead/Behind
In this connection mode, the ahead node no longer replicates
application IO. The behind's disk becomes out dated.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 2 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 12 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 3 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 23 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_strings.c | 4 | ||||
-rw-r--r-- | include/linux/drbd.h | 4 |
6 files changed, 45 insertions, 3 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index c804e44b9455..21b7439438cd 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -2217,6 +2217,8 @@ static inline int drbd_state_is_stable(union drbd_state s) | |||
2217 | case C_VERIFY_T: | 2217 | case C_VERIFY_T: |
2218 | case C_PAUSED_SYNC_S: | 2218 | case C_PAUSED_SYNC_S: |
2219 | case C_PAUSED_SYNC_T: | 2219 | case C_PAUSED_SYNC_T: |
2220 | case C_AHEAD: | ||
2221 | case C_BEHIND: | ||
2220 | /* maybe stable, look at the disk state */ | 2222 | /* maybe stable, look at the disk state */ |
2221 | break; | 2223 | break; |
2222 | 2224 | ||
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index e81d009dd061..46f27d6c0b21 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -871,16 +871,19 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state | |||
871 | 871 | ||
872 | if (ns.conn >= C_CONNECTED && | 872 | if (ns.conn >= C_CONNECTED && |
873 | ((ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED) || | 873 | ((ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED) || |
874 | (ns.disk == D_NEGOTIATING && ns.conn == C_WF_BITMAP_T))) { | 874 | (ns.disk == D_NEGOTIATING && ns.conn == C_WF_BITMAP_T) || |
875 | ns.conn >= C_AHEAD)) { | ||
875 | switch (ns.conn) { | 876 | switch (ns.conn) { |
876 | case C_WF_BITMAP_T: | 877 | case C_WF_BITMAP_T: |
877 | case C_PAUSED_SYNC_T: | 878 | case C_PAUSED_SYNC_T: |
879 | case C_BEHIND: | ||
878 | ns.disk = D_OUTDATED; | 880 | ns.disk = D_OUTDATED; |
879 | break; | 881 | break; |
880 | case C_CONNECTED: | 882 | case C_CONNECTED: |
881 | case C_WF_BITMAP_S: | 883 | case C_WF_BITMAP_S: |
882 | case C_SYNC_SOURCE: | 884 | case C_SYNC_SOURCE: |
883 | case C_PAUSED_SYNC_S: | 885 | case C_PAUSED_SYNC_S: |
886 | case C_AHEAD: | ||
884 | ns.disk = D_UP_TO_DATE; | 887 | ns.disk = D_UP_TO_DATE; |
885 | break; | 888 | break; |
886 | case C_SYNC_TARGET: | 889 | case C_SYNC_TARGET: |
@@ -893,16 +896,18 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state | |||
893 | } | 896 | } |
894 | 897 | ||
895 | if (ns.conn >= C_CONNECTED && | 898 | if (ns.conn >= C_CONNECTED && |
896 | (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED)) { | 899 | (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED || ns.conn >= C_AHEAD)) { |
897 | switch (ns.conn) { | 900 | switch (ns.conn) { |
898 | case C_CONNECTED: | 901 | case C_CONNECTED: |
899 | case C_WF_BITMAP_T: | 902 | case C_WF_BITMAP_T: |
900 | case C_PAUSED_SYNC_T: | 903 | case C_PAUSED_SYNC_T: |
901 | case C_SYNC_TARGET: | 904 | case C_SYNC_TARGET: |
905 | case C_BEHIND: | ||
902 | ns.pdsk = D_UP_TO_DATE; | 906 | ns.pdsk = D_UP_TO_DATE; |
903 | break; | 907 | break; |
904 | case C_WF_BITMAP_S: | 908 | case C_WF_BITMAP_S: |
905 | case C_PAUSED_SYNC_S: | 909 | case C_PAUSED_SYNC_S: |
910 | case C_AHEAD: | ||
906 | /* remap any consistent state to D_OUTDATED, | 911 | /* remap any consistent state to D_OUTDATED, |
907 | * but disallow "upgrade" of not even consistent states. | 912 | * but disallow "upgrade" of not even consistent states. |
908 | */ | 913 | */ |
@@ -1374,6 +1379,9 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, | |||
1374 | if (os.conn == C_WF_REPORT_PARAMS && ns.conn >= C_CONNECTED) | 1379 | if (os.conn == C_WF_REPORT_PARAMS && ns.conn >= C_CONNECTED) |
1375 | drbd_send_state(mdev); | 1380 | drbd_send_state(mdev); |
1376 | 1381 | ||
1382 | if (os.conn != C_AHEAD && ns.conn == C_AHEAD) | ||
1383 | drbd_send_state(mdev); | ||
1384 | |||
1377 | /* We are in the progress to start a full sync... */ | 1385 | /* We are in the progress to start a full sync... */ |
1378 | if ((os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) || | 1386 | if ((os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) || |
1379 | (os.conn != C_STARTING_SYNC_S && ns.conn == C_STARTING_SYNC_S)) | 1387 | (os.conn != C_STARTING_SYNC_S && ns.conn == C_STARTING_SYNC_S)) |
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index f3052d871d31..b19e8b2c4ce5 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c | |||
@@ -3179,6 +3179,9 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned | |||
3179 | if (ns.conn == C_WF_REPORT_PARAMS) | 3179 | if (ns.conn == C_WF_REPORT_PARAMS) |
3180 | ns.conn = C_CONNECTED; | 3180 | ns.conn = C_CONNECTED; |
3181 | 3181 | ||
3182 | if (peer_state.conn == C_AHEAD) | ||
3183 | ns.conn = C_BEHIND; | ||
3184 | |||
3182 | if (mdev->p_uuid && peer_state.disk >= D_NEGOTIATING && | 3185 | if (mdev->p_uuid && peer_state.disk >= D_NEGOTIATING && |
3183 | get_ldev_if_state(mdev, D_NEGOTIATING)) { | 3186 | get_ldev_if_state(mdev, D_NEGOTIATING)) { |
3184 | int cr; /* consider resync */ | 3187 | int cr; /* consider resync */ |
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 5c60d77d447c..60288fb3c4d7 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
@@ -948,6 +948,29 @@ allocate_barrier: | |||
948 | ? queue_for_net_write | 948 | ? queue_for_net_write |
949 | : queue_for_net_read); | 949 | : queue_for_net_read); |
950 | } | 950 | } |
951 | |||
952 | if (remote && mdev->net_conf->on_congestion != OC_BLOCK) { | ||
953 | int congested = 0; | ||
954 | |||
955 | if (mdev->net_conf->cong_fill && | ||
956 | atomic_read(&mdev->ap_in_flight) >= mdev->net_conf->cong_fill) { | ||
957 | dev_info(DEV, "Congestion-fill threshold reached\n"); | ||
958 | congested = 1; | ||
959 | } | ||
960 | |||
961 | if (mdev->act_log->used >= mdev->net_conf->cong_extents) { | ||
962 | dev_info(DEV, "Congestion-extents threshold reached\n"); | ||
963 | congested = 1; | ||
964 | } | ||
965 | |||
966 | if (congested) { | ||
967 | if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) | ||
968 | _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL); | ||
969 | else /*mdev->net_conf->on_congestion == OC_DISCONNECT */ | ||
970 | _drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL); | ||
971 | } | ||
972 | } | ||
973 | |||
951 | spin_unlock_irq(&mdev->req_lock); | 974 | spin_unlock_irq(&mdev->req_lock); |
952 | kfree(b); /* if someone else has beaten us to it... */ | 975 | kfree(b); /* if someone else has beaten us to it... */ |
953 | 976 | ||
diff --git a/drivers/block/drbd/drbd_strings.c b/drivers/block/drbd/drbd_strings.c index 85179e1fb50a..5b970adc3b6f 100644 --- a/drivers/block/drbd/drbd_strings.c +++ b/drivers/block/drbd/drbd_strings.c | |||
@@ -48,6 +48,8 @@ static const char *drbd_conn_s_names[] = { | |||
48 | [C_PAUSED_SYNC_T] = "PausedSyncT", | 48 | [C_PAUSED_SYNC_T] = "PausedSyncT", |
49 | [C_VERIFY_S] = "VerifyS", | 49 | [C_VERIFY_S] = "VerifyS", |
50 | [C_VERIFY_T] = "VerifyT", | 50 | [C_VERIFY_T] = "VerifyT", |
51 | [C_AHEAD] = "Ahead", | ||
52 | [C_BEHIND] = "Behind", | ||
51 | }; | 53 | }; |
52 | 54 | ||
53 | static const char *drbd_role_s_names[] = { | 55 | static const char *drbd_role_s_names[] = { |
@@ -92,7 +94,7 @@ static const char *drbd_state_sw_errors[] = { | |||
92 | const char *drbd_conn_str(enum drbd_conns s) | 94 | const char *drbd_conn_str(enum drbd_conns s) |
93 | { | 95 | { |
94 | /* enums are unsigned... */ | 96 | /* enums are unsigned... */ |
95 | return s > C_PAUSED_SYNC_T ? "TOO_LARGE" : drbd_conn_s_names[s]; | 97 | return s > C_BEHIND ? "TOO_LARGE" : drbd_conn_s_names[s]; |
96 | } | 98 | } |
97 | 99 | ||
98 | const char *drbd_role_str(enum drbd_role s) | 100 | const char *drbd_role_str(enum drbd_role s) |
diff --git a/include/linux/drbd.h b/include/linux/drbd.h index 03a08baabf11..23f31be6f00d 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h | |||
@@ -206,6 +206,10 @@ enum drbd_conns { | |||
206 | C_VERIFY_T, | 206 | C_VERIFY_T, |
207 | C_PAUSED_SYNC_S, | 207 | C_PAUSED_SYNC_S, |
208 | C_PAUSED_SYNC_T, | 208 | C_PAUSED_SYNC_T, |
209 | |||
210 | C_AHEAD, | ||
211 | C_BEHIND, | ||
212 | |||
209 | C_MASK = 31 | 213 | C_MASK = 31 |
210 | }; | 214 | }; |
211 | 215 | ||