Skip to content

Commit 9e5fe17

Browse files
mikechristiemartinkpetersen
authored andcommitted
scsi: iscsi: Rel ref after iscsi_lookup_endpoint()
Subsequent commits allow the kernel to do ep_disconnect. In that case we will have to get a proper refcount on the ep so one thread does not delete it from under another. Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Lee Duncan <[email protected]> Signed-off-by: Mike Christie <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent b25b957 commit 9e5fe17

File tree

8 files changed

+75
-32
lines changed

8 files changed

+75
-32
lines changed

drivers/infiniband/ulp/iser/iscsi_iser.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
506506
iser_conn->iscsi_conn = conn;
507507

508508
out:
509+
iscsi_put_endpoint(ep);
509510
mutex_unlock(&iser_conn->state_mutex);
510511
return error;
511512
}

drivers/scsi/be2iscsi/be_iscsi.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,22 +182,25 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
182182
struct beiscsi_endpoint *beiscsi_ep;
183183
struct iscsi_endpoint *ep;
184184
uint16_t cri_index;
185+
int rc = 0;
185186

186187
ep = iscsi_lookup_endpoint(transport_fd);
187188
if (!ep)
188189
return -EINVAL;
189190

190191
beiscsi_ep = ep->dd_data;
191192

192-
if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
193-
return -EINVAL;
193+
if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) {
194+
rc = -EINVAL;
195+
goto put_ep;
196+
}
194197

195198
if (beiscsi_ep->phba != phba) {
196199
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
197200
"BS_%d : beiscsi_ep->hba=%p not equal to phba=%p\n",
198201
beiscsi_ep->phba, phba);
199-
200-
return -EEXIST;
202+
rc = -EEXIST;
203+
goto put_ep;
201204
}
202205
cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid);
203206
if (phba->conn_table[cri_index]) {
@@ -209,7 +212,8 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
209212
beiscsi_ep->ep_cid,
210213
beiscsi_conn,
211214
phba->conn_table[cri_index]);
212-
return -EINVAL;
215+
rc = -EINVAL;
216+
goto put_ep;
213217
}
214218
}
215219

@@ -226,7 +230,10 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
226230
"BS_%d : cid %d phba->conn_table[%u]=%p\n",
227231
beiscsi_ep->ep_cid, cri_index, beiscsi_conn);
228232
phba->conn_table[cri_index] = beiscsi_conn;
229-
return 0;
233+
234+
put_ep:
235+
iscsi_put_endpoint(ep);
236+
return rc;
230237
}
231238

232239
static int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba)

drivers/scsi/bnx2i/bnx2i_iscsi.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,17 +1420,23 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
14201420
* Forcefully terminate all in progress connection recovery at the
14211421
* earliest, either in bind(), send_pdu(LOGIN), or conn_start()
14221422
*/
1423-
if (bnx2i_adapter_ready(hba))
1424-
return -EIO;
1423+
if (bnx2i_adapter_ready(hba)) {
1424+
ret_code = -EIO;
1425+
goto put_ep;
1426+
}
14251427

14261428
bnx2i_ep = ep->dd_data;
14271429
if ((bnx2i_ep->state == EP_STATE_TCP_FIN_RCVD) ||
1428-
(bnx2i_ep->state == EP_STATE_TCP_RST_RCVD))
1430+
(bnx2i_ep->state == EP_STATE_TCP_RST_RCVD)) {
14291431
/* Peer disconnect via' FIN or RST */
1430-
return -EINVAL;
1432+
ret_code = -EINVAL;
1433+
goto put_ep;
1434+
}
14311435

1432-
if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
1433-
return -EINVAL;
1436+
if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) {
1437+
ret_code = -EINVAL;
1438+
goto put_ep;
1439+
}
14341440

14351441
if (bnx2i_ep->hba != hba) {
14361442
/* Error - TCP connection does not belong to this device
@@ -1441,7 +1447,8 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
14411447
iscsi_conn_printk(KERN_ALERT, cls_conn->dd_data,
14421448
"belong to hba (%s)\n",
14431449
hba->netdev->name);
1444-
return -EEXIST;
1450+
ret_code = -EEXIST;
1451+
goto put_ep;
14451452
}
14461453
bnx2i_ep->conn = bnx2i_conn;
14471454
bnx2i_conn->ep = bnx2i_ep;
@@ -1458,6 +1465,8 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
14581465
bnx2i_put_rq_buf(bnx2i_conn, 0);
14591466

14601467
bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE);
1468+
put_ep:
1469+
iscsi_put_endpoint(ep);
14611470
return ret_code;
14621471
}
14631472

drivers/scsi/cxgbi/libcxgbi.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2690,11 +2690,13 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
26902690
err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid,
26912691
ppm->tformat.pgsz_idx_dflt);
26922692
if (err < 0)
2693-
return err;
2693+
goto put_ep;
26942694

26952695
err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
2696-
if (err)
2697-
return -EINVAL;
2696+
if (err) {
2697+
err = -EINVAL;
2698+
goto put_ep;
2699+
}
26982700

26992701
/* calculate the tag idx bits needed for this conn based on cmds_max */
27002702
cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1;
@@ -2715,7 +2717,9 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
27152717
/* init recv engine */
27162718
iscsi_tcp_hdr_recv_prep(tcp_conn);
27172719

2718-
return 0;
2720+
put_ep:
2721+
iscsi_put_endpoint(ep);
2722+
return err;
27192723
}
27202724
EXPORT_SYMBOL_GPL(cxgbi_bind_conn);
27212725

