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

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

Driver file implementing the SCSI template functions
and module initialization.

[-- Attachment #2: 03-scsi-tmpl.patch --]
[-- Type: text/x-patch, Size: 21100 bytes --]

diff -Naurp scsi-misc-2.6.orig/drivers/scsi/iscsi-sfnet/iscsi-initiator.c scsi-misc-2.6.patch/drivers/scsi/iscsi-sfnet/iscsi-initiator.c
--- scsi-misc-2.6.orig/drivers/scsi/iscsi-sfnet/iscsi-initiator.c	1969-12-31 16:00:00.000000000 -0800
+++ scsi-misc-2.6.patch/drivers/scsi/iscsi-sfnet/iscsi-initiator.c	2005-01-10 12:19:58.490683743 -0800
@@ -0,0 +1,581 @@
+/*
+ * 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 contains interfaces required by SCSI mid layer, module
+ * initialization and shutdown routines.
+ */
+#include <linux/version.h>
+#include <linux/moduleparam.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/in.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_iscsi.h>
+
+#include "iscsi-sfnet.h"
+#include "iscsi-session.h"
+#include "iscsi-protocol.h"
+#include "iscsi-task.h"
+
+/*
+ *  IMPORTANT NOTE: to prevent deadlock, when holding multiple locks,
+ *  the following locking order must be followed at all times:
+ *
+ *  session->portal_lock      - access to a session's portal info
+ *  session->task_lock        - access to a session's collections of tasks
+ *  host_lock                 - mid-layer acquires before calling queuecommand,
+ * 				and eh_*.
+ *
+ *  Note for grabbing task_lock: queuecommand and eh_timed_out are invoked in
+ *  soft_irq context. The former can be invoked in process context as well. 
+ *  Every other function where we grab task_lock, we have process context.
+ *  Hence we use spin_lock in eh_timed_out and spin_lock_bh every where else to
+ *  grab the task lock.
+ */
+
+MODULE_AUTHOR("Cisco Systems, Inc.");
+MODULE_DESCRIPTION("iSCSI initiator");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(ISCSI_DRIVER_VERSION);
+
+kmem_cache_t *iscsi_task_cache;
+static struct scsi_transport_template *iscsi_transportt;
+
+/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
+#define SNA32_CHECK 2147483648UL
+
+int
+iscsi_sna_lt(u32 n1, u32 n2)
+{
+	return n1 != n2 && ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) ||
+			    (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
+}
+
+/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
+int
+iscsi_sna_lte(u32 n1, u32 n2)
+{
+	return n1 == n2 || ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) ||
+			    (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
+}
+
+/* mark a scsi_cmnd as having a LUN communication failure */
+static inline void
+set_lun_comm_failure(struct scsi_cmnd *sc)
+{
+	sc->sense_buffer[0] = 0x70;
+	sc->sense_buffer[2] = NOT_READY;
+	sc->sense_buffer[7] = 0x6;
+	sc->sense_buffer[12] = 0x08;
+	sc->sense_buffer[13] = 0x00;
+}
+
+u32
+iscsi_command_attr(struct scsi_cmnd *cmd)
+{
+	unsigned int attr = ISCSI_ATTR_UNTAGGED;
+	char msg[2];
+
+	if (scsi_populate_tag_msg(cmd, msg) == 2) {
+		switch (msg[0]) {
+		case MSG_SIMPLE_TAG:
+			attr = ISCSI_ATTR_SIMPLE;
+			break;
+		case MSG_HEAD_TAG:
+			attr = ISCSI_ATTR_HEAD_OF_QUEUE;
+			break;
+		case MSG_ORDERED_TAG:
+			attr = ISCSI_ATTR_ORDERED;
+			break;
+		};
+	}
+
+	return attr;
+}
+
+static int
+iscsi_slave_configure(struct scsi_device *sdev)
+{
+	int depth = 1, tag = 0;
+
+        /*
+	 * TODO (one day) - when tcq is not supported we should
+	 * internally queue a command to have one ready to go right
+	 * away when the outstanding one completes.
+         */
+	if (sdev->tagged_supported) {
+		scsi_activate_tcq(sdev, ISCSI_CMDS_PER_LUN);
+		depth = ISCSI_CMDS_PER_LUN;
+		tag = MSG_ORDERED_TAG;
+	}
+
+	scsi_adjust_queue_depth(sdev, tag, depth);
+	return 0;
+}
+
+/**
+ * iscsi_eh_timed_out - handle scsi command timeouts
+ * sc: scsi command
+ *
+ * Note:
+ *    In the normal case where the session is ok or the command was queued
+ *    when the session was down (and it never came up but did not yet timeout
+ *    - TODO use device block/unblock), we will fail the command here if
+ *    we can. For all other race cases where for example the session changed
+ *    state at the same time the command timed out but we had the task lock
+ *    we just ask for more time since those events will clean themselves up.
+ **/
+static enum scsi_eh_timer_return
+iscsi_eh_timed_out(struct scsi_cmnd *sc)
+{
+	struct Scsi_Host *shost = sc->device->host;
+	struct iscsi_session *session = (struct iscsi_session *)shost->hostdata;
+	struct iscsi_task *task;
+	enum scsi_eh_timer_return ret = EH_RESET_TIMER;
+	int result = DID_BUS_BUSY << 16;
+
+	spin_lock(&session->task_lock);
+
+	task = (struct iscsi_task *)sc->SCp.ptr;
+	if (!task) {
+		/*
+		 * completed while timer was firing
+		 */
+		ret = EH_HANDLED;
+		goto done;
+	}
+
+	if (test_bit(SESSION_ESTABLISHED, &session->control_bits))
+		ret = EH_NOT_HANDLED;
+	else if (test_bit(SESSION_REPLACEMENT_TIMEDOUT, &session->control_bits))
+		result = DID_NO_CONNECT << 16;
+
+	if (task->itt == ISCSI_RSVD_TASK_TAG) {
+		sc->result = result;
+		__iscsi_complete_task(task);
+		ret = EH_HANDLED;
+	}
+
+ done:
+	spin_unlock(&session->task_lock);
+
+	return ret;
+}
+
+static int
+iscsi_eh_abort(struct scsi_cmnd *sc)
+{
+	struct Scsi_Host *shost = sc->device->host;
+	struct iscsi_session *session = (struct iscsi_session *)shost->hostdata;
+	struct iscsi_task *task, *tmf_task;
+	int ret = FAILED;
+
+	spin_unlock_irq(shost->host_lock);
+	spin_lock_bh(&session->task_lock);
+
+	/*
+	 * TODO must fix these type of tests
+	 */
+	if (!test_bit(SESSION_ESTABLISHED, &session->control_bits))
+		goto done;
+
+	task = (struct iscsi_task *)sc->SCp.ptr;
+	if (!task) {
+		iscsi_host_err(session, "eh_abort cmnd already done\n");
+		ret = SUCCESS;
+		goto done;
+	}
+
+	if (task->itt == ISCSI_RSVD_TASK_TAG) {
+		__iscsi_complete_task(task);
+		ret = SUCCESS;
+		goto done;
+	}
+
+	/*
+	 * TODO need a iscsi_dev_info
+	 */
+	iscsi_host_info(session, "Sending ABORT TASK for task itt %u\n",
+			task->itt);
+
+	tmf_task = session->mgmt_task;
+	memset(tmf_task, 0, sizeof(*tmf_task));
+	iscsi_init_task(tmf_task);
+	tmf_task->session = session;
+	tmf_task->lun = task->lun;
+	/*
+	 * this will become the refcmdsn
+	 */
+	tmf_task->cmdsn = task->cmdsn;
+	tmf_task->rtt = task->itt;
+	set_bit(ISCSI_TASK_ABORT, &tmf_task->flags);
+
+	if (!iscsi_exec_task_mgmt(tmf_task, session->abort_timeout)) {
+		ret = SUCCESS;
+		goto done;
+	}
+	/*
+	 * TMF may have failed if the task completed first (check here)
+	 */
+	if (!sc->SCp.ptr)
+		ret = SUCCESS;
+ done:
+	spin_unlock_bh(&session->task_lock);
+	spin_lock_irq(shost->host_lock);
+
+	return ret;
+}
+
+static int
+iscsi_eh_device_reset(struct scsi_cmnd *sc)
+{
+	struct Scsi_Host *shost = sc->device->host;
+	struct iscsi_session *session = (struct iscsi_session *)shost->hostdata;
+	struct iscsi_task *task;
+	int ret = FAILED;
+
+	spin_unlock_irq(shost->host_lock);
+	spin_lock_bh(&session->task_lock);
+
+	if (!test_bit(SESSION_ESTABLISHED, &session->control_bits))
+		goto done;
+
+	task = session->mgmt_task;
+	memset(task, 0, sizeof(*task));
+	iscsi_init_task(task);
+	task->session = session;
+	task->lun = sc->device->lun;
+	__set_bit(ISCSI_TASK_ABORT_TASK_SET, &task->flags);
+
+	/*
+	 * need a iscsi_dev_info
+	 */
+	iscsi_host_info(session, "Sending ABORT TASK SET\n");
+	if (!iscsi_exec_task_mgmt(task, session->abort_timeout)) {
+		ret = SUCCESS;
+		goto done;
+	}
+
+	iscsi_init_task(task);
+	__set_bit(ISCSI_TASK_LU_RESET, &task->flags);
+
+	iscsi_host_info(session, "Sending LU RESET\n");
+ 	if (!iscsi_exec_task_mgmt(task, session->reset_timeout))
+		ret = SUCCESS;
+ done:
+	spin_unlock_bh(&session->task_lock);
+	spin_lock_irq(shost->host_lock);
+
+	return ret;
+}
+
+static int
+iscsi_eh_host_reset(struct scsi_cmnd *sc)
+{
+	struct Scsi_Host *shost = sc->device->host;
+	struct iscsi_session *session = (struct iscsi_session *)shost->hostdata;
+	struct iscsi_task *task;
+	int ret = FAILED;
+
+	spin_unlock_irq(shost->host_lock);
+	spin_lock_bh(&session->task_lock);
+
+	if (!test_bit(SESSION_ESTABLISHED, &session->control_bits))
+		goto done;
+
+	task = session->mgmt_task;
+	memset(task, 0, sizeof(*task));
+	iscsi_init_task(task);
+	task->session = session;
+	__set_bit(ISCSI_TASK_TGT_WARM_RESET, &task->flags);
+
+	iscsi_host_info(session, "Sending TARGET WARM RESET\n");
+	if (iscsi_exec_task_mgmt(task, session->reset_timeout))
+		/*
+		 * no other options
+		 */
+		iscsi_drop_session(session);
+
+ done:
+	/*
+	 * if we failed, scsi-ml will put us offline
+	 * and if we were successful it will redrive the
+	 * commands, so we clean everything up from our side
+	 * so scsi-ml can retake ownership of the commands.
+	 * (At this point the tx and rx threads will not be
+	 * touching the commands since either the session
+	 * was dropped or we just did a target reset)
+	 */
+	iscsi_flush_queues(session, ISCSI_MAX_LUNS, DID_BUS_BUSY);
+
+	spin_unlock_bh(&session->task_lock);
+	if (iscsi_wait_for_session(session, 0))
+		ret = SUCCESS;
+	spin_lock_irq(shost->host_lock);
+
+	return ret;
+}
+
+void
+iscsi_complete_command(struct scsi_cmnd *sc)
+{
+	sc->SCp.ptr = NULL;
+	sc->scsi_done(sc);
+}
+
+/**
+ * iscsi_queuecommand - queuecommand interface for the iSCSI driver.
+ * @sc: scsi command from the midlayer
+ * @done: Call back function to be called once the command is executed.
+ **/
+static int
+iscsi_queuecommand(struct scsi_cmnd *sc, void (*done) (struct scsi_cmnd *))
+{
+	struct Scsi_Host *host = sc->device->host;
+	struct iscsi_session *session = (struct iscsi_session *)host->hostdata;
+	struct iscsi_task *task;
+	int ret = 0;
+
+	spin_unlock_irq(host->host_lock);
+
+	/*
+	 * record whether I/O commands have been ever been sent on this
+	 * session, to help us decide when we need the  session and should
+	 * retry logins regardless of the login status. Ignore all the
+	 * commands sent by default as part of the LUN being scanned or a
+	 * device being opened, so that sessions that have always been idle
+	 * can be dropped.  Of course, this  is always true for disks, since
+	 * Linux will do reads  looking for a partition table.
+	 */
+	switch (sc->cmnd[0]) {
+	case INQUIRY:
+	case REPORT_LUNS:
+	case TEST_UNIT_READY:
+	case READ_CAPACITY:
+	case START_STOP:
+	case MODE_SENSE:
+		break;
+	default:
+		session->commands_queued = 1;
+		break;
+	}
+
+	if (test_bit(SESSION_REPLACEMENT_TIMEDOUT, &session->control_bits)) {
+		if (printk_ratelimit())
+			iscsi_host_warn(session, "lun%u: Session terminating, "
+					"failing to queue cdb 0x%x and any "
+					"following commands\n", sc->device->lun,					sc->cmnd[0]);
+		goto fail;
+	}
+
+	/* make sure we can complete it properly later */
+	sc->scsi_done = done;
+	sc->result = 0;
+	memset(&sc->SCp, 0, sizeof(sc->SCp));
+
+	spin_lock_bh(&session->task_lock);
+
+	/*
+	 * alloc a task and add it to the pending queue so
+	 * the tx-thread will run it
+	 */ 
+	task = iscsi_alloc_task(session);
+	if (!task) {
+		ret = SCSI_MLQUEUE_HOST_BUSY;
+		goto done;
+	}
+
+	task->lun = sc->device->lun;
+	task->scsi_cmnd = sc;
+	sc->SCp.ptr = (char *)task;
+	list_add_tail(&task->queue, &session->pending_queue);
+
+	iscsi_wake_tx_thread(TX_SCSI_COMMAND, session);
+ done:
+	spin_unlock_bh(&session->task_lock);
+	spin_lock_irq(host->host_lock);
+	return ret;
+
+ fail:
+	spin_lock_irq(host->host_lock);
+	sc->result = DID_NO_CONNECT << 16;
+	sc->resid = sc->request_bufflen;
+	set_lun_comm_failure(sc);
+
+	done(sc);
+	return 0;
+}
+
+int
+iscsi_destroy_host(struct Scsi_Host *shost)
+{
+	struct iscsi_session *session = (struct iscsi_session *)shost->hostdata;
+
+	if (!test_bit(SESSION_CREATED, &session->control_bits))
+		return -EINVAL;
+
+	if (test_and_set_bit(SESSION_RELEASING, &session->control_bits))
+		return -EINVAL;
+
+	scsi_remove_host(shost);
+	iscsi_destroy_session(session);
+	scsi_host_put(shost);
+	return 0;
+}
+
+static struct scsi_host_template iscsi_driver_template = {
+	.name = "SFNet iSCSI driver",
+	.proc_name = ISCSI_PROC_NAME,
+	.module = THIS_MODULE,
+	.queuecommand = iscsi_queuecommand,
+	.eh_timed_out = iscsi_eh_timed_out,
+	.eh_abort_handler = iscsi_eh_abort,
+	.eh_device_reset_handler = iscsi_eh_device_reset,
+	.eh_host_reset_handler = iscsi_eh_host_reset,
+	.skip_settle_delay = 1,
+	.slave_configure = iscsi_slave_configure,
+	.this_id = -1,
+	.can_queue = ISCSI_CANQUEUE,
+	.sg_tablesize = ISCSI_MAX_SG,
+	.cmd_per_lun = ISCSI_CMDS_PER_LUN,
+	.use_clustering = ENABLE_CLUSTERING,
+	.max_sectors = 256,
+	.emulated = 1,
+	.shost_attrs = iscsi_host_attrs,
+};
+
+int
+iscsi_create_host(struct iscsi_session_ioctl *ioctld)
+{
+	struct Scsi_Host *shost;
+	struct iscsi_session *session;
+	int rc;
+
+	shost = scsi_host_alloc(&iscsi_driver_template, sizeof(*session));
+	if (!shost) 
+		return -ENOMEM;
+
+	shost->max_id = ISCSI_MAX_TARGETS;
+	shost->max_lun = ISCSI_MAX_LUNS;
+	shost->max_channel = ISCSI_MAX_CHANNELS;
+	shost->max_cmd_len = ISCSI_MAX_CMD_LEN;
+	shost->transportt = iscsi_transportt;
+
+	session = (struct iscsi_session *)shost->hostdata;
+	memset(session, 0, sizeof(*session));
+	session->shost = shost;
+
+	rc = iscsi_create_session(session, ioctld);
+	if (rc) {
+		scsi_host_put(shost);
+		return rc;
+	}
+
+	rc = scsi_add_host(shost, NULL);
+	if (rc) {
+		iscsi_destroy_session(session);
+		scsi_host_put(shost);
+		return rc;
+	}
+
+	scsi_scan_host(shost);
+	set_bit(SESSION_CREATED, &session->control_bits);
+
+	return 0;
+}
+
+/*
+ * This function must only be called when the sysfs and
+ * ioctl interfaces are inaccessible. For example when
+ * the module_exit function is executed the driver's sysfs
+ * and ioctl entry points will return "no device".
+ */
+static void
+iscsi_destroy_all_hosts(void)
+{
+	struct iscsi_session *session, *tmp;
+
+	list_for_each_entry_safe(session, tmp, &iscsi_sessions, list)
+		iscsi_destroy_host(session->shost);
+}
+
+static int
+iscsi_reboot_notifier_function(struct notifier_block *this,
+			       unsigned long code, void *unused)
+{
+	iscsi_destroy_all_hosts();
+	iscsi_notice("Driver shutdown completed\n");
+	return NOTIFY_DONE;
+}
+
+/* XXX move this to driver model shutdown */
+static struct notifier_block iscsi_reboot_notifier = {
+	.notifier_call = iscsi_reboot_notifier_function,
+	.next = NULL,
+	.priority = 255, /* priority, might need to have a
+			  * relook at the value
+			  */
+};
+
+static int
+__init iscsi_init(void)
+{
+	iscsi_notice("%s (%s) built for Linux %s\n", ISCSI_DRIVER_VERSION,
+		     ISCSI_DATE, UTS_RELEASE);
+
+	/* pool of iscsi tasks */
+	iscsi_task_cache = kmem_cache_create("iscsi_task_cache",
+					     sizeof(struct iscsi_task), 0,
+					     SLAB_NO_REAP, NULL, NULL);
+
+	if (!iscsi_task_cache) {
+		iscsi_err("kmem_cache_create failed\n");
+		return -ENOMEM;
+	}
+
+	iscsi_transportt = iscsi_attach_transport(&iscsi_fnt);
+	if (!iscsi_transportt)
+		goto free_cache;
+
+	if (iscsi_register_interface())
+		goto release_transport;
+
+	register_reboot_notifier(&iscsi_reboot_notifier);
+	return 0;
+
+ release_transport:
+	iscsi_release_transport(iscsi_transportt);
+ free_cache:
+	kmem_cache_destroy(iscsi_task_cache);
+	iscsi_err("Failed to init driver\n");
+	return -ENODEV;
+}
+
+static void
+__exit iscsi_cleanup(void)
+{
+	unregister_reboot_notifier(&iscsi_reboot_notifier);
+	iscsi_unregister_interface();
+	iscsi_destroy_all_hosts();
+	iscsi_release_transport(iscsi_transportt);
+	kmem_cache_destroy(iscsi_task_cache);
+}
+module_init(iscsi_init);
+module_exit(iscsi_cleanup);
diff -Naurp scsi-misc-2.6.orig/drivers/scsi/iscsi-sfnet/iscsi-sfnet.h scsi-misc-2.6.patch/drivers/scsi/iscsi-sfnet/iscsi-sfnet.h
--- scsi-misc-2.6.orig/drivers/scsi/iscsi-sfnet/iscsi-sfnet.h	1969-12-31 16:00:00.000000000 -0800
+++ scsi-misc-2.6.patch/drivers/scsi/iscsi-sfnet/iscsi-sfnet.h	2005-01-10 12:20:05.306809612 -0800
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ *
+ * Misc definitions for the iSCSI kernel module
+ */
+#ifndef ISCSI_SFNET_H_
+#define ISCSI_SFNET_H_
+
+#include <linux/socket.h>
+#include <linux/random.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_iscsi.h>
+
+struct iscsi_session;
+struct iscsi_session_ioctl;
+struct iscsi_task;
+struct iscsi_hdr;
+
+#define ISCSI_DRIVER_VERSION	"4:0.1.10.1"
+#define ISCSI_DATE		"3-Jan-2005"
+
+/* TODO (one day): compeltely test 16 byte cmd len support */
+#define ISCSI_MAX_CMD_LEN	12
+#define ISCSI_CMDS_PER_LUN	32
+#define ISCSI_MAX_CMDS_PER_LUN	128
+#define ISCSI_CANQUEUE		8192
+#define ISCSI_MAX_SG		64
+#define ISCSI_MAX_LUNS		256
+#define ISCSI_MAX_TARGETS	1
+#define ISCSI_MAX_CHANNELS	0
+
+#define ISCSI_PROC_NAME 	"iscsi-sfnet"
+
+#define iscsi_host_err(s, fmt, args...) \
+	printk(KERN_ERR "iscsi-sfnet:host%d: "fmt, s->shost->host_no, ##args)
+#define iscsi_err(fmt, args...) \
+	printk(KERN_ERR "iscsi-sfnet: "fmt, ##args)
+
+#define iscsi_host_warn(s, fmt, args...) \
+	printk(KERN_WARNING "iscsi-sfnet:host%d: "fmt, s->shost->host_no, \
+	       ##args)
+#define iscsi_warn(fmt, args...) \
+	printk(KERN_WARNING "iscsi-sfnet: "fmt, ##args)
+
+#define iscsi_host_notice(s, fmt, args...) \
+	printk(KERN_NOTICE "iscsi-sfnet:host%d: "fmt, s->shost->host_no, ##args)
+#define iscsi_notice(fmt, args...) \
+	printk(KERN_NOTICE "iscsi-sfnet: "fmt, ##args)
+
+#define iscsi_host_info(s, fmt, args...) \
+	printk(KERN_INFO "iscsi-sfnet:host%d: "fmt, s->shost->host_no, ##args)
+#define iscsi_info(fmt, args...) \
+	printk(KERN_INFO "iscsi-sfnet: "fmt, ##args)
+
+/* miscalleneous routines */
+extern unsigned int iscsi_command_attr(struct scsi_cmnd *sc);
+extern void iscsi_complete_command(struct scsi_cmnd *sc);
+
+/* Routines related to Serial Number Arithmetic */
+extern int iscsi_sna_lt(u32 n1, u32 n2);
+extern int iscsi_sna_lte(u32 n1, u32 n2);
+
+/*
+ * IO return values the driver uses in the send, recv
+ * and network code. 
+ */
+enum {
+	ISCSI_IO_SUCCESS,
+	ISCSI_IO_ERR,
+	ISCSI_IO_CRC32C_ERR,
+	ISCSI_IO_INTR,
+	ISCSI_IO_INVALID_OP,
+};
+
+/* Routines to build and transmit iSCSI PDUs and/or data */
+extern void iscsi_send_scsi_cmnd(struct iscsi_task *task);
+extern void iscsi_send_task_mgmt(struct iscsi_session *session);
+extern void iscsi_send_r2t_data(struct iscsi_session *session);
+extern void iscsi_send_nop_replys(struct iscsi_session *session);
+extern void iscsi_send_logout(struct iscsi_session *session);
+extern void iscsi_send_nop_out(struct iscsi_session *session);
+extern void iscsi_queue_unsolicited_data(struct iscsi_task *task);
+extern int iscsi_send_pdu(struct iscsi_session *session, struct iscsi_hdr *hdr,
+			  int hdr_digest, char *data, int data_digest);
+extern int iscsi_recv_pdu(struct iscsi_session *session, struct iscsi_hdr *hdr,
+			  int hdr_digest, char *data, int data_len,
+			  int data_digest);
+
+/* Routines to send and receive data on TCP/IP sockets */
+extern int iscsi_recvmsg(struct iscsi_session *session, struct kvec *iov,
+			 size_t iovn, size_t size);
+extern int iscsi_sendmsg(struct iscsi_session *session, struct kvec *iov,
+			 size_t iovn, size_t size);
+extern int iscsi_sendpage(struct iscsi_session *session, int flags,
+			  struct page *pg, unsigned int pg_offset,
+			  unsigned int len);
+extern int iscsi_connect(struct iscsi_session *session);
+extern void iscsi_disconnect(struct iscsi_session *session);
+
+/* Register a driver interface */
+extern int iscsi_register_interface(void);
+extern void iscsi_unregister_interface(void);
+
+/* ioctl and sysfs uses these routines to interact with the initiator */
+extern int iscsi_destroy_host(struct Scsi_Host *shost);
+extern int iscsi_create_host(struct iscsi_session_ioctl *ioctld);
+
+/* Global variables */
+extern struct class_device_attribute *iscsi_host_attrs[];
+extern struct iscsi_function_template iscsi_fnt;
+
+#endif

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

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

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-01-10 22:57 [PATCH 3/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.