Skip to content

Commit a112531

Browse files
KAGA-KOKOdledford
authored andcommitted
IB/srpt: Rework multi-channel support
Store initiator and target port ID's once per nexus instead of in each channel data structure. This change simplifies the duplicate connection check in srpt_cm_req_recv(). Signed-off-by: Bart Van Assche <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
1 parent 2dc98f0 commit a112531

File tree

2 files changed

+160
-60
lines changed

2 files changed

+160
-60
lines changed

drivers/infiniband/ulp/srpt/ib_srpt.c

Lines changed: 135 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,16 +1849,20 @@ static int srpt_disconnect_ch(struct srpt_rdma_ch *ch)
18491849

18501850
static bool srpt_ch_closed(struct srpt_port *sport, struct srpt_rdma_ch *ch)
18511851
{
1852+
struct srpt_nexus *nexus;
18521853
struct srpt_rdma_ch *ch2;
18531854
bool res = true;
18541855

18551856
rcu_read_lock();
1856-
list_for_each_entry(ch2, &sport->rch_list, list) {
1857-
if (ch2 == ch) {
1858-
res = false;
1859-
break;
1857+
list_for_each_entry(nexus, &sport->nexus_list, entry) {
1858+
list_for_each_entry(ch2, &nexus->ch_list, list) {
1859+
if (ch2 == ch) {
1860+
res = false;
1861+
goto done;
1862+
}
18601863
}
18611864
}
1865+
done:
18621866
rcu_read_unlock();
18631867

18641868
return res;
@@ -1891,30 +1895,78 @@ static bool srpt_disconnect_ch_sync(struct srpt_rdma_ch *ch)
18911895
return ret == 0;
18921896
}
18931897

1894-
static void srpt_set_enabled(struct srpt_port *sport, bool enabled)
1895-
__must_hold(&sport->mutex)
1898+
static void __srpt_close_all_ch(struct srpt_port *sport)
18961899
{
1900+
struct srpt_nexus *nexus;
18971901
struct srpt_rdma_ch *ch;
18981902

18991903
lockdep_assert_held(&sport->mutex);
19001904

1901-
if (sport->enabled == enabled)
1902-
return;
1903-
sport->enabled = enabled;
1904-
if (sport->enabled)
1905-
return;
1905+
list_for_each_entry(nexus, &sport->nexus_list, entry) {
1906+
list_for_each_entry(ch, &nexus->ch_list, list) {
1907+
if (srpt_disconnect_ch(ch) >= 0)
1908+
pr_info("Closing channel %s-%d because target %s_%d has been disabled\n",
1909+
ch->sess_name, ch->qp->qp_num,
1910+
sport->sdev->device->name, sport->port);
1911+
srpt_close_ch(ch);
1912+
}
1913+
}
1914+
}
1915+
1916+
/*
1917+
* Look up (i_port_id, t_port_id) in sport->nexus_list. Create an entry if
1918+
* it does not yet exist.
1919+
*/
1920+
static struct srpt_nexus *srpt_get_nexus(struct srpt_port *sport,
1921+
const u8 i_port_id[16],
1922+
const u8 t_port_id[16])
1923+
{
1924+
struct srpt_nexus *nexus = NULL, *tmp_nexus = NULL, *n;
19061925

1907-
again:
1908-
list_for_each_entry(ch, &sport->rch_list, list) {
1909-
if (ch->sport == sport) {
1910-
pr_info("%s: closing channel %s-%d\n",
1911-
sport->sdev->device->name, ch->sess_name,
1912-
ch->qp->qp_num);
1913-
if (srpt_disconnect_ch_sync(ch))
1914-
goto again;
1926+
for (;;) {
1927+
mutex_lock(&sport->mutex);
1928+
list_for_each_entry(n, &sport->nexus_list, entry) {
1929+
if (memcmp(n->i_port_id, i_port_id, 16) == 0 &&
1930+
memcmp(n->t_port_id, t_port_id, 16) == 0) {
1931+
nexus = n;
1932+
break;
1933+
}
1934+
}
1935+
if (!nexus && tmp_nexus) {
1936+
list_add_tail_rcu(&tmp_nexus->entry,
1937+
&sport->nexus_list);
1938+
swap(nexus, tmp_nexus);
19151939
}
1940+
mutex_unlock(&sport->mutex);
1941+
1942+
if (nexus)
1943+
break;
1944+
tmp_nexus = kzalloc(sizeof(*nexus), GFP_KERNEL);
1945+
if (!tmp_nexus) {
1946+
nexus = ERR_PTR(-ENOMEM);
1947+
break;
1948+
}
1949+
init_rcu_head(&tmp_nexus->rcu);
1950+
INIT_LIST_HEAD(&tmp_nexus->ch_list);
1951+
memcpy(tmp_nexus->i_port_id, i_port_id, 16);
1952+
memcpy(tmp_nexus->t_port_id, t_port_id, 16);
19161953
}
19171954

1955+
kfree(tmp_nexus);
1956+
1957+
return nexus;
1958+
}
1959+
1960+
static void srpt_set_enabled(struct srpt_port *sport, bool enabled)
1961+
__must_hold(&sport->mutex)
1962+
{
1963+
lockdep_assert_held(&sport->mutex);
1964+
1965+
if (sport->enabled == enabled)
1966+
return;
1967+
sport->enabled = enabled;
1968+
if (!enabled)
1969+
__srpt_close_all_ch(sport);
19181970
}
19191971

19201972
static void srpt_free_ch(struct kref *kref)
@@ -1984,11 +2036,12 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
19842036
{
19852037
struct srpt_device *sdev = cm_id->context;
19862038
struct srpt_port *sport = &sdev->port[param->port - 1];
2039+
struct srpt_nexus *nexus;
19872040
struct srp_login_req *req;
1988-
struct srp_login_rsp *rsp;
1989-
struct srp_login_rej *rej;
1990-
struct ib_cm_rep_param *rep_param;
1991-
struct srpt_rdma_ch *ch, *tmp_ch;
2041+
struct srp_login_rsp *rsp = NULL;
2042+
struct srp_login_rej *rej = NULL;
2043+
struct ib_cm_rep_param *rep_param = NULL;
2044+
struct srpt_rdma_ch *ch;
19922045
char i_port_id[36];
19932046
u32 it_iu_len;
19942047
int i, ret = 0;
@@ -2007,6 +2060,13 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
20072060
param->port, &sport->gid,
20082061
be16_to_cpu(param->primary_path->pkey));
20092062

2063+
nexus = srpt_get_nexus(sport, req->initiator_port_id,
2064+
req->target_port_id);
2065+
if (IS_ERR(nexus)) {
2066+
ret = PTR_ERR(nexus);
2067+
goto out;
2068+
}
2069+
20102070
rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
20112071
rej = kzalloc(sizeof(*rej), GFP_KERNEL);
20122072
rep_param = kzalloc(sizeof(*rep_param), GFP_KERNEL);
@@ -2036,29 +2096,22 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
20362096
}
20372097

20382098
if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) {
2099+
struct srpt_rdma_ch *ch2;
2100+
20392101
rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN;
20402102

20412103
mutex_lock(&sport->mutex);
2042-
2043-
list_for_each_entry_safe(ch, tmp_ch, &sport->rch_list, list) {
2044-
if (!memcmp(ch->i_port_id, req->initiator_port_id, 16)
2045-
&& !memcmp(ch->t_port_id, req->target_port_id, 16)
2046-
&& param->port == ch->sport->port
2047-
&& param->listen_id == ch->sport->sdev->cm_id
2048-
&& ch->cm_id) {
2049-
if (srpt_disconnect_ch(ch) < 0)
2050-
continue;
2051-
pr_info("Relogin - closed existing channel %s\n",
2052-
ch->sess_name);
2053-
rsp->rsp_flags =
2054-
SRP_LOGIN_RSP_MULTICHAN_TERMINATED;
2055-
}
2104+
list_for_each_entry(ch2, &nexus->ch_list, list) {
2105+
if (srpt_disconnect_ch(ch2) < 0)
2106+
continue;
2107+
pr_info("Relogin - closed existing channel %s\n",
2108+
ch2->sess_name);
2109+
rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_TERMINATED;
20562110
}
2057-
20582111
mutex_unlock(&sport->mutex);
2059-
2060-
} else
2112+
} else {
20612113
rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED;
2114+
}
20622115

20632116
if (*(__be64 *)req->target_port_id != cpu_to_be64(srpt_service_guid)
20642117
|| *(__be64 *)(req->target_port_id + 8) !=
@@ -2083,10 +2136,9 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
20832136
init_rcu_head(&ch->rcu);
20842137
kref_init(&ch->kref);
20852138
ch->pkey = be16_to_cpu(param->primary_path->pkey);
2139+
ch->nexus = nexus;
20862140
ch->zw_cqe.done = srpt_zerolength_write_done;
20872141
INIT_WORK(&ch->release_work, srpt_release_channel_work);
2088-
memcpy(ch->i_port_id, req->initiator_port_id, 16);
2089-
memcpy(ch->t_port_id, req->target_port_id, 16);
20902142
ch->sport = &sdev->port[param->port - 1];
20912143
ch->cm_id = cm_id;
20922144
cm_id->context = ch;
@@ -2147,8 +2199,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
21472199
srpt_format_guid(ch->sess_name, sizeof(ch->sess_name),
21482200
&param->primary_path->dgid.global.interface_id);
21492201
snprintf(i_port_id, sizeof(i_port_id), "0x%016llx%016llx",
2150-
be64_to_cpu(*(__be64 *)ch->i_port_id),
2151-
be64_to_cpu(*(__be64 *)(ch->i_port_id + 8)));
2202+
be64_to_cpu(*(__be64 *)nexus->i_port_id),
2203+
be64_to_cpu(*(__be64 *)(nexus->i_port_id + 8)));
21522204

21532205
pr_debug("registering session %s\n", ch->sess_name);
21542206

@@ -2208,7 +2260,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
22082260
}
22092261

22102262
mutex_lock(&sport->mutex);
2211-
list_add_tail_rcu(&ch->list, &sport->rch_list);
2263+
list_add_tail_rcu(&ch->list, &nexus->ch_list);
22122264
mutex_unlock(&sport->mutex);
22132265

22142266
goto out;
@@ -2560,24 +2612,56 @@ static void srpt_refresh_port_work(struct work_struct *work)
25602612
srpt_refresh_port(sport);
25612613
}
25622614

