aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-01-11 11:42:17 -0500
committerPhilipp Reisner <philipp.reisner@linbit.com>2011-03-10 05:45:32 -0500
commit4a23f2649698272abcd9e0c9a992d65739f32792 (patch)
tree3921ce5019d9d72befc48dbf14850c189bce5543 /drivers/block
parent2b8a90b55533c66258a1ff0fb27b8cffa95665c4 (diff)
drbd: Do not full sync if a P_SYNC_UUID packet gets lost
See also commit from 2009-08-15 "drbd_uuid_compare(): Do not full sync in case a P_SYNC_UUID packet gets lost." We saw cases where the History UUIDs where not as expected. So the detection of the special case did not trigger. With the sync UUID no longer being a random number, but deducible from the previous bitmap UUID, the detection of this special case becomes more reliable. The SyncUUID now is the previous bitmap UUID + 0x1000000000000. Rule 5a: Cs = H1p & H1p + Offset = Bp Connection was lost before SyncUUID Packet came through. Corrent (peer) UUIDs: Bp = H1p H1p = H2p H2p = 0 Become Sync target. Rule 7a: Cp = H1s & H1s + Offset = Bs Connection was lost before SyncUUID Packet came through. Correct (own) UUIDs: Bs = H1s H1s = H2s H2s = 0 Become Sync source. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/drbd/drbd_int.h1
-rw-r--r--drivers/block/drbd/drbd_main.c2
-rw-r--r--drivers/block/drbd/drbd_receiver.c35
3 files changed, 23 insertions, 15 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 84b4575fdf43..3c8eecd9666d 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -97,6 +97,7 @@ extern char usermode_helper[];
97#define ID_SYNCER (-1ULL) 97#define ID_SYNCER (-1ULL)
98#define ID_VACANT 0 98#define ID_VACANT 0
99#define is_syncer_block_id(id) ((id) == ID_SYNCER) 99#define is_syncer_block_id(id) ((id) == ID_SYNCER)
100#define UUID_NEW_BM_OFFSET ((u64)0x0001000000000000ULL)
100 101
101struct drbd_conf; 102struct drbd_conf;
102 103
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index da98bff7c333..b3b6d3190f65 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2022,7 +2022,7 @@ int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev)
2022 2022
2023 D_ASSERT(mdev->state.disk == D_UP_TO_DATE); 2023 D_ASSERT(mdev->state.disk == D_UP_TO_DATE);
2024 2024
2025 get_random_bytes(&uuid, sizeof(u64)); 2025 uuid = mdev->ldev->md.uuid[UI_BITMAP] + UUID_NEW_BM_OFFSET;
2026 drbd_uuid_set(mdev, UI_BITMAP, uuid); 2026 drbd_uuid_set(mdev, UI_BITMAP, uuid);
2027 drbd_md_sync(mdev); 2027 drbd_md_sync(mdev);
2028 p.uuid = cpu_to_be64(uuid); 2028 p.uuid = cpu_to_be64(uuid);
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index fd0957f9c230..7991183749e3 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -2293,6 +2293,8 @@ static void drbd_uuid_dump(struct drbd_conf *mdev, char *text, u64 *uuid,
2293 -2 C_SYNC_TARGET set BitMap 2293 -2 C_SYNC_TARGET set BitMap
2294 -100 after split brain, disconnect 2294 -100 after split brain, disconnect
2295-1000 unrelated data 2295-1000 unrelated data
2296-1091 requires proto 91
2297-1096 requires proto 96
2296 */ 2298 */
2297static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(local) 2299static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(local)
2298{ 2300{
@@ -2322,7 +2324,7 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
2322 if (mdev->p_uuid[UI_BITMAP] == (u64)0 && mdev->ldev->md.uuid[UI_BITMAP] != (u64)0) { 2324 if (mdev->p_uuid[UI_BITMAP] == (u64)0 && mdev->ldev->md.uuid[UI_BITMAP] != (u64)0) {
2323 2325
2324 if (mdev->agreed_pro_version < 91) 2326 if (mdev->agreed_pro_version < 91)
2325 return -1001; 2327 return -1091;
2326 2328
2327 if ((mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) && 2329 if ((mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) &&
2328 (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1))) { 2330 (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1))) {
@@ -2343,7 +2345,7 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
2343 if (mdev->ldev->md.uuid[UI_BITMAP] == (u64)0 && mdev->p_uuid[UI_BITMAP] != (u64)0) { 2345 if (mdev->ldev->md.uuid[UI_BITMAP] == (u64)0 && mdev->p_uuid[UI_BITMAP] != (u64)0) {
2344 2346
2345 if (mdev->agreed_pro_version < 91) 2347 if (mdev->agreed_pro_version < 91)
2346 return -1001; 2348 return -1091;
2347 2349
2348 if ((mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_BITMAP] & ~((u64)1)) && 2350 if ((mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_BITMAP] & ~((u64)1)) &&
2349 (mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1))) { 2351 (mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1))) {
@@ -2388,17 +2390,22 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
2388 *rule_nr = 51; 2390 *rule_nr = 51;
2389 peer = mdev->p_uuid[UI_HISTORY_START] & ~((u64)1); 2391 peer = mdev->p_uuid[UI_HISTORY_START] & ~((u64)1);
2390 if (self == peer) { 2392 if (self == peer) {
2391 self = mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1); 2393 if (mdev->agreed_pro_version < 96 ?
2392 peer = mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1); 2394 (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) ==
2393 if (self == peer) { 2395 (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1)) :
2396 peer + UUID_NEW_BM_OFFSET == (mdev->p_uuid[UI_BITMAP] & ~((u64)1))) {
2394 /* The last P_SYNC_UUID did not get though. Undo the last start of 2397 /* The last P_SYNC_UUID did not get though. Undo the last start of
2395 resync as sync source modifications of the peer's UUIDs. */ 2398 resync as sync source modifications of the peer's UUIDs. */
2396 2399
2397 if (mdev->agreed_pro_version < 91) 2400 if (mdev->agreed_pro_version < 91)
2398 return -1001; 2401 return -1091;
2399 2402
2400 mdev->p_uuid[UI_BITMAP] = mdev->p_uuid[UI_HISTORY_START]; 2403 mdev->p_uuid[UI_BITMAP] = mdev->p_uuid[UI_HISTORY_START];
2401 mdev->p_uuid[UI_HISTORY_START] = mdev->p_uuid[UI_HISTORY_START + 1]; 2404 mdev->p_uuid[UI_HISTORY_START] = mdev->p_uuid[UI_HISTORY_START + 1];
2405
2406 dev_info(DEV, "Did not got last syncUUID packet, corrected:\n");
2407 drbd_uuid_dump(mdev, "peer", mdev->p_uuid, mdev->p_uuid[UI_SIZE], mdev->p_uuid[UI_FLAGS]);
2408
2402 return -1; 2409 return -1;
2403 } 2410 }
2404 } 2411 }
@@ -2420,20 +2427,20 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
2420 *rule_nr = 71; 2427 *rule_nr = 71;
2421 self = mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1); 2428 self = mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1);
2422 if (self == peer) { 2429 if (self == peer) {
2423 self = mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1); 2430 if (mdev->agreed_pro_version < 96 ?
2424 peer = mdev->p_uuid[UI_HISTORY_START] & ~((u64)1); 2431 (mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) ==
2425 if (self == peer) { 2432 (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) :
2433 self + UUID_NEW_BM_OFFSET == (mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1))) {
2426 /* The last P_SYNC_UUID did not get though. Undo the last start of 2434 /* The last P_SYNC_UUID did not get though. Undo the last start of
2427 resync as sync source modifications of our UUIDs. */ 2435 resync as sync source modifications of our UUIDs. */
2428 2436
2429 if (mdev->agreed_pro_version < 91) 2437 if (mdev->agreed_pro_version < 91)
2430 return -1001; 2438 return -1091;
2431 2439
2432 _drbd_uuid_set(mdev, UI_BITMAP, mdev->ldev->md.uuid[UI_HISTORY_START]); 2440 _drbd_uuid_set(mdev, UI_BITMAP, mdev->ldev->md.uuid[UI_HISTORY_START]);
2433 _drbd_uuid_set(mdev, UI_HISTORY_START, mdev->ldev->md.uuid[UI_HISTORY_START + 1]); 2441 _drbd_uuid_set(mdev, UI_HISTORY_START, mdev->ldev->md.uuid[UI_HISTORY_START + 1]);
2434 2442
2435 dev_info(DEV, "Undid last start of resync:\n"); 2443 dev_info(DEV, "Last syncUUID did not get through, corrected:\n");
2436
2437 drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid, 2444 drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid,
2438 mdev->state.disk >= D_NEGOTIATING ? drbd_bm_total_weight(mdev) : 0, 0); 2445 mdev->state.disk >= D_NEGOTIATING ? drbd_bm_total_weight(mdev) : 0, 0);
2439 2446
@@ -2496,8 +2503,8 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
2496 dev_alert(DEV, "Unrelated data, aborting!\n"); 2503 dev_alert(DEV, "Unrelated data, aborting!\n");
2497 return C_MASK; 2504 return C_MASK;
2498 } 2505 }
2499 if (hg == -1001) { 2506 if (hg < -1000) {
2500 dev_alert(DEV, "To resolve this both sides have to support at least protocol 91\n"); 2507 dev_alert(DEV, "To resolve this both sides have to support at least protocol %d\n", -hg - 1000);
2501 return C_MASK; 2508 return C_MASK;
2502 } 2509 }
2503 2510