[SCSI] scsi_transport_iscsi: Add conn login, kernel to user, event to support offload...
authorManish Rangankar <manish.rangankar@qlogic.com>
Mon, 25 Jul 2011 18:48:52 +0000 (13:48 -0500)
committerJames Bottomley <JBottomley@Parallels.com>
Sat, 27 Aug 2011 14:36:23 +0000 (08:36 -0600)
Offload drivers like qla4xxx will offload the sending of the login/logout
pdus still, so this patch adds iscsi_conn_login_event which is
used by these types of drivers to notify userspace that the connection
has changed state.

It also adds a iscsi_is_session_online helper so the lld
can query the sessions state field.

Signed-off-by: Manish Rangankar <manish.rangankar@qlogic.com>
Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/scsi_transport_iscsi.c
include/scsi/iscsi_if.h
include/scsi/scsi_transport_iscsi.h

index cde679f1b01d14778fb342d5539b96a003436a25..b85f8a4b89626d7f46b0af2d39dbc4a729ed068b 100644 (file)
@@ -693,6 +693,19 @@ int iscsi_session_chkready(struct iscsi_cls_session *session)
 }
 EXPORT_SYMBOL_GPL(iscsi_session_chkready);
 
+int iscsi_is_session_online(struct iscsi_cls_session *session)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&session->lock, flags);
+       if (session->state == ISCSI_SESSION_LOGGED_IN)
+               ret = 1;
+       spin_unlock_irqrestore(&session->lock, flags);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(iscsi_is_session_online);
+
 static void iscsi_session_release(struct device *dev)
 {
        struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
@@ -1433,6 +1446,40 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_error_event);
 
+void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
+                           enum iscsi_conn_state state)
+{
+       struct nlmsghdr *nlh;
+       struct sk_buff  *skb;
+       struct iscsi_uevent *ev;
+       struct iscsi_internal *priv;
+       int len = NLMSG_SPACE(sizeof(*ev));
+
+       priv = iscsi_if_transport_lookup(conn->transport);
+       if (!priv)
+               return;
+
+       skb = alloc_skb(len, GFP_ATOMIC);
+       if (!skb) {
+               iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
+                                     "conn login (%d)\n", state);
+               return;
+       }
+
+       nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
+       ev = NLMSG_DATA(nlh);
+       ev->transport_handle = iscsi_handle(conn->transport);
+       ev->type = ISCSI_KEVENT_CONN_LOGIN_STATE;
+       ev->r.conn_login.state = state;
+       ev->r.conn_login.cid = conn->cid;
+       ev->r.conn_login.sid = iscsi_conn_get_sid(conn);
+       iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
+
+       iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn login (%d)\n",
+                             state);
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_login_event);
+
 static int
 iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi,
                    void *payload, int size)
index d3f256a232f8a5062a95207c74efcf24ce5911d3..629ca42dfe75b32123c1279c1d189c87ee126998 100644 (file)
@@ -71,6 +71,7 @@ enum iscsi_uevent_e {
 
        ISCSI_KEVENT_PATH_REQ           = KEVENT_BASE + 7,
        ISCSI_KEVENT_IF_DOWN            = KEVENT_BASE + 8,
+       ISCSI_KEVENT_CONN_LOGIN_STATE   = KEVENT_BASE + 9,
 };
 
 enum iscsi_tgt_dscvr {
@@ -198,6 +199,11 @@ struct iscsi_uevent {
                        uint32_t        cid;
                        uint64_t        recv_handle;
                } recv_req;
+               struct msg_conn_login {
+                       uint32_t        sid;
+                       uint32_t        cid;
+                       uint32_t        state; /* enum iscsi_conn_state */
+               } conn_login;
                struct msg_conn_error {
                        uint32_t        sid;
                        uint32_t        cid;
@@ -309,6 +315,16 @@ enum iscsi_net_param {
        ISCSI_NET_PARAM_IFACE_NAME              = 17,
 };
 
+enum iscsi_conn_state {
+       ISCSI_CONN_STATE_FREE,
+       ISCSI_CONN_STATE_XPT_WAIT,
+       ISCSI_CONN_STATE_IN_LOGIN,
+       ISCSI_CONN_STATE_LOGGED_IN,
+       ISCSI_CONN_STATE_IN_LOGOUT,
+       ISCSI_CONN_STATE_LOGOUT_REQUESTED,
+       ISCSI_CONN_STATE_CLEANUP_WAIT,
+};
+
 /*
  * Common error codes
  */
@@ -421,6 +437,7 @@ enum iscsi_host_param {
 #define CAP_DIGEST_OFFLOAD     0x1000  /* offload hdr and data digests */
 #define CAP_PADDING_OFFLOAD    0x2000  /* offload padding insertion, removal,
                                         and verification */
+#define CAP_LOGIN_OFFLOAD      0x4000  /* offload session login */
 
 /*
  * These flags describes reason of stop_conn() call
index 4a3edeeae8f655c83e042fe1aa635a2798f68f61..3389cd5ea94ca9a21501ea9582abb1f8556427f3 100644 (file)
@@ -156,6 +156,8 @@ extern int iscsi_unregister_transport(struct iscsi_transport *tt);
  */
 extern void iscsi_conn_error_event(struct iscsi_cls_conn *conn,
                                   enum iscsi_err error);
+extern void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
+                                  enum iscsi_conn_state state);
 extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
                          char *data, uint32_t data_size);
 
@@ -268,6 +270,7 @@ struct iscsi_iface {
        dev_printk(prefix, &(_cls_conn)->dev, fmt, ##a)
 
 extern int iscsi_session_chkready(struct iscsi_cls_session *session);
+extern int iscsi_is_session_online(struct iscsi_cls_session *session);
 extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost,
                                struct iscsi_transport *transport, int dd_size);
 extern int iscsi_add_session(struct iscsi_cls_session *session,