2615+
static bool srpt_ch_list_empty(struct srpt_port *sport)
2616+
{
2617+
struct srpt_nexus *nexus;
2618+
bool res = true;
2619+
2620+
rcu_read_lock();
2621+
list_for_each_entry(nexus, &sport->nexus_list, entry)
2622+
if (!list_empty(&nexus->ch_list))
2623+
res = false;
2624+
rcu_read_unlock();
2625+
2626+
return res;
2627+
}
2628+
25632629
/**
25642630
* srpt_release_sport - disable login and wait for associated channels
25652631
* @sport: SRPT HCA port.
25662632
*/
25672633
static int srpt_release_sport(struct srpt_port *sport)
25682634
{
2569-
int res;
2635+
struct srpt_nexus *nexus, *next_n;
2636+
struct srpt_rdma_ch *ch;
25702637

25712638
WARN_ON_ONCE(irqs_disabled());
25722639

25732640
mutex_lock(&sport->mutex);
25742641
srpt_set_enabled(sport, false);
25752642
mutex_unlock(&sport->mutex);
25762643

2577-
res = wait_event_interruptible(sport->ch_releaseQ,
2578-
list_empty_careful(&sport->rch_list));
2579-
if (res)
2580-
pr_err("%s: interrupted.\n", __func__);
2644+
while (wait_event_timeout(sport->ch_releaseQ,
2645+
srpt_ch_list_empty(sport), 5 * HZ) <= 0) {
2646+
pr_info("%s_%d: waiting for session unregistration ...\n",
2647+
sport->sdev->device->name, sport->port);
2648+
rcu_read_lock();
2649+
list_for_each_entry(nexus, &sport->nexus_list, entry) {
2650+
list_for_each_entry(ch, &nexus->ch_list, list) {
2651+
pr_info("%s-%d: state %s\n",
2652+
ch->sess_name, ch->qp->qp_num,
2653+
get_ch_state_name(ch->state));
2654+
}
2655+
}
2656+
rcu_read_unlock();
2657+
}
2658+
2659+
mutex_lock(&sport->mutex);
2660+
list_for_each_entry_safe(nexus, next_n, &sport->nexus_list, entry) {
2661+
list_del(&nexus->entry);
2662+
kfree_rcu(nexus, rcu);
2663+
}
2664+
mutex_unlock(&sport->mutex);
25812665

25822666
return 0;
25832667
}
@@ -2744,7 +2828,7 @@ static void srpt_add_one(struct ib_device *device)
27442828

