diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2010-11-10 06:08:37 -0500 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2011-03-10 05:35:06 -0500 |
commit | 3719094ec2dec411b3151f10048316d787e086f9 (patch) | |
tree | 4be7bd2bb31612e8210665b9e20985de7deb30e4 /drivers/block | |
parent | ab17b68f4579b460753a416b0afc4446381d876f (diff) |
drbd: Starting with protocol 96 we can allow app-IO while receiving the bitmap
* C_STARTING_SYNC_S, C_STARTING_SYNC_T In these states the bitmap gets
written to disk. Locking out of app-IO is done by using the
drbd_queue_bitmap_io() and drbd_bitmap_io() functions these days.
It is no longer necessary to lock out app-IO based on the connection
state.
App-IO that may come in after the BITMAP_IO flag got cleared before the
state transition to C_SYNC_(SOURCE|TARGET) does not get mirrored, sets
a bit in the local bitmap, that is already set, therefore changes nothing.
* C_WF_BITMAP_S In this state we send updates (P_OUT_OF_SYNC packets).
With that we make sure they have the same number of bits when going
into the C_SYNC_(SOURCE|TARGET) connection state.
* C_UNCONNECTED: The receiver starts, no need to lock out IO.
* C_DISCONNECTING: in drbd_disconnect() we had a wait_event()
to wait until ap_bio_cnt reaches 0. Removed that.
* C_TIMEOUT, C_BROKEN_PIPE, C_NETWORK_FAILURE
C_PROTOCOL_ERROR, C_TEAR_DOWN: Same as C_DISCONNECTING
* C_WF_REPORT_PARAMS: IO still possible since that is still
like C_WF_CONNECTION.
And we do not need to send barriers in C_WF_BITMAP_S connection state.
Allow concurrent accesses to the bitmap when receiving the bitmap.
Everything gets ORed anyways.
A drbd_free_tl_hash() is in after_state_chg_work(). At that point
all the work items of the last connections must have been processed.
Introduced a call to drbd_free_tl_hash() into drbd_free_mdev()
for paranoia reasons.
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.h | 19 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 1 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 13 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 37 |
4 files changed, 39 insertions, 31 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 9a944604939f..38bbaba8bd89 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -2213,8 +2213,9 @@ static inline int drbd_get_max_buffers(struct drbd_conf *mdev) | |||
2213 | return mxb; | 2213 | return mxb; |
2214 | } | 2214 | } |
2215 | 2215 | ||
2216 | static inline int drbd_state_is_stable(union drbd_state s) | 2216 | static inline int drbd_state_is_stable(struct drbd_conf *mdev) |
2217 | { | 2217 | { |
2218 | union drbd_state s = mdev->state; | ||
2218 | 2219 | ||
2219 | /* DO NOT add a default clause, we want the compiler to warn us | 2220 | /* DO NOT add a default clause, we want the compiler to warn us |
2220 | * for any newly introduced state we may have forgotten to add here */ | 2221 | * for any newly introduced state we may have forgotten to add here */ |
@@ -2233,11 +2234,7 @@ static inline int drbd_state_is_stable(union drbd_state s) | |||
2233 | case C_PAUSED_SYNC_T: | 2234 | case C_PAUSED_SYNC_T: |
2234 | case C_AHEAD: | 2235 | case C_AHEAD: |
2235 | case C_BEHIND: | 2236 | case C_BEHIND: |
2236 | /* maybe stable, look at the disk state */ | 2237 | /* transitional states, IO allowed */ |
2237 | break; | ||
2238 | |||
2239 | /* no new io accepted during tansitional states | ||
2240 | * like handshake or teardown */ | ||
2241 | case C_DISCONNECTING: | 2238 | case C_DISCONNECTING: |
2242 | case C_UNCONNECTED: | 2239 | case C_UNCONNECTED: |
2243 | case C_TIMEOUT: | 2240 | case C_TIMEOUT: |
@@ -2248,7 +2245,15 @@ static inline int drbd_state_is_stable(union drbd_state s) | |||
2248 | case C_WF_REPORT_PARAMS: | 2245 | case C_WF_REPORT_PARAMS: |
2249 | case C_STARTING_SYNC_S: | 2246 | case C_STARTING_SYNC_S: |
2250 | case C_STARTING_SYNC_T: | 2247 | case C_STARTING_SYNC_T: |
2248 | break; | ||
2249 | |||
2250 | /* Allow IO in BM exchange states with new protocols */ | ||
2251 | case C_WF_BITMAP_S: | 2251 | case C_WF_BITMAP_S: |
2252 | if (mdev->agreed_pro_version < 96) | ||
2253 | return 0; | ||
2254 | break; | ||
2255 | |||
2256 | /* no new io accepted in these states */ | ||
2252 | case C_WF_BITMAP_T: | 2257 | case C_WF_BITMAP_T: |
2253 | case C_WF_SYNC_UUID: | 2258 | case C_WF_SYNC_UUID: |
2254 | case C_MASK: | 2259 | case C_MASK: |
@@ -2297,7 +2302,7 @@ static inline int __inc_ap_bio_cond(struct drbd_conf *mdev) | |||
2297 | * to start during "stable" states. */ | 2302 | * to start during "stable" states. */ |
2298 | 2303 | ||
2299 | /* no new io accepted when attaching or detaching the disk */ | 2304 | /* no new io accepted when attaching or detaching the disk */ |
2300 | if (!drbd_state_is_stable(mdev->state)) | 2305 | if (!drbd_state_is_stable(mdev)) |
2301 | return 0; | 2306 | return 0; |
2302 | 2307 | ||
2303 | /* since some older kernels don't have atomic_add_unless, | 2308 | /* since some older kernels don't have atomic_add_unless, |
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 74a6d55259af..14afbd4e53a5 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -3334,6 +3334,7 @@ void drbd_free_mdev(struct drbd_conf *mdev) | |||
3334 | put_disk(mdev->vdisk); | 3334 | put_disk(mdev->vdisk); |
3335 | blk_cleanup_queue(mdev->rq_queue); | 3335 | blk_cleanup_queue(mdev->rq_queue); |
3336 | free_cpumask_var(mdev->cpu_mask); | 3336 | free_cpumask_var(mdev->cpu_mask); |
3337 | drbd_free_tl_hash(mdev); | ||
3337 | kfree(mdev); | 3338 | kfree(mdev); |
3338 | } | 3339 | } |
3339 | 3340 | ||
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 0630a2e122d3..f4aba9f894ba 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c | |||
@@ -3468,9 +3468,7 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne | |||
3468 | int ok = FALSE; | 3468 | int ok = FALSE; |
3469 | struct p_header80 *h = &mdev->data.rbuf.header.h80; | 3469 | struct p_header80 *h = &mdev->data.rbuf.header.h80; |
3470 | 3470 | ||
3471 | wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt)); | 3471 | /* drbd_bm_lock(mdev, "receive bitmap"); By intention no bm_lock */ |
3472 | |||
3473 | drbd_bm_lock(mdev, "receive bitmap"); | ||
3474 | 3472 | ||
3475 | /* maybe we should use some per thread scratch page, | 3473 | /* maybe we should use some per thread scratch page, |
3476 | * and allocate that during initial device creation? */ | 3474 | * and allocate that during initial device creation? */ |
@@ -3542,7 +3540,7 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne | |||
3542 | 3540 | ||
3543 | ok = TRUE; | 3541 | ok = TRUE; |
3544 | out: | 3542 | out: |
3545 | drbd_bm_unlock(mdev); | 3543 | /* drbd_bm_unlock(mdev); by intention no lock */ |
3546 | if (ok && mdev->state.conn == C_WF_BITMAP_S) | 3544 | if (ok && mdev->state.conn == C_WF_BITMAP_S) |
3547 | drbd_start_resync(mdev, C_SYNC_SOURCE); | 3545 | drbd_start_resync(mdev, C_SYNC_SOURCE); |
3548 | free_page((unsigned long) buffer); | 3546 | free_page((unsigned long) buffer); |
@@ -3804,13 +3802,6 @@ static void drbd_disconnect(struct drbd_conf *mdev) | |||
3804 | if (os.conn == C_DISCONNECTING) { | 3802 | if (os.conn == C_DISCONNECTING) { |
3805 | wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0); | 3803 | wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0); |
3806 | 3804 | ||
3807 | if (!is_susp(mdev->state)) { | ||
3808 | /* we must not free the tl_hash | ||
3809 | * while application io is still on the fly */ | ||
3810 | wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt)); | ||
3811 | drbd_free_tl_hash(mdev); | ||
3812 | } | ||
3813 | |||
3814 | crypto_free_hash(mdev->cram_hmac_tfm); | 3805 | crypto_free_hash(mdev->cram_hmac_tfm); |
3815 | mdev->cram_hmac_tfm = NULL; | 3806 | mdev->cram_hmac_tfm = NULL; |
3816 | 3807 | ||
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index eff0fbf69dd4..4cb8247d83c9 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
@@ -142,7 +142,7 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev, | |||
142 | 142 | ||
143 | /* before we can signal completion to the upper layers, | 143 | /* before we can signal completion to the upper layers, |
144 | * we may need to close the current epoch */ | 144 | * we may need to close the current epoch */ |
145 | if (mdev->state.conn >= C_CONNECTED && mdev->state.conn < C_AHEAD && | 145 | if (mdev->state.conn >= C_WF_BITMAP_T && mdev->state.conn < C_AHEAD && |
146 | req->epoch == mdev->newest_tle->br_number) | 146 | req->epoch == mdev->newest_tle->br_number) |
147 | queue_barrier(mdev); | 147 | queue_barrier(mdev); |
148 | 148 | ||
@@ -757,6 +757,23 @@ static int drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int s | |||
757 | return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr); | 757 | return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr); |
758 | } | 758 | } |
759 | 759 | ||
760 | static int drbd_should_do_remote(struct drbd_conf *mdev) | ||
761 | { | ||
762 | union drbd_state s = mdev->state; | ||
763 | |||
764 | return s.pdsk == D_UP_TO_DATE || | ||
765 | (s.pdsk >= D_INCONSISTENT && | ||
766 | s.conn >= C_WF_BITMAP_T && | ||
767 | s.conn < C_AHEAD); | ||
768 | } | ||
769 | static int drbd_should_send_oos(struct drbd_conf *mdev) | ||
770 | { | ||
771 | union drbd_state s = mdev->state; | ||
772 | |||
773 | return s.pdsk >= D_INCONSISTENT && | ||
774 | (s.conn == C_AHEAD || s.conn == C_WF_BITMAP_S); | ||
775 | } | ||
776 | |||
760 | static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time) | 777 | static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time) |
761 | { | 778 | { |
762 | const int rw = bio_rw(bio); | 779 | const int rw = bio_rw(bio); |
@@ -828,12 +845,9 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns | |||
828 | drbd_al_begin_io(mdev, sector); | 845 | drbd_al_begin_io(mdev, sector); |
829 | } | 846 | } |
830 | 847 | ||
831 | remote = remote && (mdev->state.pdsk == D_UP_TO_DATE || | 848 | remote = remote && drbd_should_do_remote(mdev); |
832 | (mdev->state.pdsk >= D_INCONSISTENT && | 849 | send_oos = rw == WRITE && drbd_should_send_oos(mdev); |
833 | mdev->state.conn >= C_CONNECTED && | 850 | D_ASSERT(!(remote && send_oos)); |
834 | mdev->state.conn < C_AHEAD)); | ||
835 | send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD && | ||
836 | mdev->state.pdsk >= D_INCONSISTENT); | ||
837 | 851 | ||
838 | if (!(local || remote) && !is_susp(mdev->state)) { | 852 | if (!(local || remote) && !is_susp(mdev->state)) { |
839 | if (__ratelimit(&drbd_ratelimit_state)) | 853 | if (__ratelimit(&drbd_ratelimit_state)) |
@@ -873,12 +887,9 @@ allocate_barrier: | |||
873 | } | 887 | } |
874 | 888 | ||
875 | if (remote || send_oos) { | 889 | if (remote || send_oos) { |
876 | remote = (mdev->state.pdsk == D_UP_TO_DATE || | 890 | remote = drbd_should_do_remote(mdev); |
877 | (mdev->state.pdsk >= D_INCONSISTENT && | 891 | send_oos = rw == WRITE && drbd_should_send_oos(mdev); |
878 | mdev->state.conn >= C_CONNECTED && | 892 | D_ASSERT(!(remote && send_oos)); |
879 | mdev->state.conn < C_AHEAD)); | ||
880 | send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD && | ||
881 | mdev->state.pdsk >= D_INCONSISTENT); | ||
882 | 893 | ||
883 | if (!(remote || send_oos)) | 894 | if (!(remote || send_oos)) |
884 | dev_warn(DEV, "lost connection while grabbing the req_lock!\n"); | 895 | dev_warn(DEV, "lost connection while grabbing the req_lock!\n"); |