Skip to content

Commit c014c8c

Browse files
Bart Van Asschedledford
authored andcommitted
IB/srp: Fix connection state tracking
Reception of a DREQ message only causes the state of a single channel to change. Hence move the 'connected' member variable from the target to the channel data structure. This patch avoids that following false positive warning can be reported by srp_destroy_qp(): WARNING: at drivers/infiniband/ulp/srp/ib_srp.c:617 srp_destroy_qp+0xa6/0x120 [ib_srp]() Call Trace: [<ffffffff8106e10f>] warn_slowpath_common+0x7f/0xc0 [<ffffffff8106e16a>] warn_slowpath_null+0x1a/0x20 [<ffffffffa0440226>] srp_destroy_qp+0xa6/0x120 [ib_srp] [<ffffffffa0440322>] srp_free_ch_ib+0x82/0x1e0 [ib_srp] [<ffffffffa044408b>] srp_create_target+0x7ab/0x998 [ib_srp] [<ffffffff81346f60>] dev_attr_store+0x20/0x30 [<ffffffff811dd90f>] sysfs_write_file+0xef/0x170 [<ffffffff8116d248>] vfs_write+0xc8/0x190 [<ffffffff8116d411>] sys_write+0x51/0x90 Signed-off-by: Bart Van Assche <[email protected]> Cc: Sagi Grimberg <[email protected]> Cc: Sebastian Parschauer <[email protected]> Cc: <[email protected]> #v3.19 Signed-off-by: Doug Ledford <[email protected]>
1 parent 8de9fe3 commit c014c8c

File tree

2 files changed

+30
-32
lines changed

2 files changed

+30
-32
lines changed

drivers/infiniband/ulp/srp/ib_srp.c

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -465,14 +465,13 @@ static struct srp_fr_pool *srp_alloc_fr_pool(struct srp_target_port *target)
465465
*/
466466
static void srp_destroy_qp(struct srp_rdma_ch *ch)
467467
{
468-
struct srp_target_port *target = ch->target;
469468
static struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
470469
static struct ib_recv_wr wr = { .wr_id = SRP_LAST_WR_ID };
471470
struct ib_recv_wr *bad_wr;
472471
int ret;
473472

474473
/* Destroying a QP and reusing ch->done is only safe if not connected */
475-
WARN_ON_ONCE(target->connected);
474+
WARN_ON_ONCE(ch->connected);
476475

477476
ret = ib_modify_qp(ch->qp, &attr, IB_QP_STATE);
478477
WARN_ONCE(ret, "ib_cm_init_qp_attr() returned %d\n", ret);
@@ -811,35 +810,19 @@ static bool srp_queue_remove_work(struct srp_target_port *target)
811810
return changed;
812811
}
813812