27452829
for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
27462830
sport = &sdev->port[i - 1];
2747-
INIT_LIST_HEAD(&sport->rch_list);
2831+
INIT_LIST_HEAD(&sport->nexus_list);
27482832
init_waitqueue_head(&sport->ch_releaseQ);
27492833
mutex_init(&sport->mutex);
27502834
sport->sdev = sdev;

drivers/infiniband/ulp/srpt/ib_srpt.h

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
*/
5555
#define SRP_SERVICE_NAME_PREFIX "SRP.T10:"
5656

57+
struct srpt_nexus;
58+
5759
enum {
5860
/*
5961
* SRP IOControllerProfile attributes for SRP target ports that have
@@ -240,6 +242,7 @@ enum rdma_ch_state {
240242

241243
/**
242244
* struct srpt_rdma_ch - RDMA channel
245+
* @nexus: I_T nexus this channel is associated with.
243246
* @cm_id: IB CM ID associated with the channel.
244247
* @qp: IB queue pair used for communicating over this channel.
245248
* @cq: IB completion queue for this channel.
@@ -251,8 +254,6 @@ enum rdma_ch_state {
251254
* @sq_wr_avail: number of work requests available in the send queue.
252255
* @sport: pointer to the information of the HCA port used by this
253256
* channel.
254-
* @i_port_id: 128-bit initiator port identifier copied from SRP_LOGIN_REQ.
255-
* @t_port_id: 128-bit target port identifier copied from SRP_LOGIN_REQ.
256257
* @max_ti_iu_len: maximum target-to-initiator information unit length.
257258
* @req_lim: request limit: maximum number of requests that may be sent
258259
* by the initiator without having received a response.
@@ -262,7 +263,7 @@ enum rdma_ch_state {
262263
* @state: channel state. See also enum rdma_ch_state.
263264
* @ioctx_ring: Send ring.
264265
* @ioctx_recv_ring: Receive I/O context ring.
265-
* @list: Node in srpt_port.rch_list.
266+
* @list: Node in srpt_nexus.ch_list.
266267
* @cmd_wait_list: List of SCSI commands that arrived before the RTU event. This
267268
* list contains struct srpt_ioctx elements and is protected
268269
* against concurrent modification by the cm_id spinlock.
@@ -272,6 +273,7 @@ enum rdma_ch_state {
272273
* @release_work: Allows scheduling of srpt_release_channel().
273274
*/
274275
struct srpt_rdma_ch {
276+
struct srpt_nexus *nexus;
275277
struct ib_cm_id *cm_id;
276278
struct ib_qp *qp;
277279
struct ib_cq *cq;
@@ -282,8 +284,6 @@ struct srpt_rdma_ch {
282284
u32 max_rsp_size;
283285
atomic_t sq_wr_avail;
284286
struct srpt_port *sport;
285-
u8 i_port_id[16];
286-
u8 t_port_id[16];
287287
int max_ti_iu_len;
288288
atomic_t req_lim;
289289
atomic_t req_lim_delta;
@@ -300,6 +300,22 @@ struct srpt_rdma_ch {
300300
struct work_struct release_work;
301301
};
302302

303+
/**
304+
* struct srpt_nexus - I_T nexus
305+
* @rcu: RCU head for this data structure.
306+
* @entry: srpt_port.nexus_list list node.
307+
* @ch_list: struct srpt_rdma_ch list. Protected by srpt_port.mutex.
308+
* @i_port_id: 128-bit initiator port identifier copied from SRP_LOGIN_REQ.
309+
* @t_port_id: 128-bit target port identifier copied from SRP_LOGIN_REQ.
310+
*/
311+
struct srpt_nexus {
312+
struct rcu_head rcu;
313+
struct list_head entry;
314+
struct list_head ch_list;
315+
u8 i_port_id[16];
316+
u8 t_port_id[16];
317+
};
318+
303319
/**
304320
* struct srpt_port_attib - attributes for SRPT port
305321
* @srp_max_rdma_size: Maximum size of SRP RDMA transfers for new connections.
@@ -332,9 +348,9 @@ struct srpt_port_attrib {
332348
* @port_gid_tpg: TPG associated with target port GID.
333349
* @port_gid_wwn: WWN associated with target port GID.
334350
* @port_attrib: Port attributes that can be accessed through configfs.
335-
* @ch_releaseQ: Enables waiting for removal from rch_list.
336-
* @mutex: Protects rch_list.
337-
* @rch_list: Channel list. See also srpt_rdma_ch.list.
351+
* @ch_releaseQ: Enables waiting for removal from nexus_list.
352+
* @mutex: Protects nexus_list.
353+
* @nexus_list: Nexus list. See also srpt_nexus.entry.
338354
*/
339355
struct srpt_port {
340356
struct srpt_device *sdev;
@@ -354,7 +370,7 @@ struct srpt_port {
354370
struct srpt_port_attrib port_attrib;
355371
wait_queue_head_t ch_releaseQ;
356372
struct mutex mutex;
357-
struct list_head rch_list;
373+
struct list_head nexus_list;
358374
};
359375

360376
/**

0 commit comments

Comments
 (0)