Commit 5842ea36 authored by Mike Christie's avatar Mike Christie Committed by Martin K. Petersen

scsi: iscsi: ql4xxx: Use per-session workqueue for unbinding

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.comReviewed-by: default avatarLee Duncan <lduncan@suse.com>
Reviewed-by: default avatarChris Leech <cleech@redhat.com>
Signed-off-by: default avatarMike Christie <michael.christie@oracle.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent d8ec5d67
...@@ -5096,7 +5096,7 @@ int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session) ...@@ -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]" ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
" start scan\n", ha->host_no, __func__, " start scan\n", ha->host_no, __func__,
ddb_entry->fw_ddb_index); 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; return QLA_SUCCESS;
} }
......
...@@ -2032,19 +2032,27 @@ EXPORT_SYMBOL_GPL(iscsi_alloc_session); ...@@ -2032,19 +2032,27 @@ EXPORT_SYMBOL_GPL(iscsi_alloc_session);
int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) 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; unsigned long flags;
int id = 0; int id = 0;
int err; int err;
session->sid = atomic_add_return(1, &iscsi_session_nr); 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) { if (target_id == ISCSI_MAX_TARGET) {
id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL); id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL);
if (id < 0) { if (id < 0) {
iscsi_cls_session_printk(KERN_ERR, session, iscsi_cls_session_printk(KERN_ERR, session,
"Failure in Target ID Allocation\n"); "Failure in Target ID Allocation\n");
return id; err = id;
goto destroy_wq;
} }
session->target_id = (unsigned int)id; session->target_id = (unsigned int)id;
session->ida_used = true; session->ida_used = true;
...@@ -2078,7 +2086,8 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) ...@@ -2078,7 +2086,8 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
release_ida: release_ida:
if (session->ida_used) if (session->ida_used)
ida_simple_remove(&iscsi_sess_ida, session->target_id); ida_simple_remove(&iscsi_sess_ida, session->target_id);
destroy_wq:
destroy_workqueue(session->workq);
return err; return err;
} }
EXPORT_SYMBOL_GPL(iscsi_add_session); EXPORT_SYMBOL_GPL(iscsi_add_session);
...@@ -2177,6 +2186,8 @@ void iscsi_remove_session(struct iscsi_cls_session *session) ...@@ -2177,6 +2186,8 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
transport_unregister_device(&session->dev); transport_unregister_device(&session->dev);
destroy_workqueue(session->workq);
ISCSI_DBG_TRANS_SESSION(session, "Completing session removal\n"); ISCSI_DBG_TRANS_SESSION(session, "Completing session removal\n");
device_del(&session->dev); device_del(&session->dev);
} }
...@@ -3833,8 +3844,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) ...@@ -3833,8 +3844,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
case ISCSI_UEVENT_UNBIND_SESSION: case ISCSI_UEVENT_UNBIND_SESSION:
session = iscsi_session_lookup(ev->u.d_session.sid); session = iscsi_session_lookup(ev->u.d_session.sid);
if (session) if (session)
scsi_queue_work(iscsi_session_to_shost(session), queue_work(session->workq, &session->unbind_work);
&session->unbind_work);
else else
err = -EINVAL; err = -EINVAL;
break; break;
...@@ -4707,7 +4717,6 @@ iscsi_register_transport(struct iscsi_transport *tt) ...@@ -4707,7 +4717,6 @@ iscsi_register_transport(struct iscsi_transport *tt)
INIT_LIST_HEAD(&priv->list); INIT_LIST_HEAD(&priv->list);
priv->iscsi_transport = tt; priv->iscsi_transport = tt;
priv->t.user_scan = iscsi_user_scan; priv->t.user_scan = iscsi_user_scan;
priv->t.create_work_queue = 1;
priv->dev.class = &iscsi_transport_class; priv->dev.class = &iscsi_transport_class;
dev_set_name(&priv->dev, "%s", tt->name); dev_set_name(&priv->dev, "%s", tt->name);
......
...@@ -251,6 +251,8 @@ struct iscsi_cls_session { ...@@ -251,6 +251,8 @@ struct iscsi_cls_session {
bool recovery_tmo_sysfs_override; bool recovery_tmo_sysfs_override;
struct delayed_work recovery_work; struct delayed_work recovery_work;
struct workqueue_struct *workq;
unsigned int target_id; unsigned int target_id;
bool ida_used; bool ida_used;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment