diff --git a/iscsi-scst/kernel/config.c b/iscsi-scst/kernel/config.c index e2795973f..ddfc8d236 100644 --- a/iscsi-scst/kernel/config.c +++ b/iscsi-scst/kernel/config.c @@ -25,8 +25,6 @@ #define ISCSI_PROC_LOG_ENTRY_NAME "trace_level" -#include - static struct scst_trace_log iscsi_local_trace_tbl[] = { { TRACE_D_READ, "d_read" }, @@ -233,6 +231,43 @@ err: goto out; } +#else /* CONFIG_SCST_PROC */ + +static ssize_t iscsi_version_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + TRACE_ENTRY(); + + sprintf(buf, "%s\n", ISCSI_VERSION_STRING); + +#ifdef CONFIG_SCST_EXTRACHECKS + strcat(buf, "EXTRACHECKS\n"); +#endif + +#ifdef CONFIG_SCST_TRACING + strcat(buf, "TRACING\n"); +#endif + +#ifdef CONFIG_SCST_DEBUG + strcat(buf, "DEBUG\n"); +#endif + +#ifdef CONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES + strcat(buf, "DEBUG_DIGEST_FAILURES\n"); +#endif + + TRACE_EXIT(); + return strlen(buf); +} + +static struct kobj_attribute iscsi_version_attr = + __ATTR(version, S_IRUGO, iscsi_version_show, NULL); + +const struct attribute *iscsi_attrs[] = { + &iscsi_version_attr.attr, + NULL, +}; + #endif /* CONFIG_SCST_PROC */ /* target_mutex supposed to be locked */ @@ -265,8 +300,11 @@ static int del_conn(struct iscsi_target *target, void __user *ptr) return err; session = session_lookup(target, info.sid); - if (!session) + if (!session) { + PRINT_ERROR("Session %llx not found", + (long long unsigned int)info.sid); return -ENOENT; + } return conn_del(session, &info); } diff --git a/iscsi-scst/kernel/conn.c b/iscsi-scst/kernel/conn.c index 67d040012..e0f329294 100644 --- a/iscsi-scst/kernel/conn.c +++ b/iscsi-scst/kernel/conn.c @@ -21,8 +21,6 @@ #include "iscsi.h" #include "digest.h" -#ifdef CONFIG_SCST_PROC - static int print_conn_state(char *p, size_t size, struct iscsi_conn *conn) { int pos = 0; @@ -62,16 +60,22 @@ out: return pos; } -static void print_digest_state(char *p, size_t size, unsigned long flags) +static int print_digest_state(char *p, size_t size, unsigned long flags) { + int pos; + if (DIGEST_NONE & flags) - snprintf(p, size, "%s", "none"); + pos = scnprintf(p, size, "%s", "none"); else if (DIGEST_CRC32C & flags) - snprintf(p, size, "%s", "crc32c"); + pos = scnprintf(p, size, "%s", "crc32c"); else - snprintf(p, size, "%s", "unknown"); + pos = scnprintf(p, size, "%s", "unknown"); + + return pos; } +#ifdef CONFIG_SCST_PROC + /* target_mutex supposed to be locked */ void conn_info_show(struct seq_file *seq, struct iscsi_session *session) { @@ -109,6 +113,107 @@ void conn_info_show(struct seq_file *seq, struct iscsi_session *session) } } +#else /* CONFIG_SCST_PROC */ + +static int conn_free(struct iscsi_conn *conn); + +static void iscsi_conn_release(struct kobject *kobj) +{ + struct iscsi_conn *conn; + + TRACE_ENTRY(); + + conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj); + + conn_free(conn); + + TRACE_EXIT(); + return; +} + +static struct kobj_type iscsi_conn_ktype = { + .sysfs_ops = &scst_sysfs_ops, + .release = iscsi_conn_release, +}; + +static ssize_t iscsi_conn_cid_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int pos; + struct iscsi_conn *conn; + + TRACE_ENTRY(); + + conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj); + + pos = sprintf(buf, "%u", conn->cid); + + 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, + struct kobj_attribute *attr, char *buf) +{ + int pos; + struct iscsi_conn *conn; + + TRACE_ENTRY(); + + conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj); + + pos = print_conn_state(buf, SCST_SYSFS_BLOCK_SIZE, conn); + + TRACE_EXIT_RES(pos); + return pos; +} + +static struct kobj_attribute iscsi_conn_state_attr = + __ATTR(state, S_IRUGO, iscsi_conn_state_show, NULL); + +static ssize_t iscsi_conn_hdigest_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int pos; + struct iscsi_conn *conn; + + TRACE_ENTRY(); + + conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj); + + pos = print_digest_state(buf, SCST_SYSFS_BLOCK_SIZE, + conn->hdigest_type); + + TRACE_EXIT_RES(pos); + return pos; +} + +static struct kobj_attribute iscsi_conn_hdigest_attr = + __ATTR(hdigest, S_IRUGO, iscsi_conn_hdigest_show, NULL); + +static ssize_t iscsi_conn_ddigest_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int pos; + struct iscsi_conn *conn; + + TRACE_ENTRY(); + + conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj); + + pos = print_digest_state(buf, SCST_SYSFS_BLOCK_SIZE, + conn->ddigest_type); + + TRACE_EXIT_RES(pos); + return pos; +} + +static struct kobj_attribute iscsi_conn_ddigest_attr = + __ATTR(ddigest, S_IRUGO, iscsi_conn_ddigest_show, NULL); + #endif /* CONFIG_SCST_PROC */ /* target_mutex supposed to be locked */ @@ -389,7 +494,11 @@ out: } /* target_mutex supposed to be locked */ +#ifdef CONFIG_SCST_PROC int conn_free(struct iscsi_conn *conn) +#else +static int conn_free(struct iscsi_conn *conn) +#endif { TRACE_MGMT_DBG("Freeing conn %p (sess=%p, %#Lx %u)", conn, conn->session, @@ -437,6 +546,10 @@ static int iscsi_conn_alloc(struct iscsi_session *session, { struct iscsi_conn *conn; int res = 0; +#ifndef CONFIG_SCST_PROC + struct sock *sk; + char addr[64]; +#endif conn = kzalloc(sizeof(*conn), GFP_KERNEL); if (!conn) { @@ -487,6 +600,70 @@ static int iscsi_conn_alloc(struct iscsi_session *session, if (res != 0) 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; + } + + res = kobject_init_and_add(&conn->iscsi_conn_kobj, &iscsi_conn_ktype, + scst_sysfs_get_sess_kobj(session->scst_sess), addr); + if (res != 0) { + PRINT_ERROR("Unable create sysfs entries for conn %s", + addr); + goto out_err_free2; + } + + TRACE_DBG("conn %p, iscsi_conn_kobj %p", conn, &conn->iscsi_conn_kobj); + + res = sysfs_create_file(&conn->iscsi_conn_kobj, + &iscsi_conn_state_attr.attr); + if (res != 0) { + PRINT_ERROR("Unable create sysfs attribute %s for conn %s", + iscsi_conn_state_attr.attr.name, addr); + goto out_err_free3; + } + + res = sysfs_create_file(&conn->iscsi_conn_kobj, + &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); + goto out_err_free3; + } + + res = sysfs_create_file(&conn->iscsi_conn_kobj, + &iscsi_conn_hdigest_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); + goto out_err_free3; + } +#endif /* CONFIG_SCST_PROC */ + list_add_tail(&conn->conn_list_entry, &session->conn_list); *new_conn = conn; @@ -494,6 +671,11 @@ static int iscsi_conn_alloc(struct iscsi_session *session, out: return res; +#ifndef CONFIG_SCST_PROC +out_err_free3: + kobject_put(&conn->iscsi_conn_kobj); +#endif + out_err_free2: fput(conn->file); @@ -549,8 +731,10 @@ int conn_del(struct iscsi_session *session, struct iscsi_kern_conn_info *info) int err = -EEXIST; conn = conn_lookup(session, info->cid); - if (!conn) + if (!conn) { + PRINT_ERROR("Connection %d not found", info->cid); return err; + } PRINT_INFO("Deleting connection with initiator %s (%p)", conn->session->initiator_name, conn); diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index 36baa15b4..90075abd5 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -3143,12 +3143,41 @@ static int iscsi_target_release(struct scst_tgt *scst_tgt) return 0; } +#ifndef CONFIG_SCST_PROC +static struct scst_trace_log iscsi_local_trace_tbl[] = +{ + { TRACE_D_READ, "d_read" }, + { TRACE_D_WRITE, "d_write" }, + { TRACE_CONN_OC, "conn" }, + { TRACE_CONN_OC_DBG, "conn_dbg" }, + { TRACE_D_IOV, "iov" }, + { TRACE_D_DUMP_PDU, "pdu" }, + { TRACE_NET_PG, "net_page" }, + { 0, NULL } +}; + +#define ISCSI_TRACE_TLB_HELP ", d_read, d_write, conn, conn_dbg, iov, pdu, net_page" +#endif + struct scst_tgt_template iscsi_template = { .name = "iscsi", .sg_tablesize = 0xFFFF /* no limit */, .threads_num = 0, .no_clustering = 1, .xmit_response_atomic = 0, +#ifndef CONFIG_SCST_PROC + .tgtt_attrs = iscsi_attrs, + .tgt_attrs = iscsi_tgt_attrs, + .sess_attrs = iscsi_sess_attrs, +#endif +#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) + .default_trace_flags = ISCSI_DEFAULT_LOG_FLAGS, + .trace_flags = &trace_flag, +#ifndef CONFIG_SCST_PROC + .trace_tbl = iscsi_local_trace_tbl, + .trace_tbl_help = ISCSI_TRACE_TLB_HELP, +#endif +#endif .detect = iscsi_target_detect, .release = iscsi_target_release, .xmit_response = iscsi_xmit_response, diff --git a/iscsi-scst/kernel/iscsi.h b/iscsi-scst/kernel/iscsi.h index eac117891..3a5d757d0 100644 --- a/iscsi-scst/kernel/iscsi.h +++ b/iscsi-scst/kernel/iscsi.h @@ -238,6 +238,11 @@ struct iscsi_conn { /* Doesn't need any protection */ u16 cid; + +#ifndef CONFIG_SCST_PROC + /* Doesn't need any protection */ + struct kobject iscsi_conn_kobj; +#endif /* CONFIG_SCST_PROC */ }; struct iscsi_pdu { @@ -429,7 +434,9 @@ extern struct iscsi_conn *conn_lookup(struct iscsi_session *, u16); extern void conn_reinst_finished(struct iscsi_conn *); extern int conn_add(struct iscsi_session *, struct iscsi_kern_conn_info *); extern int conn_del(struct iscsi_session *, struct iscsi_kern_conn_info *); +#ifdef CONFIG_SCST_PROC extern int conn_free(struct iscsi_conn *); +#endif extern void iscsi_make_conn_rd_active(struct iscsi_conn *conn); #define ISCSI_CONN_ACTIVE_CLOSE 1 @@ -454,6 +461,9 @@ extern int istwr(void *arg); extern void iscsi_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *scst_mcmd); /* target.c */ +#ifndef CONFIG_SCST_PROC +extern const struct attribute *iscsi_tgt_attrs[]; +#endif struct iscsi_target *target_lookup_by_id(u32); extern int target_add(struct iscsi_kern_target_info *); extern int target_del(u32 id); @@ -468,9 +478,14 @@ extern const struct seq_operations iscsi_seq_op; #ifdef CONFIG_SCST_PROC extern int iscsi_procfs_init(void); extern void iscsi_procfs_exit(void); +#else +extern const struct attribute *iscsi_attrs[]; #endif /* session.c */ +#ifndef CONFIG_SCST_PROC +extern const struct attribute *iscsi_sess_attrs[]; +#endif extern const struct file_operations session_seq_fops; extern struct iscsi_session *session_lookup(struct iscsi_target *, u64); extern void sess_reinst_finished(struct iscsi_session *); diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index d384161be..e867364cf 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -553,7 +553,11 @@ static void close_conn(struct iscsi_conn *conn) mutex_lock(&target->target_mutex); +#ifdef CONFIG_SCST_PROC conn_free(conn); +#else + kobject_put(&conn->iscsi_conn_kobj); +#endif if (list_empty(&session->conn_list)) { sBUG_ON(session->sess_reinst_successor != NULL); diff --git a/iscsi-scst/kernel/session.c b/iscsi-scst/kernel/session.c index 42ee3788b..1c503655e 100644 --- a/iscsi-scst/kernel/session.c +++ b/iscsi-scst/kernel/session.c @@ -348,4 +348,54 @@ const struct file_operations session_seq_fops = { .release = seq_release, }; +#else /* CONFIG_SCST_PROC */ + +static ssize_t iscsi_sess_sid_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 = sprintf(buf, "%llx\n", sess->sid); + + TRACE_EXIT_RES(pos); + return pos; +} + +static struct kobj_attribute iscsi_sess_sid_attr = + __ATTR(sid, S_IRUGO, iscsi_sess_sid_show, NULL); + +static ssize_t iscsi_sess_reinstating_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 = sprintf(buf, "%d\n", sess->sess_reinstating ? 1 : 0); + + TRACE_EXIT_RES(pos); + return pos; +} + +static struct kobj_attribute iscsi_sess_reinstating_attr = + __ATTR(reinstating, S_IRUGO, iscsi_sess_reinstating_show, NULL); + +const struct attribute *iscsi_sess_attrs[] = { + &iscsi_sess_sid_attr.attr, + &iscsi_sess_reinstating_attr.attr, + NULL, +}; + #endif /* CONFIG_SCST_PROC */ diff --git a/iscsi-scst/kernel/target.c b/iscsi-scst/kernel/target.c index 3a5a656c6..2c3009f37 100644 --- a/iscsi-scst/kernel/target.c +++ b/iscsi-scst/kernel/target.c @@ -92,6 +92,8 @@ static int iscsi_target_create(struct iscsi_kern_target_info *info, u32 tid) goto out_free; } + scst_tgt_set_tgt_priv(target->scst_tgt, target); + list_add_tail(&target->target_list_entry, &target_list); return 0; @@ -272,6 +274,8 @@ void target_del_all(void) return; } +#ifdef CONFIG_SCST_PROC + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) static struct list_head *seq_list_start(struct list_head *head, loff_t pos) { @@ -337,3 +341,33 @@ const struct seq_operations iscsi_seq_op = { .stop = iscsi_seq_stop, .show = iscsi_seq_show, }; + +#else /* CONFIG_SCST_PROC */ + +static ssize_t iscsi_tgt_tid_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int pos; + struct scst_tgt *scst_tgt; + struct iscsi_target *tgt; + + TRACE_ENTRY(); + + scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj); + tgt = (struct iscsi_target *)scst_tgt_get_tgt_priv(scst_tgt); + + pos = sprintf(buf, "%u\n", tgt->tid); + + TRACE_EXIT_RES(pos); + return pos; +} + +static struct kobj_attribute iscsi_tgt_tid_attr = + __ATTR(tid, S_IRUGO, iscsi_tgt_tid_show, NULL); + +const struct attribute *iscsi_tgt_attrs[] = { + &iscsi_tgt_tid_attr.attr, + NULL, +}; + +#endif /* CONFIG_SCST_PROC */ diff --git a/iscsi-scst/usr/ctldev.c b/iscsi-scst/usr/ctldev.c index 02780fed8..623e295db 100644 --- a/iscsi-scst/usr/ctldev.c +++ b/iscsi-scst/usr/ctldev.c @@ -151,7 +151,8 @@ int kernel_conn_destroy(u32 tid, u64 sid, u32 cid) if ((err = ioctl(ctrl_fd, DEL_CONN, &info)) < 0) { err = -errno; - log_error("Can't destroy conn %d %u\n", errno, cid); + log_error("Can't destroy conn (errno %d, tid %u, sid 0x%" + PRIx64 ", cid %u\n", errno, tid, sid, cid); } return err; diff --git a/scst/include/scst.h b/scst/include/scst.h index 323dd380e..ed68cf009 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -864,6 +864,9 @@ struct scst_tgt_template { /* Optional sysfs target attributes */ const struct attribute **tgt_attrs; + + /* Optional sysfs session attributes */ + const struct attribute **sess_attrs; #endif /** Private, must be inited to 0 by memset() **/ @@ -3239,6 +3242,9 @@ struct proc_dir_entry *scst_create_proc_entry(struct proc_dir_entry *root, #else /* CONFIG_SCST_PROC */ +/* Regular SCST sysfs operations */ +extern struct sysfs_ops scst_sysfs_ops; + /* * Returns target driver's root sysfs kobject. * The driver can create own files/directories/links here. @@ -3279,6 +3285,16 @@ static inline struct kobject *scst_sysfs_get_dev_kobj( return &dev->dev_kobj; } +/* + * Returns session's root sysfs kobject. + * The driver can create own files/directories/links here. + */ +static inline struct kobject *scst_sysfs_get_sess_kobj( + struct scst_session *sess) +{ + return &sess->sess_kobj; +} + #endif /* CONFIG_SCST_PROC */ /* Returns target name */ diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index c83fd6b24..ba2b166f9 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -37,7 +37,8 @@ static struct kobject *scst_devices_kobj; static struct kobject *scst_sgv_kobj; static struct kobject *scst_handlers_kobj; -static struct sysfs_ops scst_sysfs_ops; +struct sysfs_ops scst_sysfs_ops; +EXPORT_SYMBOL(scst_sysfs_ops); static const char *scst_dev_handler_types[] = { @@ -670,6 +671,7 @@ static struct kobj_type scst_session_ktype = { int scst_create_sess_sysfs(struct scst_session *sess) { int retval = 0; + const struct attribute **pattr; TRACE_ENTRY(); @@ -688,6 +690,20 @@ int scst_create_sess_sysfs(struct scst_session *sess) * it will be done by the _put function() called by the caller. */ + pattr = sess->tgt->tgtt->sess_attrs; + if (pattr != NULL) { + while (*pattr != NULL) { + retval = sysfs_create_file(&sess->sess_kobj, *pattr); + if (retval != 0) { + PRINT_ERROR("Can't add sess attr %s for sess " + "for initiator %s", (*pattr)->name, + sess->initiator_name); + goto out; + } + pattr++; + } + } + out: TRACE_EXIT_RES(retval); return retval; @@ -1515,7 +1531,7 @@ static ssize_t scst_store(struct kobject *kobj, struct attribute *attr, return kobj_attr->store(kobj, kobj_attr, buf, count); } -static struct sysfs_ops scst_sysfs_ops = { +struct sysfs_ops scst_sysfs_ops = { .show = scst_show, .store = scst_store, };