Commit 8b6dc529 authored by Bart Van Assche's avatar Bart Van Assche Committed by Doug Ledford

IB/srpt: Wait until channel release has finished during module unload

Introduce the helper function srpt_set_enabled(). Protect
sport->enabled changes with sdev->mutex. Makes configfs writes
into 'enabled' wait until all channel resources have been freed.
Wait until channel release has finished during kernel module
unload.
Signed-off-by: default avatarBart Van Assche <bart.vanassche@wdc.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 01b3ee13
...@@ -1821,19 +1821,31 @@ static bool srpt_disconnect_ch_sync(struct srpt_rdma_ch *ch) ...@@ -1821,19 +1821,31 @@ static bool srpt_disconnect_ch_sync(struct srpt_rdma_ch *ch)
return wait; return wait;
} }
static void __srpt_close_all_ch(struct srpt_device *sdev) static void srpt_set_enabled(struct srpt_port *sport, bool enabled)
__must_hold(&sdev->mutex)
{ {
struct srpt_device *sdev = sport->sdev;
struct srpt_rdma_ch *ch; struct srpt_rdma_ch *ch;
lockdep_assert_held(&sdev->mutex); lockdep_assert_held(&sdev->mutex);
if (sport->enabled == enabled)
return;
sport->enabled = enabled;
if (sport->enabled)
return;
again:
list_for_each_entry(ch, &sdev->rch_list, list) { list_for_each_entry(ch, &sdev->rch_list, list) {
if (srpt_disconnect_ch(ch) >= 0) if (ch->sport == sport) {
pr_info("Closing channel %s-%d because target %s has been disabled\n", pr_info("%s: closing channel %s-%d\n",
ch->sess_name, ch->qp->qp_num, sdev->device->name, ch->sess_name,
sdev->device->name); ch->qp->qp_num);
srpt_close_ch(ch); if (srpt_disconnect_ch_sync(ch))
goto again;
}
} }
} }
static void srpt_free_ch(struct kref *kref) static void srpt_free_ch(struct kref *kref)
...@@ -2496,8 +2508,7 @@ static int srpt_release_sdev(struct srpt_device *sdev) ...@@ -2496,8 +2508,7 @@ static int srpt_release_sdev(struct srpt_device *sdev)
mutex_lock(&sdev->mutex); mutex_lock(&sdev->mutex);
for (i = 0; i < ARRAY_SIZE(sdev->port); i++) for (i = 0; i < ARRAY_SIZE(sdev->port); i++)
sdev->port[i].enabled = false; srpt_set_enabled(&sdev->port[i], false);
__srpt_close_all_ch(sdev);
mutex_unlock(&sdev->mutex); mutex_unlock(&sdev->mutex);
res = wait_event_interruptible(sdev->ch_releaseQ, res = wait_event_interruptible(sdev->ch_releaseQ,
...@@ -3083,7 +3094,6 @@ static ssize_t srpt_tpg_enable_store(struct config_item *item, ...@@ -3083,7 +3094,6 @@ static ssize_t srpt_tpg_enable_store(struct config_item *item,
struct se_portal_group *se_tpg = to_tpg(item); struct se_portal_group *se_tpg = to_tpg(item);
struct srpt_port *sport = srpt_tpg_to_sport(se_tpg); struct srpt_port *sport = srpt_tpg_to_sport(se_tpg);
struct srpt_device *sdev = sport->sdev; struct srpt_device *sdev = sport->sdev;
struct srpt_rdma_ch *ch;
unsigned long tmp; unsigned long tmp;
int ret; int ret;
...@@ -3097,24 +3107,11 @@ static ssize_t srpt_tpg_enable_store(struct config_item *item, ...@@ -3097,24 +3107,11 @@ static ssize_t srpt_tpg_enable_store(struct config_item *item,
pr_err("Illegal value for srpt_tpg_store_enable: %lu\n", tmp); pr_err("Illegal value for srpt_tpg_store_enable: %lu\n", tmp);
return -EINVAL; return -EINVAL;
} }
if (sport->enabled == tmp)
goto out;
sport->enabled = tmp;
if (sport->enabled)
goto out;
mutex_lock(&sdev->mutex); mutex_lock(&sdev->mutex);
list_for_each_entry(ch, &sdev->rch_list, list) { srpt_set_enabled(sport, tmp);
if (ch->sport == sport) {
pr_debug("%s: ch %p %s-%d\n", __func__, ch,
ch->sess_name, ch->qp->qp_num);
srpt_disconnect_ch(ch);
srpt_close_ch(ch);
}
}
mutex_unlock(&sdev->mutex); mutex_unlock(&sdev->mutex);
out:
return count; return count;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment