diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2012-05-07 06:00:56 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 10:58:27 -0500 |
commit | 5016b82a49eb06cbe2002db7bd8a5501ba4ef6d1 (patch) | |
tree | 63b88abacaf6048a64531daced95ef47b6888e03 /drivers/block/drbd | |
parent | 07be15b12c41dbc5ceae130be2e0b655f7611691 (diff) |
drbd: fix race between drbdadm invalidate/verify and finishing resync
When a resync or online verify is finished or aborted,
drbd does a bulk write-out of changed bitmap pages.
If *in that very moment* a new verify or resync is triggered,
this can race:
ASSERT( !test_bit(BITMAP_IO, &mdev->flags) ) in drbd_main.c
FIXME going to queue 'set_n_write from StartingSync' but 'write from resync_finished' still pending?
and similar.
This can be observed with e.g. tight invalidate loops in test scripts,
and probably has no real-life implication.
Still, that race can be solved by first quiescen the device,
before starting a new resync or verify.
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_nl.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 3a8fa89f673a..cbd45de533cb 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -2372,6 +2372,7 @@ int drbd_adm_invalidate(struct sk_buff *skb, struct genl_info *info) | |||
2372 | 2372 | ||
2373 | /* If there is still bitmap IO pending, probably because of a previous | 2373 | /* If there is still bitmap IO pending, probably because of a previous |
2374 | * resync just being finished, wait for it before requesting a new resync. */ | 2374 | * resync just being finished, wait for it before requesting a new resync. */ |
2375 | drbd_suspend_io(mdev); | ||
2375 | wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags)); | 2376 | wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags)); |
2376 | 2377 | ||
2377 | retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_T), CS_ORDERED); | 2378 | retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_T), CS_ORDERED); |
@@ -2390,6 +2391,7 @@ int drbd_adm_invalidate(struct sk_buff *skb, struct genl_info *info) | |||
2390 | 2391 | ||
2391 | retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_T)); | 2392 | retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_T)); |
2392 | } | 2393 | } |
2394 | drbd_resume_io(mdev); | ||
2393 | 2395 | ||
2394 | out: | 2396 | out: |
2395 | drbd_adm_finish(info, retcode); | 2397 | drbd_adm_finish(info, retcode); |
@@ -2435,6 +2437,11 @@ int drbd_adm_invalidate_peer(struct sk_buff *skb, struct genl_info *info) | |||
2435 | 2437 | ||
2436 | mdev = adm_ctx.mdev; | 2438 | mdev = adm_ctx.mdev; |
2437 | 2439 | ||
2440 | /* If there is still bitmap IO pending, probably because of a previous | ||
2441 | * resync just being finished, wait for it before requesting a new resync. */ | ||
2442 | drbd_suspend_io(mdev); | ||
2443 | wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags)); | ||
2444 | |||
2438 | retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S), CS_ORDERED); | 2445 | retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S), CS_ORDERED); |
2439 | if (retcode < SS_SUCCESS) { | 2446 | if (retcode < SS_SUCCESS) { |
2440 | if (retcode == SS_NEED_CONNECTION && mdev->state.role == R_PRIMARY) { | 2447 | if (retcode == SS_NEED_CONNECTION && mdev->state.role == R_PRIMARY) { |
@@ -2450,6 +2457,7 @@ int drbd_adm_invalidate_peer(struct sk_buff *skb, struct genl_info *info) | |||
2450 | } else | 2457 | } else |
2451 | retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S)); | 2458 | retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S)); |
2452 | } | 2459 | } |
2460 | drbd_resume_io(mdev); | ||
2453 | 2461 | ||
2454 | out: | 2462 | out: |
2455 | drbd_adm_finish(info, retcode); | 2463 | drbd_adm_finish(info, retcode); |
@@ -2903,8 +2911,10 @@ int drbd_adm_start_ov(struct sk_buff *skb, struct genl_info *info) | |||
2903 | } | 2911 | } |
2904 | /* If there is still bitmap IO pending, e.g. previous resync or verify | 2912 | /* If there is still bitmap IO pending, e.g. previous resync or verify |
2905 | * just being finished, wait for it before requesting a new resync. */ | 2913 | * just being finished, wait for it before requesting a new resync. */ |
2914 | drbd_suspend_io(mdev); | ||
2906 | wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags)); | 2915 | wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags)); |
2907 | retcode = drbd_request_state(mdev,NS(conn,C_VERIFY_S)); | 2916 | retcode = drbd_request_state(mdev,NS(conn,C_VERIFY_S)); |
2917 | drbd_resume_io(mdev); | ||
2908 | out: | 2918 | out: |
2909 | drbd_adm_finish(info, retcode); | 2919 | drbd_adm_finish(info, retcode); |
2910 | return 0; | 2920 | return 0; |