On Friday, January 17, 2020 at 3:33:35 PM UTC-8, Gabriel Krisman Bertazi 
wrote:
>
> From: Frank Mayhar <[email protected]> 
>
> iSCSI session destruction can be arbitrarily slow, since it might 
> require network operations and serialization inside the scsi layer. 
> This patch adds a new user event to trigger the destruction work 
> asynchronously, releasing the rx_queue_mutex as soon as the operation is 
> queued and before it is performed.  This change allow other operations 
> to run in other sessions in the meantime, removing one of the major 
> iSCSI bottlenecks for us. 
>
> To prevent the session from being used after the destruction request, we 
> remove it immediately from the sesslist. This simplifies the locking 
> required during the asynchronous removal. 
>
> Co-developed-by: Khazhismel Kumykov <[email protected]> 
> Signed-off-by: Khazhismel Kumykov <[email protected]> 
> Signed-off-by: Frank Mayhar <[email protected]> 
> Co-developed-by: Gabriel Krisman Bertazi <[email protected]> 
> Signed-off-by: Gabriel Krisman Bertazi <[email protected]> 
> --- 
>
> This patch requires a patch that just went upstream to apply cleanly. 
> it is ("iscsi: Don't destroy session if there are outstanding 
> connections"), which was just merged by Martin into 5.6/scsi-queue. 
> Please make sure you have it in your tree, otherwise this one won't 
> apply. 
>
>  drivers/scsi/scsi_transport_iscsi.c | 36 +++++++++++++++++++++++++++++ 
>  include/scsi/iscsi_if.h             |  1 + 
>  include/scsi/scsi_transport_iscsi.h |  1 + 
>  3 files changed, 38 insertions(+) 
>
> diff --git a/drivers/scsi/scsi_transport_iscsi.c 
> b/drivers/scsi/scsi_transport_iscsi.c 
> index ba6cfaf71aef..e9a8e0317b0d 100644 
> --- a/drivers/scsi/scsi_transport_iscsi.c 
> +++ b/drivers/scsi/scsi_transport_iscsi.c 
> @@ -95,6 +95,8 @@ static DECLARE_WORK(stop_conn_work, stop_conn_work_fn); 
>  static atomic_t iscsi_session_nr; /* sysfs session id for next new 
> session */ 
>  static struct workqueue_struct *iscsi_eh_timer_workq; 
>   
> +static struct workqueue_struct *iscsi_destroy_workq; 
> + 
>  static DEFINE_IDA(iscsi_sess_ida); 
>  /* 
>   * list of registered transports and lock that must 
> @@ -1615,6 +1617,7 @@ static struct sock *nls; 
>  static DEFINE_MUTEX(rx_queue_mutex); 
>   
>  static LIST_HEAD(sesslist); 
> +static LIST_HEAD(sessdestroylist); 
>  static DEFINE_SPINLOCK(sesslock); 
>  static LIST_HEAD(connlist); 
>  static LIST_HEAD(connlist_err); 
> @@ -2035,6 +2038,14 @@ static void __iscsi_unbind_session(struct 
> work_struct *work) 
>          ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n"); 
>  } 
>   
> +static void __iscsi_destroy_session(struct work_struct *work) 
> +{ 
> +        struct iscsi_cls_session *session = 
> +                container_of(work, struct iscsi_cls_session, 
> destroy_work); 
> + 
> +        session->transport->destroy_session(session); 
> +} 
> + 
>  struct iscsi_cls_session * 
>  iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport 
> *transport, 
>                      int dd_size) 
> @@ -2057,6 +2068,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct 
> iscsi_transport *transport, 
>          INIT_WORK(&session->block_work, __iscsi_block_session); 
>          INIT_WORK(&session->unbind_work, __iscsi_unbind_session); 
>          INIT_WORK(&session->scan_work, iscsi_scan_session); 
> +        INIT_WORK(&session->destroy_work, __iscsi_destroy_session); 
>          spin_lock_init(&session->lock); 
>   
>          /* this is released in the dev's release function */ 
> @@ -3617,6 +3629,23 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct 
> nlmsghdr *nlh, uint32_t *group) 
>                  else 
>                          transport->destroy_session(session); 
>                  break; 
> +        case ISCSI_UEVENT_DESTROY_SESSION_ASYNC: 
> +                session = iscsi_session_lookup(ev->u.d_session.sid); 
> +                if (!session) 
> +                        err = -EINVAL; 
> +                else if (iscsi_session_has_conns(ev->u.d_session.sid)) 
> +                        err = -EBUSY; 
> +                else { 
> +                        unsigned long flags; 
> + 
> +                        /* Prevent this session from being found again */ 
> +                        spin_lock_irqsave(&sesslock, flags); 
> +                        list_move(&session->sess_list, &sessdestroylist); 
> +                        spin_unlock_irqrestore(&sesslock, flags); 
> + 
> +                        queue_work(iscsi_destroy_workq, 
> &session->destroy_work); 
> +                } 
> +                break; 
>          case ISCSI_UEVENT_UNBIND_SESSION: 
>                  session = iscsi_session_lookup(ev->u.d_session.sid); 
>                  if (session) 
> @@ -4662,8 +4691,14 @@ static __init int iscsi_transport_init(void) 
>                  goto release_nls; 
>          } 
>   
> +        iscsi_destroy_workq = 
> create_singlethread_workqueue("iscsi_destroy"); 
> +        if (!iscsi_destroy_workq) 
> +                goto destroy_wq; 
> + 
>          return 0; 
>   
> +destroy_wq: 
> +        destroy_workqueue(iscsi_eh_timer_workq); 
>  release_nls: 
>          netlink_kernel_release(nls); 
>  unregister_flashnode_bus: 
> @@ -4685,6 +4720,7 @@ static __init int iscsi_transport_init(void) 
>   
>  static void __exit iscsi_transport_exit(void) 
>  { 
> +        destroy_workqueue(iscsi_destroy_workq); 
>          destroy_workqueue(iscsi_eh_timer_workq); 
>          netlink_kernel_release(nls); 
>          bus_unregister(&iscsi_flashnode_bus); 
> diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h 
> index 92b11c7e0b4f..deacaee53e61 100644 
> --- a/include/scsi/iscsi_if.h 
> +++ b/include/scsi/iscsi_if.h 
> @@ -60,6 +60,7 @@ enum iscsi_uevent_e { 
>          ISCSI_UEVENT_LOGOUT_FLASHNODE_SID        = UEVENT_BASE + 30, 
>          ISCSI_UEVENT_SET_CHAP                = UEVENT_BASE + 31, 
>          ISCSI_UEVENT_GET_HOST_STATS        = UEVENT_BASE + 32, 
> +        ISCSI_UEVENT_DESTROY_SESSION_ASYNC        = UEVENT_BASE + 33, 
>   
>          /* up events */ 
>          ISCSI_KEVENT_RECV_PDU                = KEVENT_BASE + 1, 
> diff --git a/include/scsi/scsi_transport_iscsi.h 
> b/include/scsi/scsi_transport_iscsi.h 
> index 2129dc9e2dec..fa8814245796 100644 
> --- a/include/scsi/scsi_transport_iscsi.h 
> +++ b/include/scsi/scsi_transport_iscsi.h 
> @@ -226,6 +226,7 @@ struct iscsi_cls_session { 
>          struct work_struct unblock_work; 
>          struct work_struct scan_work; 
>          struct work_struct unbind_work; 
> +        struct work_struct destroy_work; 
>   
>          /* recovery fields */ 
>          int recovery_tmo; 
> -- 
> 2.25.0.rc2 
>

Reviewed-by: Lee Duncan <[email protected]> 

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/open-iscsi/fb865b89-22a5-4d82-bceb-4b4075e7eacf%40googlegroups.com.

Reply via email to