diff --git a/iscsi-scst/kernel/isert-scst/iser.h b/iscsi-scst/kernel/isert-scst/iser.h index 65ae7e3db..a638c296f 100644 --- a/iscsi-scst/kernel/isert-scst/iser.h +++ b/iscsi-scst/kernel/isert-scst/iser.h @@ -256,6 +256,9 @@ struct isert_global { spinlock_t portal_lock; /* protected by portal_lock */ struct list_head portal_list; + /* Number of live portal objects. Protected by portal_lock. */ + int portal_cnt; + wait_queue_head_t portal_wq; /* protected by dev_list_mutex */ struct list_head dev_list; struct workqueue_struct *conn_wq; @@ -270,6 +273,8 @@ int isert_datamover_cleanup(void); void isert_portal_list_add(struct isert_portal *portal); void isert_portal_list_remove(struct isert_portal *portal); +void isert_decrease_portal_cnt(void); +void isert_wait_for_portal_release(void); void isert_dev_list_add(struct isert_device *isert_dev); void isert_dev_list_remove(struct isert_device *isert_dev); diff --git a/iscsi-scst/kernel/isert-scst/iser_global.c b/iscsi-scst/kernel/isert-scst/iser_global.c index 9834fc481..82b43cbcb 100644 --- a/iscsi-scst/kernel/isert-scst/iser_global.c +++ b/iscsi-scst/kernel/isert-scst/iser_global.c @@ -49,6 +49,7 @@ void isert_portal_list_add(struct isert_portal *portal) { spin_lock(&isert_glob.portal_lock); list_add_tail(&portal->list_node, &isert_glob.portal_list); + isert_glob.portal_cnt++; spin_unlock(&isert_glob.portal_lock); } @@ -59,6 +60,32 @@ void isert_portal_list_remove(struct isert_portal *portal) spin_unlock(&isert_glob.portal_lock); } +void isert_decrease_portal_cnt(void) +{ + spin_lock(&isert_glob.portal_lock); + WARN_ON_ONCE(isert_glob.portal_cnt <= 0); + spin_unlock(&isert_glob.portal_lock); + + if (--isert_glob.portal_cnt == 0) + wake_up_all(&isert_glob.portal_wq); +} + +static int isert_portal_cnt(void) +{ + int portal_cnt; + + spin_lock(&isert_glob.portal_lock); + portal_cnt = isert_glob.portal_cnt; + spin_unlock(&isert_glob.portal_lock); + + return portal_cnt; +} + +void isert_wait_for_portal_release(void) +{ + wait_event(isert_glob.portal_wq, isert_portal_cnt() == 0); +} + void isert_dev_list_add(struct isert_device *isert_dev) { list_add_tail(&isert_dev->devs_node, &isert_glob.dev_list); @@ -90,6 +117,7 @@ void isert_portal_list_release_all(void) list_for_each_entry_safe(portal, n, &isert_glob.portal_list, list_node) isert_portal_release(portal); + isert_wait_for_portal_release(); } void isert_conn_queue_work(struct work_struct *w) @@ -99,10 +127,13 @@ void isert_conn_queue_work(struct work_struct *w) int isert_global_init(void) { + isert_glob.portal_cnt = 0; + INIT_LIST_HEAD(&isert_glob.portal_list); INIT_LIST_HEAD(&isert_glob.dev_list); spin_lock_init(&isert_glob.portal_lock); + init_waitqueue_head(&isert_glob.portal_wq); isert_glob.conn_wq = create_workqueue("isert_conn_wq"); if (!isert_glob.conn_wq) { diff --git a/iscsi-scst/kernel/isert-scst/iser_rdma.c b/iscsi-scst/kernel/isert-scst/iser_rdma.c index f38207573..10051f7cd 100644 --- a/iscsi-scst/kernel/isert-scst/iser_rdma.c +++ b/iscsi-scst/kernel/isert-scst/iser_rdma.c @@ -1900,6 +1900,8 @@ static void isert_portal_free(struct isert_portal *portal) kfree(portal); module_put(THIS_MODULE); + + isert_decrease_portal_cnt(); } void isert_portal_release(struct isert_portal *portal) @@ -1925,9 +1927,6 @@ void isert_portal_release(struct isert_portal *portal) isert_portal_free(portal); mutex_unlock(&dev_list_mutex); - while (portal->refcnt > 0) - msleep(100); - PRINT_INFO("done releasing portal %p", portal); } diff --git a/iscsi-scst/kernel/isert-scst/isert_login.c b/iscsi-scst/kernel/isert-scst/isert_login.c index 99ed1a909..d1ed53f07 100644 --- a/iscsi-scst/kernel/isert-scst/isert_login.c +++ b/iscsi-scst/kernel/isert-scst/isert_login.c @@ -1052,6 +1052,7 @@ void isert_close_all_portals(void) for (i = 0; i < isert_listen_dev.free_portal_idx; ++i) isert_portal_remove(isert_listen_dev.portal_h[i]); + isert_wait_for_portal_release(); isert_listen_dev.free_portal_idx = 0; }