aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2010-06-24 08:34:40 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2010-10-14 09:08:27 -0400
commitf70b3511599c49a3dc20ae349d6cdc5af47659df (patch)
tree1d5971f48f5fe95988df64f5ab1f22333c492dc9
parent8f488156c0635dcc9c668737d05386113a745ef9 (diff)
drbd: Do not try to free tl_hash in drbd_disconnect() when IO is suspended
We may not free tl_hash when IO is suspended, since we can not wait until ap_bio_cnt reaches zero. We can do this after susp reched 0, since then tl_clear was called 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.h1
-rw-r--r--drivers/block/drbd/drbd_main.c4
-rw-r--r--drivers/block/drbd/drbd_nl.c4
-rw-r--r--drivers/block/drbd/drbd_receiver.c60
4 files changed, 43 insertions, 26 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index aa9bb213fe70..f84ffb17a7e5 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1493,6 +1493,7 @@ extern void _drbd_wait_ee_list_empty(struct drbd_conf *mdev,
1493extern void drbd_set_recv_tcq(struct drbd_conf *mdev, int tcq_enabled); 1493extern void drbd_set_recv_tcq(struct drbd_conf *mdev, int tcq_enabled);
1494extern void _drbd_clear_done_ee(struct drbd_conf *mdev, struct list_head *to_be_freed); 1494extern void _drbd_clear_done_ee(struct drbd_conf *mdev, struct list_head *to_be_freed);
1495extern void drbd_flush_workqueue(struct drbd_conf *mdev); 1495extern void drbd_flush_workqueue(struct drbd_conf *mdev);
1496extern void drbd_free_tl_hash(struct drbd_conf *mdev);
1496 1497
1497/* yes, there is kernel_setsockopt, but only since 2.6.18. we don't need to 1498/* yes, there is kernel_setsockopt, but only since 2.6.18. we don't need to
1498 * mess with get_fs/set_fs, we know we are KERNEL_DS always. */ 1499 * mess with get_fs/set_fs, we know we are KERNEL_DS always. */
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 9fe9bdd9e33d..8d14635e7faf 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1409,6 +1409,10 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
1409 (os.user_isp && !ns.user_isp)) 1409 (os.user_isp && !ns.user_isp))
1410 resume_next_sg(mdev); 1410 resume_next_sg(mdev);
1411 1411
1412 /* free tl_hash if we Got thawed and are C_STANDALONE */
1413 if (ns.conn == C_STANDALONE && ns.susp == 0 && mdev->tl_hash)
1414 drbd_free_tl_hash(mdev);
1415
1412 /* Upon network connection, we need to start the receiver */ 1416 /* Upon network connection, we need to start the receiver */
1413 if (os.conn == C_STANDALONE && ns.conn == C_UNCONNECTED) 1417 if (os.conn == C_STANDALONE && ns.conn == C_UNCONNECTED)
1414 drbd_thread_start(&mdev->receiver); 1418 drbd_thread_start(&mdev->receiver);
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index dc0a9acbfdf1..6c08e637e25c 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1391,6 +1391,7 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
1391 } 1391 }
1392 } 1392 }
1393 1393
1394 drbd_flush_workqueue(mdev);
1394 spin_lock_irq(&mdev->req_lock); 1395 spin_lock_irq(&mdev->req_lock);
1395 if (mdev->net_conf != NULL) { 1396 if (mdev->net_conf != NULL) {
1396 retcode = ERR_NET_CONFIGURED; 1397 retcode = ERR_NET_CONFIGURED;
@@ -1429,10 +1430,9 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
1429 mdev->int_dig_out=int_dig_out; 1430 mdev->int_dig_out=int_dig_out;
1430 mdev->int_dig_in=int_dig_in; 1431 mdev->int_dig_in=int_dig_in;
1431 mdev->int_dig_vv=int_dig_vv; 1432 mdev->int_dig_vv=int_dig_vv;
1433 retcode = _drbd_set_state(_NS(mdev, conn, C_UNCONNECTED), CS_VERBOSE, NULL);
1432 spin_unlock_irq(&mdev->req_lock); 1434 spin_unlock_irq(&mdev->req_lock);
1433 1435
1434 retcode = _drbd_request_state(mdev, NS(conn, C_UNCONNECTED), CS_VERBOSE);
1435
1436 kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE); 1436 kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
1437 reply->ret_code = retcode; 1437 reply->ret_code = retcode;
1438 drbd_reconfig_done(mdev); 1438 drbd_reconfig_done(mdev);
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 22d74d79ba42..5e49ee75d3c9 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -3691,6 +3691,36 @@ void drbd_flush_workqueue(struct drbd_conf *mdev)
3691 wait_for_completion(&barr.done); 3691 wait_for_completion(&barr.done);
3692} 3692}
3693 3693
3694void drbd_free_tl_hash(struct drbd_conf *mdev)
3695{
3696 struct hlist_head *h;
3697
3698 spin_lock_irq(&mdev->req_lock);
3699
3700 if (!mdev->tl_hash || mdev->state.conn != C_STANDALONE) {
3701 spin_unlock_irq(&mdev->req_lock);
3702 return;
3703 }
3704 /* paranoia code */
3705 for (h = mdev->ee_hash; h < mdev->ee_hash + mdev->ee_hash_s; h++)
3706 if (h->first)
3707 dev_err(DEV, "ASSERT FAILED ee_hash[%u].first == %p, expected NULL\n",
3708 (int)(h - mdev->ee_hash), h->first);
3709 kfree(mdev->ee_hash);
3710 mdev->ee_hash = NULL;
3711 mdev->ee_hash_s = 0;
3712
3713 /* paranoia code */
3714 for (h = mdev->tl_hash; h < mdev->tl_hash + mdev->tl_hash_s; h++)
3715 if (h->first)
3716 dev_err(DEV, "ASSERT FAILED tl_hash[%u] == %p, expected NULL\n",
3717 (int)(h - mdev->tl_hash), h->first);
3718 kfree(mdev->tl_hash);
3719 mdev->tl_hash = NULL;
3720 mdev->tl_hash_s = 0;
3721 spin_unlock_irq(&mdev->req_lock);
3722}
3723
3694static void drbd_disconnect(struct drbd_conf *mdev) 3724static void drbd_disconnect(struct drbd_conf *mdev)
3695{ 3725{
3696 enum drbd_fencing_p fp; 3726 enum drbd_fencing_p fp;
@@ -3774,32 +3804,14 @@ static void drbd_disconnect(struct drbd_conf *mdev)
3774 spin_unlock_irq(&mdev->req_lock); 3804 spin_unlock_irq(&mdev->req_lock);
3775 3805
3776 if (os.conn == C_DISCONNECTING) { 3806 if (os.conn == C_DISCONNECTING) {
3777 struct hlist_head *h;
3778 wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0); 3807 wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0);
3779 3808
3780 /* we must not free the tl_hash 3809 if (!mdev->state.susp) {
3781 * while application io is still on the fly */ 3810 /* we must not free the tl_hash
3782 wait_event(mdev->misc_wait, atomic_read(&mdev->ap_bio_cnt) == 0); 3811 * while application io is still on the fly */
3783 3812 wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
3784 spin_lock_irq(&mdev->req_lock); 3813 drbd_free_tl_hash(mdev);
3785 /* paranoia code */ 3814 }
3786 for (h = mdev->ee_hash; h < mdev->ee_hash + mdev->ee_hash_s; h++)
3787 if (h->first)
3788 dev_err(DEV, "ASSERT FAILED ee_hash[%u].first == %p, expected NULL\n",
3789 (int)(h - mdev->ee_hash), h->first);
3790 kfree(mdev->ee_hash);
3791 mdev->ee_hash = NULL;
3792 mdev->ee_hash_s = 0;
3793
3794 /* paranoia code */
3795 for (h = mdev->tl_hash; h < mdev->tl_hash + mdev->tl_hash_s; h++)
3796 if (h->first)
3797 dev_err(DEV, "ASSERT FAILED tl_hash[%u] == %p, expected NULL\n",
3798 (int)(h - mdev->tl_hash), h->first);
3799 kfree(mdev->tl_hash);
3800 mdev->tl_hash = NULL;
3801 mdev->tl_hash_s = 0;
3802 spin_unlock_irq(&mdev->req_lock);
3803 3815
3804 crypto_free_hash(mdev->cram_hmac_tfm); 3816 crypto_free_hash(mdev->cram_hmac_tfm);
3805 mdev->cram_hmac_tfm = NULL; 3817 mdev->cram_hmac_tfm = NULL;