#define ISCSI_PROC_LOG_ENTRY_NAME "trace_level"
-#include <linux/proc_fs.h>
-
static struct scst_trace_log iscsi_local_trace_tbl[] =
{
{ TRACE_D_READ, "d_read" },
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 */
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);
}
#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;
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)
{
}
}
+#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 */
}
/* 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,
{
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) {
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;
out:
return res;
+#ifndef CONFIG_SCST_PROC
+out_err_free3:
+ kobject_put(&conn->iscsi_conn_kobj);
+#endif
+
out_err_free2:
fput(conn->file);
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);
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,
/* 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 {
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
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);
#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 *);
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);
.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 */
goto out_free;
}
+ scst_tgt_set_tgt_priv(target->scst_tgt, target);
+
list_add_tail(&target->target_list_entry, &target_list);
return 0;
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)
{
.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 */
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;
/* 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() **/
#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.
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 */
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[] =
{
int scst_create_sess_sysfs(struct scst_session *sess)
{
int retval = 0;
+ const struct attribute **pattr;
TRACE_ENTRY();
* 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;
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,
};