]> git.baikalelectronics.ru Git - kernel.git/commitdiff
scsi: iscsi: ql4xxx: Use per-session workqueue for unbinding
authorMike Christie <michael.christie@oracle.com>
Sat, 26 Feb 2022 23:04:33 +0000 (17:04 -0600)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 2 Mar 2022 04:56:28 +0000 (23:56 -0500)
We currently allocate a workqueue per host and only use it for removing the
target. For the session per host case we could be using this workqueue to
be able to do recoveries (block, unblock, timeout handling) in parallel. To
also allow offload drivers to do their session recoveries in parallel, this
drops the per host workqueue and replaces it with a per session one.

Link: https://lore.kernel.org/r/20220226230435.38733-5-michael.christie@oracle.com
Reviewed-by: Lee Duncan <lduncan@suse.com>
Reviewed-by: Chris Leech <cleech@redhat.com>
Signed-off-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi_transport_iscsi.c
include/scsi/scsi_transport_iscsi.h

index b49c38416fb9c4642271f3486bb40727ba615dc6..3f6cb2a5c2c28bcad03be2a3d400fc7a83470093 100644 (file)
@@ -5096,7 +5096,7 @@ int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session)
                ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
                           " start scan\n", ha->host_no, __func__,
                           ddb_entry->fw_ddb_index);
-               scsi_queue_work(ha->host, &ddb_entry->sess->scan_work);
+               queue_work(ddb_entry->sess->workq, &ddb_entry->sess->scan_work);
        }
        return QLA_SUCCESS;
 }
index 05cd4bca979e4643f0b12795331f451bfa2ad3d2..ecb592a70e03eaccf9ced2e7479f32e9f1c89eb4 100644 (file)
@@ -2032,19 +2032,27 @@ EXPORT_SYMBOL_GPL(iscsi_alloc_session);
 
 int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
 {
+       struct Scsi_Host *shost = iscsi_session_to_shost(session);
        unsigned long flags;
        int id = 0;
        int err;
 
        session->sid = atomic_add_return(1, &iscsi_session_nr);
 
+       session->workq = alloc_workqueue("iscsi_ctrl_%d:%d",
+                       WQ_SYSFS | WQ_MEM_RECLAIM | WQ_UNBOUND, 0,
+                       shost->host_no, session->sid);
+       if (!session->workq)
+               return -ENOMEM;
+
        if (target_id == ISCSI_MAX_TARGET) {
                id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL);
 
                if (id < 0) {
                        iscsi_cls_session_printk(KERN_ERR, session,
                                        "Failure in Target ID Allocation\n");
-                       return id;
+                       err = id;
+                       goto destroy_wq;
                }
                session->target_id = (unsigned int)id;
                session->ida_used = true;
@@ -2078,7 +2086,8 @@ release_dev:
 release_ida:
        if (session->ida_used)
                ida_simple_remove(&iscsi_sess_ida, session->target_id);
-
+destroy_wq:
+       destroy_workqueue(session->workq);
        return err;
 }
 EXPORT_SYMBOL_GPL(iscsi_add_session);
@@ -2177,6 +2186,8 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
 
        transport_unregister_device(&session->dev);
 
+       destroy_workqueue(session->workq);
+
        ISCSI_DBG_TRANS_SESSION(session, "Completing session removal\n");
        device_del(&session->dev);
 }
@@ -3833,8 +3844,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
        case ISCSI_UEVENT_UNBIND_SESSION:
                session = iscsi_session_lookup(ev->u.d_session.sid);
                if (session)
-                       scsi_queue_work(iscsi_session_to_shost(session),
-                                       &session->unbind_work);
+                       queue_work(session->workq, &session->unbind_work);
                else
                        err = -EINVAL;
                break;
@@ -4707,7 +4717,6 @@ iscsi_register_transport(struct iscsi_transport *tt)
        INIT_LIST_HEAD(&priv->list);
        priv->iscsi_transport = tt;
        priv->t.user_scan = iscsi_user_scan;
-       priv->t.create_work_queue = 1;
 
        priv->dev.class = &iscsi_transport_class;
        dev_set_name(&priv->dev, "%s", tt->name);
index 90b55db46d7c2fa34d77644eb1d5b465da4cec9c..7a0d24d3b916ab2281b90dccaf69300245f21fcc 100644 (file)
@@ -251,6 +251,8 @@ struct iscsi_cls_session {
        bool recovery_tmo_sysfs_override;
        struct delayed_work recovery_work;
 
+       struct workqueue_struct *workq;
+
        unsigned int target_id;
        bool ida_used;