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");
 
                                                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_alloc_conn(struct iscsi_cls_session *sess,