On 2/26/22 3:04 PM, Mike Christie wrote: > 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. > > Signed-off-by: Mike Christie <michael.christie@xxxxxxxxxx> > --- > drivers/scsi/qla4xxx/ql4_os.c | 2 +- > drivers/scsi/scsi_transport_iscsi.c | 19 ++++++++++++++----- > include/scsi/scsi_transport_iscsi.h | 2 ++ > 3 files changed, 17 insertions(+), 6 deletions(-) > > diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c > index 0ae936d839f1..955d8cb675f1 100644 > --- a/drivers/scsi/qla4xxx/ql4_os.c > +++ b/drivers/scsi/qla4xxx/ql4_os.c > @@ -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; > } > diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c > index 05cd4bca979e..ecb592a70e03 100644 > --- a/drivers/scsi/scsi_transport_iscsi.c > +++ b/drivers/scsi/scsi_transport_iscsi.c > @@ -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 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) > 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); > diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h > index 90b55db46d7c..7a0d24d3b916 100644 > --- a/include/scsi/scsi_transport_iscsi.h > +++ b/include/scsi/scsi_transport_iscsi.h > @@ -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; > Reviewed-by: Chris Leech <cleech@xxxxxxxxxx>