diff mbox series

[4/6] scsi: iscsi, ql4: Use per session workqueue for unbinding.

Message ID 20220226230435.38733-5-michael.christie@oracle.com
State New
Headers show
Series iscsi: Speed up failover with lots of devices. | expand

Commit Message

Mike Christie Feb. 26, 2022, 11:04 p.m. UTC
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@oracle.com>
---
 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(-)

Comments

Lee Duncan Feb. 28, 2022, 6:19 p.m. UTC | #1
On 2/26/22 15:04, 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@oracle.com>
> ---
>   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: Lee Duncan <lduncan@suse.com>
Chris Leech Feb. 28, 2022, 8:07 p.m. UTC | #2
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@oracle.com>
> ---
>  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@redhat.com>
diff mbox series

Patch

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;