]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
scsi: iscsi: Rel ref after iscsi_lookup_endpoint()
authorMike Christie <michael.christie@oracle.com>
Tue, 25 May 2021 18:17:59 +0000 (13:17 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 Apr 2022 07:23:16 +0000 (09:23 +0200)
[ Upstream commit 9e5fe1700896c85040943fdc0d3fee0dd3e0d36f ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/infiniband/ulp/iser/iscsi_iser.c
drivers/scsi/be2iscsi/be_iscsi.c
drivers/scsi/bnx2i/bnx2i_iscsi.c
drivers/scsi/cxgbi/libcxgbi.c
drivers/scsi/qedi/qedi_iscsi.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi_transport_iscsi.c
include/scsi/scsi_transport_iscsi.h

index 8857d83227104976b53ffc8d9a4c60ebcac17122..a16e066989fa5b1428ae54b3c73e3f6ae1e94022 100644 (file)
@@ -499,6 +499,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;
 }
index a13c203ef7a9a88260cfb430ab4f537498f17963..c4881657a807b6fd83647bd57aae8efcd9ead377 100644 (file)
@@ -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)
index 173d8c6a8cbf7515feaa9cd83f47270e37efc1a9..649664dc6da445a9b81095999c066c2ab9b78667 100644 (file)
@@ -1422,17 +1422,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
@@ -1443,7 +1449,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;
@@ -1460,6 +1467,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;
 }
 
index ecb134b4699f2378796c78eab1c71fdf40d5ce2d..506b561670af0f917b1d25ed4cb90b6eaef10b4e 100644 (file)
@@ -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);
 
index 8f8036ae9a5672db61d4ef0f9bee53524f1a7dfa..5f7e62f19d83a057e8f378d3eb062c493c48c6f8 100644 (file)
@@ -387,6 +387,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)
@@ -394,11 +395,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;
@@ -408,13 +414,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,
index a8b8bf118c76e887683e4bf7d2d008d9cd56390f..8d82d2a83059d587944005328df8e32c00aafa72 100644 (file)
@@ -3238,6 +3238,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;
 }
 
index ed0c7e812445fd4612f7eab7da8ed73beba3f622..dea0944ebbfa061bf8855cc50372be3501999c39 100644 (file)
@@ -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);
 
@@ -2983,6 +2988,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
        }
 
        transport->ep_disconnect(ep);
+       iscsi_put_endpoint(ep);
        return 0;
 }
 
@@ -3008,6 +3014,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,
@@ -3691,6 +3698,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);
@@ -3762,6 +3770,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 "
index eb6ed499324d384b02803367fa977426dcb1182e..09992f019dc9d6d523053fff1845c92ca9b19f99 100644 (file)
@@ -444,6 +444,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,