mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
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/20210525181821.7617-7-michael.christie@oracle.com Reviewed-by: Lee Duncan <lduncan@suse.com> Signed-off-by: Mike Christie <michael.christie@oracle.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
b25b957d2d
commit
9e5fe17008
@ -506,6 +506,7 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
iser_conn->iscsi_conn = conn;
|
||||
|
||||
out:
|
||||
iscsi_put_endpoint(ep);
|
||||
mutex_unlock(&iser_conn->state_mutex);
|
||||
return error;
|
||||
}
|
||||
|
@ -182,6 +182,7 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
struct beiscsi_endpoint *beiscsi_ep;
|
||||
struct iscsi_endpoint *ep;
|
||||
uint16_t cri_index;
|
||||
int rc = 0;
|
||||
|
||||
ep = iscsi_lookup_endpoint(transport_fd);
|
||||
if (!ep)
|
||||
@ -189,15 +190,17 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
|
||||
beiscsi_ep = ep->dd_data;
|
||||
|
||||
if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
|
||||
return -EINVAL;
|
||||
if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) {
|
||||
rc = -EINVAL;
|
||||
goto put_ep;
|
||||
}
|
||||
|
||||
if (beiscsi_ep->phba != phba) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : beiscsi_ep->hba=%p not equal to phba=%p\n",
|
||||
beiscsi_ep->phba, phba);
|
||||
|
||||
return -EEXIST;
|
||||
rc = -EEXIST;
|
||||
goto put_ep;
|
||||
}
|
||||
cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid);
|
||||
if (phba->conn_table[cri_index]) {
|
||||
@ -209,7 +212,8 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
beiscsi_ep->ep_cid,
|
||||
beiscsi_conn,
|
||||
phba->conn_table[cri_index]);
|
||||
return -EINVAL;
|
||||
rc = -EINVAL;
|
||||
goto put_ep;
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,7 +230,10 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
"BS_%d : cid %d phba->conn_table[%u]=%p\n",
|
||||
beiscsi_ep->ep_cid, cri_index, beiscsi_conn);
|
||||
phba->conn_table[cri_index] = beiscsi_conn;
|
||||
return 0;
|
||||
|
||||
put_ep:
|
||||
iscsi_put_endpoint(ep);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba)
|
||||
|
@ -1420,17 +1420,23 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
* Forcefully terminate all in progress connection recovery at the
|
||||
* earliest, either in bind(), send_pdu(LOGIN), or conn_start()
|
||||
*/
|
||||
if (bnx2i_adapter_ready(hba))
|
||||
return -EIO;
|
||||
if (bnx2i_adapter_ready(hba)) {
|
||||
ret_code = -EIO;
|
||||
goto put_ep;
|
||||
}
|
||||
|
||||
bnx2i_ep = ep->dd_data;
|
||||
if ((bnx2i_ep->state == EP_STATE_TCP_FIN_RCVD) ||
|
||||
(bnx2i_ep->state == EP_STATE_TCP_RST_RCVD))
|
||||
(bnx2i_ep->state == EP_STATE_TCP_RST_RCVD)) {
|
||||
/* Peer disconnect via' FIN or RST */
|
||||
return -EINVAL;
|
||||
ret_code = -EINVAL;
|
||||
goto put_ep;
|
||||
}
|
||||
|
||||
if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
|
||||
return -EINVAL;
|
||||
if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) {
|
||||
ret_code = -EINVAL;
|
||||
goto put_ep;
|
||||
}
|
||||
|
||||
if (bnx2i_ep->hba != hba) {
|
||||
/* Error - TCP connection does not belong to this device
|
||||
@ -1441,7 +1447,8 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
iscsi_conn_printk(KERN_ALERT, cls_conn->dd_data,
|
||||
"belong to hba (%s)\n",
|
||||
hba->netdev->name);
|
||||
return -EEXIST;
|
||||
ret_code = -EEXIST;
|
||||
goto put_ep;
|
||||
}
|
||||
bnx2i_ep->conn = bnx2i_conn;
|
||||
bnx2i_conn->ep = bnx2i_ep;
|
||||
@ -1458,6 +1465,8 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
bnx2i_put_rq_buf(bnx2i_conn, 0);
|
||||
|
||||
bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE);
|
||||
put_ep:
|
||||
iscsi_put_endpoint(ep);
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
|
@ -2690,11 +2690,13 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
|
||||
err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid,
|
||||
ppm->tformat.pgsz_idx_dflt);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto put_ep;
|
||||
|
||||
err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
|
||||
if (err)
|
||||
return -EINVAL;
|
||||
if (err) {
|
||||
err = -EINVAL;
|
||||
goto put_ep;
|
||||
}
|
||||
|
||||
/* calculate the tag idx bits needed for this conn based on cmds_max */
|
||||
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,
|
||||
/* init recv engine */
|
||||
iscsi_tcp_hdr_recv_prep(tcp_conn);
|
||||
|
||||
return 0;
|
||||
put_ep:
|
||||
iscsi_put_endpoint(ep);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cxgbi_bind_conn);
|
||||
|
||||
|
@ -377,6 +377,7 @@ static int qedi_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
struct qedi_ctx *qedi = iscsi_host_priv(shost);
|
||||
struct qedi_endpoint *qedi_ep;
|
||||
struct iscsi_endpoint *ep;
|
||||
int rc = 0;
|
||||
|
||||
ep = iscsi_lookup_endpoint(transport_fd);
|
||||
if (!ep)
|
||||
@ -384,11 +385,16 @@ static int qedi_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
|
||||
qedi_ep = ep->dd_data;
|
||||
if ((qedi_ep->state == EP_STATE_TCP_FIN_RCVD) ||
|
||||
(qedi_ep->state == EP_STATE_TCP_RST_RCVD))
|
||||
return -EINVAL;
|
||||
(qedi_ep->state == EP_STATE_TCP_RST_RCVD)) {
|
||||
rc = -EINVAL;
|
||||
goto put_ep;
|
||||
}
|
||||
|
||||
if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) {
|
||||
rc = -EINVAL;
|
||||
goto put_ep;
|
||||
}
|
||||
|
||||
if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
|
||||
return -EINVAL;
|
||||
|
||||
qedi_ep->conn = qedi_conn;
|
||||
qedi_conn->ep = qedi_ep;
|
||||
@ -398,13 +404,18 @@ static int qedi_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
qedi_conn->cmd_cleanup_req = 0;
|
||||
qedi_conn->cmd_cleanup_cmpl = 0;
|
||||
|
||||
if (qedi_bind_conn_to_iscsi_cid(qedi, qedi_conn))
|
||||
return -EINVAL;
|
||||
if (qedi_bind_conn_to_iscsi_cid(qedi, qedi_conn)) {
|
||||
rc = -EINVAL;
|
||||
goto put_ep;
|
||||
}
|
||||
|
||||
|
||||
spin_lock_init(&qedi_conn->tmf_work_lock);
|
||||
INIT_LIST_HEAD(&qedi_conn->tmf_work_list);
|
||||
init_waitqueue_head(&qedi_conn->wait_queue);
|
||||
return 0;
|
||||
put_ep:
|
||||
iscsi_put_endpoint(ep);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qedi_iscsi_update_conn(struct qedi_ctx *qedi,
|
||||
|
@ -3235,6 +3235,7 @@ static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
conn = cls_conn->dd_data;
|
||||
qla_conn = conn->dd_data;
|
||||
qla_conn->qla_ep = ep->dd_data;
|
||||
iscsi_put_endpoint(ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -266,9 +266,20 @@ void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
|
||||
|
||||
void iscsi_put_endpoint(struct iscsi_endpoint *ep)
|
||||
{
|
||||
put_device(&ep->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_put_endpoint);
|
||||
|
||||
/**
|
||||
* iscsi_lookup_endpoint - get ep from handle
|
||||
* @handle: endpoint handle
|
||||
*
|
||||
* Caller must do a iscsi_put_endpoint.
|
||||
*/
|
||||
struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
|
||||
{
|
||||
struct iscsi_endpoint *ep;
|
||||
struct device *dev;
|
||||
|
||||
dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
|
||||
@ -276,13 +287,7 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
ep = iscsi_dev_to_endpoint(dev);
|
||||
/*
|
||||
* we can drop this now because the interface will prevent
|
||||
* removals and lookups from racing.
|
||||
*/
|
||||
put_device(dev);
|
||||
return ep;
|
||||
return iscsi_dev_to_endpoint(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
|
||||
|
||||
@ -2990,6 +2995,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
|
||||
}
|
||||
|
||||
transport->ep_disconnect(ep);
|
||||
iscsi_put_endpoint(ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3015,6 +3021,7 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
|
||||
|
||||
ev->r.retcode = transport->ep_poll(ep,
|
||||
ev->u.ep_poll.timeout_ms);
|
||||
iscsi_put_endpoint(ep);
|
||||
break;
|
||||
case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
|
||||
rc = iscsi_if_ep_disconnect(transport,
|
||||
@ -3698,6 +3705,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
|
||||
ev->u.c_bound_session.initial_cmdsn,
|
||||
ev->u.c_bound_session.cmds_max,
|
||||
ev->u.c_bound_session.queue_depth);
|
||||
iscsi_put_endpoint(ep);
|
||||
break;
|
||||
case ISCSI_UEVENT_DESTROY_SESSION:
|
||||
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)
|
||||
mutex_lock(&conn->ep_mutex);
|
||||
conn->ep = ep;
|
||||
mutex_unlock(&conn->ep_mutex);
|
||||
iscsi_put_endpoint(ep);
|
||||
} else
|
||||
iscsi_cls_conn_printk(KERN_ERR, conn,
|
||||
"Could not set ep conn "
|
||||
|
@ -442,6 +442,7 @@ extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time);
|
||||
extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size);
|
||||
extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep);
|
||||
extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle);
|
||||
extern void iscsi_put_endpoint(struct iscsi_endpoint *ep);
|
||||
extern int iscsi_block_scsi_eh(struct scsi_cmnd *cmd);
|
||||
extern struct iscsi_iface *iscsi_create_iface(struct Scsi_Host *shost,
|
||||
struct iscsi_transport *t,
|
||||
|
Loading…
Reference in New Issue
Block a user