814-
static bool srp_change_conn_state(struct srp_target_port *target,
815-
bool connected)
816-
{
817-
bool changed = false;
818-
819-
spin_lock_irq(&target->lock);
820-
if (target->connected != connected) {
821-
target->connected = connected;
822-
changed = true;
823-
}
824-
spin_unlock_irq(&target->lock);
825-
826-
return changed;
827-
}
828-
829813
static void srp_disconnect_target(struct srp_target_port *target)
830814
{
831815
struct srp_rdma_ch *ch;
832816
int i;
833817

834-
if (srp_change_conn_state(target, false)) {
835-
/* XXX should send SRP_I_LOGOUT request */
818+
/* XXX should send SRP_I_LOGOUT request */
836819

837-
for (i = 0; i < target->ch_count; i++) {
838-
ch = &target->ch[i];
839-
if (ch->cm_id && ib_send_cm_dreq(ch->cm_id, NULL, 0)) {
840-
shost_printk(KERN_DEBUG, target->scsi_host,
841-
PFX "Sending CM DREQ failed\n");
842-
}
820+
for (i = 0; i < target->ch_count; i++) {
821+
ch = &target->ch[i];
822+
ch->connected = false;
823+
if (ch->cm_id && ib_send_cm_dreq(ch->cm_id, NULL, 0)) {
824+
shost_printk(KERN_DEBUG, target->scsi_host,
825+
PFX "Sending CM DREQ failed\n");
843826
}
844827
}
845828
}
@@ -986,12 +969,26 @@ static void srp_rport_delete(struct srp_rport *rport)
986969
srp_queue_remove_work(target);
987970
}
988971

972+
/**
973+
* srp_connected_ch() - number of connected channels
974+
* @target: SRP target port.
975+
*/
976+
static int srp_connected_ch(struct srp_target_port *target)
977+
{
978+
int i, c = 0;
979+
980+
for (i = 0; i < target->ch_count; i++)
981+
c += target->ch[i].connected;
982+
983+
return c;
984+
}
985+
989986
static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich)
990987
{
991988
struct srp_target_port *target = ch->target;
992989
int ret;
993990

994-
WARN_ON_ONCE(!multich && target->connected);
991+
WARN_ON_ONCE(!multich && srp_connected_ch(target) > 0);
995992

996993
ret = srp_lookup_path(ch);
997994
if (ret)
@@ -1014,7 +1011,7 @@ static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich)
10141011
*/
10151012
switch (ch->status) {
10161013
case 0:
1017-
srp_change_conn_state(target, true);
1014+
ch->connected = true;
10181015
return 0;
10191016

10201017
case SRP_PORT_REDIRECT:
@@ -1930,7 +1927,7 @@ static void srp_handle_qp_err(u64 wr_id, enum ib_wc_status wc_status,
19301927
return;
19311928
}
19321929

1933-
if (target->connected && !target->qp_in_error) {
1930+
if (ch->connected && !target->qp_in_error) {
19341931
if (wr_id & LOCAL_INV_WR_ID_MASK) {
19351932
shost_printk(KERN_ERR, target->scsi_host, PFX
19361933
"LOCAL_INV failed with status %d\n",
@@ -2368,7 +2365,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
23682365
case IB_CM_DREQ_RECEIVED:
23692366
shost_printk(KERN_WARNING, target->scsi_host,
23702367
PFX "DREQ received - connection closed\n");
2371-
srp_change_conn_state(target, false);
2368+
ch->connected = false;
23722369
if (ib_send_cm_drep(cm_id, NULL, 0))
23732370
shost_printk(KERN_ERR, target->scsi_host,
23742371
PFX "Sending CM DREP failed\n");
@@ -2424,7 +2421,7 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag,
24242421
struct srp_iu *iu;
24252422
struct srp_tsk_mgmt *tsk_mgmt;
24262423

2427-
if (!target->connected || target->qp_in_error)
2424+
if (!ch->connected || target->qp_in_error)
24282425
return -1;
24292426

24302427
init_completion(&ch->tsk_mgmt_done);
@@ -2798,7 +2795,8 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
27982795
scsi_scan_target(&target->scsi_host->shost_gendev,
27992796
0, target->scsi_id, SCAN_WILD_CARD, 0);
28002797

2801-
if (!target->connected || target->qp_in_error) {
2798+
if (srp_connected_ch(target) < target->ch_count ||
2799+
target->qp_in_error) {
28022800
shost_printk(KERN_INFO, target->scsi_host,
28032801
PFX "SCSI scan failed - removing SCSI host\n");
28042802
srp_queue_remove_work(target);

drivers/infiniband/ulp/srp/ib_srp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ struct srp_rdma_ch {
170170

171171
struct completion tsk_mgmt_done;
172172
u8 tsk_mgmt_status;
173+
bool connected;
173174
};
174175

175176
/**
@@ -214,7 +215,6 @@ struct srp_target_port {
214215
__be16 pkey;
215216

216217
u32 rq_tmo_jiffies;
217-
bool connected;
218218

219219
int zero_req_lim;
220220

0 commit comments

Comments
 (0)