diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2010-06-24 08:34:40 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2010-10-14 09:08:27 -0400 |
commit | f70b3511599c49a3dc20ae349d6cdc5af47659df (patch) | |
tree | 1d5971f48f5fe95988df64f5ab1f22333c492dc9 /drivers/block/drbd/drbd_receiver.c | |
parent | 8f488156c0635dcc9c668737d05386113a745ef9 (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>
Diffstat (limited to 'drivers/block/drbd/drbd_receiver.c')
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 60 |
1 files changed, 36 insertions, 24 deletions
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 | ||
3694 | void 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 | |||
3694 | static void drbd_disconnect(struct drbd_conf *mdev) | 3724 | static 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; |