lkml.org 
[lkml]   [2022]   [Aug]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 436/779] scsi: iscsi: Add helper to remove a session from the kernel
    Date
    From: Mike Christie <michael.christie@oracle.com>

    [ Upstream commit bb42856bfd54fda1cbc7c470fcf5db1596938f4f ]

    During qedi shutdown we need to stop the iSCSI layer from sending new nops
    as pings and from responding to target ones and make sure there is no
    running connection cleanups. Commit d1f2ce77638d ("scsi: qedi: Fix host
    removal with running sessions") converted the driver to use the libicsi
    helper to drive session removal, so the above issues could be handled. The
    problem is that during system shutdown iscsid will not be running so when
    we try to remove the root session we will hang waiting for userspace to
    reply.

    Add a helper that will drive the destruction of sessions like these during
    system shutdown.

    Link: https://lore.kernel.org/r/20220616222738.5722-5-michael.christie@oracle.com
    Tested-by: Nilesh Javali <njavali@marvell.com>
    Reviewed-by: Nilesh Javali <njavali@marvell.com>
    Signed-off-by: Mike Christie <michael.christie@oracle.com>
    Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/scsi/scsi_transport_iscsi.c | 49 +++++++++++++++++++++++++++++
    include/scsi/scsi_transport_iscsi.h | 1 +
    2 files changed, 50 insertions(+)

    diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
    index 671a03b80c30..f46ae5391758 100644
    --- a/drivers/scsi/scsi_transport_iscsi.c
    +++ b/drivers/scsi/scsi_transport_iscsi.c
    @@ -2360,6 +2360,55 @@ static void iscsi_cleanup_conn_work_fn(struct work_struct *work)
    ISCSI_DBG_TRANS_CONN(conn, "cleanup done.\n");
    }

    +static int iscsi_iter_force_destroy_conn_fn(struct device *dev, void *data)
    +{
    + struct iscsi_transport *transport;
    + struct iscsi_cls_conn *conn;
    +
    + if (!iscsi_is_conn_dev(dev))
    + return 0;
    +
    + conn = iscsi_dev_to_conn(dev);
    + transport = conn->transport;
    +
    + if (READ_ONCE(conn->state) != ISCSI_CONN_DOWN)
    + iscsi_if_stop_conn(conn, STOP_CONN_TERM);
    +
    + transport->destroy_conn(conn);
    + return 0;
    +}
    +
    +/**
    + * iscsi_force_destroy_session - destroy a session from the kernel
    + * @session: session to destroy
    + *
    + * Force the destruction of a session from the kernel. This should only be
    + * used when userspace is no longer running during system shutdown.
    + */
    +void iscsi_force_destroy_session(struct iscsi_cls_session *session)
    +{
    + struct iscsi_transport *transport = session->transport;
    + unsigned long flags;
    +
    + WARN_ON_ONCE(system_state == SYSTEM_RUNNING);
    +
    + spin_lock_irqsave(&sesslock, flags);
    + if (list_empty(&session->sess_list)) {
    + spin_unlock_irqrestore(&sesslock, flags);
    + /*
    + * Conn/ep is already freed. Session is being torn down via
    + * async path. For shutdown we don't care about it so return.
    + */
    + return;
    + }
    + spin_unlock_irqrestore(&sesslock, flags);
    +
    + device_for_each_child(&session->dev, NULL,
    + iscsi_iter_force_destroy_conn_fn);
    + transport->destroy_session(session);
    +}
    +EXPORT_SYMBOL_GPL(iscsi_force_destroy_session);
    +
    void iscsi_free_session(struct iscsi_cls_session *session)
    {
    ISCSI_DBG_TRANS_SESSION(session, "Freeing session\n");
    diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
    index 3ecf9702287b..0f2f149ad916 100644
    --- a/include/scsi/scsi_transport_iscsi.h
    +++ b/include/scsi/scsi_transport_iscsi.h
    @@ -441,6 +441,7 @@ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
    struct iscsi_transport *t,
    int dd_size,
    unsigned int target_id);
    +extern void iscsi_force_destroy_session(struct iscsi_cls_session *session);
    extern void iscsi_remove_session(struct iscsi_cls_session *session);
    extern void iscsi_free_session(struct iscsi_cls_session *session);
    extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-08-15 21:12    [W:3.021 / U:0.132 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site