All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 9/10][RFC] linux-iscsi driver
@ 2005-01-10 23:03 Mike Christie
  0 siblings, 0 replies; only message in thread
From: Mike Christie @ 2005-01-10 23:03 UTC (permalink / raw)
  To: linux-scsi

[-- Attachment #1: Type: text/plain, Size: 208 bytes --]

Implements the driver interface which includes the
IOCTL and sysfs files. We currently do not have
any 32/64 bit conversion code but we will add it
if/when we know for sure the IOCL is the correct way
to go.

[-- Attachment #2: 09-interface.patch --]
[-- Type: text/x-patch, Size: 16285 bytes --]

diff -Naurp scsi-misc-2.6.orig/drivers/scsi/iscsi-sfnet/iscsi-attr.c scsi-misc-2.6.patch/drivers/scsi/iscsi-sfnet/iscsi-attr.c
--- scsi-misc-2.6.orig/drivers/scsi/iscsi-sfnet/iscsi-attr.c	1969-12-31 16:00:00.000000000 -0800
+++ scsi-misc-2.6.patch/drivers/scsi/iscsi-sfnet/iscsi-attr.c	2005-01-10 12:34:01.270434248 -0800
@@ -0,0 +1,214 @@
+/*
+ * iSCSI driver for Linux
+ * Copyright (C) 2002 Cisco Systems, Inc.
+ * Copyright (C) 2004 Mike Christie
+ * Copyright (C) 2004 IBM Corporation
+ * maintained by linux-iscsi-devel@lists.sourceforge.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ *
+ * The sysfs host attributes are defined here. 
+ */
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_host.h>
+
+#include "iscsi-session.h"
+#include "iscsi-sfnet.h"
+
+static ssize_t
+store_do_shutdown(struct class_device *class_dev, const char *buf, size_t count)
+{
+	iscsi_destroy_host(class_to_shost(class_dev));
+	return count;
+}
+
+static ssize_t
+store_drop_session(struct class_device *class_dev, const char *buf, size_t count)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct iscsi_session *session = (struct iscsi_session *)shost->hostdata;
+
+	iscsi_drop_session(session);
+	return count;
+}
+
+static CLASS_DEVICE_ATTR(shutdown, S_IWUSR, NULL, store_do_shutdown);
+static CLASS_DEVICE_ATTR(drop_session, S_IWUSR, NULL, store_drop_session);
+
+/*
+ * Macro to show session values specific to this driver
+ * on the scsi host's class dev. Some of them could also
+ * be moved to the transport class one day.
+ */
+#define session_show_function(field, format_string)			\
+static ssize_t								\
+show_##field (struct class_device *class_dev, char *buf)		\
+{									\
+	struct Scsi_Host *shost = class_to_shost(class_dev);		\
+	struct iscsi_session *session;					\
+	session = (struct iscsi_session *)shost->hostdata;		\
+	return snprintf(buf, 20, format_string, session->field);	\
+}
+
+#define session_rd_attr(field, format_string)			\
+	session_show_function(field, format_string)		\
+static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
+
+/*
+ * These times need to be fixed if they are going to be used
+ * by userspace. Should we also just spit out the time for the app
+ * instead.
+ */
+session_rd_attr(session_established_time, "%lu");
+session_rd_attr(session_drop_time, "%lu");
+session_rd_attr(ever_established, "%d");
+session_rd_attr(login_timeout, "%d");
+session_rd_attr(active_timeout, "%d");
+session_rd_attr(idle_timeout, "%d");
+session_rd_attr(ping_timeout, "%d");
+session_rd_attr(window_closed, "%lu");
+
+struct class_device_attribute *iscsi_host_attrs[] = {
+	&class_device_attr_shutdown,
+	&class_device_attr_drop_session,
+	&class_device_attr_session_established_time,
+	&class_device_attr_session_drop_time,
+	&class_device_attr_ever_established,
+	&class_device_attr_login_timeout,
+	&class_device_attr_active_timeout,
+	&class_device_attr_idle_timeout,
+	&class_device_attr_ping_timeout,
+	&class_device_attr_window_closed,
+	NULL
+};
+
+
+#define iscsi_transport_get_fn(field)					\
+static void								\
+iscsi_get_##field (struct scsi_target *stgt)				\
+{									\
+	struct Scsi_Host *shost = dev_to_shost(stgt->dev.parent);	\
+	struct iscsi_session *session;					\
+	session = (struct iscsi_session *)shost->hostdata;		\
+	iscsi_##field(stgt) = session->field;				\
+}
+
+iscsi_transport_get_fn(tsih);
+iscsi_transport_get_fn(initial_r2t);
+iscsi_transport_get_fn(immediate_data);
+iscsi_transport_get_fn(header_digest);
+iscsi_transport_get_fn(data_digest);
+iscsi_transport_get_fn(max_burst_len);
+iscsi_transport_get_fn(first_burst_len);
+iscsi_transport_get_fn(max_recv_data_segment_len);
+
+#define iscsi_target_transport_cp_fn(field)				\
+static ssize_t								\
+iscsi_get_##field (struct scsi_target *stgt, char *buf, ssize_t count)	\
+{									\
+	struct Scsi_Host *shost = dev_to_shost(stgt->dev.parent);	\
+	struct iscsi_session *session;					\
+	session = (struct iscsi_session *)shost->hostdata;		\
+	return snprintf(buf, count - 1, "%s\n", session->field);	\
+}
+
+iscsi_target_transport_cp_fn(target_name);
+iscsi_target_transport_cp_fn(target_alias);
+
+static void
+iscsi_get_ip_address(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct iscsi_session *session = (struct iscsi_session *)shost->hostdata;
+	struct sockaddr_in *addr = (struct sockaddr_in *)&session->addr;
+	/*
+	 * I am pretty sure I messed up the socket data structure
+	 * for ipv6 support. For now just do ipv4 until I can test
+	 */
+	iscsi_addr_type(starget) = addr->sin_family;
+	memcpy(&iscsi_sin_addr(starget), &addr->sin_addr,
+	       sizeof(struct in_addr));
+}
+
+static void
+iscsi_get_port(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct iscsi_session *session = (struct iscsi_session *)shost->hostdata;
+
+	struct sockaddr_in *addr = (struct sockaddr_in *)&session->addr;
+	iscsi_port(starget) = addr->sin_port;
+}
+
+static void
+iscsi_get_tpgt(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct iscsi_session *session = (struct iscsi_session *)shost->hostdata;
+
+	iscsi_tpgt(starget) = session->portal_group_tag;
+}
+
+static void
+iscsi_get_isid(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct iscsi_session *session = (struct iscsi_session *)shost->hostdata;
+	memcpy(iscsi_isid(starget), session->isid, sizeof(session->isid));
+}
+
+#define iscsi_host_transport_cp_fn(field)				\
+static ssize_t								\
+iscsi_get_##field (struct Scsi_Host *shost, char *buf, ssize_t count)	\
+{									\
+	struct iscsi_session *s = (struct iscsi_session *)shost->hostdata; \
+	return snprintf(buf, count - 1, "%s\n", s->field);		\
+}
+
+iscsi_host_transport_cp_fn(initiator_name);
+iscsi_host_transport_cp_fn(initiator_alias);
+
+struct iscsi_function_template iscsi_fnt = {
+	.get_isid = iscsi_get_isid,
+	.show_isid = 1,
+	.get_tsih = iscsi_get_tsih,
+	.show_tsih = 1,
+	.get_port = iscsi_get_port,
+	.show_port = 1,
+	.get_tpgt = iscsi_get_tpgt,
+	.show_tpgt = 1,
+	.get_ip_address = iscsi_get_ip_address,
+	.show_ip_address = 1, 
+	.get_initial_r2t = iscsi_get_initial_r2t,
+	.show_initial_r2t = 1,
+	.get_immediate_data = iscsi_get_immediate_data,
+	.show_immediate_data = 1,
+	.get_header_digest = iscsi_get_header_digest,
+	.show_header_digest = 1,
+	.get_data_digest = iscsi_get_data_digest,
+	.show_data_digest = 1,
+	.get_max_burst_len = iscsi_get_max_burst_len,
+	.show_max_burst_len = 1,
+	.get_first_burst_len = iscsi_get_first_burst_len,
+	.show_first_burst_len = 1,
+	.get_max_recv_data_segment_len = iscsi_get_max_recv_data_segment_len,
+	.show_max_recv_data_segment_len = 1,
+	.get_target_name = iscsi_get_target_name,
+	.show_target_name = 1,
+	.get_target_alias = iscsi_get_target_alias,
+	.show_target_alias = 1,
+	.get_initiator_alias = iscsi_get_initiator_alias,
+	.show_initiator_alias = 1,
+	.get_initiator_name = iscsi_get_initiator_name,
+	.show_initiator_name = 1,
+};
diff -Naurp scsi-misc-2.6.orig/drivers/scsi/iscsi-sfnet/iscsi-ioctl.c scsi-misc-2.6.patch/drivers/scsi/iscsi-sfnet/iscsi-ioctl.c
--- scsi-misc-2.6.orig/drivers/scsi/iscsi-sfnet/iscsi-ioctl.c	1969-12-31 16:00:00.000000000 -0800
+++ scsi-misc-2.6.patch/drivers/scsi/iscsi-sfnet/iscsi-ioctl.c	2005-01-10 12:34:16.464457282 -0800
@@ -0,0 +1,140 @@
+/*
+ * iSCSI driver for Linux
+ * Copyright (C) 2001 Cisco Systems, Inc.
+ * Copyright (C) 2004 Mike Christie
+ * Copyright (C) 2004 IBM Corporation
+ * maintained by linux-iscsi-devel@lists.sourceforge.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ *
+ * This file handles iscsi ioctl calls
+ */
+#include <linux/capability.h>
+#include <asm/uaccess.h>
+
+#include "iscsi-session.h"
+#include "iscsi-ioctl.h"
+#include "iscsi-sfnet.h"
+
+static int
+iscsi_ioctl_establish_session(void __user *arg)
+{
+	int rc;
+	struct iscsi_session *session;
+	struct iscsi_session_ioctl *ioctld;
+
+	ioctld = kmalloc(sizeof(*ioctld), GFP_KERNEL);
+	if (!ioctld) {
+		iscsi_err("Couldn't allocate space for session ioctl data\n");
+		return -ENOMEM;
+	}
+
+	if (copy_from_user(ioctld, (void *)arg, sizeof(*ioctld))) {
+		iscsi_err("Cannot copy session ioctl data\n");
+		kfree(ioctld);
+		return -EFAULT;
+	}
+
+	if (ioctld->ioctl_version != ISCSI_SESSION_IOCTL_VERSION) {
+		iscsi_err("ioctl version %u incorrect, expecting %u\n",
+			  ioctld->ioctl_version, ISCSI_SESSION_IOCTL_VERSION);
+		return -EINVAL;
+	}
+
+	/*
+	 * TODO - should update wait for the relogin?
+	 */
+	session = iscsi_find_session(ioctld->target_name, ioctld->isid,
+				     ioctld->portal.tag);
+	if (session) {
+		rc = iscsi_update_session(session, ioctld);
+		scsi_host_put(session->shost);
+	} else if (ioctld->update) {
+		iscsi_err("Could not find session to update\n");
+		rc = -EAGAIN;
+	} else
+		rc = iscsi_create_host(ioctld);
+
+	kfree(ioctld);
+	return rc;
+}
+
+static int
+iscsi_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		unsigned long arg)
+{
+	void __user *_arg = (void __user *) arg;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	if (_IOC_TYPE(cmd) != ISCSI_IOCTL)
+		return -ENOTTY;
+
+	if (cmd == ISCSI_ESTABLISH_SESSION)
+		return iscsi_ioctl_establish_session(_arg);
+
+	iscsi_err("Requested ioctl not found\n");
+	return -EINVAL;
+}
+
+static struct class_simple *iscsictl_sysfs_class;
+static int control_major;
+static const char *control_name = "iscsictl";
+
+static struct file_operations control_fops = {
+      .owner = THIS_MODULE,
+      .ioctl = iscsi_ctl_ioctl,
+};
+
+/*
+ * This file could be replaced with sysfs, but if it stays
+ * we need some 32bit conversion code to work on Power
+ */
+int
+iscsi_register_interface(void)
+{
+	control_major = register_chrdev(0, control_name, &control_fops);
+	if (control_major < 0) {
+		iscsi_err("Failed to register the control device\n");
+		return -ENODEV;
+	}
+	iscsi_notice("Control device major number %d\n", control_major);
+
+	 /* Provide udev support for the control device. */
+	iscsictl_sysfs_class = class_simple_create(THIS_MODULE,
+						   "iscsi_control");
+	if (!iscsictl_sysfs_class)
+		goto unreg_chrdev;
+
+	if (!class_simple_device_add(iscsictl_sysfs_class,
+				     MKDEV(control_major, 0), NULL,
+				     "iscsictl"))
+		goto destroy_iscsictl_cls;
+
+	return 0;
+
+ destroy_iscsictl_cls:
+	class_simple_destroy(iscsictl_sysfs_class);
+ unreg_chrdev:
+	unregister_chrdev(control_major, control_name);
+	return -ENODEV;
+}
+
+void
+iscsi_unregister_interface(void)
+{
+	class_simple_device_remove(MKDEV(control_major, 0));
+	class_simple_destroy(iscsictl_sysfs_class);
+	unregister_chrdev(control_major, control_name);
+}
diff -Naurp scsi-misc-2.6.orig/drivers/scsi/iscsi-sfnet/iscsi-ioctl.h scsi-misc-2.6.patch/drivers/scsi/iscsi-sfnet/iscsi-ioctl.h
--- scsi-misc-2.6.orig/drivers/scsi/iscsi-sfnet/iscsi-ioctl.h	1969-12-31 16:00:00.000000000 -0800
+++ scsi-misc-2.6.patch/drivers/scsi/iscsi-sfnet/iscsi-ioctl.h	2005-01-10 12:34:16.464457282 -0800
@@ -0,0 +1,67 @@
+/*
+ * iSCSI driver for Linux
+ * Copyright (C) 2001 Cisco Systems, Inc.
+ * Copyright (C) 2004 Mike Christie
+ * Copyright (C) 2004 IBM Corporation
+ * maintained by linux-iscsi-devel@lists.sourceforge.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ *
+ * include for ioctl calls between the daemon and the kernel module
+ */
+#ifndef ISCSI_IOCTL_H_
+#define ISCSI_IOCTL_H_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#include "iscsi-protocol.h"
+#include "iscsi-portal.h"
+#include "iscsi-auth-client.h"
+
+/*
+ * still not sure if the ioctl is going to stay
+ * so can fix up later
+ */
+struct iscsi_session_ioctl {
+	__u32		ioctl_version;
+	__u32		config_number;
+	int		update;
+	__u8		isid[6];
+	/*
+	 * passwords can contain NULL chars so we need
+	 * the length.
+	 */
+	int		password_length;
+	char		username[AUTH_STR_MAX_LEN];
+	unsigned char	password[AUTH_STR_MAX_LEN];
+	int		password_length_in;
+	char		username_in[AUTH_STR_MAX_LEN];
+	unsigned char	password_in[AUTH_STR_MAX_LEN];
+	unsigned char	target_name[TARGET_NAME_MAXLEN + 1];
+	unsigned char	initiator_name[TARGET_NAME_MAXLEN + 1];
+	unsigned char	initiator_alias[TARGET_NAME_MAXLEN + 1];
+	struct iscsi_portal_info portal;
+};
+
+#define ISCSI_SESSION_IOCTL_VERSION 25
+
+/*
+ * ioctls
+ */
+#define ISCSI_EST_SESS_CMD 0
+
+#define ISCSI_IOCTL 0xbc
+#define ISCSI_ESTABLISH_SESSION _IOW(ISCSI_IOCTL, ISCSI_EST_SESS_CMD, \
+					struct iscsi_session_ioctl)
+#endif
diff -Naurp scsi-misc-2.6.orig/drivers/scsi/iscsi-sfnet/iscsi-protocol.h scsi-misc-2.6.patch/drivers/scsi/iscsi-sfnet/iscsi-protocol.h
--- scsi-misc-2.6.orig/drivers/scsi/iscsi-sfnet/iscsi-protocol.h	1969-12-31 16:00:00.000000000 -0800
+++ scsi-misc-2.6.patch/drivers/scsi/iscsi-sfnet/iscsi-protocol.h	2005-01-10 12:34:22.232707066 -0800
@@ -0,0 +1,53 @@
+/*
+ * iSCSI driver for Linux
+ * Copyright (C) 2001 Cisco Systems, Inc.
+ * maintained by linux-iscsi-devel@lists.sourceforge.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ *
+ * This file sets up definitions of messages and constants used by the
+ * iSCSI protocol.
+ */
+#ifndef ISCSI_PROTOCOL_H_
+#define ISCSI_PROTOCOL_H_
+
+#include <scsi/iscsi.h>
+
+/* assumes a pointer to a 3-byte array */
+#define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2]))
+
+/* assumes a pointer to a 3 byte array, and an integer value */
+#define hton24(p, v) {\
+        p[0] = (((v) >> 16) & 0xFF); \
+        p[1] = (((v) >> 8) & 0xFF); \
+        p[2] = ((v) & 0xFF); \
+}
+
+/* for Login min, max, active version fields */
+#define ISCSI_MIN_VERSION	ISCSI_DRAFT20_VERSION
+#define ISCSI_MAX_VERSION	ISCSI_DRAFT20_VERSION
+
+/* Padding word length */
+#define PAD_WORD_LEN		4
+
+/* maximum length for text values */
+#define TARGET_NAME_MAXLEN	255
+
+/*
+ * We should come up with a enum or some defines (in iscsi.h)
+ * of all the iSCSI defaults so we can verify values against
+ * what we receive (from the ioctl and targets)
+ */
+#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH	8192
+
+#endif

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-01-10 23:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-01-10 23:03 [PATCH 9/10][RFC] linux-iscsi driver Mike Christie

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.