From 5329898ad8b7aeb4f6d9e432db73fc40b51229d4 Mon Sep 17 00:00:00 2001 From: vlnb Date: Mon, 2 Nov 2009 18:07:54 +0000 Subject: [PATCH] Various sysfs related fixes git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1309 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/include/iscsi_scst.h | 2 - iscsi-scst/kernel/conn.c | 148 ++++++++++++++++---------------- iscsi-scst/kernel/iscsi.h | 6 +- iscsi-scst/kernel/nthread.c | 11 +-- iscsi-scst/kernel/session.c | 64 ++++++++++++++ iscsi-scst/usr/conn.c | 4 +- iscsi-scst/usr/ctldev.c | 4 +- iscsi-scst/usr/iscsid.h | 2 +- scst/src/scst_sysfs.c | 69 +++++++++++++-- 9 files changed, 208 insertions(+), 102 deletions(-) diff --git a/iscsi-scst/include/iscsi_scst.h b/iscsi-scst/include/iscsi_scst.h index 95e1ca3..b351fcb 100644 --- a/iscsi-scst/include/iscsi_scst.h +++ b/iscsi-scst/include/iscsi_scst.h @@ -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; }; diff --git a/iscsi-scst/kernel/conn.c b/iscsi-scst/kernel/conn.c index e0f3292..ee8e419 100644 --- a/iscsi-scst/kernel/conn.c +++ b/iscsi-scst/kernel/conn.c @@ -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: diff --git a/iscsi-scst/kernel/iscsi.h b/iscsi-scst/kernel/iscsi.h index 3a5d757..9d371e2 100644 --- a/iscsi-scst/kernel/iscsi.h +++ b/iscsi-scst/kernel/iscsi.h @@ -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; diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index e867364..8415850 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -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; } diff --git a/iscsi-scst/kernel/session.c b/iscsi-scst/kernel/session.c index 1c50365..a25f60e 100644 --- a/iscsi-scst/kernel/session.c +++ b/iscsi-scst/kernel/session.c @@ -16,6 +16,24 @@ #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, }; diff --git a/iscsi-scst/usr/conn.c b/iscsi-scst/usr/conn.c index 01eb4cc..d89aefd 100644 --- a/iscsi-scst/usr/conn.c +++ b/iscsi-scst/usr/conn.c @@ -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; diff --git a/iscsi-scst/usr/ctldev.c b/iscsi-scst/usr/ctldev.c index 623e295..3557e25 100644 --- a/iscsi-scst/usr/ctldev.c +++ b/iscsi-scst/usr/ctldev.c @@ -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) { diff --git a/iscsi-scst/usr/iscsid.h b/iscsi-scst/usr/iscsid.h index 083ca49..fba0535 100644 --- a/iscsi-scst/usr/iscsid.h +++ b/iscsi-scst/usr/iscsid.h @@ -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 */ diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index ba2b166..c13a812 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -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; -- 2.17.1