Various sysfs related fixes
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Mon, 2 Nov 2009 18:07:54 +0000 (18:07 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Mon, 2 Nov 2009 18:07:54 +0000 (18:07 +0000)
git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1309 d57e44dd-8a1f-0410-8b47-8ef2f437770f

iscsi-scst/include/iscsi_scst.h
iscsi-scst/kernel/conn.c
iscsi-scst/kernel/iscsi.h
iscsi-scst/kernel/nthread.c
iscsi-scst/kernel/session.c
iscsi-scst/usr/conn.c
iscsi-scst/usr/ctldev.c
iscsi-scst/usr/iscsid.h
scst/src/scst_sysfs.c

index 95e1ca3..b351fcb 100644 (file)
@@ -59,8 +59,6 @@ struct iscsi_kern_conn_info {
        u32 cid;
        u32 stat_sn;
        u32 exp_stat_sn;
-       int header_digest;
-       int data_digest;
        int fd;
 };
 
index e0f3292..ee8e419 100644 (file)
@@ -60,20 +60,6 @@ out:
        return pos;
 }
 
-static int print_digest_state(char *p, size_t size, unsigned long flags)
-{
-       int pos;
-
-       if (DIGEST_NONE & flags)
-               pos = scnprintf(p, size, "%s", "none");
-       else if (DIGEST_CRC32C & flags)
-               pos = scnprintf(p, size, "%s", "crc32c");
-       else
-               pos = scnprintf(p, size, "%s", "unknown");
-
-       return pos;
-}
-
 #ifdef CONFIG_SCST_PROC
 
 /* target_mutex supposed to be locked */
@@ -101,6 +87,8 @@ void conn_info_show(struct seq_file *seq, struct iscsi_session *session)
 #endif
                        break;
                default:
+                       snprintf(buf, sizeof(buf), "Unknown family %d",
+                               sk->sk_family);
                        break;
                }
                seq_printf(seq, "\t\tcid:%u ip:%s ", conn->cid, buf);
