diff options
author | Bart Van Assche <bart.vanassche@sandisk.com> | 2016-02-11 14:08:34 -0500 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-02-29 17:12:36 -0500 |
commit | 8628991fbe6a9086189f55f0b33dee7f25108ecc (patch) | |
tree | 4cfe8e1c7373c8a93c1d68de0a3b815d98c86240 | |
parent | c13c90ea6762d834a07c0aa18134d98794f6fc3d (diff) |
IB/srpt: Use a mutex to protect the channel list
In a later patch a function that can block will be called while
iterating over the rch_list. Hence protect that list with a
mutex instead of a spinlock. And since it is not allowed to sleep
while the task state != TASK_RUNNING, convert the list test in
srpt_ch_list_empty() into a lockless test.
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Cc: Sagi Grimberg <sagig@mellanox.com>
Cc: Alex Estrin <alex.estrin@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r-- | drivers/infiniband/ulp/srpt/ib_srpt.c | 42 | ||||
-rw-r--r-- | drivers/infiniband/ulp/srpt/ib_srpt.h | 4 |
2 files changed, 17 insertions, 29 deletions
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 0bf204ec443e..33bd408c5eea 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c | |||
@@ -1862,12 +1862,11 @@ static void __srpt_close_ch(struct srpt_rdma_ch *ch) | |||
1862 | */ | 1862 | */ |
1863 | static void srpt_close_ch(struct srpt_rdma_ch *ch) | 1863 | static void srpt_close_ch(struct srpt_rdma_ch *ch) |
1864 | { | 1864 | { |
1865 | struct srpt_device *sdev; | 1865 | struct srpt_device *sdev = ch->sport->sdev; |
1866 | 1866 | ||
1867 | sdev = ch->sport->sdev; | 1867 | mutex_lock(&sdev->mutex); |
1868 | spin_lock_irq(&sdev->spinlock); | ||
1869 | __srpt_close_ch(ch); | 1868 | __srpt_close_ch(ch); |
1870 | spin_unlock_irq(&sdev->spinlock); | 1869 | mutex_unlock(&sdev->mutex); |
1871 | } | 1870 | } |
1872 | 1871 | ||
1873 | /** | 1872 | /** |
@@ -1954,11 +1953,11 @@ static void srpt_release_channel_work(struct work_struct *w) | |||
1954 | ch->sport->sdev, ch->rq_size, | 1953 | ch->sport->sdev, ch->rq_size, |
1955 | ch->rsp_size, DMA_TO_DEVICE); | 1954 | ch->rsp_size, DMA_TO_DEVICE); |
1956 | 1955 | ||
1957 | spin_lock_irq(&sdev->spinlock); | 1956 | mutex_lock(&sdev->mutex); |
1958 | list_del_init(&ch->list); | 1957 | list_del_init(&ch->list); |
1959 | if (ch->release_done) | 1958 | if (ch->release_done) |
1960 | complete(ch->release_done); | 1959 | complete(ch->release_done); |
1961 | spin_unlock_irq(&sdev->spinlock); | 1960 | mutex_unlock(&sdev->mutex); |
1962 | 1961 | ||
1963 | wake_up(&sdev->ch_releaseQ); | 1962 | wake_up(&sdev->ch_releaseQ); |
1964 | 1963 | ||
@@ -2039,7 +2038,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, | |||
2039 | if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) { | 2038 | if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) { |
2040 | rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN; | 2039 | rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN; |
2041 | 2040 | ||
2042 | spin_lock_irq(&sdev->spinlock); | 2041 | mutex_lock(&sdev->mutex); |
2043 | 2042 | ||
2044 | list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) { | 2043 | list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) { |
2045 | if (!memcmp(ch->i_port_id, req->initiator_port_id, 16) | 2044 | if (!memcmp(ch->i_port_id, req->initiator_port_id, 16) |
@@ -2063,7 +2062,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, | |||
2063 | } | 2062 | } |
2064 | } | 2063 | } |
2065 | 2064 | ||
2066 | spin_unlock_irq(&sdev->spinlock); | 2065 | mutex_unlock(&sdev->mutex); |
2067 | 2066 | ||
2068 | } else | 2067 | } else |
2069 | rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED; | 2068 | rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED; |
@@ -2208,9 +2207,9 @@ try_again: | |||
2208 | goto release_channel; | 2207 | goto release_channel; |
2209 | } | 2208 | } |
2210 | 2209 | ||
2211 | spin_lock_irq(&sdev->spinlock); | 2210 | mutex_lock(&sdev->mutex); |
2212 | list_add_tail(&ch->list, &sdev->rch_list); | 2211 | list_add_tail(&ch->list, &sdev->rch_list); |
2213 | spin_unlock_irq(&sdev->spinlock); | 2212 | mutex_unlock(&sdev->mutex); |
2214 | 2213 | ||
2215 | goto out; | 2214 | goto out; |
2216 | 2215 | ||
@@ -2653,17 +2652,6 @@ static void srpt_refresh_port_work(struct work_struct *work) | |||
2653 | srpt_refresh_port(sport); | 2652 | srpt_refresh_port(sport); |
2654 | } | 2653 | } |
2655 | 2654 | ||
2656 | static int srpt_ch_list_empty(struct srpt_device *sdev) | ||
2657 | { | ||
2658 | int res; | ||
2659 | |||
2660 | spin_lock_irq(&sdev->spinlock); | ||
2661 | res = list_empty(&sdev->rch_list); | ||
2662 | spin_unlock_irq(&sdev->spinlock); | ||
2663 | |||
2664 | return res; | ||
2665 | } | ||
2666 | |||
2667 | /** | 2655 | /** |
2668 | * srpt_release_sdev() - Free the channel resources associated with a target. | 2656 | * srpt_release_sdev() - Free the channel resources associated with a target. |
2669 | */ | 2657 | */ |
@@ -2676,13 +2664,13 @@ static int srpt_release_sdev(struct srpt_device *sdev) | |||
2676 | 2664 | ||
2677 | BUG_ON(!sdev); | 2665 | BUG_ON(!sdev); |
2678 | 2666 | ||
2679 | spin_lock_irq(&sdev->spinlock); | 2667 | mutex_lock(&sdev->mutex); |
2680 | list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) | 2668 | list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) |
2681 | __srpt_close_ch(ch); | 2669 | __srpt_close_ch(ch); |
2682 | spin_unlock_irq(&sdev->spinlock); | 2670 | mutex_unlock(&sdev->mutex); |
2683 | 2671 | ||
2684 | res = wait_event_interruptible(sdev->ch_releaseQ, | 2672 | res = wait_event_interruptible(sdev->ch_releaseQ, |
2685 | srpt_ch_list_empty(sdev)); | 2673 | list_empty_careful(&sdev->rch_list)); |
2686 | if (res) | 2674 | if (res) |
2687 | pr_err("%s: interrupted.\n", __func__); | 2675 | pr_err("%s: interrupted.\n", __func__); |
2688 | 2676 | ||
@@ -2743,7 +2731,7 @@ static void srpt_add_one(struct ib_device *device) | |||
2743 | sdev->device = device; | 2731 | sdev->device = device; |
2744 | INIT_LIST_HEAD(&sdev->rch_list); | 2732 | INIT_LIST_HEAD(&sdev->rch_list); |
2745 | init_waitqueue_head(&sdev->ch_releaseQ); | 2733 | init_waitqueue_head(&sdev->ch_releaseQ); |
2746 | spin_lock_init(&sdev->spinlock); | 2734 | mutex_init(&sdev->mutex); |
2747 | 2735 | ||
2748 | sdev->pd = ib_alloc_pd(device); | 2736 | sdev->pd = ib_alloc_pd(device); |
2749 | if (IS_ERR(sdev->pd)) | 2737 | if (IS_ERR(sdev->pd)) |
@@ -2971,12 +2959,12 @@ static void srpt_close_session(struct se_session *se_sess) | |||
2971 | pr_debug("ch %s-%d state %d\n", ch->sess_name, ch->qp->qp_num, | 2959 | pr_debug("ch %s-%d state %d\n", ch->sess_name, ch->qp->qp_num, |
2972 | ch->state); | 2960 | ch->state); |
2973 | 2961 | ||
2974 | spin_lock_irq(&sdev->spinlock); | 2962 | mutex_lock(&sdev->mutex); |
2975 | BUG_ON(ch->release_done); | 2963 | BUG_ON(ch->release_done); |
2976 | ch->release_done = &release_done; | 2964 | ch->release_done = &release_done; |
2977 | wait = !list_empty(&ch->list); | 2965 | wait = !list_empty(&ch->list); |
2978 | __srpt_close_ch(ch); | 2966 | __srpt_close_ch(ch); |
2979 | spin_unlock_irq(&sdev->spinlock); | 2967 | mutex_unlock(&sdev->mutex); |
2980 | 2968 | ||
2981 | if (!wait) | 2969 | if (!wait) |
2982 | return; | 2970 | return; |
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h index 9c326c71607c..5883295a7b97 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.h +++ b/drivers/infiniband/ulp/srpt/ib_srpt.h | |||
@@ -342,7 +342,7 @@ struct srpt_port { | |||
342 | * @ioctx_ring: Per-HCA SRQ. | 342 | * @ioctx_ring: Per-HCA SRQ. |
343 | * @rch_list: Per-device channel list -- see also srpt_rdma_ch.list. | 343 | * @rch_list: Per-device channel list -- see also srpt_rdma_ch.list. |
344 | * @ch_releaseQ: Enables waiting for removal from rch_list. | 344 | * @ch_releaseQ: Enables waiting for removal from rch_list. |
345 | * @spinlock: Protects rch_list and tpg. | 345 | * @mutex: Protects rch_list. |
346 | * @port: Information about the ports owned by this HCA. | 346 | * @port: Information about the ports owned by this HCA. |
347 | * @event_handler: Per-HCA asynchronous IB event handler. | 347 | * @event_handler: Per-HCA asynchronous IB event handler. |
348 | * @list: Node in srpt_dev_list. | 348 | * @list: Node in srpt_dev_list. |
@@ -356,7 +356,7 @@ struct srpt_device { | |||
356 | struct srpt_recv_ioctx **ioctx_ring; | 356 | struct srpt_recv_ioctx **ioctx_ring; |
357 | struct list_head rch_list; | 357 | struct list_head rch_list; |
358 | wait_queue_head_t ch_releaseQ; | 358 | wait_queue_head_t ch_releaseQ; |
359 | spinlock_t spinlock; | 359 | struct mutex mutex; |
360 | struct srpt_port port[2]; | 360 | struct srpt_port port[2]; |
361 | struct ib_event_handler event_handler; | 361 | struct ib_event_handler event_handler; |
362 | struct list_head list; | 362 | struct list_head list; |