drivers/scsi/qedi/qedi_iscsi.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -377,18 +377,24 @@ static int qedi_conn_bind(struct iscsi_cls_session *cls_session,
377377
struct qedi_ctx *qedi = iscsi_host_priv(shost);
378378
struct qedi_endpoint *qedi_ep;
379379
struct iscsi_endpoint *ep;
380+
int rc = 0;
380381

381382
ep = iscsi_lookup_endpoint(transport_fd);
382383
if (!ep)
383384
return -EINVAL;
384385

385386
qedi_ep = ep->dd_data;
386387
if ((qedi_ep->state == EP_STATE_TCP_FIN_RCVD) ||
387-
(qedi_ep->state == EP_STATE_TCP_RST_RCVD))
388-
return -EINVAL;
388+
(qedi_ep->state == EP_STATE_TCP_RST_RCVD)) {
389+
rc = -EINVAL;
390+
goto put_ep;
391+
}
392+
393+
if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) {
394+
rc = -EINVAL;
395+
goto put_ep;
396+
}
389397

390-
if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
391-
return -EINVAL;
392398

393399
qedi_ep->conn = qedi_conn;
394400
qedi_conn->ep = qedi_ep;
@@ -398,13 +404,18 @@ static int qedi_conn_bind(struct iscsi_cls_session *cls_session,
398404
qedi_conn->cmd_cleanup_req = 0;
399405
qedi_conn->cmd_cleanup_cmpl = 0;
400406

401-
if (qedi_bind_conn_to_iscsi_cid(qedi, qedi_conn))
402-
return -EINVAL;
407+
if (qedi_bind_conn_to_iscsi_cid(qedi, qedi_conn)) {
408+
rc = -EINVAL;
409+
goto put_ep;
410+
}
411+
403412

404413
spin_lock_init(&qedi_conn->tmf_work_lock);
405414
INIT_LIST_HEAD(&qedi_conn->tmf_work_list);
406415
init_waitqueue_head(&qedi_conn->wait_queue);
407-
return 0;
416+
put_ep:
417+
iscsi_put_endpoint(ep);
418+
return rc;
408419
}
409420

410421
static int qedi_iscsi_update_conn(struct qedi_ctx *qedi,

drivers/scsi/qla4xxx/ql4_os.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3235,6 +3235,7 @@ static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,
32353235
conn = cls_conn->dd_data;
32363236
qla_conn = conn->dd_data;
32373237
qla_conn->qla_ep = ep->dd_data;
3238+
iscsi_put_endpoint(ep);
32383239
return 0;
32393240
}
32403241

drivers/scsi/scsi_transport_iscsi.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -266,23 +266,28 @@ void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
266266
}
267267
EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
268268

269+
void iscsi_put_endpoint(struct iscsi_endpoint *ep)
270+
{
271+
put_device(&ep->dev);
272+
}
273+
EXPORT_SYMBOL_GPL(iscsi_put_endpoint);
274+
275+
/**
276+
* iscsi_lookup_endpoint - get ep from handle
277+
* @handle: endpoint handle
278+
*
279+
* Caller must do a iscsi_put_endpoint.
280+
*/
269281
struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
270282
{
271-
struct iscsi_endpoint *ep;
272283
struct device *dev;
273284

274285
dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
275286
iscsi_match_epid);
276287
if (!dev)
277288
return NULL;
278289

279-
ep = iscsi_dev_to_endpoint(dev);
280-
/*
281-
* we can drop this now because the interface will prevent
282-
* removals and lookups from racing.
283-
*/
284-
put_device(dev);
285-
return ep;
290+
return iscsi_dev_to_endpoint(dev);
286291
}
287292
EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
288293

@@ -2990,6 +2995,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
29902995
}
29912996

29922997
transport->ep_disconnect(ep);
2998+
iscsi_put_endpoint(ep);
29932999
return 0;
29943000
}
29953001

@@ -3015,6 +3021,7 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
30153021

30163022
ev->r.retcode = transport->ep_poll(ep,
30173023
ev->u.ep_poll.timeout_ms);
3024+
iscsi_put_endpoint(ep);
30183025
break;
30193026
case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
30203027
rc = iscsi_if_ep_disconnect(transport,
@@ -3698,6 +3705,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
36983705
ev->u.c_bound_session.initial_cmdsn,
36993706
ev->u.c_bound_session.cmds_max,
37003707
ev->u.c_bound_session.queue_depth);
3708+
iscsi_put_endpoint(ep);
37013709
break;
37023710
case ISCSI_UEVENT_DESTROY_SESSION:
37033711
session = iscsi_session_lookup(ev->u.d_session.sid);
@@ -3769,6 +3777,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
37693777
mutex_lock(&conn->ep_mutex);
37703778
conn->ep = ep;
37713779
mutex_unlock(&conn->ep_mutex);
3780+
iscsi_put_endpoint(ep);
37723781
} else
37733782
iscsi_cls_conn_printk(KERN_ERR, conn,
37743783
"Could not set ep conn "

include/scsi/scsi_transport_iscsi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time);
442442
extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size);
443443
extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep);
444444
extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle);
445+
extern void iscsi_put_endpoint(struct iscsi_endpoint *ep);
445446
extern int iscsi_block_scsi_eh(struct scsi_cmnd *cmd);
446447
extern struct iscsi_iface *iscsi_create_iface(struct Scsi_Host *shost,
447448
struct iscsi_transport *t,

0 commit comments

Comments
 (0)