@@ -120,12 +108,16 @@ static int conn_free(struct iscsi_conn *conn);
 static void iscsi_conn_release(struct kobject *kobj)
 {
        struct iscsi_conn *conn;
+       struct iscsi_target *target;
 
        TRACE_ENTRY();
 
        conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
+       target = conn->target;
 
+       mutex_lock(&target->target_mutex);
        conn_free(conn);
+       mutex_unlock(&target->target_mutex);
 
        TRACE_EXIT();
        return;
@@ -136,26 +128,41 @@ static struct kobj_type iscsi_conn_ktype = {
        .release = iscsi_conn_release,
 };
 
-static ssize_t iscsi_conn_cid_show(struct kobject *kobj,
-       struct kobj_attribute *attr, char *buf)
+static ssize_t iscsi_get_initiator_ip(struct iscsi_conn *conn,
+       char *buf, int size)
 {
        int pos;
-       struct iscsi_conn *conn;
+       struct sock *sk;
 
        TRACE_ENTRY();
 
-       conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
-
-       pos = sprintf(buf, "%u", conn->cid);
+       sk = conn->sock->sk;
+       switch (sk->sk_family) {
+       case AF_INET:
+               pos = scnprintf(buf, size,
+                        "%u.%u.%u.%u", NIPQUAD(inet_sk(sk)->daddr));
+               break;
+       case AF_INET6:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+               pos = scnprintf(buf, size,
+                        "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
+                        NIP6(inet6_sk(sk)->daddr));
+#else
+               pos = scnprintf(buf, size, "[%p6]",
+                       &inet6_sk(sk)->daddr);
+#endif
+               break;
+       default:
+               pos = scnprintf(buf, size, "Unknown family %d",
+                       sk->sk_family);
+               break;
+       }
 
        TRACE_EXIT_RES(pos);
        return pos;
 }
 
-static struct kobj_attribute iscsi_conn_cid_attr =
-       __ATTR(cid, S_IRUGO, iscsi_conn_cid_show, NULL);
-
-static ssize_t iscsi_conn_state_show(struct kobject *kobj,
+static ssize_t iscsi_conn_ip_show(struct kobject *kobj,
        struct kobj_attribute *attr, char *buf)
 {
        int pos;
@@ -165,16 +172,16 @@ static ssize_t iscsi_conn_state_show(struct kobject *kobj,
 
        conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
 
-       pos = print_conn_state(buf, SCST_SYSFS_BLOCK_SIZE, conn);
+       pos = iscsi_get_initiator_ip(conn, buf, SCST_SYSFS_BLOCK_SIZE);
 
        TRACE_EXIT_RES(pos);
        return pos;
 }
 
-static struct kobj_attribute iscsi_conn_state_attr =
-       __ATTR(state, S_IRUGO, iscsi_conn_state_show, NULL);
+static struct kobj_attribute iscsi_conn_ip_attr =
+       __ATTR(ip, S_IRUGO, iscsi_conn_ip_show, NULL);
 
-static ssize_t iscsi_conn_hdigest_show(struct kobject *kobj,
+static ssize_t iscsi_conn_cid_show(struct kobject *kobj,
        struct kobj_attribute *attr, char *buf)
 {
        int pos;
@@ -184,17 +191,16 @@ static ssize_t iscsi_conn_hdigest_show(struct kobject *kobj,
 
        conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
 
-       pos = print_digest_state(buf, SCST_SYSFS_BLOCK_SIZE,
-               conn->hdigest_type);
+       pos = sprintf(buf, "%u", conn->cid);
 
        TRACE_EXIT_RES(pos);
        return pos;
 }
 
-static struct kobj_attribute iscsi_conn_hdigest_attr =
-       __ATTR(hdigest, S_IRUGO, iscsi_conn_hdigest_show, NULL);
+static struct kobj_attribute iscsi_conn_cid_attr =
+       __ATTR(cid, S_IRUGO, iscsi_conn_cid_show, NULL);
 
-static ssize_t iscsi_conn_ddigest_show(struct kobject *kobj,
+static ssize_t iscsi_conn_state_show(struct kobject *kobj,
        struct kobj_attribute *attr, char *buf)
 {
        int pos;
@@ -204,15 +210,14 @@ static ssize_t iscsi_conn_ddigest_show(struct kobject *kobj,
 
        conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
 
-       pos = print_digest_state(buf, SCST_SYSFS_BLOCK_SIZE,
-               conn->ddigest_type);
+       pos = print_conn_state(buf, SCST_SYSFS_BLOCK_SIZE, conn);
 
        TRACE_EXIT_RES(pos);
        return pos;
 }
 
-static struct kobj_attribute iscsi_conn_ddigest_attr =
-       __ATTR(ddigest, S_IRUGO, iscsi_conn_ddigest_show, NULL);
+static struct kobj_attribute iscsi_conn_state_attr =
+       __ATTR(state, S_IRUGO, iscsi_conn_state_show, NULL);
 
 #endif /* CONFIG_SCST_PROC */
 
@@ -500,10 +505,10 @@ int conn_free(struct iscsi_conn *conn)
 static int conn_free(struct iscsi_conn *conn)
 #endif
 {
+       struct iscsi_session *session = conn->session;
+
        TRACE_MGMT_DBG("Freeing conn %p (sess=%p, %#Lx %u)", conn,
-                      conn->session,
-                      (long long unsigned int)conn->session->sid,
-                      conn->cid);
+               session, (long long unsigned int)session->sid, conn->cid);
 
        del_timer_sync(&conn->rsp_timer);
 
@@ -518,7 +523,7 @@ static int conn_free(struct iscsi_conn *conn)
        if (test_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags)) {
                struct iscsi_conn *c;
                TRACE_MGMT_DBG("Freeing being reinstated conn %p", conn);
-               list_for_each_entry(c, &conn->session->conn_list,
+               list_for_each_entry(c, &session->conn_list,
                                        conn_list_entry) {
                        if (c->conn_reinst_successor == conn) {
                                c->conn_reinst_successor = NULL;
@@ -537,6 +542,11 @@ static int conn_free(struct iscsi_conn *conn)
 
        kfree(conn);
 
+       if (list_empty(&session->conn_list)) {
+               sBUG_ON(session->sess_reinst_successor != NULL);
+               session_free(session, true);
+       }
+
        return 0;
 }
 
@@ -547,7 +557,8 @@ static int iscsi_conn_alloc(struct iscsi_session *session,
        struct iscsi_conn *conn;
        int res = 0;
 #ifndef CONFIG_SCST_PROC
-       struct sock *sk;
+       struct iscsi_conn *c;
+       int n = 1;
        char addr[64];
 #endif
 
@@ -577,8 +588,8 @@ static int iscsi_conn_alloc(struct iscsi_session *session,
        conn->rd_state = ISCSI_CONN_RD_STATE_IDLE;
        conn->wr_state = ISCSI_CONN_WR_STATE_IDLE;
 
-       conn->hdigest_type = info->header_digest;
-       conn->ddigest_type = info->data_digest;
+       conn->hdigest_type = session->sess_param.header_digest;
+       conn->ddigest_type = session->sess_param.data_digest;
        res = digest_init(conn);
        if (res != 0)
                goto out_err_free1;
@@ -601,24 +612,22 @@ static int iscsi_conn_alloc(struct iscsi_session *session,
                goto out_err_free2;
 
 #ifndef CONFIG_SCST_PROC
-       sk = conn->sock->sk;
-       switch (sk->sk_family) {
-       case AF_INET:
-               snprintf(addr, sizeof(addr),
-                        "%u.%u.%u.%u", NIPQUAD(inet_sk(sk)->daddr));
-               break;
-       case AF_INET6:
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
-               snprintf(addr, sizeof(addr),
-                        "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
-                        NIP6(inet6_sk(sk)->daddr));
-#else
-               snprintf(addr, sizeof(addr), "[%p6]",
-                       &inet6_sk(sk)->daddr);
-#endif
-               break;
-       default:
-               break;
+       iscsi_get_initiator_ip(conn, addr, sizeof(addr));
+
+restart:
+       list_for_each_entry(c, &session->conn_list, conn_list_entry) {
+               if (strcmp(addr, conn->iscsi_conn_kobj.name) == 0) {
+                       char c_addr[64];
+
+                       iscsi_get_initiator_ip(conn, c_addr, sizeof(c_addr));
+
+                       TRACE_DBG("Dublicated conn from the same initiator "
+                               "%s found", c_addr);
+
+                       snprintf(addr, sizeof(addr), "%s_%d", c_addr, n);
+                       n++;
+                       goto restart;
+               }
        }
 
        res = kobject_init_and_add(&conn->iscsi_conn_kobj, &iscsi_conn_ktype,
@@ -643,23 +652,15 @@ static int iscsi_conn_alloc(struct iscsi_session *session,
                        &iscsi_conn_cid_attr.attr);
        if (res != 0) {
                PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
-                       iscsi_conn_state_attr.attr.name, addr);
+                       iscsi_conn_cid_attr.attr.name, addr);
                goto out_err_free3;
        }
 
        res = sysfs_create_file(&conn->iscsi_conn_kobj,
-                       &iscsi_conn_hdigest_attr.attr);
+                       &iscsi_conn_ip_attr.attr);
        if (res != 0) {
                PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
-                       iscsi_conn_hdigest_attr.attr.name, addr);
-               goto out_err_free3;
-       }
-
-       res = sysfs_create_file(&conn->iscsi_conn_kobj,
-                       &iscsi_conn_ddigest_attr.attr);
-       if (res != 0) {
-               PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
-                       iscsi_conn_ddigest_attr.attr.name, addr);
+                       iscsi_conn_ip_attr.attr.name, addr);
                goto out_err_free3;
        }
 #endif /* CONFIG_SCST_PROC */
@@ -674,6 +675,7 @@ out:
 #ifndef CONFIG_SCST_PROC
 out_err_free3:
        kobject_put(&conn->iscsi_conn_kobj);
+       goto out;
 #endif
 
 out_err_free2:
index 3a5d757..9d371e2 100644 (file)
@@ -195,7 +195,7 @@ struct iscsi_conn {
        void (*old_data_ready)(struct sock *, int);
        void (*old_write_space)(struct sock *);
 
-       /* Both read only */
+       /* Both read only. Stay here for better CPU cache locality. */
        int hdigest_type;
        int ddigest_type;
 
@@ -483,7 +483,9 @@ extern const struct attribute *iscsi_attrs[];
 #endif
 
 /* session.c */
-#ifndef CONFIG_SCST_PROC
+#ifdef CONFIG_SCST_PROC
+int print_digest_state(char *p, size_t size, unsigned long flags);
+#else
 extern const struct attribute *iscsi_sess_attrs[];
 #endif
 extern const struct file_operations session_seq_fops;
index e867364..8415850 100644 (file)
@@ -551,21 +551,14 @@ static void close_conn(struct iscsi_conn *conn)
                         conn);
        event_send(target->tid, session->sid, conn->cid, E_CONN_CLOSE, 0);
 
-       mutex_lock(&target->target_mutex);
-
 #ifdef CONFIG_SCST_PROC
+       mutex_lock(&target->target_mutex);
        conn_free(conn);
+       mutex_unlock(&target->target_mutex);
 #else
        kobject_put(&conn->iscsi_conn_kobj);
 #endif
 
-       if (list_empty(&session->conn_list)) {
-               sBUG_ON(session->sess_reinst_successor != NULL);
-               session_free(session, true);
-       }
-
-       mutex_unlock(&target->target_mutex);
-
        TRACE_EXIT();
        return;
 }
index 1c50365..a25f60e 100644 (file)
 
 #include "iscsi.h"
 
+#ifdef CONFIG_SCST_PROC 
+int print_digest_state(char *p, size_t size, unsigned long flags)
+#else
+static int print_digest_state(char *p, size_t size, unsigned long flags)
+#endif
+{
+       int pos;
+
+       if (DIGEST_NONE & flags)
+               pos = scnprintf(p, size, "%s", "none");
+       else if (DIGEST_CRC32C & flags)
+               pos = scnprintf(p, size, "%s", "crc32c");
+       else
+               pos = scnprintf(p, size, "%s", "unknown");
+
+       return pos;
+}
+
 /* target_mutex supposed to be locked */
 struct iscsi_session *session_lookup(struct iscsi_target *target, u64 sid)
 {
@@ -392,9 +410,55 @@ static ssize_t iscsi_sess_reinstating_show(struct kobject *kobj,
 static struct kobj_attribute iscsi_sess_reinstating_attr =
        __ATTR(reinstating, S_IRUGO, iscsi_sess_reinstating_show, NULL);
 
+static ssize_t iscsi_sess_hdigest_show(struct kobject *kobj,
+       struct kobj_attribute *attr, char *buf)
+{
+       int pos;
+       struct scst_session *scst_sess;
+       struct iscsi_session *sess;
+
+       TRACE_ENTRY();
+
+       scst_sess = container_of(kobj, struct scst_session, sess_kobj);
+       sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
+
+       pos = print_digest_state(buf, SCST_SYSFS_BLOCK_SIZE,
+               sess->sess_param.header_digest);
+
+       TRACE_EXIT_RES(pos);
+       return pos;
+}
+
+static struct kobj_attribute iscsi_sess_hdigest_attr =
+       __ATTR(hdigest, S_IRUGO, iscsi_sess_hdigest_show, NULL);
+
+static ssize_t iscsi_sess_ddigest_show(struct kobject *kobj,
+       struct kobj_attribute *attr, char *buf)
+{
+       int pos;
+       struct scst_session *scst_sess;
+       struct iscsi_session *sess;
+
+       TRACE_ENTRY();
+
+       scst_sess = container_of(kobj, struct scst_session, sess_kobj);
+       sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
+
+       pos = print_digest_state(buf, SCST_SYSFS_BLOCK_SIZE,
+               sess->sess_param.data_digest);
+
+       TRACE_EXIT_RES(pos);
+       return pos;
+}
+
+static struct kobj_attribute iscsi_sess_ddigest_attr =
+       __ATTR(ddigest, S_IRUGO, iscsi_sess_ddigest_show, NULL);
+
 const struct attribute *iscsi_sess_attrs[] = {
        &iscsi_sess_sid_attr.attr,
        &iscsi_sess_reinstating_attr.attr,
+       &iscsi_sess_hdigest_attr.attr,
+       &iscsi_sess_ddigest_attr.attr,
        NULL,
 };
 
index 01eb4cc..d89aefd 100644 (file)
@@ -61,9 +61,7 @@ void conn_pass_to_kern(struct connection *conn, int fd)
                fd, conn->cid, conn->stat_sn, conn->exp_stat_sn, conn->sid.id64);
 
        err = kernel_conn_create(conn->tid, conn->sess->sid.id64, conn->cid,
-                             conn->stat_sn, conn->exp_stat_sn, fd,
-                             conn->session_param[key_header_digest].val,
-                             conn->session_param[key_data_digest].val);
+                             conn->stat_sn, conn->exp_stat_sn, fd);
 
        /* We don't need to return err, because we are going to close conn anyway */
        return;
index 623e295..3557e25 100644 (file)
@@ -258,7 +258,7 @@ int kernel_session_destroy(u32 tid, u64 sid)
 }
 
 int kernel_conn_create(u32 tid, u64 sid, u32 cid, u32 stat_sn, u32 exp_stat_sn,
-                            int fd, u32 hdigest, u32 ddigest)
+       int fd)
 {
        struct iscsi_kern_conn_info info;
        int res;
@@ -271,8 +271,6 @@ int kernel_conn_create(u32 tid, u64 sid, u32 cid, u32 stat_sn, u32 exp_stat_sn,
        info.stat_sn = stat_sn;
        info.exp_stat_sn = exp_stat_sn;
        info.fd = fd;
-       info.header_digest = hdigest;
-       info.data_digest = ddigest;
 
        res = ioctl(ctrl_fd, ADD_CONN, &info);
        if (res < 0) {
index 083ca49..fba0535 100644 (file)
@@ -240,7 +240,7 @@ extern int kernel_session_create(u32 tid, u64 sid, u32 exp_cmd_sn,
        char *name, char *user);
 extern int kernel_session_destroy(u32 tid, u64 sid);
 extern int kernel_conn_create(u32 tid, u64 sid, u32 cid, u32 stat_sn, u32 exp_stat_sn,
-       int fd, u32 hdigest, u32 ddigest);
+       int fd);
 extern int kernel_conn_destroy(u32 tid, u64 sid, u32 cid);     
 
 /* event.c */
index ba2b166..c13a812 100644 (file)
@@ -643,8 +643,23 @@ ssize_t scst_sess_sysfs_commands_show(struct kobject *kobj,
 static struct kobj_attribute session_commands_attr =
        __ATTR(commands, S_IRUGO, scst_sess_sysfs_commands_show, NULL);
 
+ssize_t scst_sess_sysfs_initiator_name_show(struct kobject *kobj,
+                           struct kobj_attribute *attr, char *buf)
+{
+       struct scst_session *sess;
+
+       sess = container_of(kobj, struct scst_session, sess_kobj);
+
+       return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n",
+               sess->initiator_name);
+}
+
+static struct kobj_attribute session_initiator_name_attr =
+       __ATTR(initiator_name, S_IRUGO, scst_sess_sysfs_initiator_name_show, NULL);
+
 static struct attribute *scst_session_attrs[] = {
        &session_commands_attr.attr,
+       &session_initiator_name_attr.attr,
        NULL,
 };
 
@@ -668,21 +683,53 @@ static struct kobj_type scst_session_ktype = {
        .default_attrs = scst_session_attrs,
 };
 
+/* scst_mutex supposed to be locked */
 int scst_create_sess_sysfs(struct scst_session *sess)
 {
        int retval = 0;
+       struct scst_session *s;
        const struct attribute **pattr;
+       char *name = (char *)sess->initiator_name;
+       int len = strlen(name) + 1, n = 1;
 
        TRACE_ENTRY();
 
+restart:
+       list_for_each_entry(s, &sess->tgt->sess_list, sess_list_entry) {
+               if (!s->sess_kobj_initialized)
+                       continue;
+
+               if (strcmp(name, s->sess_kobj.name) == 0) {
+                       if (s == sess)
+                               continue;
+
+                       TRACE_DBG("Dublicated session from the same initiator "
+                               "%s found", name);
+
+                       if (name == sess->initiator_name) {
+                               len = strlen(sess->initiator_name);
+                               len += 20;
+                               name = kmalloc(len, GFP_KERNEL);
+                               if (name == NULL) {
+                                       PRINT_ERROR("Unable to allocate a "
+                                               "replacement name (size %d)",
+                                               len);
+                               }
+                       }
+
+                       snprintf(name, len, "%s_%d", sess->initiator_name, n);
+                       n++;
+                       goto restart;
+               }
+       }
+
        sess->sess_kobj_initialized = 1;
 
        retval = kobject_init_and_add(&sess->sess_kobj, &scst_session_ktype,
-                             sess->tgt->tgt_sess_kobj, sess->initiator_name);
+                             sess->tgt->tgt_sess_kobj, name);
        if (retval != 0) {
-               PRINT_ERROR("Can't add session %s to sysfs",
-                           sess->initiator_name);
-               goto out;
+               PRINT_ERROR("Can't add session %s to sysfs", name);
+               goto out_free;
        }
 
        /*
@@ -697,14 +744,17 @@ int scst_create_sess_sysfs(struct scst_session *sess)
                        if (retval != 0) {
                                PRINT_ERROR("Can't add sess attr %s for sess "
                                        "for initiator %s", (*pattr)->name,
-                                       sess->initiator_name);
-                               goto out;
+                                       name);
+                               goto out_free;
                        }
                        pattr++;
                }
        }
 
-out:
+out_free:
+       if (name != sess->initiator_name)
+               kfree(name);
+
        TRACE_EXIT_RES(retval);
        return retval;
 }
@@ -772,7 +822,7 @@ int scst_create_acg_dev_sysfs(struct scst_acg *acg, unsigned int virt_lun,
 {
        int retval;
        struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
-       char str[10];
+       char str[20];
 
        TRACE_ENTRY();
 
@@ -789,7 +839,8 @@ int scst_create_acg_dev_sysfs(struct scst_acg *acg, unsigned int virt_lun,
                goto out;
        }
 
-       snprintf(str, sizeof(str), "%u", acg_dev->dev->dev_exported_lun_num++);
+       snprintf(str, sizeof(str), "export%u",
+               acg_dev->dev->dev_exported_lun_num++);
 
        acg_dev->acg_dev_kobj_initialized = 1;