diff --git a/drbd/drbd_main.c b/drbd/drbd_main.c index 1a1c4f6..719a5fe 100644 --- a/drbd/drbd_receiver.c +++ b/drbd/drbd_receiver.c @@ -357,7 +357,7 @@ int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list) } -STATIC void reclaim_net_ee(struct drbd_conf *mdev) +STATIC enum { RN_EMPTY, RN_NOT_EMPTY } reclaim_net_ee(struct drbd_conf *mdev) { struct drbd_epoch_entry *e; struct list_head *le, *tle; @@ -370,10 +370,12 @@ STATIC void reclaim_net_ee(struct drbd_conf *mdev) list_for_each_safe(le, tle, &mdev->net_ee) { e = list_entry(le, struct drbd_epoch_entry, w.list); if (drbd_bio_has_active_page(e->private_bio)) - break; + return RN_NOT_EMPTY; list_del(le); drbd_free_ee(mdev, e); } + + return RN_EMPTY; } @@ -3552,7 +3554,13 @@ STATIC void drbd_disconnect(struct drbd_conf *mdev) _drbd_wait_ee_list_empty(mdev, &mdev->sync_ee); _drbd_clear_done_ee(mdev); _drbd_wait_ee_list_empty(mdev, &mdev->read_ee); - reclaim_net_ee(mdev); + while (reclaim_net_ee(mdev) == RN_NOT_EMPTY) { + spin_unlock_irq(&mdev->req_lock); + dev_info(DEV, "Waiting for TCP to finally give up all page references\n"); + __set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ / 10); + spin_lock_irq(&mdev->req_lock); + } spin_unlock_irq(&mdev->req_lock); /* We do not have data structures that would allow us to