From patchwork Wed Jun 22 12:30:06 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Bader X-Patchwork-Id: 101451 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 04161B703D for ; Wed, 22 Jun 2011 22:30:37 +1000 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1QZMZd-0002Bp-0y; Wed, 22 Jun 2011 12:30:25 +0000 Received: from adelie.canonical.com ([91.189.90.139]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1QZMZO-0002Bj-Du for kernel-team@lists.ubuntu.com; Wed, 22 Jun 2011 12:30:10 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by adelie.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1QZMZO-0002it-7h for ; Wed, 22 Jun 2011 12:30:10 +0000 Received: from p5b2e55c3.dip.t-dialin.net ([91.46.85.195] helo=[192.168.2.5]) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1QZMZM-0001Gw-D3 for kernel-team@lists.ubuntu.com; Wed, 22 Jun 2011 12:30:10 +0000 Message-ID: <4E01E04E.6040509@canonical.com> Date: Wed, 22 Jun 2011 14:30:06 +0200 From: Stefan Bader User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.17) Gecko/20110516 Lightning/1.0b2 Thunderbird/3.1.10 MIME-Version: 1.0 To: Ubuntu Kernel Team Subject: [Oneiric] Ged rid of iscsitarget in the kernel X-Enigmail-Version: 1.1.2 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com This should be done as a DKMS module. Not that we do build it anymore but maybe ripping it out right away will give the right message. -Stefan From 522a0eb1fcf3a6d47b86aa400494e488160cc5b1 Mon Sep 17 00:00:00 2001 From: Stefan Bader Date: Wed, 22 Jun 2011 10:51:54 +0200 Subject: [PATCH] UBUNTU: SAUCE: iscsitarget: Remove driver from the kernel This driver is not boot/install essential and is provided by the iscsitarget-dkms package. Having it in the kernel itself only duplicates code and adds a chance of getting out of sync. Signed-off-by: Stefan Bader --- debian.master/config/config.common.ubuntu | 1 - ubuntu/Kconfig | 4 - ubuntu/Makefile | 4 - ubuntu/iscsitarget/BOM | 2 - ubuntu/iscsitarget/Kconfig | 3 - ubuntu/iscsitarget/Makefile | 17 - ubuntu/iscsitarget/block-io.c | 327 ----- ubuntu/iscsitarget/compat.h | 30 - ubuntu/iscsitarget/config.c | 362 ------ ubuntu/iscsitarget/conn.c | 262 ---- ubuntu/iscsitarget/digest.c | 279 ---- ubuntu/iscsitarget/digest.h | 20 - ubuntu/iscsitarget/event.c | 96 -- ubuntu/iscsitarget/file-io.c | 261 ---- ubuntu/iscsitarget/include/iet_u.h | 151 --- ubuntu/iscsitarget/iotype.c | 110 -- ubuntu/iscsitarget/iotype.h | 42 - ubuntu/iscsitarget/iscsi.c | 1967 ----------------------------- ubuntu/iscsitarget/iscsi.h | 524 -------- ubuntu/iscsitarget/iscsi_dbg.h | 137 -- ubuntu/iscsitarget/iscsi_hdr.h | 509 -------- ubuntu/iscsitarget/nthread.c | 790 ------------ ubuntu/iscsitarget/null-io.c | 98 -- ubuntu/iscsitarget/param.c | 205 --- ubuntu/iscsitarget/session.c | 180 --- ubuntu/iscsitarget/target.c | 374 ------ ubuntu/iscsitarget/target_disk.c | 589 --------- ubuntu/iscsitarget/tio.c | 121 -- ubuntu/iscsitarget/ua.c | 176 --- ubuntu/iscsitarget/volume.c | 422 ------ ubuntu/iscsitarget/wthread.c | 258 ---- 31 files changed, 0 insertions(+), 8321 deletions(-) delete mode 100644 ubuntu/iscsitarget/BOM delete mode 100644 ubuntu/iscsitarget/Kconfig delete mode 100644 ubuntu/iscsitarget/Makefile delete mode 100644 ubuntu/iscsitarget/block-io.c delete mode 100644 ubuntu/iscsitarget/compat.h delete mode 100644 ubuntu/iscsitarget/config.c delete mode 100644 ubuntu/iscsitarget/conn.c delete mode 100644 ubuntu/iscsitarget/digest.c delete mode 100644 ubuntu/iscsitarget/digest.h delete mode 100644 ubuntu/iscsitarget/event.c delete mode 100644 ubuntu/iscsitarget/file-io.c delete mode 100644 ubuntu/iscsitarget/include/iet_u.h delete mode 100644 ubuntu/iscsitarget/iotype.c delete mode 100644 ubuntu/iscsitarget/iotype.h delete mode 100644 ubuntu/iscsitarget/iscsi.c delete mode 100644 ubuntu/iscsitarget/iscsi.h delete mode 100644 ubuntu/iscsitarget/iscsi_dbg.h delete mode 100644 ubuntu/iscsitarget/iscsi_hdr.h delete mode 100644 ubuntu/iscsitarget/nthread.c delete mode 100644 ubuntu/iscsitarget/null-io.c delete mode 100644 ubuntu/iscsitarget/param.c delete mode 100644 ubuntu/iscsitarget/session.c delete mode 100644 ubuntu/iscsitarget/target.c delete mode 100644 ubuntu/iscsitarget/target_disk.c delete mode 100644 ubuntu/iscsitarget/tio.c delete mode 100644 ubuntu/iscsitarget/ua.c delete mode 100644 ubuntu/iscsitarget/volume.c delete mode 100644 ubuntu/iscsitarget/wthread.c diff --git a/debian.master/config/config.common.ubuntu b/debian.master/config/config.common.ubuntu index 202ef91..7f30751 100644 --- a/debian.master/config/config.common.ubuntu +++ b/debian.master/config/config.common.ubuntu @@ -4156,7 +4156,6 @@ CONFIG_SCSI_IN2000=m CONFIG_SCSI_INIA100=m CONFIG_SCSI_INITIO=m CONFIG_SCSI_IPS=m -# CONFIG_SCSI_ISCSITARGET is not set CONFIG_SCSI_ISCSI_ATTRS=m # CONFIG_SCSI_IZIP_EPP16 is not set # CONFIG_SCSI_IZIP_SLOW_CTR is not set diff --git a/ubuntu/Kconfig b/ubuntu/Kconfig index 443457e..0159dd3 100644 --- a/ubuntu/Kconfig +++ b/ubuntu/Kconfig @@ -34,10 +34,6 @@ source "ubuntu/omnibook/Kconfig" ## ## ## -source "ubuntu/iscsitarget/Kconfig" -## -## -## source "ubuntu/rtl8192se/Kconfig" ## ## diff --git a/ubuntu/Makefile b/ubuntu/Makefile index 43b53d1..f71a0d5 100644 --- a/ubuntu/Makefile +++ b/ubuntu/Makefile @@ -36,10 +36,6 @@ obj-$(CONFIG_NDISWRAPPER) += ndiswrapper/ ## ## ## -obj-$(CONFIG_SCSI_ISCSITARGET) += iscsitarget/ -## -## -## obj-$(CONFIG_RTL8192SE) += rtl8192se/ ## ## diff --git a/ubuntu/iscsitarget/BOM b/ubuntu/iscsitarget/BOM deleted file mode 100644 index 40751ae..0000000 --- a/ubuntu/iscsitarget/BOM +++ /dev/null @@ -1,2 +0,0 @@ -Downloaded from: http://sourceforge.net/projects/iscsitarget/files/ -Current Version: 1.4.20.2 diff --git a/ubuntu/iscsitarget/Kconfig b/ubuntu/iscsitarget/Kconfig deleted file mode 100644 index e5964dc..0000000 --- a/ubuntu/iscsitarget/Kconfig +++ /dev/null @@ -1,3 +0,0 @@ -config SCSI_ISCSITARGET - tristate "iSCSI Target Driver" - depends on SCSI diff --git a/ubuntu/iscsitarget/Makefile b/ubuntu/iscsitarget/Makefile deleted file mode 100644 index 727c706..0000000 --- a/ubuntu/iscsitarget/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# -# Makefile for the Linux kernel device drivers. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile. - -EXTRA_CFLAGS += -I$(src)/include - -obj-m += iscsi_trgt.o -iscsi_trgt-objs := tio.o iscsi.o nthread.o wthread.o config.o digest.o \ - conn.o session.o target.o volume.o iotype.o \ - file-io.o null-io.o target_disk.o event.o param.o \ - block-io.o ua.o - diff --git a/ubuntu/iscsitarget/block-io.c b/ubuntu/iscsitarget/block-io.c deleted file mode 100644 index 3e7de38..0000000 --- a/ubuntu/iscsitarget/block-io.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Target device block I/O. - * - * Based on file I/O driver from FUJITA Tomonori - * (C) 2004 - 2005 FUJITA Tomonori - * (C) 2006 Andre Brinkmann - * (C) 2007 Ross Walker - * (C) 2007 Ming Zhang - * This code is licenced under the GPL. - */ - -#include -#include -#include -#include - -#include "iscsi.h" -#include "iscsi_dbg.h" -#include "iotype.h" - -struct blockio_data { - char *path; - struct block_device *bdev; -}; - -struct tio_work { - atomic_t error; - atomic_t bios_remaining; - struct completion tio_complete; -}; - -static void blockio_bio_endio(struct bio *bio, int error) -{ - struct tio_work *tio_work = bio->bi_private; - - error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? error : -EIO; - - if (error) - atomic_set(&tio_work->error, error); - - /* If last bio signal completion */ - if (atomic_dec_and_test(&tio_work->bios_remaining)) - complete(&tio_work->tio_complete); - - bio_put(bio); -} - -/* - * Blockio_make_request(): The function translates an iscsi-request into - * a number of requests to the corresponding block device. - */ -static int -blockio_make_request(struct iet_volume *volume, struct tio *tio, int rw) -{ - struct blockio_data *bio_data = volume->private; - struct request_queue *bdev_q = bdev_get_queue(bio_data->bdev); - struct tio_work *tio_work; - struct bio *tio_bio = NULL, *bio = NULL, *biotail = NULL; - - u32 offset = tio->offset; - u32 size = tio->size; - u32 tio_index = 0; - - int max_pages = 1; - int err = 0; - - loff_t ppos = ((loff_t) tio->idx << PAGE_SHIFT) + offset; - - /* Calculate max_pages for bio_alloc (memory saver) */ - if (bdev_q) - max_pages = bio_get_nr_vecs(bio_data->bdev); - - tio_work = kzalloc(sizeof (*tio_work), GFP_KERNEL); - if (!tio_work) - return -ENOMEM; - - atomic_set(&tio_work->error, 0); - atomic_set(&tio_work->bios_remaining, 0); - init_completion(&tio_work->tio_complete); - - /* Main processing loop, allocate and fill all bios */ - while (tio_index < tio->pg_cnt) { - bio = bio_alloc(GFP_KERNEL, min(max_pages, BIO_MAX_PAGES)); - if (!bio) { - err = -ENOMEM; - goto out; - } - - /* bi_sector is ALWAYS in units of 512 bytes */ - bio->bi_sector = ppos >> 9; - bio->bi_bdev = bio_data->bdev; - bio->bi_end_io = blockio_bio_endio; - bio->bi_private = tio_work; - - if (tio_bio) - biotail = biotail->bi_next = bio; - else - tio_bio = biotail = bio; - - atomic_inc(&tio_work->bios_remaining); - - /* Loop for filling bio */ - while (tio_index < tio->pg_cnt) { - unsigned int bytes = PAGE_SIZE - offset; - - if (bytes > size) - bytes = size; - - if (!bio_add_page(bio, tio->pvec[tio_index], bytes, offset)) - break; - - size -= bytes; - ppos += bytes; - - offset = 0; - - tio_index++; - } - } - - /* Walk the list, submitting bios 1 by 1 */ - while (tio_bio) { - bio = tio_bio; - tio_bio = tio_bio->bi_next; - bio->bi_next = NULL; - - submit_bio(rw, bio); - } - - if (bdev_q && bdev_q->unplug_fn) - bdev_q->unplug_fn(bdev_q); - - wait_for_completion(&tio_work->tio_complete); - - err = atomic_read(&tio_work->error); - - kfree(tio_work); - - return err; -out: - while (tio_bio) { - bio = tio_bio; - tio_bio = tio_bio->bi_next; - - bio_put(bio); - } - - kfree(tio_work); - - return err; -} - -static int -blockio_open_path(struct iet_volume *volume, const char *path) -{ - struct blockio_data *bio_data = volume->private; - struct block_device *bdev; - int flags = FMODE_READ | (LUReadonly(volume) ? 0 : FMODE_WRITE); - int err = 0; - - bio_data->path = kstrdup(path, GFP_KERNEL); - if (!bio_data->path) - return -ENOMEM; - - bdev = blkdev_get_by_path(path, flags | FMODE_EXCL, THIS_MODULE); - if (IS_ERR(bdev)) { - err = PTR_ERR(bdev); - eprintk("Can't open device %s, error %d\n", path, err); - bio_data->bdev = NULL; - } else { - bio_data->bdev = bdev; - fsync_bdev(bio_data->bdev); - } - - return err; -} - -/* Create an enumeration of our accepted actions */ -enum -{ - opt_path, opt_ignore, opt_err, -}; - -/* Create a match table using our action enums and their matching options */ -static match_table_t tokens = { - {opt_path, "path=%s"}, - {opt_ignore, "scsiid=%s"}, - {opt_ignore, "scsisn=%s"}, - {opt_ignore, "type=%s"}, - {opt_ignore, "iomode=%s"}, - {opt_ignore, "blocksize=%s"}, - {opt_err, NULL}, -}; - -static int -parse_blockio_params(struct iet_volume *volume, char *params) -{ - struct blockio_data *info = volume->private; - int err = 0; - char *p, *q; - - /* Loop through parameters separated by commas, look up our - * parameter in match table, return enumeration and arguments - * select case based on the returned enum and run the action */ - while ((p = strsep(¶ms, ",")) != NULL) { - substring_t args[MAX_OPT_ARGS]; - int token; - if (!*p) - continue; - iet_strtolower(p); - token = match_token(p, tokens, args); - switch (token) { - case opt_path: - if (info->path) { - iprintk("Target %s, LUN %u: " - "duplicate \"Path\" param\n", - volume->target->name, volume->lun); - err = -EINVAL; - goto out; - } - if (!(q = match_strdup(&args[0]))) { - err = -ENOMEM; - goto out; - } - err = blockio_open_path(volume, q); - kfree(q); - if (err < 0) - goto out; - break; - case opt_ignore: - break; - default: - iprintk("Target %s, LUN %u: unknown param %s\n", - volume->target->name, volume->lun, p); - return -EINVAL; - } - } - - if (!info->path) { - iprintk("Target %s, LUN %u: missing \"Path\" param\n", - volume->target->name, volume->lun); - err = -EINVAL; - } - - out: - return err; -} - -static void -blockio_detach(struct iet_volume *volume) -{ - struct blockio_data *bio_data = volume->private; - int flags = FMODE_READ | (LUReadonly(volume) ? 0 : FMODE_WRITE); - - if (bio_data->bdev) - blkdev_put(bio_data->bdev, flags | FMODE_EXCL); - kfree(bio_data->path); - - kfree(volume->private); -} - -static int -blockio_attach(struct iet_volume *volume, char *args) -{ - struct blockio_data *bio_data; - int err = 0; - - if (volume->private) { - eprintk("Lun %u already attached on Target %s \n", - volume->lun, volume->target->name); - return -EBUSY; - } - - bio_data = kzalloc(sizeof (*bio_data), GFP_KERNEL); - if (!bio_data) - return -ENOMEM; - - volume->private = bio_data; - - err = parse_blockio_params(volume, args); - if (!err) { - /* see Documentation/ABI/testing/sysfs-block */ - unsigned bsz = bdev_logical_block_size(bio_data->bdev); - if (!volume->blk_shift) - volume->blk_shift = blksize_bits(bsz); - else if (volume->blk_shift < blksize_bits(bsz)) { - eprintk("Specified block size (%u) smaller than " - "device %s logical block size (%u)\n", - (1 << volume->blk_shift), bio_data->path, bsz); - err = -EINVAL; - } - } - if (err < 0) { - eprintk("Error attaching Lun %u to Target %s \n", - volume->lun, volume->target->name); - goto out; - } - - volume->blk_cnt = bio_data->bdev->bd_inode->i_size >> volume->blk_shift; - - /* Offer neither write nor read caching */ - ClearLURCache(volume); - ClearLUWCache(volume); - - out: - if (err < 0) - blockio_detach(volume); - - return err; -} - -static void -blockio_show(struct iet_volume *volume, struct seq_file *seq) -{ - struct blockio_data *bio_data = volume->private; - - /* Used to display blockio volume info in /proc/net/iet/volumes */ - seq_printf(seq, " path:%s\n", bio_data->path); -} - -struct iotype blockio = { - .name = "blockio", - .attach = blockio_attach, - .make_request = blockio_make_request, - .detach = blockio_detach, - .show = blockio_show, -}; diff --git a/ubuntu/iscsitarget/compat.h b/ubuntu/iscsitarget/compat.h deleted file mode 100644 index 631a49c..0000000 --- a/ubuntu/iscsitarget/compat.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Kernel compatibility routines - * - * Copyright (C) 2008 Ross Walker - * - * Released under the terms of the GNU GPL v2.0. - */ - -#ifndef __IET_COMPAT_H__ -#define __IET_COMPAT_H__ - -#include - -#ifndef DECLARE_COMPLETION_ONSTACK -#define DECLARE_COMPLETION_ONSTACK(work) DECLARE_COMPLETION(work) -#endif - -#ifndef is_power_of_2 -#define is_power_of_2(n) (n != 0 && ((n & (n - 1)) == 0)) -#endif - -#ifndef log2 -#define log2(n) ((sizeof(n) <= 4) ? (fls(n) - 1) : (fls64(n) - 1)) -#endif - -#ifndef roundup_pow_of_two -#define roundup_pow_of_two(n) (1UL << fls_long(n - 1)) -#endif - -#endif /* __IET_COMPAT_H__ */ diff --git a/ubuntu/iscsitarget/config.c b/ubuntu/iscsitarget/config.c deleted file mode 100644 index 2146504..0000000 --- a/ubuntu/iscsitarget/config.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * (C) 2004 - 2005 FUJITA Tomonori - * - * This code is licenced under the GPL. - */ - -#include - -#include "iscsi.h" -#include "iscsi_dbg.h" - -static DEFINE_SEMAPHORE(ioctl_sem); - -struct proc_entries { - const char *name; - struct file_operations *fops; -}; - -static struct proc_entries iet_proc_entries[] = -{ - {"volume", &volume_seq_fops}, - {"session", &session_seq_fops}, -}; - -static struct proc_dir_entry *proc_iet_dir; - -void iet_procfs_exit(void) -{ - int i; - - if (!proc_iet_dir) - return; - - for (i = 0; i < ARRAY_SIZE(iet_proc_entries); i++) - remove_proc_entry(iet_proc_entries[i].name, proc_iet_dir); - - remove_proc_entry(proc_iet_dir->name, proc_iet_dir->parent); -} - -int iet_procfs_init(void) -{ - int i; - struct proc_dir_entry *ent; - - if (!(proc_iet_dir = proc_mkdir("iet", init_net.proc_net))) - goto err; - - for (i = 0; i < ARRAY_SIZE(iet_proc_entries); i++) { - ent = create_proc_entry(iet_proc_entries[i].name, 0, proc_iet_dir); - if (ent) - ent->proc_fops = iet_proc_entries[i].fops; - else - goto err; - } - - return 0; - -err: - if (proc_iet_dir) - iet_procfs_exit(); - - return -ENOMEM; -} - -static int get_module_info(unsigned long ptr) -{ - struct module_info info; - int err; - - snprintf(info.version, sizeof(info.version), "%s", IET_VERSION_STRING); - - err = copy_to_user((void *) ptr, &info, sizeof(info)); - if (err) - return -EFAULT; - - return 0; -} - -static int get_conn_info(struct iscsi_target *target, unsigned long ptr) -{ - struct iscsi_session *session; - struct iscsi_conn *conn; - struct conn_info info; - int err; - - err = copy_from_user(&info, (void *) ptr, sizeof(info)); - if (err) - return -EFAULT; - - session = session_lookup(target, info.sid); - if (!session) - return -ENOENT; - - conn = conn_lookup(session, info.cid); - if (!conn) - return -ENOENT; - - info.cid = conn->cid; - info.stat_sn = conn->stat_sn; - info.exp_stat_sn = conn->exp_stat_sn; - - err = copy_to_user((void *) ptr, &info, sizeof(info)); - if (err) - return -EFAULT; - - return 0; -} - -static int add_conn(struct iscsi_target *target, unsigned long ptr) -{ - struct iscsi_session *session; - struct conn_info info; - int err; - - err = copy_from_user(&info, (void *) ptr, sizeof(info)); - if (err) - return -EFAULT; - - session = session_lookup(target, info.sid); - if (!session) - return -ENOENT; - - return conn_add(session, &info); -} - -static int del_conn(struct iscsi_target *target, unsigned long ptr) -{ - struct iscsi_session *session; - struct conn_info info; - int err; - - err = copy_from_user(&info, (void *) ptr, sizeof(info)); - if (err) - return -EFAULT; - - session = session_lookup(target, info.sid); - if (!session) - return -ENOENT; - - return conn_del(session, &info); -} - -static int get_session_info(struct iscsi_target *target, unsigned long ptr) -{ - struct iscsi_session *session; - struct session_info info; - int err; - - err = copy_from_user(&info, (void *) ptr, sizeof(info)); - if (err) - return -EFAULT; - - session = session_lookup(target, info.sid); - if (!session) - return -ENOENT; - - info.exp_cmd_sn = session->exp_cmd_sn; - info.max_cmd_sn = session->max_cmd_sn; - - err = copy_to_user((void *) ptr, &info, sizeof(info)); - if (err) - return -EFAULT; - - return 0; -} - -static int add_session(struct iscsi_target *target, unsigned long ptr) -{ - struct session_info info; - int err; - - err = copy_from_user(&info, (void *) ptr, sizeof(info)); - if (err) - return -EFAULT; - - return session_add(target, &info); -} - -static int del_session(struct iscsi_target *target, unsigned long ptr) -{ - struct session_info info; - int err; - - err = copy_from_user(&info, (void *) ptr, sizeof(info)); - if (err) - return -EFAULT; - - return session_del(target, info.sid); -} - -static int add_volume(struct iscsi_target *target, unsigned long ptr) -{ - struct volume_info info; - int err; - - err = copy_from_user(&info, (void *) ptr, sizeof(info)); - if (err) - return -EFAULT; - - return volume_add(target, &info); -} - -static int del_volume(struct iscsi_target *target, unsigned long ptr) -{ - struct volume_info info; - int err; - - err = copy_from_user(&info, (void *) ptr, sizeof(info)); - if (err) - return -EFAULT; - - return iscsi_volume_del(target, &info); -} - -static int iscsi_param_config(struct iscsi_target *target, unsigned long ptr, int set) -{ - struct iscsi_param_info info; - int err; - - err = copy_from_user(&info, (void *) ptr, sizeof(info)); - if (err) - return -EFAULT; - - err = iscsi_param_set(target, &info, set); - if (err < 0 || set) - return err; - - err = copy_to_user((void *) ptr, &info, sizeof(info)); - if (err) - return -EFAULT; - - return 0; -} - -static int add_target(unsigned long ptr) -{ - struct target_info info; - int err; - - err = copy_from_user(&info, (void *) ptr, sizeof(info)); - if (err) - return -EFAULT; - - err = target_add(&info); - if (err < 0) - return err; - - err = copy_to_user((void *) ptr, &info, sizeof(info)); - if (err) - return -EFAULT; - - return 0; -} - -static long ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct iscsi_target *target = NULL; - long err; - u32 id; - - err = down_interruptible(&ioctl_sem); - if (err < 0) - return err; - - if (cmd == GET_MODULE_INFO) { - err = get_module_info(arg); - goto done; - } - - if (cmd == ADD_TARGET) { - err = add_target(arg); - goto done; - } - - err = get_user(id, (u32 *) arg); - if (err < 0) - goto done; - - /* locking handled in target_del */ - if (cmd == DEL_TARGET) { - err = target_del(id); - goto done; - } - - target = target_lookup_by_id(id); - if (!target) { - err = -ENOENT; - goto done; - } - - err = target_lock(target, 1); - if (err < 0) - goto done; - - switch (cmd) { - case ADD_VOLUME: - err = add_volume(target, arg); - break; - - case DEL_VOLUME: - err = del_volume(target, arg); - break; - - case ADD_SESSION: - err = add_session(target, arg); - break; - - case DEL_SESSION: - err = del_session(target, arg); - break; - - case GET_SESSION_INFO: - err = get_session_info(target, arg); - break; - - case ISCSI_PARAM_SET: - err = iscsi_param_config(target, arg, 1); - break; - - case ISCSI_PARAM_GET: - err = iscsi_param_config(target, arg, 0); - break; - - case ADD_CONN: - err = add_conn(target, arg); - break; - - case DEL_CONN: - err = del_conn(target, arg); - break; - - case GET_CONN_INFO: - err = get_conn_info(target, arg); - break; - default: - eprintk("invalid ioctl cmd %x\n", cmd); - err = -EINVAL; - } - - target_unlock(target); -done: - up(&ioctl_sem); - - return err; -} - -static int release(struct inode *i __attribute__((unused)), - struct file *f __attribute__((unused))) -{ - down(&ioctl_sem); - target_del_all(); - up(&ioctl_sem); - - return 0; -} - -struct file_operations ctr_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = ioctl, - .compat_ioctl = ioctl, - .release = release -}; diff --git a/ubuntu/iscsitarget/conn.c b/ubuntu/iscsitarget/conn.c deleted file mode 100644 index f2c98b7..0000000 --- a/ubuntu/iscsitarget/conn.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2002-2003 Ardis Technolgies - * - * Released under the terms of the GNU GPL v2.0. - */ - -#include -#include -#include -#include - -#include "iscsi.h" -#include "iscsi_dbg.h" -#include "digest.h" - -static void print_conn_state(char *p, size_t size, unsigned long state) -{ - if (test_bit(CONN_ACTIVE, &state)) - snprintf(p, size, "%s", "active"); - else if (test_bit(CONN_CLOSING, &state)) - snprintf(p, size, "%s", "closing"); - else - snprintf(p, size, "%s", "unknown"); -} - -static void print_digest_state(char *p, size_t size, unsigned long flags) -{ - if (DIGEST_NONE & flags) - snprintf(p, size, "%s", "none"); - else if (DIGEST_CRC32C & flags) - snprintf(p, size, "%s", "crc32c"); - else - snprintf(p, size, "%s", "unknown"); -} - -void conn_info_show(struct seq_file *seq, struct iscsi_session *session) -{ - struct iscsi_conn *conn; - struct sock *sk; - char buf[64]; - - list_for_each_entry(conn, &session->conn_list, list) { - sk = conn->sock->sk; - switch (sk->sk_family) { - case AF_INET: - snprintf(buf, sizeof(buf), - "%pI4", &inet_sk(sk)->inet_daddr); - break; - case AF_INET6: - snprintf(buf, sizeof(buf), "[%pI6]", - &inet6_sk(sk)->daddr); - break; - default: - break; - } - seq_printf(seq, "\t\tcid:%u ip:%s ", conn->cid, buf); - print_conn_state(buf, sizeof(buf), conn->state); - seq_printf(seq, "state:%s ", buf); - print_digest_state(buf, sizeof(buf), conn->hdigest_type); - seq_printf(seq, "hd:%s ", buf); - print_digest_state(buf, sizeof(buf), conn->ddigest_type); - seq_printf(seq, "dd:%s\n", buf); - } -} - -struct iscsi_conn *conn_lookup(struct iscsi_session *session, u16 cid) -{ - struct iscsi_conn *conn; - - list_for_each_entry(conn, &session->conn_list, list) { - if (conn->cid == cid) - return conn; - } - return NULL; -} - -static void iet_state_change(struct sock *sk) -{ - struct iscsi_conn *conn = sk->sk_user_data; - struct iscsi_target *target = conn->session->target; - - if (sk->sk_state != TCP_ESTABLISHED) - conn_close(conn); - else - nthread_wakeup(target); - - target->nthread_info.old_state_change(sk); -} - -static void iet_data_ready(struct sock *sk, int len) -{ - struct iscsi_conn *conn = sk->sk_user_data; - struct iscsi_target *target = conn->session->target; - - nthread_wakeup(target); - target->nthread_info.old_data_ready(sk, len); -} - -/* - * @locking: grabs the target's nthread_lock to protect it from races with - * set_conn_wspace_wait() - */ -static void iet_write_space(struct sock *sk) -{ - struct iscsi_conn *conn = sk->sk_user_data; - struct network_thread_info *info = &conn->session->target->nthread_info; - - spin_lock_bh(&info->nthread_lock); - - if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && - test_bit(CONN_WSPACE_WAIT, &conn->state)) { - clear_bit(CONN_WSPACE_WAIT, &conn->state); - __nthread_wakeup(info); - } - - spin_unlock_bh(&info->nthread_lock); - - info->old_write_space(sk); -} - -static void iet_socket_bind(struct iscsi_conn *conn) -{ - int opt = 1; - mm_segment_t oldfs; - struct iscsi_session *session = conn->session; - struct iscsi_target *target = session->target; - - dprintk(D_GENERIC, "%llu\n", (unsigned long long) session->sid); - - conn->sock = SOCKET_I(conn->file->f_dentry->d_inode); - conn->sock->sk->sk_user_data = conn; - - write_lock_bh(&conn->sock->sk->sk_callback_lock); - target->nthread_info.old_state_change = conn->sock->sk->sk_state_change; - conn->sock->sk->sk_state_change = iet_state_change; - - target->nthread_info.old_data_ready = conn->sock->sk->sk_data_ready; - conn->sock->sk->sk_data_ready = iet_data_ready; - - target->nthread_info.old_write_space = conn->sock->sk->sk_write_space; - conn->sock->sk->sk_write_space = iet_write_space; - write_unlock_bh(&conn->sock->sk->sk_callback_lock); - - oldfs = get_fs(); - set_fs(get_ds()); - conn->sock->ops->setsockopt(conn->sock, SOL_TCP, TCP_NODELAY, (void *)&opt, sizeof(opt)); - set_fs(oldfs); -} - -int conn_free(struct iscsi_conn *conn) -{ - dprintk(D_GENERIC, "%p %#Lx %u\n", conn->session, - (unsigned long long) conn->session->sid, conn->cid); - - assert(atomic_read(&conn->nr_cmnds) == 0); - assert(list_empty(&conn->pdu_list)); - assert(list_empty(&conn->write_list)); - - list_del(&conn->list); - list_del(&conn->poll_list); - - del_timer_sync(&conn->nop_timer); - digest_cleanup(conn); - kfree(conn); - - return 0; -} - -static int iet_conn_alloc(struct iscsi_session *session, struct conn_info *info) -{ - struct iscsi_conn *conn; - - dprintk(D_SETUP, "%#Lx:%u\n", (unsigned long long) session->sid, info->cid); - - conn = kzalloc(sizeof(*conn), GFP_KERNEL); - if (!conn) - return -ENOMEM; - - conn->session = session; - conn->cid = info->cid; - conn->stat_sn = info->stat_sn; - conn->exp_stat_sn = info->exp_stat_sn; - - conn->hdigest_type = info->header_digest; - conn->ddigest_type = info->data_digest; - if (digest_init(conn) < 0) { - kfree(conn); - return -ENOMEM; - } - - spin_lock_init(&conn->list_lock); - atomic_set(&conn->nr_cmnds, 0); - atomic_set(&conn->nr_busy_cmnds, 0); - INIT_LIST_HEAD(&conn->pdu_list); - INIT_LIST_HEAD(&conn->write_list); - INIT_LIST_HEAD(&conn->poll_list); - init_timer(&conn->nop_timer); - - list_add(&conn->list, &session->conn_list); - - set_bit(CONN_ACTIVE, &conn->state); - - conn->file = fget(info->fd); - iet_socket_bind(conn); - - list_add(&conn->poll_list, &session->target->nthread_info.active_conns); - - nthread_wakeup(conn->session->target); - - return 0; -} - -void conn_close(struct iscsi_conn *conn) -{ - struct iscsi_cmnd *cmnd; - struct iscsi_session *session = conn->session; - - if (test_and_clear_bit(CONN_ACTIVE, &conn->state)) - set_bit(CONN_CLOSING, &conn->state); - - spin_lock(&conn->list_lock); - list_for_each_entry(cmnd, &conn->pdu_list, conn_list) { - set_cmnd_tmfabort(cmnd); - if (cmnd->lun) { - ua_establish_for_session(session, cmnd->lun->lun, 0x47, 0x7f); - iscsi_cmnd_set_sense(cmnd, UNIT_ATTENTION, 0x6e, 0x0); - } - } - spin_unlock(&conn->list_lock); - - nthread_wakeup(conn->session->target); -} - -int conn_add(struct iscsi_session *session, struct conn_info *info) -{ - struct iscsi_conn *conn; - int err; - - conn = conn_lookup(session, info->cid); - if (conn) - conn_close(conn); - - err = iet_conn_alloc(session, info); - if (!err && conn) - err = -EEXIST; - - return err; -} - -int conn_del(struct iscsi_session *session, struct conn_info *info) -{ - struct iscsi_conn *conn; - int err = -EEXIST; - - conn = conn_lookup(session, info->cid); - if (!conn) - return err; - - conn_close(conn); - - return 0; -} diff --git a/ubuntu/iscsitarget/digest.c b/ubuntu/iscsitarget/digest.c deleted file mode 100644 index 32b4d76..0000000 --- a/ubuntu/iscsitarget/digest.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * iSCSI digest handling. - * (C) 2004 - 2006 Xiranet Communications GmbH - * This code is licensed under the GPL. - */ - -#include - -#include "iscsi.h" -#include "digest.h" -#include "iscsi_dbg.h" - -void digest_alg_available(unsigned int *val) -{ - if (*val & DIGEST_CRC32C && - !crypto_has_alg("crc32c", 0, CRYPTO_ALG_ASYNC)) { - printk("CRC32C digest algorithm not available in kernel\n"); - *val |= ~DIGEST_CRC32C; - } -} - -/** - * initialize support for digest calculation. - * - * digest_init - - * @conn: ptr to connection to make use of digests - * - * @return: 0 on success, < 0 on error - */ -int digest_init(struct iscsi_conn *conn) -{ - int err = 0; - - if (!(conn->hdigest_type & DIGEST_ALL)) - conn->hdigest_type = DIGEST_NONE; - - if (!(conn->ddigest_type & DIGEST_ALL)) - conn->ddigest_type = DIGEST_NONE; - - if (conn->hdigest_type & DIGEST_CRC32C || - conn->ddigest_type & DIGEST_CRC32C) { - conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - conn->rx_hash.flags = 0; - if (IS_ERR(conn->rx_hash.tfm)) { - conn->rx_hash.tfm = NULL; - err = -ENOMEM; - goto out; - } - - conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - conn->tx_hash.flags = 0; - if (IS_ERR(conn->tx_hash.tfm)) { - conn->tx_hash.tfm = NULL; - err = -ENOMEM; - goto out; - } - } - -out: - if (err) - digest_cleanup(conn); - - return err; -} - -/** - * free resources used for digest calculation. - * - * digest_cleanup - - * @conn: ptr to connection that made use of digests - */ -void digest_cleanup(struct iscsi_conn *conn) -{ - if (conn->tx_hash.tfm) - crypto_free_hash(conn->tx_hash.tfm); - if (conn->rx_hash.tfm) - crypto_free_hash(conn->rx_hash.tfm); -} - -/** - * debug handling of header digest errors: - * simulates a digest error after n PDUs / every n-th PDU of type - * HDIGEST_ERR_CORRUPT_PDU_TYPE. - */ -static inline void __dbg_simulate_header_digest_error(struct iscsi_cmnd *cmnd) -{ -#define HDIGEST_ERR_AFTER_N_CMNDS 1000 -#define HDIGEST_ERR_ONLY_ONCE 1 -#define HDIGEST_ERR_CORRUPT_PDU_TYPE ISCSI_OP_SCSI_CMD -#define HDIGEST_ERR_CORRUPT_PDU_WITH_DATA_ONLY 0 - - static int num_cmnds = 0; - static int num_errs = 0; - - if (cmnd_opcode(cmnd) == HDIGEST_ERR_CORRUPT_PDU_TYPE) { - if (HDIGEST_ERR_CORRUPT_PDU_WITH_DATA_ONLY) { - if (cmnd->pdu.datasize) - num_cmnds++; - } else - num_cmnds++; - } - - if ((num_cmnds == HDIGEST_ERR_AFTER_N_CMNDS) - && (!(HDIGEST_ERR_ONLY_ONCE && num_errs))) { - printk("*** Faking header digest error ***\n"); - printk("\tcmnd: 0x%x, itt 0x%x, sn 0x%x\n", - cmnd_opcode(cmnd), - be32_to_cpu(cmnd->pdu.bhs.itt), - be32_to_cpu(cmnd->pdu.bhs.sn)); - cmnd->hdigest = ~cmnd->hdigest; - /* make things even worse by manipulating header fields */ - cmnd->pdu.datasize += 8; - num_errs++; - num_cmnds = 0; - } - return; -} - -/** - * debug handling of data digest errors: - * simulates a digest error after n PDUs / every n-th PDU of type - * DDIGEST_ERR_CORRUPT_PDU_TYPE. - */ -static inline void __dbg_simulate_data_digest_error(struct iscsi_cmnd *cmnd) -{ -#define DDIGEST_ERR_AFTER_N_CMNDS 50 -#define DDIGEST_ERR_ONLY_ONCE 1 -#define DDIGEST_ERR_CORRUPT_PDU_TYPE ISCSI_OP_SCSI_DATA_OUT -#define DDIGEST_ERR_CORRUPT_UNSOL_DATA_ONLY 0 - - static int num_cmnds = 0; - static int num_errs = 0; - - if ((cmnd->pdu.datasize) - && (cmnd_opcode(cmnd) == DDIGEST_ERR_CORRUPT_PDU_TYPE)) { - switch (cmnd_opcode(cmnd)) { - case ISCSI_OP_SCSI_DATA_OUT: - if ((DDIGEST_ERR_CORRUPT_UNSOL_DATA_ONLY) - && (cmnd->pdu.bhs.ttt != ISCSI_RESERVED_TAG)) - break; - default: - num_cmnds++; - } - } - - if ((num_cmnds == DDIGEST_ERR_AFTER_N_CMNDS) - && (!(DDIGEST_ERR_ONLY_ONCE && num_errs)) - && (cmnd->pdu.datasize) - && (!cmnd->conn->read_overflow)) { - printk("*** Faking data digest error: ***"); - printk("\tcmnd 0x%x, itt 0x%x, sn 0x%x\n", - cmnd_opcode(cmnd), - be32_to_cpu(cmnd->pdu.bhs.itt), - be32_to_cpu(cmnd->pdu.bhs.sn)); - cmnd->ddigest = ~cmnd->ddigest; - num_errs++; - num_cmnds = 0; - } -} - -static void digest_header(struct hash_desc *hash, struct iscsi_pdu *pdu, - u8 *crc) -{ - struct scatterlist sg[2]; - unsigned int nbytes = sizeof(struct iscsi_hdr); - - sg_init_table(sg, pdu->ahssize ? 2 : 1); - - sg_set_buf(&sg[0], &pdu->bhs, nbytes); - if (pdu->ahssize) { - sg_set_buf(&sg[1], pdu->ahs, pdu->ahssize); - nbytes += pdu->ahssize; - } - - crypto_hash_init(hash); - crypto_hash_update(hash, sg, nbytes); - crypto_hash_final(hash, crc); -} - -int digest_rx_header(struct iscsi_cmnd *cmnd) -{ - u32 crc; - - digest_header(&cmnd->conn->rx_hash, &cmnd->pdu, (u8 *) &crc); - if (crc != cmnd->hdigest) - return -EIO; - - return 0; -} - -void digest_tx_header(struct iscsi_cmnd *cmnd) -{ - digest_header(&cmnd->conn->tx_hash, &cmnd->pdu, (u8 *) &cmnd->hdigest); -} - -static void digest_data(struct hash_desc *hash, struct iscsi_cmnd *cmnd, - struct tio *tio, u32 offset, u8 *crc) -{ - struct scatterlist *sg = cmnd->conn->hash_sg; - u32 size, length; - int i, idx, count; - unsigned int nbytes; - - size = cmnd->pdu.datasize; - nbytes = size = (size + 3) & ~3; - - offset += tio->offset; - idx = offset >> PAGE_CACHE_SHIFT; - offset &= ~PAGE_CACHE_MASK; - count = get_pgcnt(size, offset); - assert(idx + count <= tio->pg_cnt); - - assert(count <= ISCSI_CONN_IOV_MAX); - - sg_init_table(sg, ARRAY_SIZE(cmnd->conn->hash_sg)); - crypto_hash_init(hash); - - for (i = 0; size; i++) { - if (offset + size > PAGE_CACHE_SIZE) - length = PAGE_CACHE_SIZE - offset; - else - length = size; - - sg_set_page(&sg[i], tio->pvec[idx + i], length, offset); - size -= length; - offset = 0; - } - - sg_mark_end(&sg[i - 1]); - - crypto_hash_update(hash, sg, nbytes); - crypto_hash_final(hash, crc); -} - -int digest_rx_data(struct iscsi_cmnd *cmnd) -{ - struct tio *tio; - struct iscsi_cmnd *scsi_cmnd; - struct iscsi_data_out_hdr *req; - u32 offset, crc; - - switch (cmnd_opcode(cmnd)) { - case ISCSI_OP_SCSI_REJECT: - case ISCSI_OP_PDU_REJECT: - case ISCSI_OP_DATA_REJECT: - return 0; - case ISCSI_OP_SCSI_DATA_OUT: - scsi_cmnd = cmnd->req; - req = (struct iscsi_data_out_hdr *) &cmnd->pdu.bhs; - tio = scsi_cmnd->tio; - offset = be32_to_cpu(req->buffer_offset); - break; - default: - tio = cmnd->tio; - offset = 0; - } - - digest_data(&cmnd->conn->rx_hash, cmnd, tio, offset, (u8 *) &crc); - - if (!cmnd->conn->read_overflow && - (cmnd_opcode(cmnd) != ISCSI_OP_PDU_REJECT)) { - if (crc != cmnd->ddigest) - return -EIO; - } - - return 0; -} - -void digest_tx_data(struct iscsi_cmnd *cmnd) -{ - struct tio *tio = cmnd->tio; - struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs; - - assert(tio); - digest_data(&cmnd->conn->tx_hash, cmnd, tio, - be32_to_cpu(req->buffer_offset), (u8 *) &cmnd->ddigest); -} diff --git a/ubuntu/iscsitarget/digest.h b/ubuntu/iscsitarget/digest.h deleted file mode 100644 index 9b9d845..0000000 --- a/ubuntu/iscsitarget/digest.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * iSCSI digest handling. - * (C) 2004 Xiranet Communications GmbH - * This code is licensed under the GPL. - */ - -#ifndef __IET_DIGEST_H__ -#define __IET_DIGEST_H__ - -extern void digest_alg_available(unsigned int *val); -extern int digest_init(struct iscsi_conn *conn); -extern void digest_cleanup(struct iscsi_conn *conn); - -extern int digest_rx_header(struct iscsi_cmnd *cmnd); -extern int digest_rx_data(struct iscsi_cmnd *cmnd); - -extern void digest_tx_header(struct iscsi_cmnd *cmnd); -extern void digest_tx_data(struct iscsi_cmnd *cmnd); - -#endif /* __IET_DIGEST_H__ */ diff --git a/ubuntu/iscsitarget/event.c b/ubuntu/iscsitarget/event.c deleted file mode 100644 index 240404d..0000000 --- a/ubuntu/iscsitarget/event.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Event notification code. - * (C) 2005 FUJITA Tomonori - * This code is licenced under the GPL. - * - * Some functions are based on audit code. - */ - -#include -#include "iet_u.h" -#include "iscsi_dbg.h" - -static struct sock *nl; -static u32 ietd_pid; - -static int event_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) -{ - u32 uid, pid, seq; - char *data; - - pid = NETLINK_CREDS(skb)->pid; - uid = NETLINK_CREDS(skb)->uid; - seq = nlh->nlmsg_seq; - data = NLMSG_DATA(nlh); - - ietd_pid = pid; - - return 0; -} - -static void event_recv_skb(struct sk_buff *skb) -{ - int err; - struct nlmsghdr *nlh; - u32 rlen; - - while (skb->len >= NLMSG_SPACE(0)) { - nlh = (struct nlmsghdr *)skb->data; - if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) - break; - rlen = NLMSG_ALIGN(nlh->nlmsg_len); - if (rlen > skb->len) - rlen = skb->len; - if ((err = event_recv_msg(skb, nlh))) { - netlink_ack(skb, nlh, -err); - } else if (nlh->nlmsg_flags & NLM_F_ACK) - netlink_ack(skb, nlh, 0); - skb_pull(skb, rlen); - } -} - -static int notify(void *data, int len, int gfp_mask) -{ - struct sk_buff *skb; - struct nlmsghdr *nlh; - static u32 seq = 0; - - if (!(skb = alloc_skb(NLMSG_SPACE(len), gfp_mask))) - return -ENOMEM; - - nlh = __nlmsg_put(skb, ietd_pid, seq++, NLMSG_DONE, len - sizeof(*nlh), 0); - - memcpy(NLMSG_DATA(nlh), data, len); - - return netlink_unicast(nl, skb, ietd_pid, 0); -} - -int event_send(u32 tid, u64 sid, u32 cid, u32 state, int atomic) -{ - int err; - struct iet_event event; - - event.tid = tid; - event.sid = sid; - event.cid = cid; - event.state = state; - - err = notify(&event, NLMSG_SPACE(sizeof(struct iet_event)), 0); - - return err; -} - -int event_init(void) -{ - nl = netlink_kernel_create(&init_net, NETLINK_IET, 1, event_recv_skb, - NULL, THIS_MODULE); - if (!nl) - return -ENOMEM; - else - return 0; -} - -void event_exit(void) -{ - netlink_kernel_release(nl); -} diff --git a/ubuntu/iscsitarget/file-io.c b/ubuntu/iscsitarget/file-io.c deleted file mode 100644 index a050fcc..0000000 --- a/ubuntu/iscsitarget/file-io.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Target device file I/O. - * (C) 2004 - 2005 FUJITA Tomonori - * This code is licenced under the GPL. - */ - -#include -#include -#include -#include - -#include "iscsi.h" -#include "iscsi_dbg.h" -#include "iotype.h" - -struct fileio_data { - char *path; - struct file *filp; -}; - -static int fileio_make_request(struct iet_volume *lu, struct tio *tio, int rw) -{ - struct fileio_data *p = lu->private; - struct file *filp; - mm_segment_t oldfs; - struct page *page; - u32 offset, size; - loff_t ppos, count; - char *buf; - int i, err = 0; - ssize_t ret; - - assert(p); - filp = p->filp; - size = tio->size; - offset= tio->offset; - - ppos = (loff_t) tio->idx << PAGE_CACHE_SHIFT; - ppos += offset; - - for (i = 0; i < tio->pg_cnt; i++) { - page = tio->pvec[i]; - assert(page); - buf = page_address(page); - buf += offset; - - if (offset + size > PAGE_CACHE_SIZE) - count = PAGE_CACHE_SIZE - offset; - else - count = size; - - oldfs = get_fs(); - set_fs(get_ds()); - - if (rw == READ) - ret = vfs_read(filp, buf, count, &ppos); - else - ret = vfs_write(filp, buf, count, &ppos); - - set_fs(oldfs); - - if (ret != count) { - eprintk("I/O error %lld, %ld\n", count, (long) ret); - err = -EIO; - } - - size -= count; - offset = 0; - } - assert(!size); - - return err; -} - -static int fileio_sync(struct iet_volume *lu, struct tio *tio) -{ - struct fileio_data *p = lu->private; - struct inode *inode = p->filp->f_dentry->d_inode; - struct address_space *mapping = inode->i_mapping; - loff_t ppos, count; - int res; - - if (tio) { - ppos = (loff_t) tio->idx << PAGE_CACHE_SHIFT; - ppos += tio->offset; - count = tio->size; - } else { - ppos = 0; - count = lu->blk_cnt << lu->blk_shift; - } - - res = filemap_write_and_wait_range(mapping, ppos, ppos + count - 1); - if (res) { - eprintk("I/O error: syncing pages failed: %d\n", res); - return -EIO; - } else - return 0; -} - -static int open_path(struct iet_volume *volume, const char *path) -{ - int err = 0; - struct fileio_data *info = volume->private; - struct file *filp; - mm_segment_t oldfs; - int flags; - - info->path = kstrdup(path, GFP_KERNEL); - if (!info->path) - return -ENOMEM; - - oldfs = get_fs(); - set_fs(get_ds()); - flags = (LUReadonly(volume) ? O_RDONLY : O_RDWR) | O_LARGEFILE; - filp = filp_open(path, flags, 0); - set_fs(oldfs); - - if (IS_ERR(filp)) { - err = PTR_ERR(filp); - eprintk("Can't open %s %d\n", path, err); - info->filp = NULL; - } else - info->filp = filp; - - return err; -} - -enum { - opt_path, opt_ignore, opt_err, -}; - -static match_table_t tokens = { - {opt_path, "path=%s"}, - {opt_ignore, "scsiid=%s"}, - {opt_ignore, "scsisn=%s"}, - {opt_ignore, "type=%s"}, - {opt_ignore, "iomode=%s"}, - {opt_ignore, "blocksize=%s"}, - {opt_err, NULL}, -}; - -static int parse_fileio_params(struct iet_volume *volume, char *params) -{ - struct fileio_data *info = volume->private; - int err = 0; - char *p, *q; - - while ((p = strsep(¶ms, ",")) != NULL) { - substring_t args[MAX_OPT_ARGS]; - int token; - if (!*p) - continue; - iet_strtolower(p); - token = match_token(p, tokens, args); - switch (token) { - case opt_path: - if (info->path) { - iprintk("Target %s, LUN %u: " - "duplicate \"Path\" param\n", - volume->target->name, volume->lun); - err = -EINVAL; - goto out; - } - if (!(q = match_strdup(&args[0]))) { - err = -ENOMEM; - goto out; - } - err = open_path(volume, q); - kfree(q); - if (err < 0) - goto out; - break; - case opt_ignore: - break; - default: - iprintk("Target %s, LUN %u: unknown param %s\n", - volume->target->name, volume->lun, p); - return -EINVAL; - } - } - - if (!info->path) { - iprintk("Target %s, LUN %u: missing \"Path\" param\n", - volume->target->name, volume->lun); - err = -EINVAL; - } -out: - return err; -} - -static void fileio_detach(struct iet_volume *lu) -{ - struct fileio_data *p = lu->private; - - kfree(p->path); - if (p->filp) - filp_close(p->filp, NULL); - kfree(p); - lu->private = NULL; -} - -static int fileio_attach(struct iet_volume *lu, char *args) -{ - int err = 0; - struct fileio_data *p; - struct inode *inode; - - if (lu->private) { - printk("already attached ? %d\n", lu->lun); - return -EBUSY; - } - - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return -ENOMEM; - - lu->private = p; - - if ((err = parse_fileio_params(lu, args)) < 0) { - eprintk("%d\n", err); - goto out; - } - inode = p->filp->f_dentry->d_inode; - - if (S_ISREG(inode->i_mode)) - ; - else if (S_ISBLK(inode->i_mode)) - inode = inode->i_bdev->bd_inode; - else { - err = -EINVAL; - goto out; - } - - if (!lu->blk_shift) - lu->blk_shift = blksize_bits(IET_DEF_BLOCK_SIZE); - - lu->blk_cnt = inode->i_size >> lu->blk_shift; - - /* we're using the page cache */ - SetLURCache(lu); -out: - if (err < 0) - fileio_detach(lu); - return err; -} - -static void fileio_show(struct iet_volume *lu, struct seq_file *seq) -{ - struct fileio_data *p = lu->private; - seq_printf(seq, " path:%s\n", p->path); -} - -struct iotype fileio = -{ - .name = "fileio", - .attach = fileio_attach, - .make_request = fileio_make_request, - .sync = fileio_sync, - .detach = fileio_detach, - .show = fileio_show, -}; diff --git a/ubuntu/iscsitarget/include/iet_u.h b/ubuntu/iscsitarget/include/iet_u.h deleted file mode 100644 index 6fdc716..0000000 --- a/ubuntu/iscsitarget/include/iet_u.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef _IET_U_H -#define _IET_U_H - -#define IET_VERSION_STRING "1.4.20.2" - -/* The maximum length of 223 bytes in the RFC. */ -#define ISCSI_NAME_LEN 256 -#define ISCSI_ARGS_LEN 2048 - -#define ISCSI_LISTEN_PORT 3260 - -#define SCSI_ID_LEN 16 -#define SCSI_SN_LEN (SCSI_ID_LEN * 2) - -#ifndef aligned_u64 -#define aligned_u64 unsigned long long __attribute__((aligned(8))) -#endif - -struct module_info { - char version[128]; -}; - -struct target_info { - u32 tid; - char name[ISCSI_NAME_LEN]; -}; - -struct volume_info { - u32 tid; - u32 lun; - aligned_u64 args_ptr; - u32 args_len; -}; - -struct session_info { - u32 tid; - - aligned_u64 sid; - char initiator_name[ISCSI_NAME_LEN]; - u32 exp_cmd_sn; - u32 max_cmd_sn; -}; - -#define DIGEST_ALL (DIGEST_NONE | DIGEST_CRC32C) -#define DIGEST_NONE (1 << 0) -#define DIGEST_CRC32C (1 << 1) - -struct conn_info { - u32 tid; - aligned_u64 sid; - - u32 cid; - u32 stat_sn; - u32 exp_stat_sn; - int header_digest; - int data_digest; - int fd; -}; - -enum { - key_initial_r2t, - key_immediate_data, - key_max_connections, - key_max_recv_data_length, - key_max_xmit_data_length, - key_max_burst_length, - key_first_burst_length, - key_default_wait_time, - key_default_retain_time, - key_max_outstanding_r2t, - key_data_pdu_inorder, - key_data_sequence_inorder, - key_error_recovery_level, - key_header_digest, - key_data_digest, - key_ofmarker, - key_ifmarker, - key_ofmarkint, - key_ifmarkint, - session_key_last, -}; - -enum { - key_wthreads, - key_target_type, - key_queued_cmnds, - key_nop_interval, - key_nop_timeout, - target_key_last, -}; - -enum { - key_session, - key_target, -}; - -struct iscsi_param_info { - u32 tid; - aligned_u64 sid; - - u32 param_type; - u32 partial; - - u32 session_param[session_key_last]; - u32 target_param[target_key_last]; -}; - -enum iet_event_state { - E_CONN_CLOSE, -}; - -struct iet_event { - u32 tid; - aligned_u64 sid; - u32 cid; - u32 state; -}; - -#define DEFAULT_NR_WTHREADS 8 -#define MIN_NR_WTHREADS 1 -#define MAX_NR_WTHREADS 128 - -#define DEFAULT_NR_QUEUED_CMNDS 32 -#define MIN_NR_QUEUED_CMNDS 1 -#define MAX_NR_QUEUED_CMNDS 256 - -#define DEFAULT_NOP_INTERVAL 0 -#define MIN_NOP_INTERVAL 0 -#define MAX_NOP_INTERVAL 90 - -#define DEFAULT_NOP_TIMEOUT 0 -#define MIN_NOP_TIMEOUT 0 -#define MAX_NOP_TIMEOUT 90 - -#define NETLINK_IET 21 - -#define GET_MODULE_INFO _IOW('i', 20, struct module_info) -#define ADD_TARGET _IOWR('i', 21, struct target_info) -#define DEL_TARGET _IOW('i', 22, struct target_info) -#define ADD_VOLUME _IOW('i', 24, struct volume_info) -#define DEL_VOLUME _IOW('i', 25, struct volume_info) -#define ADD_SESSION _IOW('i', 26, struct session_info) -#define DEL_SESSION _IOW('i', 27, struct session_info) -#define GET_SESSION_INFO _IOWR('i', 28, struct session_info) -#define ADD_CONN _IOW('i', 29, struct conn_info) -#define DEL_CONN _IOW('i', 30, struct conn_info) -#define GET_CONN_INFO _IOWR('i', 31, struct conn_info) -#define ISCSI_PARAM_SET _IOW('i', 32, struct iscsi_param_info) -#define ISCSI_PARAM_GET _IOWR('i', 33, struct iscsi_param_info) - -#endif diff --git a/ubuntu/iscsitarget/iotype.c b/ubuntu/iscsitarget/iotype.c deleted file mode 100644 index 007d1fe..0000000 --- a/ubuntu/iscsitarget/iotype.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Manager for various I/O types. - * (C) 2004 - 2005 FUJITA Tomonori - * This code is licenced under the GPL. - */ - -#include "iscsi.h" -#include "iotype.h" -#include "iscsi_dbg.h" - -static LIST_HEAD(iotypes); -static rwlock_t iotypes_lock = __RW_LOCK_UNLOCKED(iotypes_lock); - -static struct iotype *find_iotype(const char *name) -{ - struct iotype *iot = NULL; - - list_for_each_entry(iot, &iotypes, iot_list) { - if (strcmp(iot->name, name) == 0) - return iot; - } - return NULL; -} - -struct iotype *get_iotype(const char *name) -{ - struct iotype *iot; - - read_lock(&iotypes_lock); - iot = find_iotype(name); - read_unlock(&iotypes_lock); - - return iot; -} - -void put_iotype(struct iotype *iot) -{ - if (!iot) - return; - return; -} - -static int register_iotype(struct iotype *iot) -{ - int err = 0; - struct iotype *p; - - write_lock(&iotypes_lock); - - p = find_iotype(iot->name); - if (p) - err = -EBUSY; - else - list_add_tail(&iot->iot_list, &iotypes); - - write_unlock(&iotypes_lock); - - return err; -} - -static int unregister_iotype(struct iotype *iot) -{ - int err = 0; - struct iotype *p; - - write_lock(&iotypes_lock); - - p = find_iotype(iot->name); - if (p && p == iot) - list_del_init(&iot->iot_list); - else - err = -EINVAL; - - write_unlock(&iotypes_lock); - - - return err; -} - -struct iotype *iotype_array[] = { - &fileio, - &blockio, - &nullio, -}; - -int iotype_init(void) -{ - int i, err; - - for (i = 0; i < ARRAY_SIZE(iotype_array); i++) { - if (!(err = register_iotype(iotype_array[i]))) - iprintk("Registered io type %s\n", - iotype_array[i]->name); - else { - eprintk("Failed to register io type %s\n", - iotype_array[i]->name); - break; - } - } - - return err; -} - -void iotype_exit(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(iotype_array); i++) - unregister_iotype(iotype_array[i]); -} diff --git a/ubuntu/iscsitarget/iotype.h b/ubuntu/iscsitarget/iotype.h deleted file mode 100644 index db7956a..0000000 --- a/ubuntu/iscsitarget/iotype.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * (C) 2004 - 2005 FUJITA Tomonori - * This code is licenced under the GPL. - */ - -#include -#include "iscsi.h" - -#ifndef __IOTYPE_H__ -#define __IOTYPE_H__ - -struct iotype { - const char *name; - struct list_head iot_list; - - int (*attach)(struct iet_volume *dev, char *args); - int (*make_request)(struct iet_volume *dev, struct tio *tio, int rw); - int (*sync)(struct iet_volume *dev, struct tio *tio); - void (*detach)(struct iet_volume *dev); - void (*show)(struct iet_volume *dev, struct seq_file *seq); -}; - -extern struct iotype fileio; -extern struct iotype nullio; -extern struct iotype blockio; - -extern int iotype_init(void); -extern void iotype_exit(void); - -/* For option parameter parsing. - * This is slightly iet specific: we only tolower() up to the first '='. - * Note that this changes *c _in place_, but our parsing - * routines copy the input to a scratch page before parsing anyways. */ -static inline void iet_strtolower(char *c) -{ - if (!c) - return; - for (; *c && *c != '='; c++) - *c = tolower(*c); -} - -#endif diff --git a/ubuntu/iscsitarget/iscsi.c b/ubuntu/iscsitarget/iscsi.c deleted file mode 100644 index 05197f2..0000000 --- a/ubuntu/iscsitarget/iscsi.c +++ /dev/null @@ -1,1967 +0,0 @@ -/* - * Copyright (C) 2002-2003 Ardis Technolgies - * Copyright (C) 2008 Arne Redlich - * - * Released under the terms of the GNU GPL v2.0. - */ - -#include -#include -#include -#include - -#include "iscsi.h" -#include "iscsi_dbg.h" -#include "iotype.h" - -unsigned long debug_enable_flags; -unsigned long worker_thread_pool_size; - -static struct kmem_cache *iscsi_cmnd_cache; -static u8 dummy_data[PAGE_SIZE]; - -static int ctr_major; -static char ctr_name[] = "ietctl"; -extern struct file_operations ctr_fops; - -static u32 cmnd_write_size(struct iscsi_cmnd *cmnd) -{ - struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd); - - if (hdr->flags & ISCSI_CMD_WRITE) - return be32_to_cpu(hdr->data_length); - return 0; -} - -static u32 cmnd_read_size(struct iscsi_cmnd *cmnd) -{ - struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd); - - if (hdr->flags & ISCSI_CMD_READ) { - struct iscsi_rlength_ahdr *ahdr = - (struct iscsi_rlength_ahdr *)cmnd->pdu.ahs; - - if (!(hdr->flags & ISCSI_CMD_WRITE)) - return be32_to_cpu(hdr->data_length); - if (ahdr && ahdr->ahstype == ISCSI_AHSTYPE_RLENGTH) - return be32_to_cpu(ahdr->read_length); - } - return 0; -} - -static void iscsi_device_queue_cmnd(struct iscsi_cmnd *cmnd) -{ - set_cmnd_waitio(cmnd); - wthread_queue(cmnd); -} - -static void iscsi_scsi_queuecmnd(struct iscsi_cmnd *cmnd) -{ - struct iscsi_queue *queue = &cmnd->lun->queue; - - dprintk(D_GENERIC, "%p\n", cmnd); - - if ((cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) != ISCSI_CMD_UNTAGGED && - (cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) != ISCSI_CMD_SIMPLE) { - cmnd->pdu.bhs.flags &= ~ISCSI_CMD_ATTR_MASK; - cmnd->pdu.bhs.flags |= ISCSI_CMD_UNTAGGED; - } - - spin_lock(&queue->queue_lock); - - set_cmnd_queued(cmnd); - - switch (cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) { - case ISCSI_CMD_UNTAGGED: - case ISCSI_CMD_SIMPLE: - if (!list_empty(&queue->wait_list) || queue->ordered_cmnd) - goto pending; - queue->active_cnt++; - break; - - default: - BUG(); - } - spin_unlock(&queue->queue_lock); - - iscsi_device_queue_cmnd(cmnd); - return; - pending: - assert(list_empty(&cmnd->list)); - - list_add_tail(&cmnd->list, &queue->wait_list); - spin_unlock(&queue->queue_lock); - return; -} - -static void iscsi_scsi_dequeuecmnd(struct iscsi_cmnd *cmnd) -{ - struct iscsi_queue *queue; - - if (!cmnd->lun) - return; - queue = &cmnd->lun->queue; - spin_lock(&queue->queue_lock); - switch (cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) { - case ISCSI_CMD_UNTAGGED: - case ISCSI_CMD_SIMPLE: - --queue->active_cnt; - break; - case ISCSI_CMD_ORDERED: - case ISCSI_CMD_HEAD_OF_QUEUE: - case ISCSI_CMD_ACA: - BUG(); - default: - /* Should the iscsi_scsi_queuecmnd func reject this ? */ - break; - } - - while (!list_empty(&queue->wait_list)) { - cmnd = list_entry(queue->wait_list.next, struct iscsi_cmnd, list); - switch ((cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK)) { - case ISCSI_CMD_UNTAGGED: - case ISCSI_CMD_SIMPLE: - list_del_init(&cmnd->list); - queue->active_cnt++; - iscsi_device_queue_cmnd(cmnd); - break; - case ISCSI_CMD_ORDERED: - case ISCSI_CMD_HEAD_OF_QUEUE: - case ISCSI_CMD_ACA: - BUG(); - } - } - - spin_unlock(&queue->queue_lock); - - return; -} - -/** - * create a new command. - * - * iscsi_cmnd_create - - * @conn: ptr to connection (for i/o) - * - * @return ptr to command or NULL - */ - -struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *conn, int req) -{ - struct iscsi_cmnd *cmnd; - - /* TODO: async interface is necessary ? */ - cmnd = kmem_cache_alloc(iscsi_cmnd_cache, GFP_KERNEL|__GFP_NOFAIL); - - memset(cmnd, 0, sizeof(*cmnd)); - INIT_LIST_HEAD(&cmnd->list); - INIT_LIST_HEAD(&cmnd->pdu_list); - INIT_LIST_HEAD(&cmnd->conn_list); - INIT_LIST_HEAD(&cmnd->hash_list); - cmnd->conn = conn; - spin_lock(&conn->list_lock); - atomic_inc(&conn->nr_cmnds); - if (req) - list_add_tail(&cmnd->conn_list, &conn->pdu_list); - spin_unlock(&conn->list_lock); - cmnd->tio = NULL; - - dprintk(D_GENERIC, "%p:%p\n", conn, cmnd); - - return cmnd; -} - -/** - * create a new command used as response. - * - * iscsi_cmnd_create_rsp_cmnd - - * @cmnd: ptr to request command - * - * @return ptr to response command or NULL - */ - -static struct iscsi_cmnd *iscsi_cmnd_create_rsp_cmnd(struct iscsi_cmnd *cmnd, int final) -{ - struct iscsi_cmnd *rsp = cmnd_alloc(cmnd->conn, 0); - - if (final) - set_cmnd_final(rsp); - list_add_tail(&rsp->pdu_list, &cmnd->pdu_list); - rsp->req = cmnd; - return rsp; -} - -static struct iscsi_cmnd *get_rsp_cmnd(struct iscsi_cmnd *req) -{ - return list_entry(req->pdu_list.prev, struct iscsi_cmnd, pdu_list); -} - -static void iscsi_cmnds_init_write(struct list_head *send) -{ - struct iscsi_cmnd *cmnd = list_entry(send->next, struct iscsi_cmnd, list); - struct iscsi_conn *conn = cmnd->conn; - struct list_head *pos, *next; - - spin_lock(&conn->list_lock); - - list_for_each_safe(pos, next, send) { - cmnd = list_entry(pos, struct iscsi_cmnd, list); - - dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd)); - - list_del_init(&cmnd->list); - assert(conn == cmnd->conn); - list_add_tail(&cmnd->list, &conn->write_list); - } - - spin_unlock(&conn->list_lock); - - nthread_wakeup(conn->session->target); -} - -static void iscsi_cmnd_init_write(struct iscsi_cmnd *cmnd) -{ - LIST_HEAD(head); - - if (!list_empty(&cmnd->list)) { - eprintk("%x %x %x %x %lx %u %u %u %u %u %u %u %d %d\n", - cmnd_itt(cmnd), cmnd_ttt(cmnd), cmnd_opcode(cmnd), - cmnd_scsicode(cmnd), cmnd->flags, cmnd->r2t_sn, - cmnd->r2t_length, cmnd->is_unsolicited_data, - cmnd->target_task_tag, cmnd->outstanding_r2t, - cmnd->hdigest, cmnd->ddigest, - list_empty(&cmnd->pdu_list), list_empty(&cmnd->hash_list)); - - assert(list_empty(&cmnd->list)); - } - list_add(&cmnd->list, &head); - iscsi_cmnds_init_write(&head); -} - -static void do_send_data_rsp(struct iscsi_cmnd *cmnd) -{ - struct iscsi_conn *conn = cmnd->conn; - struct iscsi_cmnd *data_cmnd; - struct tio *tio = cmnd->tio; - struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); - struct iscsi_data_in_hdr *rsp; - u32 pdusize, expsize, scsisize, size, offset, sn; - LIST_HEAD(send); - - dprintk(D_GENERIC, "%p\n", cmnd); - pdusize = conn->session->param.max_xmit_data_length; - expsize = cmnd_read_size(cmnd); - size = min(expsize, tio->size); - offset = 0; - sn = 0; - - while (1) { - data_cmnd = iscsi_cmnd_create_rsp_cmnd(cmnd, size <= pdusize); - tio_get(tio); - data_cmnd->tio = tio; - rsp = (struct iscsi_data_in_hdr *)&data_cmnd->pdu.bhs; - - rsp->opcode = ISCSI_OP_SCSI_DATA_IN; - rsp->itt = req->itt; - rsp->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); - rsp->buffer_offset = offset; - rsp->data_sn = cpu_to_be32(sn); - - if (size <= pdusize) { - data_cmnd->pdu.datasize = size; - rsp->flags = ISCSI_FLG_FINAL | ISCSI_FLG_STATUS; - - scsisize = tio->size; - if (scsisize < expsize) { - rsp->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW; - size = expsize - scsisize; - } else if (scsisize > expsize) { - rsp->flags |= ISCSI_FLG_RESIDUAL_OVERFLOW; - size = scsisize - expsize; - } else - size = 0; - rsp->residual_count = cpu_to_be32(size); - list_add_tail(&data_cmnd->list, &send); - - break; - } - - data_cmnd->pdu.datasize = pdusize; - - size -= pdusize; - offset += pdusize; - sn++; - - list_add_tail(&data_cmnd->list, &send); - } - - iscsi_cmnds_init_write(&send); -} - -static struct iscsi_cmnd *create_scsi_rsp(struct iscsi_cmnd *req) -{ - struct iscsi_cmnd *rsp; - struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req); - struct iscsi_scsi_rsp_hdr *rsp_hdr; - struct iscsi_sense_data *sense; - - rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); - - rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs; - rsp_hdr->opcode = ISCSI_OP_SCSI_RSP; - rsp_hdr->flags = ISCSI_FLG_FINAL; - rsp_hdr->response = ISCSI_RESPONSE_COMMAND_COMPLETED; - rsp_hdr->cmd_status = req->status; - rsp_hdr->itt = req_hdr->itt; - - if (req->status == SAM_STAT_CHECK_CONDITION) { - assert(!rsp->tio); - rsp->tio = tio_alloc(1); - sense = (struct iscsi_sense_data *) - page_address(rsp->tio->pvec[0]); - - assert(sense); - clear_page(sense); - sense->length = cpu_to_be16(IET_SENSE_BUF_SIZE); - - memcpy(sense->data, req->sense_buf, IET_SENSE_BUF_SIZE); - rsp->pdu.datasize = sizeof(struct iscsi_sense_data) + - IET_SENSE_BUF_SIZE; - - rsp->tio->size = (rsp->pdu.datasize + 3) & -4; - rsp->tio->offset = 0; - } - - return rsp; -} - -void iscsi_cmnd_set_sense(struct iscsi_cmnd *cmnd, u8 sense_key, u8 asc, - u8 ascq) -{ - cmnd->status = SAM_STAT_CHECK_CONDITION; - - cmnd->sense_buf[0] = 0xf0; - cmnd->sense_buf[2] = sense_key; - cmnd->sense_buf[7] = 6; // Additional sense length - cmnd->sense_buf[12] = asc; - cmnd->sense_buf[13] = ascq; - - /* Call to ACA/UAI handler */ -} - -static struct iscsi_cmnd *create_sense_rsp(struct iscsi_cmnd *req, - u8 sense_key, u8 asc, u8 ascq) -{ - iscsi_cmnd_set_sense(req, sense_key, asc, ascq); - return create_scsi_rsp(req); -} - -void send_scsi_rsp(struct iscsi_cmnd *req, void (*func)(struct iscsi_cmnd *)) -{ - struct iscsi_cmnd *rsp; - struct iscsi_scsi_rsp_hdr *rsp_hdr; - u32 size; - - func(req); - rsp = create_scsi_rsp(req); - - switch (req->status) { - case SAM_STAT_GOOD: - case SAM_STAT_RESERVATION_CONFLICT: - rsp_hdr = (struct iscsi_scsi_rsp_hdr *) &rsp->pdu.bhs; - if ((size = cmnd_read_size(req)) != 0) { - rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW; - rsp_hdr->residual_count = cpu_to_be32(size); - } - break; - default: - break; - } - - iscsi_cmnd_init_write(rsp); -} - -void send_data_rsp(struct iscsi_cmnd *req, void (*func)(struct iscsi_cmnd *)) -{ - struct iscsi_cmnd *rsp; - - func(req); - - if (req->status == SAM_STAT_GOOD) - do_send_data_rsp(req); - else { - rsp = create_scsi_rsp(req); - iscsi_cmnd_init_write(rsp); - } -} - -/** - * Free a command. - * Also frees the additional header. - * - * iscsi_cmnd_remove - - * @cmnd: ptr to command - */ - -static void iscsi_cmnd_remove(struct iscsi_cmnd *cmnd) -{ - struct iscsi_conn *conn; - - if (!cmnd) - return; - - if (cmnd_timer_active(cmnd)) { - clear_cmnd_timer_active(cmnd); - del_timer_sync(&cmnd->timer); - } - - dprintk(D_GENERIC, "%p\n", cmnd); - conn = cmnd->conn; - kfree(cmnd->pdu.ahs); - - if (!list_empty(&cmnd->list)) { - struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); - - eprintk("cmnd %p still on some list?, %x, %x, %x, %x, %x, %x, %x %lx\n", - cmnd, req->opcode, req->scb[0], req->flags, req->itt, - be32_to_cpu(req->data_length), - req->cmd_sn, be32_to_cpu(cmnd->pdu.datasize), - conn->state); - - if (cmnd->req) { - struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd->req); - eprintk("%p %x %u\n", req, req->opcode, req->scb[0]); - } - dump_stack(); - BUG(); - } - list_del(&cmnd->list); - spin_lock(&conn->list_lock); - atomic_dec(&conn->nr_cmnds); - list_del(&cmnd->conn_list); - spin_unlock(&conn->list_lock); - - if (cmnd->tio) - tio_put(cmnd->tio); - - kmem_cache_free(iscsi_cmnd_cache, cmnd); -} - -static void cmnd_skip_pdu(struct iscsi_cmnd *cmnd) -{ - struct iscsi_conn *conn = cmnd->conn; - struct tio *tio = cmnd->tio; - char *addr; - u32 size; - int i; - - eprintk("%x %x %x %u\n", cmnd_itt(cmnd), cmnd_opcode(cmnd), - cmnd_hdr(cmnd)->scb[0], cmnd->pdu.datasize); - - if (!(size = cmnd->pdu.datasize)) - return; - - if (tio) - assert(tio->pg_cnt > 0); - else - tio = cmnd->tio = tio_alloc(1); - - addr = page_address(tio->pvec[0]); - assert(addr); - size = (size + 3) & -4; - conn->read_size = size; - for (i = 0; size > PAGE_CACHE_SIZE; i++, size -= PAGE_CACHE_SIZE) { - assert(i < ISCSI_CONN_IOV_MAX); - conn->read_iov[i].iov_base = addr; - conn->read_iov[i].iov_len = PAGE_CACHE_SIZE; - } - conn->read_iov[i].iov_base = addr; - conn->read_iov[i].iov_len = size; - conn->read_msg.msg_iov = conn->read_iov; - conn->read_msg.msg_iovlen = ++i; -} - -static void iscsi_cmnd_reject(struct iscsi_cmnd *req, int reason) -{ - struct iscsi_cmnd *rsp; - struct iscsi_reject_hdr *rsp_hdr; - struct tio *tio; - char *addr; - - rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); - rsp_hdr = (struct iscsi_reject_hdr *)&rsp->pdu.bhs; - - rsp_hdr->opcode = ISCSI_OP_REJECT; - rsp_hdr->ffffffff = ISCSI_RESERVED_TAG; - rsp_hdr->reason = reason; - - rsp->tio = tio = tio_alloc(1); - addr = page_address(tio->pvec[0]); - clear_page(addr); - memcpy(addr, &req->pdu.bhs, sizeof(struct iscsi_hdr)); - tio->size = rsp->pdu.datasize = sizeof(struct iscsi_hdr); - cmnd_skip_pdu(req); - - req->pdu.bhs.opcode = ISCSI_OP_PDU_REJECT; -} - -static void cmnd_set_sn(struct iscsi_cmnd *cmnd, int set_stat_sn) -{ - struct iscsi_conn *conn = cmnd->conn; - struct iscsi_session *sess = conn->session; - - if (set_stat_sn) - cmnd->pdu.bhs.sn = cpu_to_be32(conn->stat_sn++); - cmnd->pdu.bhs.exp_sn = cpu_to_be32(sess->exp_cmd_sn); - cmnd->pdu.bhs.max_sn = cpu_to_be32(sess->exp_cmd_sn + sess->max_queued_cmnds); -} - -static void update_stat_sn(struct iscsi_cmnd *cmnd) -{ - struct iscsi_conn *conn = cmnd->conn; - u32 exp_stat_sn; - - cmnd->pdu.bhs.exp_sn = exp_stat_sn = be32_to_cpu(cmnd->pdu.bhs.exp_sn); - dprintk(D_GENERIC, "%x,%x\n", cmnd_opcode(cmnd), exp_stat_sn); - if ((int)(exp_stat_sn - conn->exp_stat_sn) > 0 && - (int)(exp_stat_sn - conn->stat_sn) <= 0) { - // free pdu resources - cmnd->conn->exp_stat_sn = exp_stat_sn; - } -} - -static int check_cmd_sn(struct iscsi_cmnd *cmnd) -{ - struct iscsi_session *session = cmnd->conn->session; - u32 cmd_sn; - - cmnd->pdu.bhs.sn = cmd_sn = be32_to_cpu(cmnd->pdu.bhs.sn); - - dprintk(D_GENERIC, "cmd_sn(%u) exp_cmd_sn(%u) max_cmd_sn(%u)\n", - cmd_sn, session->exp_cmd_sn, session->max_cmd_sn); - - if (between(cmd_sn, session->exp_cmd_sn, session->max_cmd_sn)) - return 0; - else if (cmnd_immediate(cmnd)) - return 0; - - eprintk("sequence error: cmd_sn(%u) exp_cmd_sn(%u) max_cmd_sn(%u)\n", - cmd_sn, session->exp_cmd_sn, session->max_cmd_sn); - - set_cmnd_tmfabort(cmnd); - - return -ISCSI_REASON_PROTOCOL_ERROR; -} - -static struct iscsi_cmnd *__cmnd_find_hash(struct iscsi_session *session, u32 itt, u32 ttt) -{ - struct list_head *head; - struct iscsi_cmnd *cmnd; - - head = &session->cmnd_hash[cmnd_hashfn(itt)]; - - list_for_each_entry(cmnd, head, hash_list) { - if (cmnd->pdu.bhs.itt == itt) { - if ((ttt != ISCSI_RESERVED_TAG) && (ttt != cmnd->target_task_tag)) - continue; - return cmnd; - } - } - - return NULL; -} - -static struct iscsi_cmnd *cmnd_find_hash(struct iscsi_session *session, u32 itt, u32 ttt) -{ - struct iscsi_cmnd *cmnd; - - spin_lock(&session->cmnd_hash_lock); - - cmnd = __cmnd_find_hash(session, itt, ttt); - - spin_unlock(&session->cmnd_hash_lock); - - return cmnd; -} - -static int cmnd_insert_hash_ttt(struct iscsi_cmnd *cmnd, u32 ttt) -{ - struct iscsi_session *session = cmnd->conn->session; - struct iscsi_cmnd *tmp; - struct list_head *head; - int err = 0; - u32 itt = cmnd->pdu.bhs.itt; - - head = &session->cmnd_hash[cmnd_hashfn(itt)]; - - spin_lock(&session->cmnd_hash_lock); - - tmp = __cmnd_find_hash(session, itt, ttt); - if (!tmp) { - list_add_tail(&cmnd->hash_list, head); - set_cmnd_hashed(cmnd); - } else - err = -ISCSI_REASON_TASK_IN_PROGRESS; - - spin_unlock(&session->cmnd_hash_lock); - - return err; -} - -static int cmnd_insert_hash(struct iscsi_cmnd *cmnd) -{ - int err; - - dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd->pdu.bhs.itt); - - if (cmnd->pdu.bhs.itt == ISCSI_RESERVED_TAG) - return -ISCSI_REASON_PROTOCOL_ERROR; - - err = cmnd_insert_hash_ttt(cmnd, ISCSI_RESERVED_TAG); - if (!err) { - update_stat_sn(cmnd); - err = check_cmd_sn(cmnd); - } else if (!cmnd_immediate(cmnd)) - set_cmnd_tmfabort(cmnd); - - return err; -} - -static void __cmnd_remove_hash(struct iscsi_cmnd *cmnd) -{ - list_del(&cmnd->hash_list); -} - -static void cmnd_remove_hash(struct iscsi_cmnd *cmnd) -{ - struct iscsi_session *session = cmnd->conn->session; - struct iscsi_cmnd *tmp; - - spin_lock(&session->cmnd_hash_lock); - - tmp = __cmnd_find_hash(session, cmnd->pdu.bhs.itt, - cmnd->target_task_tag); - if (tmp && tmp == cmnd) - __cmnd_remove_hash(tmp); - else - eprintk("%p:%x not found\n", cmnd, cmnd_itt(cmnd)); - - spin_unlock(&session->cmnd_hash_lock); -} - -static void cmnd_skip_data(struct iscsi_cmnd *req) -{ - struct iscsi_cmnd *rsp; - struct iscsi_scsi_rsp_hdr *rsp_hdr; - u32 size; - - rsp = get_rsp_cmnd(req); - rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs; - if (cmnd_opcode(rsp) != ISCSI_OP_SCSI_RSP) { - eprintk("unexpected response command %u\n", cmnd_opcode(rsp)); - return; - } - - size = cmnd_write_size(req); - if (size) { - rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW; - rsp_hdr->residual_count = cpu_to_be32(size); - } - size = cmnd_read_size(req); - if (size) { - if (cmnd_hdr(req)->flags & ISCSI_CMD_WRITE) { - rsp_hdr->flags |= ISCSI_FLG_BIRESIDUAL_UNDERFLOW; - rsp_hdr->bi_residual_count = cpu_to_be32(size); - } else { - rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW; - rsp_hdr->residual_count = cpu_to_be32(size); - } - } - req->pdu.bhs.opcode = - (req->pdu.bhs.opcode & ~ISCSI_OPCODE_MASK) | ISCSI_OP_SCSI_REJECT; - - cmnd_skip_pdu(req); -} - -static int cmnd_recv_pdu(struct iscsi_conn *conn, struct tio *tio, u32 offset, u32 size) -{ - int idx, i; - char *addr; - - dprintk(D_GENERIC, "%p %u,%u\n", tio, offset, size); - offset += tio->offset; - - if (!(offset < tio->offset + tio->size) || - !(offset + size <= tio->offset + tio->size)) { - eprintk("%u %u %u %u", offset, size, tio->offset, tio->size); - return -EIO; - } - assert(offset < tio->offset + tio->size); - assert(offset + size <= tio->offset + tio->size); - - idx = offset >> PAGE_CACHE_SHIFT; - offset &= ~PAGE_CACHE_MASK; - - conn->read_msg.msg_iov = conn->read_iov; - conn->read_size = size = (size + 3) & -4; - conn->read_overflow = 0; - - i = 0; - while (1) { - assert(tio->pvec[idx]); - addr = page_address(tio->pvec[idx]); - assert(addr); - conn->read_iov[i].iov_base = addr + offset; - if (offset + size <= PAGE_CACHE_SIZE) { - conn->read_iov[i].iov_len = size; - conn->read_msg.msg_iovlen = ++i; - break; - } - conn->read_iov[i].iov_len = PAGE_CACHE_SIZE - offset; - size -= conn->read_iov[i].iov_len; - offset = 0; - if (++i >= ISCSI_CONN_IOV_MAX) { - conn->read_msg.msg_iovlen = i; - conn->read_overflow = size; - conn->read_size -= size; - break; - } - - idx++; - } - - return 0; -} - -static void set_offset_and_length(struct iet_volume *lu, u8 *cmd, loff_t *off, u32 *len) -{ - assert(lu); - - switch (cmd[0]) { - case READ_6: - case WRITE_6: - *off = ((cmd[1] & 0x1f) << 16) + (cmd[2] << 8) + cmd[3]; - *len = cmd[4]; - if (!*len) - *len = 256; - break; - case READ_10: - case WRITE_10: - case WRITE_VERIFY: - *off = (u32)cmd[2] << 24 | (u32)cmd[3] << 16 | - (u32)cmd[4] << 8 | (u32)cmd[5]; - *len = (cmd[7] << 8) + cmd[8]; - break; - case READ_16: - case WRITE_16: - *off = (u64)cmd[2] << 56 | (u64)cmd[3] << 48 | - (u64)cmd[4] << 40 | (u64)cmd[5] << 32 | - (u64)cmd[6] << 24 | (u64)cmd[7] << 16 | - (u64)cmd[8] << 8 | (u64)cmd[9]; - *len = (u32)cmd[10] << 24 | (u32)cmd[11] << 16 | - (u32)cmd[12] << 8 | (u32)cmd[13]; - break; - default: - BUG(); - } - - *off <<= lu->blk_shift; - *len <<= lu->blk_shift; -} - -static u32 translate_lun(u16 * data) -{ - u8 *p = (u8 *) data; - u32 lun = ~0U; - - switch (*p >> 6) { - case 0: - lun = p[1]; - break; - case 1: - lun = (0x3f & p[0]) << 8 | p[1]; - break; - case 2: - case 3: - default: - eprintk("%u %u %u %u\n", data[0], data[1], data[2], data[3]); - break; - } - - return lun; -} - -static void send_r2t(struct iscsi_cmnd *req) -{ - struct iscsi_cmnd *rsp; - struct iscsi_r2t_hdr *rsp_hdr; - u32 length, offset, burst; - LIST_HEAD(send); - - length = req->r2t_length; - burst = req->conn->session->param.max_burst_length; - offset = be32_to_cpu(cmnd_hdr(req)->data_length) - length; - - do { - rsp = iscsi_cmnd_create_rsp_cmnd(req, 0); - rsp->pdu.bhs.ttt = req->target_task_tag; - - rsp_hdr = (struct iscsi_r2t_hdr *)&rsp->pdu.bhs; - rsp_hdr->opcode = ISCSI_OP_R2T; - rsp_hdr->flags = ISCSI_FLG_FINAL; - memcpy(rsp_hdr->lun, cmnd_hdr(req)->lun, 8); - rsp_hdr->itt = cmnd_hdr(req)->itt; - rsp_hdr->r2t_sn = cpu_to_be32(req->r2t_sn++); - rsp_hdr->buffer_offset = cpu_to_be32(offset); - if (length > burst) { - rsp_hdr->data_length = cpu_to_be32(burst); - length -= burst; - offset += burst; - } else { - rsp_hdr->data_length = cpu_to_be32(length); - length = 0; - } - - dprintk(D_WRITE, "%x %u %u %u %u\n", cmnd_itt(req), - be32_to_cpu(rsp_hdr->data_length), - be32_to_cpu(rsp_hdr->buffer_offset), - be32_to_cpu(rsp_hdr->r2t_sn), req->outstanding_r2t); - - list_add_tail(&rsp->list, &send); - - if (++req->outstanding_r2t >= req->conn->session->param.max_outstanding_r2t) - break; - - } while (length); - - iscsi_cmnds_init_write(&send); -} - -static void scsi_cmnd_exec(struct iscsi_cmnd *cmnd) -{ - assert(!cmnd->r2t_length); - - if (cmnd->lun) { - iscsi_scsi_queuecmnd(cmnd); - } else { - iscsi_device_queue_cmnd(cmnd); - } -} - -static int nop_out_start(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) -{ - u32 size, tmp; - int i, err = 0; - - if (cmnd_ttt(cmnd) != cpu_to_be32(ISCSI_RESERVED_TAG)) { - cmnd->req = cmnd_find_hash(conn->session, cmnd->pdu.bhs.itt, - cmnd->pdu.bhs.ttt); - if (!cmnd->req) { - /* - * We didn't request this NOP-Out (by sending a - * NOP-In, see 10.18.2 of the RFC) or our fake NOP-Out - * timed out. - */ - eprintk("initiator bug %x\n", cmnd_itt(cmnd)); - err = -ISCSI_REASON_PROTOCOL_ERROR; - goto out; - } - - del_timer_sync(&cmnd->req->timer); - clear_cmnd_timer_active(cmnd->req); - dprintk(D_GENERIC, "NOP-Out: %p, ttt %x, timer %p\n", - cmnd->req, cmnd_ttt(cmnd->req), &cmnd->req->timer); - } - - if (cmnd_itt(cmnd) == cpu_to_be32(ISCSI_RESERVED_TAG)) { - if (!cmnd_immediate(cmnd)) - eprintk("%s\n", "initiator bug!"); - update_stat_sn(cmnd); - err = check_cmd_sn(cmnd); - if (err) - goto out; - } else if ((err = cmnd_insert_hash(cmnd)) < 0) { - eprintk("ignore this request %x\n", cmnd_itt(cmnd)); - goto out; - } - - if ((size = cmnd->pdu.datasize)) { - size = (size + 3) & -4; - conn->read_msg.msg_iov = conn->read_iov; - if (cmnd->pdu.bhs.itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { - struct tio *tio; - int pg_cnt = get_pgcnt(size, 0); - - assert(pg_cnt < ISCSI_CONN_IOV_MAX); - cmnd->tio = tio = tio_alloc(pg_cnt); - tio_set(tio, size, 0); - - for (i = 0; i < pg_cnt; i++) { - conn->read_iov[i].iov_base - = page_address(tio->pvec[i]); - tmp = min_t(u32, size, PAGE_CACHE_SIZE); - conn->read_iov[i].iov_len = tmp; - conn->read_size += tmp; - size -= tmp; - } - } else { - for (i = 0; i < ISCSI_CONN_IOV_MAX; i++) { - conn->read_iov[i].iov_base = dummy_data; - tmp = min_t(u32, size, sizeof(dummy_data)); - conn->read_iov[i].iov_len = tmp; - conn->read_size += tmp; - size -= tmp; - } - } - assert(!size); - conn->read_overflow = size; - conn->read_msg.msg_iovlen = i; - } - -out: - return err; -} - -static u32 get_next_ttt(struct iscsi_session *session) -{ - u32 ttt; - - if (session->next_ttt == ISCSI_RESERVED_TAG) - session->next_ttt++; - ttt = session->next_ttt++; - - return cpu_to_be32(ttt); -} - -static void scsi_cmnd_start(struct iscsi_conn *conn, struct iscsi_cmnd *req) -{ - struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req); - - dprintk(D_GENERIC, "scsi command: %02x\n", req_hdr->scb[0]); - - req->lun = volume_get(conn->session->target, translate_lun(req_hdr->lun)); - if (!req->lun) { - switch (req_hdr->scb[0]) { - case INQUIRY: - case REPORT_LUNS: - break; - default: - eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); - create_sense_rsp(req, ILLEGAL_REQUEST, 0x25, 0x0); - cmnd_skip_data(req); - goto out; - } - } else - set_cmnd_lunit(req); - - switch (req_hdr->scb[0]) { - case SERVICE_ACTION_IN: - if ((req_hdr->scb[1] & 0x1f) != 0x10) - goto error; - case INQUIRY: - case REPORT_LUNS: - case TEST_UNIT_READY: - case SYNCHRONIZE_CACHE: - case VERIFY: - case VERIFY_16: - case START_STOP: - case READ_CAPACITY: - case MODE_SENSE: - case REQUEST_SENSE: - case RESERVE: - case RELEASE: - { - if (!(req_hdr->flags & ISCSI_CMD_FINAL) || req->pdu.datasize) { - /* unexpected unsolicited data */ - eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); - create_sense_rsp(req, ABORTED_COMMAND, 0xc, 0xc); - cmnd_skip_data(req); - } - break; - } - case READ_6: - case READ_10: - case READ_16: - { - loff_t offset; - u32 length; - - if (!(req_hdr->flags & ISCSI_CMD_FINAL) || req->pdu.datasize) { - /* unexpected unsolicited data */ - eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); - create_sense_rsp(req, ABORTED_COMMAND, 0xc, 0xc); - cmnd_skip_data(req); - break; - } - - set_offset_and_length(req->lun, req_hdr->scb, &offset, &length); - req->tio = tio_alloc(get_pgcnt(length, offset)); - tio_set(req->tio, length, offset); - break; - } - case WRITE_6: - case WRITE_10: - case WRITE_16: - case WRITE_VERIFY: - { - struct iscsi_sess_param *param = &conn->session->param; - loff_t offset; - u32 length; - - req->r2t_length = be32_to_cpu(req_hdr->data_length) - req->pdu.datasize; - req->is_unsolicited_data = !(req_hdr->flags & ISCSI_CMD_FINAL); - req->target_task_tag = get_next_ttt(conn->session); - - if (LUReadonly(req->lun)) { - create_sense_rsp(req, DATA_PROTECT, 0x27, 0x0); - cmnd_skip_data(req); - break; - } - - if (!param->immediate_data && req->pdu.datasize) - eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); - - if (param->initial_r2t && !(req_hdr->flags & ISCSI_CMD_FINAL)) - eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); - - if (req_hdr->scb[0] == WRITE_VERIFY && req_hdr->scb[1] & 0x02) - eprintk("Verification is ignored %x\n", cmnd_itt(req)); - - set_offset_and_length(req->lun, req_hdr->scb, &offset, &length); - if (cmnd_write_size(req) != length) - eprintk("%x %u %u\n", cmnd_itt(req), cmnd_write_size(req), length); - - req->tio = tio_alloc(get_pgcnt(length, offset)); - tio_set(req->tio, length, offset); - - if (req->pdu.datasize) { - if (cmnd_recv_pdu(conn, req->tio, 0, req->pdu.datasize) < 0) - assert(0); - } - break; - } - error: - default: - eprintk("Unsupported %x\n", req_hdr->scb[0]); - create_sense_rsp(req, ILLEGAL_REQUEST, 0x20, 0x0); - cmnd_skip_data(req); - break; - } - -out: - return; -} - -static void data_out_start(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) -{ - struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs; - struct iscsi_cmnd *scsi_cmnd = NULL; - u32 offset = be32_to_cpu(req->buffer_offset); - - update_stat_sn(cmnd); - - cmnd->req = scsi_cmnd = cmnd_find_hash(conn->session, req->itt, req->ttt); - if (!scsi_cmnd) { - eprintk("unable to find scsi task %x %x\n", - cmnd_itt(cmnd), cmnd_ttt(cmnd)); - goto skip_data; - } - - if (scsi_cmnd->r2t_length < cmnd->pdu.datasize) { - eprintk("invalid data len %x %u %u\n", - cmnd_itt(scsi_cmnd), cmnd->pdu.datasize, scsi_cmnd->r2t_length); - goto skip_data; - } - - if (scsi_cmnd->r2t_length + offset != cmnd_write_size(scsi_cmnd)) { - eprintk("%x %u %u %u\n", cmnd_itt(scsi_cmnd), scsi_cmnd->r2t_length, - offset, cmnd_write_size(scsi_cmnd)); - goto skip_data; - } - - scsi_cmnd->r2t_length -= cmnd->pdu.datasize; - - if (req->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) { - /* unsolicited burst data */ - if (scsi_cmnd->pdu.bhs.flags & ISCSI_FLG_FINAL) { - eprintk("unexpected data from %x %x\n", - cmnd_itt(cmnd), cmnd_ttt(cmnd)); - goto skip_data; - } - } - - dprintk(D_WRITE, "%u %p %p %p %u %u\n", req->ttt, cmnd, scsi_cmnd, - scsi_cmnd->tio, offset, cmnd->pdu.datasize); - - if (cmnd_recv_pdu(conn, scsi_cmnd->tio, offset, cmnd->pdu.datasize) < 0) - goto skip_data; - return; - -skip_data: - cmnd->pdu.bhs.opcode = ISCSI_OP_DATA_REJECT; - cmnd_skip_pdu(cmnd); - return; -} - -static void iscsi_session_push_cmnd(struct iscsi_cmnd *cmnd); - -static void data_out_end(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) -{ - struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *) &cmnd->pdu.bhs; - struct iscsi_cmnd *scsi_cmnd; - u32 offset; - - assert(cmnd); - scsi_cmnd = cmnd->req; - assert(scsi_cmnd); - - if (conn->read_overflow) { - eprintk("%x %u\n", cmnd_itt(cmnd), conn->read_overflow); - assert(scsi_cmnd->tio); - offset = be32_to_cpu(req->buffer_offset); - offset += cmnd->pdu.datasize - conn->read_overflow; - if (cmnd_recv_pdu(conn, scsi_cmnd->tio, offset, conn->read_overflow) < 0) - assert(0); - return; - } - - if (req->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) { - if (req->flags & ISCSI_FLG_FINAL) { - scsi_cmnd->is_unsolicited_data = 0; - iscsi_session_push_cmnd(scsi_cmnd); - } - } else { - /* TODO : proper error handling */ - if (!(req->flags & ISCSI_FLG_FINAL) && scsi_cmnd->r2t_length == 0) - eprintk("initiator error %x\n", cmnd_itt(scsi_cmnd)); - - if (!(req->flags & ISCSI_FLG_FINAL)) - goto out; - - scsi_cmnd->outstanding_r2t--; - - if (scsi_cmnd->r2t_length == 0) - assert(list_empty(&scsi_cmnd->pdu_list)); - - iscsi_session_push_cmnd(scsi_cmnd); - } - -out: - iscsi_cmnd_remove(cmnd); - return; -} - -static void __cmnd_abort(struct iscsi_cmnd *cmnd) -{ - if (cmnd_rxstart(cmnd)) - set_cmnd_tmfabort(cmnd); - - if (cmnd_waitio(cmnd)) - return; - - if (cmnd->conn->read_cmnd != cmnd) - cmnd_release(cmnd, 1); -} - -static int cmnd_abort(struct iscsi_session *session, struct iscsi_cmnd *req) -{ - struct iscsi_task_mgt_hdr *req_hdr = - (struct iscsi_task_mgt_hdr *)&req->pdu.bhs; - struct iscsi_cmnd *cmnd; - - u32 min_cmd_sn = req_hdr->cmd_sn - session->max_queued_cmnds; - - req_hdr->ref_cmd_sn = be32_to_cpu(req_hdr->ref_cmd_sn); - - dprintk(D_GENERIC, "cmd_sn(%u) ref_cmd_sn(%u) min_cmd_sn(%u) rtt(%x)" - " lun(%d) cid(%u)\n", - req_hdr->cmd_sn, req_hdr->ref_cmd_sn, min_cmd_sn, req_hdr->rtt, - translate_lun(req_hdr->lun), req->conn->cid); - - if (after(req_hdr->ref_cmd_sn, req_hdr->cmd_sn)) - return ISCSI_RESPONSE_FUNCTION_REJECTED; - - if (!(cmnd = cmnd_find_hash(session, req_hdr->rtt, ISCSI_RESERVED_TAG))) { - if (between(req_hdr->ref_cmd_sn, min_cmd_sn, req_hdr->cmd_sn)) - return ISCSI_RESPONSE_FUNCTION_COMPLETE; - else - return ISCSI_RESPONSE_UNKNOWN_TASK; - } - - dprintk(D_GENERIC, "itt(%x) opcode(%x) scsicode(%x) lun(%d) cid(%u)\n", - cmnd_itt(cmnd), cmnd_opcode(cmnd), cmnd_scsicode(cmnd), - translate_lun(cmnd_hdr(cmnd)->lun), cmnd->conn->cid); - - if (cmnd_opcode(cmnd) == ISCSI_OP_SCSI_TASK_MGT_MSG) - return ISCSI_RESPONSE_FUNCTION_REJECTED; - - if (translate_lun(cmnd_hdr(cmnd)->lun) != - translate_lun(req_hdr->lun)) - return ISCSI_RESPONSE_FUNCTION_REJECTED; - - if (cmnd->conn && test_bit(CONN_ACTIVE, &cmnd->conn->state)) { - if (cmnd->conn->cid != req->conn->cid) - return ISCSI_RESPONSE_FUNCTION_REJECTED; - } else { - /* Switch cmnd connection allegiance */ - } - - __cmnd_abort(cmnd); - - return ISCSI_RESPONSE_FUNCTION_COMPLETE; -} - -static int target_reset(struct iscsi_cmnd *req, u32 lun, int all) -{ - struct iscsi_target *target = req->conn->session->target; - struct iscsi_session *session; - struct iscsi_conn *conn; - struct iscsi_cmnd *cmnd, *tmp; - struct iet_volume *volume; - - list_for_each_entry(session, &target->session_list, list) { - list_for_each_entry(conn, &session->conn_list, list) { - list_for_each_entry_safe(cmnd, tmp, &conn->pdu_list, conn_list) { - if (cmnd == req) - continue; - - if (all) - __cmnd_abort(cmnd); - else if (translate_lun(cmnd_hdr(cmnd)->lun) - == lun) - __cmnd_abort(cmnd); - } - } - } - - list_for_each_entry(volume, &target->volumes, list) { - if (all || volume->lun == lun) { - /* force release */ - volume_release(volume, 0, 1); - /* power-on, reset, or bus device reset occurred */ - ua_establish_for_all_sessions(target, volume->lun, - 0x29, 0x0); - } - } - - return 0; -} - -static void task_set_abort(struct iscsi_cmnd *req) -{ - struct iscsi_session *session = req->conn->session; - struct iscsi_conn *conn; - struct iscsi_cmnd *cmnd, *tmp; - - list_for_each_entry(conn, &session->conn_list, list) { - list_for_each_entry_safe(cmnd, tmp, &conn->pdu_list, conn_list) { - if (translate_lun(cmnd_hdr(cmnd)->lun) - != translate_lun(cmnd_hdr(req)->lun)) - continue; - - if (before(cmnd_hdr(cmnd)->cmd_sn, - cmnd_hdr(req)->cmd_sn)) - __cmnd_abort(cmnd); - } - } -} - -static inline char *tmf_desc(int fun) -{ - static char *tmf_desc[] = { - "Unknown Function", - "Abort Task", - "Abort Task Set", - "Clear ACA", - "Clear Task Set", - "Logical Unit Reset", - "Target Warm Reset", - "Target Cold Reset", - "Task Reassign", - }; - - if ((fun < ISCSI_FUNCTION_ABORT_TASK) || - (fun > ISCSI_FUNCTION_TASK_REASSIGN)) - fun = 0; - - return tmf_desc[fun]; -} - -static inline char *rsp_desc(int rsp) -{ - static char *rsp_desc[] = { - "Function Complete", - "Unknown Task", - "Unknown LUN", - "Task Allegiant", - "Failover Unsupported", - "Function Unsupported", - "No Authorization", - "Function Rejected", - "Unknown Response", - }; - - if (((rsp < ISCSI_RESPONSE_FUNCTION_COMPLETE) || - (rsp > ISCSI_RESPONSE_NO_AUTHORIZATION)) && - (rsp != ISCSI_RESPONSE_FUNCTION_REJECTED)) - rsp = 8; - else if (rsp == ISCSI_RESPONSE_FUNCTION_REJECTED) - rsp = 7; - - return rsp_desc[rsp]; -} - -static void execute_task_management(struct iscsi_cmnd *req) -{ - struct iscsi_conn *conn = req->conn; - struct iscsi_session *session = conn->session; - struct iscsi_target *target = session->target; - struct iscsi_cmnd *rsp; - struct iscsi_task_mgt_hdr *req_hdr = (struct iscsi_task_mgt_hdr *)&req->pdu.bhs; - struct iscsi_task_rsp_hdr *rsp_hdr; - u32 lun; - int function = req_hdr->function & ISCSI_FUNCTION_MASK; - - rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); - rsp_hdr = (struct iscsi_task_rsp_hdr *)&rsp->pdu.bhs; - - rsp_hdr->opcode = ISCSI_OP_SCSI_TASK_MGT_RSP; - rsp_hdr->flags = ISCSI_FLG_FINAL; - rsp_hdr->itt = req_hdr->itt; - rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_COMPLETE; - - switch (function) { - case ISCSI_FUNCTION_ABORT_TASK: - case ISCSI_FUNCTION_ABORT_TASK_SET: - case ISCSI_FUNCTION_CLEAR_ACA: - case ISCSI_FUNCTION_CLEAR_TASK_SET: - case ISCSI_FUNCTION_LOGICAL_UNIT_RESET: - lun = translate_lun(req_hdr->lun); - if (!volume_lookup(target, lun)) { - rsp_hdr->response = ISCSI_RESPONSE_UNKNOWN_LUN; - goto out; - } - } - - switch (function) { - case ISCSI_FUNCTION_ABORT_TASK: - rsp_hdr->response = cmnd_abort(conn->session, req); - break; - case ISCSI_FUNCTION_ABORT_TASK_SET: - task_set_abort(req); - break; - case ISCSI_FUNCTION_CLEAR_ACA: - rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED; - break; - case ISCSI_FUNCTION_CLEAR_TASK_SET: - rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED; - break; - case ISCSI_FUNCTION_LOGICAL_UNIT_RESET: - target_reset(req, translate_lun(req_hdr->lun), 0); - break; - case ISCSI_FUNCTION_TARGET_WARM_RESET: - case ISCSI_FUNCTION_TARGET_COLD_RESET: - target_reset(req, 0, 1); - if (function == ISCSI_FUNCTION_TARGET_COLD_RESET) - set_cmnd_close(rsp); - break; - case ISCSI_FUNCTION_TASK_REASSIGN: - rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED; - break; - default: - rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_REJECTED; - break; - } -out: - iprintk("%s (%02x) issued on tid:%d lun:%d by sid:%llu (%s)\n", - tmf_desc(function), function, target->tid, - translate_lun(req_hdr->lun), session->sid, - rsp_desc(rsp_hdr->response)); - - iscsi_cmnd_init_write(rsp); -} - -static void nop_hdr_setup(struct iscsi_hdr *hdr, u8 opcode, __be32 itt, - __be32 ttt) -{ - hdr->opcode = opcode; - hdr->flags = ISCSI_FLG_FINAL; - hdr->itt = itt; - hdr->ttt = ttt; -} - -static void nop_out_exec(struct iscsi_cmnd *req) -{ - struct iscsi_cmnd *rsp; - - if (cmnd_itt(req) != cpu_to_be32(ISCSI_RESERVED_TAG)) { - rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); - - nop_hdr_setup(&rsp->pdu.bhs, ISCSI_OP_NOP_IN, req->pdu.bhs.itt, - cpu_to_be32(ISCSI_RESERVED_TAG)); - - if (req->pdu.datasize) - assert(req->tio); - else - assert(!req->tio); - - if (req->tio) { - tio_get(req->tio); - rsp->tio = req->tio; - } - - assert(get_pgcnt(req->pdu.datasize, 0) < ISCSI_CONN_IOV_MAX); - rsp->pdu.datasize = req->pdu.datasize; - iscsi_cmnd_init_write(rsp); - } else { - if (req->req) { - dprintk(D_GENERIC, "releasing NOP-Out %p, ttt %x; " - "removing NOP-In %p, ttt %x\n", req->req, - cmnd_ttt(req->req), req, cmnd_ttt(req)); - cmnd_release(req->req, 0); - } - iscsi_cmnd_remove(req); - } -} - -static void nop_in_timeout(unsigned long data) -{ - struct iscsi_cmnd *req = (struct iscsi_cmnd *)data; - - printk(KERN_INFO "NOP-In ping timed out - closing sid:cid %llu:%u\n", - req->conn->session->sid, req->conn->cid); - clear_cmnd_timer_active(req); - conn_close(req->conn); -} - -/* create a fake NOP-Out req and treat the NOP-In as our rsp to it */ -void send_nop_in(struct iscsi_conn *conn) -{ - struct iscsi_cmnd *req = cmnd_alloc(conn, 1); - struct iscsi_cmnd *rsp = iscsi_cmnd_create_rsp_cmnd(req, 0); - - req->target_task_tag = get_next_ttt(conn->session); - - - nop_hdr_setup(&req->pdu.bhs, ISCSI_OP_NOP_OUT, - cpu_to_be32(ISCSI_RESERVED_TAG), req->target_task_tag); - nop_hdr_setup(&rsp->pdu.bhs, ISCSI_OP_NOP_IN, - cpu_to_be32(ISCSI_RESERVED_TAG), req->target_task_tag); - - dprintk(D_GENERIC, "NOP-Out: %p, ttt %x, timer %p; " - "NOP-In: %p, ttt %x;\n", req, cmnd_ttt(req), &req->timer, rsp, - cmnd_ttt(rsp)); - - init_timer(&req->timer); - req->timer.data = (unsigned long)req; - req->timer.function = nop_in_timeout; - - if (cmnd_insert_hash_ttt(req, req->target_task_tag)) { - eprintk("%s\n", - "failed to insert fake NOP-Out into hash table"); - cmnd_release(rsp, 0); - cmnd_release(req, 0); - } else - iscsi_cmnd_init_write(rsp); -} - -static void nop_in_tx_end(struct iscsi_cmnd *cmnd) -{ - struct iscsi_conn *conn = cmnd->conn; - u32 t; - - if (cmnd->pdu.bhs.ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) - return; - - /* - * NOP-In ping issued by the target. - * FIXME: Sanitize the NOP timeout earlier, during configuration - */ - t = conn->session->target->trgt_param.nop_timeout; - - if (!t || t > conn->session->target->trgt_param.nop_interval) { - eprintk("Adjusting NOPTimeout of tid %u from %u to %u " - "(== NOPInterval)\n", conn->session->target->tid, - t, - conn->session->target->trgt_param.nop_interval); - t = conn->session->target->trgt_param.nop_interval; - conn->session->target->trgt_param.nop_timeout = t; - } - - dprintk(D_GENERIC, "NOP-In %p, %x: timer %p\n", cmnd, cmnd_ttt(cmnd), - &cmnd->req->timer); - - set_cmnd_timer_active(cmnd->req); - mod_timer(&cmnd->req->timer, jiffies + HZ * t); -} - -static void logout_exec(struct iscsi_cmnd *req) -{ - struct iscsi_logout_req_hdr *req_hdr; - struct iscsi_cmnd *rsp; - struct iscsi_logout_rsp_hdr *rsp_hdr; - - req_hdr = (struct iscsi_logout_req_hdr *)&req->pdu.bhs; - rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); - rsp_hdr = (struct iscsi_logout_rsp_hdr *)&rsp->pdu.bhs; - rsp_hdr->opcode = ISCSI_OP_LOGOUT_RSP; - rsp_hdr->flags = ISCSI_FLG_FINAL; - rsp_hdr->itt = req_hdr->itt; - set_cmnd_close(rsp); - iscsi_cmnd_init_write(rsp); -} - -static void iscsi_cmnd_exec(struct iscsi_cmnd *cmnd) -{ - dprintk(D_GENERIC, "%p,%x,%u\n", cmnd, cmnd_opcode(cmnd), cmnd->pdu.bhs.sn); - - switch (cmnd_opcode(cmnd)) { - case ISCSI_OP_NOP_OUT: - nop_out_exec(cmnd); - break; - case ISCSI_OP_SCSI_CMD: - scsi_cmnd_exec(cmnd); - break; - case ISCSI_OP_SCSI_TASK_MGT_MSG: - execute_task_management(cmnd); - break; - case ISCSI_OP_LOGOUT_CMD: - logout_exec(cmnd); - break; - case ISCSI_OP_SCSI_REJECT: - iscsi_cmnd_init_write(get_rsp_cmnd(cmnd)); - break; - case ISCSI_OP_TEXT_CMD: - case ISCSI_OP_SNACK_CMD: - break; - default: - eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd)); - break; - } -} - -static void __cmnd_send_pdu(struct iscsi_conn *conn, struct tio *tio, u32 offset, u32 size) -{ - dprintk(D_GENERIC, "%p %u,%u\n", tio, offset, size); - offset += tio->offset; - - assert(offset <= tio->offset + tio->size); - assert(offset + size <= tio->offset + tio->size); - - conn->write_tcmnd = tio; - conn->write_offset = offset; - conn->write_size += size; -} - -static void cmnd_send_pdu(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) -{ - u32 size; - struct tio *tio; - - if (!cmnd->pdu.datasize) - return; - - size = (cmnd->pdu.datasize + 3) & -4; - tio = cmnd->tio; - assert(tio); - assert(tio->size == size); - __cmnd_send_pdu(conn, tio, 0, size); -} - -static void set_cork(struct socket *sock, int on) -{ - int opt = on; - mm_segment_t oldfs; - - oldfs = get_fs(); - set_fs(get_ds()); - sock->ops->setsockopt(sock, SOL_TCP, TCP_CORK, (void *)&opt, sizeof(opt)); - set_fs(oldfs); -} - -void cmnd_release(struct iscsi_cmnd *cmnd, int force) -{ - struct iscsi_cmnd *req, *rsp; - int is_last = 0; - - if (!cmnd) - return; - -/* eprintk("%x %lx %d\n", cmnd_opcode(cmnd), cmnd->flags, force); */ - - req = cmnd->req; - is_last = cmnd_final(cmnd); - - if (force) { - while (!list_empty(&cmnd->pdu_list)) { - rsp = list_entry(cmnd->pdu_list.next, struct iscsi_cmnd, pdu_list); - list_del_init(&rsp->list); - list_del(&rsp->pdu_list); - iscsi_cmnd_remove(rsp); - } - list_del_init(&cmnd->list); - } else - if (cmnd_queued(cmnd)) - iscsi_scsi_dequeuecmnd(cmnd); - - if (cmnd_hashed(cmnd)) - cmnd_remove_hash(cmnd); - - if (cmnd_lunit(cmnd)) { - assert(cmnd->lun); - volume_put(cmnd->lun); - } - - list_del_init(&cmnd->pdu_list); - iscsi_cmnd_remove(cmnd); - - if (is_last) { - assert(!force); - assert(req); - cmnd_release(req, 0); - } - - return; -} - -void cmnd_tx_start(struct iscsi_cmnd *cmnd) -{ - struct iscsi_conn *conn = cmnd->conn; - struct iovec *iop; - - dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd)); - assert(cmnd); - iscsi_cmnd_set_length(&cmnd->pdu); - - set_cork(conn->sock, 1); - - conn->write_iop = iop = conn->write_iov; - iop->iov_base = &cmnd->pdu.bhs; - iop->iov_len = sizeof(cmnd->pdu.bhs); - iop++; - conn->write_size = sizeof(cmnd->pdu.bhs); - - switch (cmnd_opcode(cmnd)) { - case ISCSI_OP_NOP_IN: - if (cmnd->pdu.bhs.itt == ISCSI_RESERVED_TAG) { - /* NOP-In ping generated by us. Don't advance StatSN. */ - cmnd_set_sn(cmnd, 0); - cmnd_set_sn(cmnd->req, 0); - cmnd->pdu.bhs.sn = cpu_to_be32(conn->stat_sn); - cmnd->req->pdu.bhs.sn = cpu_to_be32(conn->stat_sn); - } else - cmnd_set_sn(cmnd, 1); - cmnd_send_pdu(conn, cmnd); - break; - case ISCSI_OP_SCSI_RSP: - cmnd_set_sn(cmnd, 1); - cmnd_send_pdu(conn, cmnd); - break; - case ISCSI_OP_SCSI_TASK_MGT_RSP: - cmnd_set_sn(cmnd, 1); - break; - case ISCSI_OP_TEXT_RSP: - cmnd_set_sn(cmnd, 1); - break; - case ISCSI_OP_SCSI_DATA_IN: - { - struct iscsi_data_in_hdr *rsp = (struct iscsi_data_in_hdr *)&cmnd->pdu.bhs; - u32 offset; - - cmnd_set_sn(cmnd, (rsp->flags & ISCSI_FLG_FINAL) ? 1 : 0); - offset = rsp->buffer_offset; - rsp->buffer_offset = cpu_to_be32(offset); - __cmnd_send_pdu(conn, cmnd->tio, offset, cmnd->pdu.datasize); - break; - } - case ISCSI_OP_LOGOUT_RSP: - cmnd_set_sn(cmnd, 1); - break; - case ISCSI_OP_R2T: - cmnd_set_sn(cmnd, 0); - cmnd->pdu.bhs.sn = cpu_to_be32(conn->stat_sn); - break; - case ISCSI_OP_ASYNC_MSG: - cmnd_set_sn(cmnd, 1); - break; - case ISCSI_OP_REJECT: - cmnd_set_sn(cmnd, 1); - cmnd_send_pdu(conn, cmnd); - break; - default: - eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd)); - break; - } - - iop->iov_len = 0; - // move this? - conn->write_size = (conn->write_size + 3) & -4; - iscsi_dump_pdu(&cmnd->pdu); -} - -void cmnd_tx_end(struct iscsi_cmnd *cmnd) -{ - struct iscsi_conn *conn = cmnd->conn; - - dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd)); - switch (cmnd_opcode(cmnd)) { - case ISCSI_OP_NOP_IN: - nop_in_tx_end(cmnd); - break; - case ISCSI_OP_SCSI_RSP: - case ISCSI_OP_SCSI_TASK_MGT_RSP: - case ISCSI_OP_TEXT_RSP: - case ISCSI_OP_R2T: - case ISCSI_OP_ASYNC_MSG: - case ISCSI_OP_REJECT: - case ISCSI_OP_SCSI_DATA_IN: - case ISCSI_OP_LOGOUT_RSP: - break; - default: - eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd)); - assert(0); - break; - } - - if (cmnd_close(cmnd)) - conn_close(conn); - - list_del_init(&cmnd->list); - set_cork(cmnd->conn->sock, 0); -} - -/** - * Push the command for execution. - * This functions reorders the commands. - * Called from the read thread. - * - * iscsi_session_push_cmnd - - * @cmnd: ptr to command - */ - -static void iscsi_session_push_cmnd(struct iscsi_cmnd *cmnd) -{ - struct iscsi_session *session = cmnd->conn->session; - struct list_head *entry; - u32 cmd_sn; - - if (cmnd->r2t_length) { - if (!cmnd->is_unsolicited_data) - send_r2t(cmnd); - return; - } - - dprintk(D_GENERIC, "%p:%x %u,%u\n", - cmnd, cmnd_opcode(cmnd), cmnd->pdu.bhs.sn, session->exp_cmd_sn); - - if (cmnd_immediate(cmnd)) { - iscsi_cmnd_exec(cmnd); - return; - } - - cmd_sn = cmnd->pdu.bhs.sn; - if (cmd_sn == session->exp_cmd_sn) { - while (1) { - session->exp_cmd_sn = ++cmd_sn; - iscsi_cmnd_exec(cmnd); - - if (list_empty(&session->pending_list)) - break; - - cmnd = list_entry(session->pending_list.next, struct iscsi_cmnd, list); - if (cmnd->pdu.bhs.sn != cmd_sn) - break; - - list_del_init(&cmnd->list); - clear_cmnd_pending(cmnd); - } - } else { - set_cmnd_pending(cmnd); - - list_for_each(entry, &session->pending_list) { - struct iscsi_cmnd *tmp = list_entry(entry, struct iscsi_cmnd, list); - if (before(cmd_sn, tmp->pdu.bhs.sn)) - break; - } - - assert(list_empty(&cmnd->list)); - - list_add_tail(&cmnd->list, entry); - } -} - -static int check_segment_length(struct iscsi_cmnd *cmnd) -{ - struct iscsi_conn *conn = cmnd->conn; - struct iscsi_sess_param *param = &conn->session->param; - - if (cmnd->pdu.datasize > param->max_recv_data_length) { - eprintk("data too long %x %u %u\n", cmnd_itt(cmnd), - cmnd->pdu.datasize, param->max_recv_data_length); - - if (get_pgcnt(cmnd->pdu.datasize, 0) > ISCSI_CONN_IOV_MAX) { - conn_close(conn); - return -EINVAL; - } - } - - return 0; -} - -void cmnd_rx_start(struct iscsi_cmnd *cmnd) -{ - struct iscsi_conn *conn = cmnd->conn; - int err = 0; - - iscsi_dump_pdu(&cmnd->pdu); - - set_cmnd_rxstart(cmnd); - if (check_segment_length(cmnd) < 0) - return; - - switch (cmnd_opcode(cmnd)) { - case ISCSI_OP_NOP_OUT: - err = nop_out_start(conn, cmnd); - break; - case ISCSI_OP_SCSI_CMD: - if (!(err = cmnd_insert_hash(cmnd))) - scsi_cmnd_start(conn, cmnd); - break; - case ISCSI_OP_SCSI_TASK_MGT_MSG: - err = cmnd_insert_hash(cmnd); - break; - case ISCSI_OP_SCSI_DATA_OUT: - data_out_start(conn, cmnd); - break; - case ISCSI_OP_LOGOUT_CMD: - err = cmnd_insert_hash(cmnd); - break; - case ISCSI_OP_TEXT_CMD: - case ISCSI_OP_SNACK_CMD: - err = -ISCSI_REASON_UNSUPPORTED_COMMAND; - break; - default: - err = -ISCSI_REASON_UNSUPPORTED_COMMAND; - break; - } - - if (err < 0) { - eprintk("%x %x %d\n", cmnd_opcode(cmnd), cmnd_itt(cmnd), err); - iscsi_cmnd_reject(cmnd, -err); - } -} - -void cmnd_rx_end(struct iscsi_cmnd *cmnd) -{ - struct iscsi_conn *conn = cmnd->conn; - - if (cmnd_tmfabort(cmnd)) { - cmnd_release(cmnd, 1); - return; - } - - dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd)); - switch (cmnd_opcode(cmnd)) { - case ISCSI_OP_SCSI_REJECT: - case ISCSI_OP_NOP_OUT: - case ISCSI_OP_SCSI_CMD: - case ISCSI_OP_SCSI_TASK_MGT_MSG: - case ISCSI_OP_TEXT_CMD: - case ISCSI_OP_LOGOUT_CMD: - iscsi_session_push_cmnd(cmnd); - break; - case ISCSI_OP_SCSI_DATA_OUT: - data_out_end(conn, cmnd); - break; - case ISCSI_OP_SNACK_CMD: - break; - case ISCSI_OP_PDU_REJECT: - iscsi_cmnd_init_write(get_rsp_cmnd(cmnd)); - break; - case ISCSI_OP_DATA_REJECT: - cmnd_release(cmnd, 0); - break; - default: - eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd)); - BUG(); - break; - } -} - -static void iscsi_exit(void) -{ - wthread_module_exit(); - - unregister_chrdev(ctr_major, ctr_name); - - iet_procfs_exit(); - - event_exit(); - - tio_exit(); - - iotype_exit(); - - ua_exit(); - - if (iscsi_cmnd_cache) - kmem_cache_destroy(iscsi_cmnd_cache); -} - -static int iscsi_init(void) -{ - int err = -ENOMEM; - - printk("iSCSI Enterprise Target Software - version %s\n", IET_VERSION_STRING); - - if ((ctr_major = register_chrdev(0, ctr_name, &ctr_fops)) < 0) { - eprintk("failed to register the control device %d\n", ctr_major); - return ctr_major; - } - - if ((err = iet_procfs_init()) < 0) - goto err; - - if ((err = event_init()) < 0) - goto err; - - iscsi_cmnd_cache = KMEM_CACHE(iscsi_cmnd, 0); - if (!iscsi_cmnd_cache) - goto err; - - err = ua_init(); - if (err < 0) - goto err; - - if ((err = tio_init()) < 0) - goto err; - - if ((err = iotype_init()) < 0) - goto err; - - if ((err = wthread_module_init()) < 0) - goto err; - - return 0; - -err: - iscsi_exit(); - return err; -} - -module_param(worker_thread_pool_size, ulong, S_IRUGO); -MODULE_PARM_DESC(worker_thread_pool_size, - "Size of the worker thread pool " - "(0 = dedicated threads per target (default))"); - -module_param(debug_enable_flags, ulong, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug_enable_flags, - "debug bitmask, low bits (0 ... 8) used, see iscsi_dbg.h"); - -module_init(iscsi_init); -module_exit(iscsi_exit); - -MODULE_VERSION(IET_VERSION_STRING); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("iSCSI Enterprise Target"); -MODULE_AUTHOR("IET development team "); diff --git a/ubuntu/iscsitarget/iscsi.h b/ubuntu/iscsitarget/iscsi.h deleted file mode 100644 index 9ded23a..0000000 --- a/ubuntu/iscsitarget/iscsi.h +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright (C) 2002-2003 Ardis Technolgies - * Copyright (C) 2008 Arne Redlich - * - * Released under the terms of the GNU GPL v2.0. - */ - -#ifndef __ISCSI_H__ -#define __ISCSI_H__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iscsi_hdr.h" -#include "iet_u.h" -#include "compat.h" - -#define IET_SENSE_BUF_SIZE 18 - -struct iscsi_sess_param { - int initial_r2t; - int immediate_data; - int max_connections; - int max_recv_data_length; - int max_xmit_data_length; - int max_burst_length; - int first_burst_length; - int default_wait_time; - int default_retain_time; - int max_outstanding_r2t; - int data_pdu_inorder; - int data_sequence_inorder; - int error_recovery_level; - int header_digest; - int data_digest; - int ofmarker; - int ifmarker; - int ofmarkint; - int ifmarkint; -}; - -struct iscsi_trgt_param { - int wthreads; - int target_type; - int queued_cmnds; - int nop_interval; - int nop_timeout; -}; - -struct tio { - u32 pg_cnt; - - pgoff_t idx; - u32 offset; - u32 size; - - struct page **pvec; - - atomic_t count; -}; - -struct network_thread_info { - struct task_struct *task; - unsigned long flags; - struct list_head active_conns; - - spinlock_t nthread_lock; - - void (*old_state_change)(struct sock *); - void (*old_data_ready)(struct sock *, int); - void (*old_write_space)(struct sock *); -}; - -struct worker_thread_info; - -struct worker_thread { - struct task_struct *w_task; - struct list_head w_list; - struct worker_thread_info *w_info; -}; - -struct worker_thread_info { - spinlock_t wthread_lock; - - u32 nr_running_wthreads; - - struct list_head wthread_list; - struct list_head work_queue; - - wait_queue_head_t wthread_sleep; - - struct io_context *wthread_ioc; -}; - -struct iscsi_cmnd; - -struct target_type { - int id; - int (*execute_cmnd) (struct iscsi_cmnd *); -}; - -enum iscsi_device_state { - IDEV_RUNNING, - IDEV_DEL, -}; - -struct iscsi_target { - struct list_head t_list; - u32 tid; - - char name[ISCSI_NAME_LEN]; - - struct iscsi_sess_param sess_param; - struct iscsi_trgt_param trgt_param; - - atomic_t nr_volumes; - struct list_head volumes; - struct list_head session_list; - - /* Prevents races between add/del session and adding UAs */ - spinlock_t session_list_lock; - - struct network_thread_info nthread_info; - /* Points either to own list or global pool */ - struct worker_thread_info * wthread_info; - - struct semaphore target_sem; -}; - -struct iscsi_queue { - spinlock_t queue_lock; - struct iscsi_cmnd *ordered_cmnd; - struct list_head wait_list; - int active_cnt; -}; - -struct iet_volume { - u32 lun; - - enum iscsi_device_state l_state; - atomic_t l_count; - - struct iscsi_target *target; - struct list_head list; - - struct iscsi_queue queue; - - u8 scsi_id[SCSI_ID_LEN]; - u8 scsi_sn[SCSI_SN_LEN + 1]; - - u32 blk_shift; - u64 blk_cnt; - - u64 reserve_sid; - spinlock_t reserve_lock; - - unsigned long flags; - - struct iotype *iotype; - void *private; -}; - -enum lu_flags { - LU_READONLY, - LU_WCACHE, - LU_RCACHE, -}; - -#define LUReadonly(lu) test_bit(LU_READONLY, &(lu)->flags) -#define SetLUReadonly(lu) set_bit(LU_READONLY, &(lu)->flags) - -#define LUWCache(lu) test_bit(LU_WCACHE, &(lu)->flags) -#define SetLUWCache(lu) set_bit(LU_WCACHE, &(lu)->flags) -#define ClearLUWCache(lu) clear_bit(LU_WCACHE, &(lu)->flags) - -#define LURCache(lu) test_bit(LU_RCACHE, &(lu)->flags) -#define SetLURCache(lu) set_bit(LU_RCACHE, &(lu)->flags) -#define ClearLURCache(lu) clear_bit(LU_RCACHE, &(lu)->flags) - -#define IET_HASH_ORDER 8 -#define cmnd_hashfn(itt) hash_long((itt), IET_HASH_ORDER) - -#define UA_HASH_LEN 8 - -struct iscsi_session { - struct list_head list; - struct iscsi_target *target; - struct completion *done; - char *initiator; - u64 sid; - - u32 exp_cmd_sn; - u32 max_cmd_sn; - - struct iscsi_sess_param param; - u32 max_queued_cmnds; - - struct list_head conn_list; - - struct list_head pending_list; - - spinlock_t cmnd_hash_lock; - struct list_head cmnd_hash[1 << IET_HASH_ORDER]; - - spinlock_t ua_hash_lock; - struct list_head ua_hash[UA_HASH_LEN]; - - u32 next_ttt; -}; - -enum connection_state_bit { - CONN_ACTIVE, - CONN_CLOSING, - CONN_WSPACE_WAIT, - CONN_NEED_NOP_IN, -}; - -#define ISCSI_CONN_IOV_MAX (((256 << 10) >> PAGE_SHIFT) + 1) - -struct iscsi_conn { - struct list_head list; /* list entry in session list */ - struct iscsi_session *session; /* owning session */ - - u16 cid; - unsigned long state; - - u32 stat_sn; - u32 exp_stat_sn; - - int hdigest_type; - int ddigest_type; - - struct list_head poll_list; - - struct file *file; - struct socket *sock; - spinlock_t list_lock; - atomic_t nr_cmnds; - atomic_t nr_busy_cmnds; - struct list_head pdu_list; /* in/outcoming pdus */ - struct list_head write_list; /* list of data pdus to be sent */ - struct timer_list nop_timer; - - struct iscsi_cmnd *read_cmnd; - struct msghdr read_msg; - struct iovec read_iov[ISCSI_CONN_IOV_MAX]; - u32 read_size; - u32 read_overflow; - int read_state; - - struct iscsi_cmnd *write_cmnd; - struct iovec write_iov[ISCSI_CONN_IOV_MAX]; - struct iovec *write_iop; - struct tio *write_tcmnd; - u32 write_size; - u32 write_offset; - int write_state; - - struct hash_desc rx_hash; - struct hash_desc tx_hash; - struct scatterlist hash_sg[ISCSI_CONN_IOV_MAX]; -}; - -struct iscsi_pdu { - struct iscsi_hdr bhs; - void *ahs; - unsigned int ahssize; - unsigned int datasize; -}; - -typedef void (iet_show_info_t)(struct seq_file *seq, struct iscsi_target *target); - -struct iscsi_cmnd { - struct list_head list; - struct list_head conn_list; - unsigned long flags; - struct iscsi_conn *conn; - struct iet_volume *lun; - - struct iscsi_pdu pdu; - struct list_head pdu_list; - - struct list_head hash_list; - - struct tio *tio; - - u8 status; - - struct timer_list timer; - - u32 r2t_sn; - u32 r2t_length; - u32 is_unsolicited_data; - u32 target_task_tag; - u32 outstanding_r2t; - - u32 hdigest; - u32 ddigest; - - struct iscsi_cmnd *req; - - unsigned char sense_buf[IET_SENSE_BUF_SIZE]; -}; - -struct ua_entry { - struct list_head entry; - struct iscsi_session *session; /* only used for debugging ATM */ - u32 lun; - u8 asc; - u8 ascq; -}; - -#define ISCSI_OP_SCSI_REJECT ISCSI_OP_VENDOR1_CMD -#define ISCSI_OP_PDU_REJECT ISCSI_OP_VENDOR2_CMD -#define ISCSI_OP_DATA_REJECT ISCSI_OP_VENDOR3_CMD -#define ISCSI_OP_SCSI_ABORT ISCSI_OP_VENDOR4_CMD - -/* iscsi.c */ -extern unsigned long worker_thread_pool_size; -extern struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *, int); -extern void cmnd_rx_start(struct iscsi_cmnd *); -extern void cmnd_rx_end(struct iscsi_cmnd *); -extern void cmnd_tx_start(struct iscsi_cmnd *); -extern void cmnd_tx_end(struct iscsi_cmnd *); -extern void cmnd_release(struct iscsi_cmnd *, int); -extern void send_data_rsp(struct iscsi_cmnd *, void (*)(struct iscsi_cmnd *)); -extern void send_scsi_rsp(struct iscsi_cmnd *, void (*)(struct iscsi_cmnd *)); -extern void iscsi_cmnd_set_sense(struct iscsi_cmnd *, u8 sense_key, u8 asc, - u8 ascq); -extern void send_nop_in(struct iscsi_conn *); - -/* conn.c */ -extern struct iscsi_conn *conn_lookup(struct iscsi_session *, u16); -extern int conn_add(struct iscsi_session *, struct conn_info *); -extern int conn_del(struct iscsi_session *, struct conn_info *); -extern int conn_free(struct iscsi_conn *); -extern void conn_close(struct iscsi_conn *); -extern void conn_info_show(struct seq_file *, struct iscsi_session *); - -/* nthread.c */ -extern int nthread_init(struct iscsi_target *); -extern int nthread_start(struct iscsi_target *); -extern int nthread_stop(struct iscsi_target *); -extern void __nthread_wakeup(struct network_thread_info *); -extern void nthread_wakeup(struct iscsi_target *); - -/* wthread.c */ -extern int wthread_init(struct worker_thread_info *info); -extern int wthread_start(struct worker_thread_info *info, int wthreads, u32 tid); -extern int wthread_stop(struct worker_thread_info *info); -extern void wthread_queue(struct iscsi_cmnd *); -extern struct target_type *target_type_array[]; -extern int wthread_module_init(void); -extern void wthread_module_exit(void); -extern struct worker_thread_info *worker_thread_pool; - -/* target.c */ -extern int target_lock(struct iscsi_target *, int); -extern void target_unlock(struct iscsi_target *); -struct iscsi_target *target_lookup_by_id(u32); -extern int target_add(struct target_info *); -extern int target_del(u32 id); -extern void target_del_all(void); -extern struct seq_operations iet_seq_op; - -/* config.c */ -extern int iet_procfs_init(void); -extern void iet_procfs_exit(void); -extern int iet_info_show(struct seq_file *, iet_show_info_t *); - -/* session.c */ -extern struct file_operations session_seq_fops; -extern struct iscsi_session *session_lookup(struct iscsi_target *, u64); -extern int session_add(struct iscsi_target *, struct session_info *); -extern int session_del(struct iscsi_target *, u64); - -/* volume.c */ -extern struct file_operations volume_seq_fops; -extern int volume_add(struct iscsi_target *, struct volume_info *); -extern int iscsi_volume_del(struct iscsi_target *, struct volume_info *); -extern void iscsi_volume_destroy(struct iet_volume *); -extern struct iet_volume *volume_lookup(struct iscsi_target *, u32); -extern struct iet_volume *volume_get(struct iscsi_target *, u32); -extern void volume_put(struct iet_volume *); -extern int volume_reserve(struct iet_volume *volume, u64 sid); -extern int volume_release(struct iet_volume *volume, u64 sid, int force); -extern int is_volume_reserved(struct iet_volume *volume, u64 sid); - -/* tio.c */ -extern int tio_init(void); -extern void tio_exit(void); -extern struct tio *tio_alloc(int); -extern void tio_get(struct tio *); -extern void tio_put(struct tio *); -extern void tio_set(struct tio *, u32, loff_t); -extern int tio_read(struct iet_volume *, struct tio *); -extern int tio_write(struct iet_volume *, struct tio *); -extern int tio_sync(struct iet_volume *, struct tio *); - -/* iotype.c */ -extern struct iotype *get_iotype(const char *name); -extern void put_iotype(struct iotype *iot); - -/* params.c */ -extern int iscsi_param_set(struct iscsi_target *, struct iscsi_param_info *, int); - -/* target_disk.c */ -extern struct target_type disk_ops; - -/* event.c */ -extern int event_send(u32, u64, u32, u32, int); -extern int event_init(void); -extern void event_exit(void); - -/* ua.c */ -int ua_init(void); -void ua_exit(void); -struct ua_entry * ua_get_first(struct iscsi_session *, u32 lun); -struct ua_entry * ua_get_match(struct iscsi_session *, u32 lun, u8 asc, - u8 ascq); -void ua_free(struct ua_entry *); -int ua_pending(struct iscsi_session *, u32 lun); -void ua_establish_for_session(struct iscsi_session *, u32 lun, u8 asc, - u8 ascq); -void ua_establish_for_other_sessions(struct iscsi_session *, u32 lun, u8 asc, - u8 ascq); -void ua_establish_for_all_sessions(struct iscsi_target *, u32 lun, u8 asc, - u8 ascq); - -#define get_pgcnt(size, offset) ((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) - -static inline void iscsi_cmnd_get_length(struct iscsi_pdu *pdu) -{ -#if defined(__BIG_ENDIAN) - pdu->ahssize = pdu->bhs.length.ahslength * 4; - pdu->datasize = pdu->bhs.length.datalength; -#elif defined(__LITTLE_ENDIAN) - pdu->ahssize = (pdu->bhs.length & 0xff) * 4; - pdu->datasize = be32_to_cpu(pdu->bhs.length & ~0xff); -#else -#error -#endif -} - -static inline void iscsi_cmnd_set_length(struct iscsi_pdu *pdu) -{ -#if defined(__BIG_ENDIAN) - pdu->bhs.length.ahslength = pdu->ahssize / 4; - pdu->bhs.length.datalength = pdu->datasize; -#elif defined(__LITTLE_ENDIAN) - pdu->bhs.length = cpu_to_be32(pdu->datasize) | (pdu->ahssize / 4); -#else -#error -#endif -} - -#define cmnd_hdr(cmnd) ((struct iscsi_scsi_cmd_hdr *) (&((cmnd)->pdu.bhs))) -#define cmnd_ttt(cmnd) cpu_to_be32((cmnd)->pdu.bhs.ttt) -#define cmnd_itt(cmnd) cpu_to_be32((cmnd)->pdu.bhs.itt) -#define cmnd_opcode(cmnd) ((cmnd)->pdu.bhs.opcode & ISCSI_OPCODE_MASK) -#define cmnd_scsicode(cmnd) cmnd_hdr(cmnd)->scb[0] -#define cmnd_immediate(cmnd) ((cmnd)->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE) - -/* default and maximum scsi level block sizes */ -#define IET_DEF_BLOCK_SIZE 512 -#define IET_MAX_BLOCK_SIZE 4096 - -enum cmnd_flags { - CMND_hashed, - CMND_queued, - CMND_final, - CMND_waitio, - CMND_close, - CMND_lunit, - CMND_pending, - CMND_tmfabort, - CMND_rxstart, - CMND_timer_active, -}; - -#define set_cmnd_hashed(cmnd) set_bit(CMND_hashed, &(cmnd)->flags) -#define cmnd_hashed(cmnd) test_bit(CMND_hashed, &(cmnd)->flags) - -#define set_cmnd_queued(cmnd) set_bit(CMND_queued, &(cmnd)->flags) -#define cmnd_queued(cmnd) test_bit(CMND_queued, &(cmnd)->flags) - -#define set_cmnd_final(cmnd) set_bit(CMND_final, &(cmnd)->flags) -#define cmnd_final(cmnd) test_bit(CMND_final, &(cmnd)->flags) - -#define set_cmnd_waitio(cmnd) set_bit(CMND_waitio, &(cmnd)->flags) -#define cmnd_waitio(cmnd) test_bit(CMND_waitio, &(cmnd)->flags) - -#define set_cmnd_close(cmnd) set_bit(CMND_close, &(cmnd)->flags) -#define cmnd_close(cmnd) test_bit(CMND_close, &(cmnd)->flags) - -#define set_cmnd_lunit(cmnd) set_bit(CMND_lunit, &(cmnd)->flags) -#define cmnd_lunit(cmnd) test_bit(CMND_lunit, &(cmnd)->flags) - -#define set_cmnd_pending(cmnd) set_bit(CMND_pending, &(cmnd)->flags) -#define clear_cmnd_pending(cmnd) clear_bit(CMND_pending, &(cmnd)->flags) -#define cmnd_pending(cmnd) test_bit(CMND_pending, &(cmnd)->flags) - -#define set_cmnd_tmfabort(cmnd) set_bit(CMND_tmfabort, &(cmnd)->flags) -#define cmnd_tmfabort(cmnd) test_bit(CMND_tmfabort, &(cmnd)->flags) - -#define set_cmnd_rxstart(cmnd) set_bit(CMND_rxstart, &(cmnd)->flags) -#define cmnd_rxstart(cmnd) test_bit(CMND_rxstart, &(cmnd)->flags) - -#define set_cmnd_timer_active(cmnd) set_bit(CMND_timer_active, &(cmnd)->flags) -#define clear_cmnd_timer_active(cmnd) \ - clear_bit(CMND_timer_active, &(cmnd)->flags) -#define cmnd_timer_active(cmnd) test_bit(CMND_timer_active, &(cmnd)->flags) - -#define VENDOR_ID "IET" -#define PRODUCT_ID "VIRTUAL-DISK" -#define PRODUCT_REV "0" - -#endif /* __ISCSI_H__ */ diff --git a/ubuntu/iscsitarget/iscsi_dbg.h b/ubuntu/iscsitarget/iscsi_dbg.h deleted file mode 100644 index d8d5966..0000000 --- a/ubuntu/iscsitarget/iscsi_dbg.h +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef ISCSI_DBG_H -#define ISCSI_DBG_H - -#define D_SETUP (1UL << 0) -#define D_EXIT (1UL << 1) -#define D_GENERIC (1UL << 2) -#define D_READ (1UL << 3) -#define D_WRITE (1UL << 4) -#define D_IOD (1UL << 5) -#define D_THREAD (1UL << 6) -#define D_TASK_MGT (1UL << 7) -#define D_IOMODE (1UL << 8) -#define D_UAC (1UL << 9) - -#define D_DATA (D_READ | D_WRITE) - -extern unsigned long debug_enable_flags; - -#define PFX "iscsi_trgt: " - -#define dprintk(debug, fmt, args...) do { \ - if ((debug) & debug_enable_flags) { \ - printk(KERN_DEBUG PFX "%s(%d) " fmt, __FUNCTION__,\ - __LINE__, args);\ - } \ -} while (0) - -#define dprintk_ua(ua, sess, lun) \ - dprintk(D_UAC, "sess %llu, lun %u: %p %x %x\n", \ - (sess)->sid, lun, ua, \ - (ua) ? (ua)->asc : 0, \ - (ua) ? (ua)->ascq : 0) - -#define eprintk(fmt, args...) do { \ - printk(KERN_ERR PFX "%s(%d) " fmt, __FUNCTION__, \ - __LINE__, args);\ -} while (0) - -#define iprintk(X...) printk(KERN_INFO PFX X) - -#define assert(p) do { \ - if (!(p)) { \ - printk(KERN_CRIT PFX "BUG at %s:%d assert(%s)\n",\ - __FILE__, __LINE__, #p); \ - dump_stack(); \ - BUG(); \ - } \ -} while (0) - -#ifdef D_IOV -static inline void iscsi_dump_iov(struct msghdr *msg) -{ - int i; - printk(PFX "%p, %d\n", msg->msg_iov, msg->msg_iovlen); - for (i = 0; i < min_t(size_t, msg->msg_iovlen, ISCSI_CONN_IOV_MAX); i++) - printk(PFX "%d: %p,%d\n", i, msg->msg_iov[i].iov_base, - msg->msg_iov[i].iov_len); -} -#else -#define iscsi_dump_iov(x) do {} while (0) -#endif - -#ifdef D_DUMP_PDU -static void iscsi_dump_char(int ch) -{ - static unsigned char text[16]; - static int i = 0; - - if (ch < 0) { - while ((i % 16) != 0) { - printk(" "); - text[i] = ' '; - i++; - if ((i % 16) == 0) - printk(" | %.16s |\n", text); - else if ((i % 4) == 0) - printk(" |"); - } - i = 0; - return; - } - - text[i] = (ch < 0x20 || (ch >= 0x80 && ch <= 0xa0)) ? ' ' : ch; - printk(" %02x", ch); - i++; - if ((i % 16) == 0) { - printk(" | %.16s |\n", text); - i = 0; - } else if ((i % 4) == 0) - printk(" |"); -} - -static inline void iscsi_dump_pdu(struct iscsi_pdu *pdu) -{ - unsigned char *buf; - int i; - - buf = (void *)&pdu->bhs; - printk(PFX "BHS: (%p,%d)\n", buf, sizeof(pdu->bhs)); - for (i = 0; i < sizeof(pdu->bhs); i++) - iscsi_dump_char(*buf++); - iscsi_dump_char(-1); - - buf = (void *)pdu->ahs; - printk(PFX "AHS: (%p,%d)\n", buf, pdu->ahssize); - for (i = 0; i < pdu->ahssize; i++) - iscsi_dump_char(*buf++); - iscsi_dump_char(-1); - - printk(PFX "Data: (%d)\n", pdu->datasize); -} - -#else -#define iscsi_dump_pdu(x) do {} while (0) -#endif - -#define show_param(param)\ -{\ - dprintk(D_SETUP, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",\ - (param)->initial_r2t,\ - (param)->immediate_data,\ - (param)->max_connections,\ - (param)->max_recv_data_length,\ - (param)->max_xmit_data_length,\ - (param)->max_burst_length,\ - (param)->first_burst_length,\ - (param)->default_wait_time,\ - (param)->default_retain_time,\ - (param)->max_outstanding_r2t,\ - (param)->data_pdu_inorder,\ - (param)->data_sequence_inorder,\ - (param)->error_recovery_level,\ - (param)->header_digest,\ - (param)->data_digest);\ -} - -#endif diff --git a/ubuntu/iscsitarget/iscsi_hdr.h b/ubuntu/iscsitarget/iscsi_hdr.h deleted file mode 100644 index 2cbcd4f..0000000 --- a/ubuntu/iscsitarget/iscsi_hdr.h +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright (C) 2002-2003 Ardis Technolgies - * - * Released under the terms of the GNU GPL v2.0. - */ - -#ifndef __ISCSI_HDR_H__ -#define __ISCSI_HDR_H__ - -#include -#include - -#define ISCSI_VERSION 0 - -#ifndef __packed -#define __packed __attribute__ ((packed)) -#endif - -struct iscsi_hdr { - u8 opcode; /* 0 */ - u8 flags; - u8 spec1[2]; -#if defined(__BIG_ENDIAN_BITFIELD) - struct { /* 4 */ - unsigned ahslength : 8; - unsigned datalength : 24; - } length; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - u32 length; /* 4 */ -#endif - u16 lun[4]; /* 8 */ - u32 itt; /* 16 */ - u32 ttt; /* 20 */ - u32 sn; /* 24 */ - u32 exp_sn; /* 28 */ - u32 max_sn; /* 32 */ - u32 spec3[3]; /* 36 */ -} __packed; /* 48 */ - -/* Opcode encoding bits */ -#define ISCSI_OP_RETRY 0x80 -#define ISCSI_OP_IMMEDIATE 0x40 -#define ISCSI_OPCODE_MASK 0x3F - -/* Client to Server Message Opcode values */ -#define ISCSI_OP_NOP_OUT 0x00 -#define ISCSI_OP_SCSI_CMD 0x01 -#define ISCSI_OP_SCSI_TASK_MGT_MSG 0x02 -#define ISCSI_OP_LOGIN_CMD 0x03 -#define ISCSI_OP_TEXT_CMD 0x04 -#define ISCSI_OP_SCSI_DATA_OUT 0x05 -#define ISCSI_OP_LOGOUT_CMD 0x06 -#define ISCSI_OP_SNACK_CMD 0x10 - -#define ISCSI_OP_VENDOR1_CMD 0x1c -#define ISCSI_OP_VENDOR2_CMD 0x1d -#define ISCSI_OP_VENDOR3_CMD 0x1e -#define ISCSI_OP_VENDOR4_CMD 0x1f - -/* Server to Client Message Opcode values */ -#define ISCSI_OP_NOP_IN 0x20 -#define ISCSI_OP_SCSI_RSP 0x21 -#define ISCSI_OP_SCSI_TASK_MGT_RSP 0x22 -#define ISCSI_OP_LOGIN_RSP 0x23 -#define ISCSI_OP_TEXT_RSP 0x24 -#define ISCSI_OP_SCSI_DATA_IN 0x25 -#define ISCSI_OP_LOGOUT_RSP 0x26 -#define ISCSI_OP_R2T 0x31 -#define ISCSI_OP_ASYNC_MSG 0x32 -#define ISCSI_OP_REJECT 0x3f - -struct iscsi_ahs_hdr { - u16 ahslength; - u8 ahstype; -} __packed; - -#define ISCSI_AHSTYPE_CDB 1 -#define ISCSI_AHSTYPE_RLENGTH 2 - -union iscsi_sid { - struct { - u8 isid[6]; /* Initiator Session ID */ - u16 tsih; /* Target Session ID */ - } id; - u64 id64; -} __packed; - -struct iscsi_scsi_cmd_hdr { - u8 opcode; - u8 flags; - u16 rsvd1; - u8 ahslength; - u8 datalength[3]; - u16 lun[4]; - u32 itt; - u32 data_length; - u32 cmd_sn; - u32 exp_stat_sn; - u8 scb[16]; -} __packed; - -#define ISCSI_CMD_FINAL 0x80 -#define ISCSI_CMD_READ 0x40 -#define ISCSI_CMD_WRITE 0x20 -#define ISCSI_CMD_ATTR_MASK 0x07 -#define ISCSI_CMD_UNTAGGED 0x00 -#define ISCSI_CMD_SIMPLE 0x01 -#define ISCSI_CMD_ORDERED 0x02 -#define ISCSI_CMD_HEAD_OF_QUEUE 0x03 -#define ISCSI_CMD_ACA 0x04 - -struct iscsi_cdb_ahdr { - u16 ahslength; - u8 ahstype; - u8 reserved; - u8 cdb[0]; -} __packed; - -struct iscsi_rlength_ahdr { - u16 ahslength; - u8 ahstype; - u8 reserved; - u32 read_length; -} __packed; - -struct iscsi_scsi_rsp_hdr { - u8 opcode; - u8 flags; - u8 response; - u8 cmd_status; - u8 ahslength; - u8 datalength[3]; - u32 rsvd1[2]; - u32 itt; - u32 snack; - u32 stat_sn; - u32 exp_cmd_sn; - u32 max_cmd_sn; - u32 exp_data_sn; - u32 bi_residual_count; - u32 residual_count; -} __packed; - -#define ISCSI_FLG_RESIDUAL_UNDERFLOW 0x02 -#define ISCSI_FLG_RESIDUAL_OVERFLOW 0x04 -#define ISCSI_FLG_BIRESIDUAL_UNDERFLOW 0x08 -#define ISCSI_FLG_BIRESIDUAL_OVERFLOW 0x10 - -#define ISCSI_RESPONSE_COMMAND_COMPLETED 0x00 -#define ISCSI_RESPONSE_TARGET_FAILURE 0x01 - -struct iscsi_sense_data { - u16 length; - u8 data[0]; -} __packed; - -struct iscsi_task_mgt_hdr { - u8 opcode; - u8 function; - u16 rsvd1; - u8 ahslength; - u8 datalength[3]; - u16 lun[4]; - u32 itt; - u32 rtt; - u32 cmd_sn; - u32 exp_stat_sn; - u32 ref_cmd_sn; - u32 exp_data_sn; - u32 rsvd2[2]; -} __packed; - -#define ISCSI_FUNCTION_MASK 0x7f - -#define ISCSI_FUNCTION_ABORT_TASK 1 -#define ISCSI_FUNCTION_ABORT_TASK_SET 2 -#define ISCSI_FUNCTION_CLEAR_ACA 3 -#define ISCSI_FUNCTION_CLEAR_TASK_SET 4 -#define ISCSI_FUNCTION_LOGICAL_UNIT_RESET 5 -#define ISCSI_FUNCTION_TARGET_WARM_RESET 6 -#define ISCSI_FUNCTION_TARGET_COLD_RESET 7 -#define ISCSI_FUNCTION_TASK_REASSIGN 8 - -struct iscsi_task_rsp_hdr { - u8 opcode; - u8 flags; - u8 response; - u8 rsvd1; - u8 ahslength; - u8 datalength[3]; - u32 rsvd2[2]; - u32 itt; - u32 rsvd3; - u32 stat_sn; - u32 exp_cmd_sn; - u32 max_cmd_sn; - u32 rsvd4[3]; -} __packed; - -#define ISCSI_RESPONSE_FUNCTION_COMPLETE 0 -#define ISCSI_RESPONSE_UNKNOWN_TASK 1 -#define ISCSI_RESPONSE_UNKNOWN_LUN 2 -#define ISCSI_RESPONSE_TASK_ALLEGIANT 3 -#define ISCSI_RESPONSE_FAILOVER_UNSUPPORTED 4 -#define ISCSI_RESPONSE_FUNCTION_UNSUPPORTED 5 -#define ISCSI_RESPONSE_NO_AUTHORIZATION 6 -#define ISCSI_RESPONSE_FUNCTION_REJECTED 255 - -struct iscsi_data_out_hdr { - u8 opcode; - u8 flags; - u16 rsvd1; - u8 ahslength; - u8 datalength[3]; - u16 lun[4]; - u32 itt; - u32 ttt; - u32 rsvd2; - u32 exp_stat_sn; - u32 rsvd3; - u32 data_sn; - u32 buffer_offset; - u32 rsvd4; -} __packed; - -struct iscsi_data_in_hdr { - u8 opcode; - u8 flags; - u8 rsvd1; - u8 cmd_status; - u8 ahslength; - u8 datalength[3]; - u32 rsvd2[2]; - u32 itt; - u32 ttt; - u32 stat_sn; - u32 exp_cmd_sn; - u32 max_cmd_sn; - u32 data_sn; - u32 buffer_offset; - u32 residual_count; -} __packed; - -#define ISCSI_FLG_STATUS 0x01 - -struct iscsi_r2t_hdr { - u8 opcode; - u8 flags; - u16 rsvd1; - u8 ahslength; - u8 datalength[3]; - u16 lun[4]; - u32 itt; - u32 ttt; - u32 stat_sn; - u32 exp_cmd_sn; - u32 max_cmd_sn; - u32 r2t_sn; - u32 buffer_offset; - u32 data_length; -} __packed; - -struct iscsi_async_msg_hdr { - u8 opcode; - u8 flags; - u16 rsvd1; - u8 ahslength; - u8 datalength[3]; - u16 lun[4]; - u32 ffffffff; - u32 rsvd2; - u32 stat_sn; - u32 exp_cmd_sn; - u32 max_cmd_sn; - u8 async_event; - u8 async_vcode; - u16 param1; - u16 param2; - u16 param3; - u32 rsvd3; -} __packed; - -#define ISCSI_ASYNC_SCSI 0 -#define ISCSI_ASYNC_LOGOUT 1 -#define ISCSI_ASYNC_DROP_CONNECTION 2 -#define ISCSI_ASYNC_DROP_SESSION 3 -#define ISCSI_ASYNC_PARAM_REQUEST 4 -#define ISCSI_ASYNC_VENDOR 255 - -struct iscsi_text_req_hdr { - u8 opcode; - u8 flags; - u16 rsvd1; - u8 ahslength; - u8 datalength[3]; - u32 rsvd2[2]; - u32 itt; - u32 ttt; - u32 cmd_sn; - u32 exp_stat_sn; - u32 rsvd3[4]; -} __packed; - -struct iscsi_text_rsp_hdr { - u8 opcode; - u8 flags; - u16 rsvd1; - u8 ahslength; - u8 datalength[3]; - u32 rsvd2[2]; - u32 itt; - u32 ttt; - u32 stat_sn; - u32 exp_cmd_sn; - u32 max_cmd_sn; - u32 rsvd3[3]; -} __packed; - -struct iscsi_login_req_hdr { - u8 opcode; - u8 flags; - u8 max_version; /* Max. version supported */ - u8 min_version; /* Min. version supported */ - u8 ahslength; - u8 datalength[3]; - union iscsi_sid sid; - u32 itt; /* Initiator Task Tag */ - u16 cid; /* Connection ID */ - u16 rsvd1; - u32 cmd_sn; - u32 exp_stat_sn; - u32 rsvd2[4]; -} __packed; - -struct iscsi_login_rsp_hdr { - u8 opcode; - u8 flags; - u8 max_version; /* Max. version supported */ - u8 active_version; /* Active version */ - u8 ahslength; - u8 datalength[3]; - union iscsi_sid sid; - u32 itt; /* Initiator Task Tag */ - u32 rsvd1; - u32 stat_sn; - u32 exp_cmd_sn; - u32 max_cmd_sn; - u8 status_class; /* see Login RSP ststus classes below */ - u8 status_detail; /* see Login RSP Status details below */ - u8 rsvd2[10]; -} __packed; - -#define ISCSI_FLG_FINAL 0x80 -#define ISCSI_FLG_TRANSIT 0x80 -#define ISCSI_FLG_CSG_SECURITY 0x00 -#define ISCSI_FLG_CSG_LOGIN 0x04 -#define ISCSI_FLG_CSG_FULL_FEATURE 0x0c -#define ISCSI_FLG_CSG_MASK 0x0c -#define ISCSI_FLG_NSG_SECURITY 0x00 -#define ISCSI_FLG_NSG_LOGIN 0x01 -#define ISCSI_FLG_NSG_FULL_FEATURE 0x03 -#define ISCSI_FLG_NSG_MASK 0x03 - -/* Login Status response classes */ -#define ISCSI_STATUS_SUCCESS 0x00 -#define ISCSI_STATUS_REDIRECT 0x01 -#define ISCSI_STATUS_INITIATOR_ERR 0x02 -#define ISCSI_STATUS_TARGET_ERR 0x03 - -/* Login Status response detail codes */ -/* Class-0 (Success) */ -#define ISCSI_STATUS_ACCEPT 0x00 - -/* Class-1 (Redirection) */ -#define ISCSI_STATUS_TGT_MOVED_TEMP 0x01 -#define ISCSI_STATUS_TGT_MOVED_PERM 0x02 - -/* Class-2 (Initiator Error) */ -#define ISCSI_STATUS_INIT_ERR 0x00 -#define ISCSI_STATUS_AUTH_FAILED 0x01 -#define ISCSI_STATUS_TGT_FORBIDDEN 0x02 -#define ISCSI_STATUS_TGT_NOT_FOUND 0x03 -#define ISCSI_STATUS_TGT_REMOVED 0x04 -#define ISCSI_STATUS_NO_VERSION 0x05 -#define ISCSI_STATUS_TOO_MANY_CONN 0x06 -#define ISCSI_STATUS_MISSING_FIELDS 0x07 -#define ISCSI_STATUS_CONN_ADD_FAILED 0x08 -#define ISCSI_STATUS_INV_SESSION_TYPE 0x09 -#define ISCSI_STATUS_SESSION_NOT_FOUND 0x0a -#define ISCSI_STATUS_INV_REQ_TYPE 0x0b - -/* Class-3 (Target Error) */ -#define ISCSI_STATUS_TARGET_ERROR 0x00 -#define ISCSI_STATUS_SVC_UNAVAILABLE 0x01 -#define ISCSI_STATUS_NO_RESOURCES 0x02 - -struct iscsi_logout_req_hdr { - u8 opcode; - u8 flags; - u16 rsvd1; - u8 ahslength; - u8 datalength[3]; - u32 rsvd2[2]; - u32 itt; - u16 cid; - u16 rsvd3; - u32 cmd_sn; - u32 exp_stat_sn; - u32 rsvd4[4]; -} __packed; - -struct iscsi_logout_rsp_hdr { - u8 opcode; - u8 flags; - u8 response; - u8 rsvd1; - u8 ahslength; - u8 datalength[3]; - u32 rsvd2[2]; - u32 itt; - u32 rsvd3; - u32 stat_sn; - u32 exp_cmd_sn; - u32 max_cmd_sn; - u32 rsvd4; - u16 time2wait; - u16 time2retain; - u32 rsvd5; -} __packed; - -struct iscsi_snack_req_hdr { - u8 opcode; - u8 flags; - u16 rsvd1; - u8 ahslength; - u8 datalength[3]; - u32 rsvd2[2]; - u32 itt; - u32 ttt; - u32 rsvd3; - u32 exp_stat_sn; - u32 rsvd4[2]; - u32 beg_run; - u32 run_length; -} __packed; - -struct iscsi_reject_hdr { - u8 opcode; - u8 flags; - u8 reason; - u8 rsvd1; - u8 ahslength; - u8 datalength[3]; - u32 rsvd2[2]; - u32 ffffffff; - u32 rsvd3; - u32 stat_sn; - u32 exp_cmd_sn; - u32 max_cmd_sn; - u32 data_sn; - u32 rsvd4[2]; -} __packed; - -#define ISCSI_REASON_NO_FULL_FEATURE_PHASE 0x01 -#define ISCSI_REASON_DATA_DIGEST_ERROR 0x02 -#define ISCSI_REASON_DATA_SNACK_REJECT 0x03 -#define ISCSI_REASON_PROTOCOL_ERROR 0x04 -#define ISCSI_REASON_UNSUPPORTED_COMMAND 0x05 -#define ISCSI_REASON_IMMEDIATE_COMMAND_REJECT 0x06 -#define ISCSI_REASON_TASK_IN_PROGRESS 0x07 -#define ISCSI_REASON_INVALID_SNACK 0x08 -#define ISCSI_REASON_NO_BOOKMARK 0x09 -#define ISCSI_REASON_BOOKMARK_REJECT 0x0a -#define ISCSI_REASON_NEGOTIATION_RESET 0x0b -#define ISCSI_REASON_WAITING_LOGOUT 0x0c - - -struct iscsi_nop_out_hdr { - u8 opcode; - u8 flags; - u16 rsvd1; - u8 ahslength; - u8 datalength[3]; - u16 lun[4]; - u32 itt; - u32 ttt; - u32 cmd_sn; - u32 exp_stat_sn; - u32 rsvd2[4]; -} __packed; - -struct iscsi_nop_in_hdr { - u8 opcode; - u8 flags; - u16 rsvd1; - u8 ahslength; - u8 datalength[3]; - u16 lun[4]; - u32 itt; - u32 ttt; - u32 stat_sn; - u32 exp_cmd_sn; - u32 max_cmd_sn; - u32 rsvd2[3]; -} __packed; - -#define ISCSI_RESERVED_TAG (0xffffffffU) - -#endif /* __ISCSI_HDR_H__ */ diff --git a/ubuntu/iscsitarget/nthread.c b/ubuntu/iscsitarget/nthread.c deleted file mode 100644 index 52cd69a..0000000 --- a/ubuntu/iscsitarget/nthread.c +++ /dev/null @@ -1,790 +0,0 @@ -/* - * Network thread. - * (C) 2004 - 2005 FUJITA Tomonori - * (C) 2008 Arne Redlich - * - * This code is licenced under the GPL. - */ - -#include -#include -#include -#include - -#include "iscsi.h" -#include "iscsi_dbg.h" -#include "digest.h" - -enum daemon_state_bit { - D_ACTIVE, - D_DATA_READY, -}; - -void __nthread_wakeup(struct network_thread_info *info) -{ - set_bit(D_DATA_READY, &info->flags); - wake_up_process(info->task); -} - -void nthread_wakeup(struct iscsi_target *target) -{ - struct network_thread_info *info = &target->nthread_info; - - spin_lock_bh(&info->nthread_lock); - __nthread_wakeup(info); - spin_unlock_bh(&info->nthread_lock); -} - -static inline void iscsi_conn_init_read(struct iscsi_conn *conn, void *data, size_t len) -{ - len = (len + 3) & -4; // XXX ??? - conn->read_iov[0].iov_base = data; - conn->read_iov[0].iov_len = len; - conn->read_msg.msg_iov = conn->read_iov; - conn->read_msg.msg_iovlen = 1; - conn->read_size = (len + 3) & -4; -} - -static void iscsi_conn_read_ahs(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) -{ - cmnd->pdu.ahs = kmalloc(cmnd->pdu.ahssize, __GFP_NOFAIL|GFP_KERNEL); - assert(cmnd->pdu.ahs); - iscsi_conn_init_read(conn, cmnd->pdu.ahs, cmnd->pdu.ahssize); -} - -static struct iscsi_cmnd * iscsi_get_send_cmnd(struct iscsi_conn *conn) -{ - struct iscsi_cmnd *cmnd = NULL; - - spin_lock(&conn->list_lock); - if (!list_empty(&conn->write_list)) { - cmnd = list_entry(conn->write_list.next, struct iscsi_cmnd, list); - list_del_init(&cmnd->list); - } - spin_unlock(&conn->list_lock); - - return cmnd; -} - -static int is_data_available(struct iscsi_conn *conn) -{ - int avail, res; - mm_segment_t oldfs; - struct socket *sock = conn->sock; - - oldfs = get_fs(); - set_fs(get_ds()); - res = sock->ops->ioctl(sock, SIOCINQ, (unsigned long) &avail); - set_fs(oldfs); - return (res >= 0) ? avail : res; -} - -static void forward_iov(struct msghdr *msg, int len) -{ - while (msg->msg_iov->iov_len <= len) { - len -= msg->msg_iov->iov_len; - msg->msg_iov++; - msg->msg_iovlen--; - } - - msg->msg_iov->iov_base = (char *) msg->msg_iov->iov_base + len; - msg->msg_iov->iov_len -= len; -} - -static int do_recv(struct iscsi_conn *conn, int state) -{ - mm_segment_t oldfs; - struct msghdr msg; - struct iovec iov[ISCSI_CONN_IOV_MAX]; - int i, len, res; - - if (!test_bit(CONN_ACTIVE, &conn->state)) { - res = -EIO; - goto out; - } - - if (is_data_available(conn) <= 0) { - res = -EAGAIN; - goto out; - } - - msg.msg_iov = iov; - msg.msg_iovlen = min_t(size_t, conn->read_msg.msg_iovlen, ISCSI_CONN_IOV_MAX); - for (i = 0, len = 0; i < msg.msg_iovlen; i++) { - iov[i] = conn->read_msg.msg_iov[i]; - len += iov[i].iov_len; - } - - oldfs = get_fs(); - set_fs(get_ds()); - res = sock_recvmsg(conn->sock, &msg, len, MSG_DONTWAIT | MSG_NOSIGNAL); - set_fs(oldfs); - - if (res <= 0) { - switch (res) { - case -EAGAIN: - case -ERESTARTSYS: - break; - default: - eprintk("%d\n", res); - conn_close(conn); - break; - } - } else { - conn->read_size -= res; - if (conn->read_size) - forward_iov(&conn->read_msg, res); - else - conn->read_state = state; - } - -out: - dprintk(D_IOD, "%d\n", res); - - return res; -} - -enum rx_state { - RX_INIT_BHS, /* Must be zero. */ - RX_BHS, - - RX_INIT_AHS, - RX_AHS, - - RX_INIT_HDIGEST, - RX_HDIGEST, - RX_CHECK_HDIGEST, - - RX_INIT_DATA, - RX_DATA, - - RX_INIT_DDIGEST, - RX_DDIGEST, - RX_CHECK_DDIGEST, - - RX_END, -}; - -static void rx_ddigest(struct iscsi_conn *conn, int state) -{ - struct iscsi_cmnd *cmnd = conn->read_cmnd; - int res = digest_rx_data(cmnd); - - if (!res) - conn->read_state = state; - else - conn_close(conn); -} - -static void rx_hdigest(struct iscsi_conn *conn, int state) -{ - struct iscsi_cmnd *cmnd = conn->read_cmnd; - int res = digest_rx_header(cmnd); - - if (!res) - conn->read_state = state; - else - conn_close(conn); -} - -static struct iscsi_cmnd *create_cmnd(struct iscsi_conn *conn) -{ - struct iscsi_cmnd *cmnd; - - cmnd = cmnd_alloc(conn, 1); - iscsi_conn_init_read(cmnd->conn, &cmnd->pdu.bhs, sizeof(cmnd->pdu.bhs)); - conn->read_state = RX_BHS; - - return cmnd; -} - -static int recv(struct iscsi_conn *conn) -{ - struct iscsi_cmnd *cmnd = conn->read_cmnd; - int hdigest, ddigest, res = 1; - - if (!test_bit(CONN_ACTIVE, &conn->state)) - return -EIO; - - hdigest = conn->hdigest_type & DIGEST_NONE ? 0 : 1; - ddigest = conn->ddigest_type & DIGEST_NONE ? 0 : 1; - -next_state: - switch (conn->read_state) { - case RX_INIT_BHS: - assert(!cmnd); - cmnd = conn->read_cmnd = create_cmnd(conn); - case RX_BHS: - res = do_recv(conn, RX_INIT_AHS); - if (res <= 0 || conn->read_state != RX_INIT_AHS) - break; - case RX_INIT_AHS: - iscsi_cmnd_get_length(&cmnd->pdu); - if (cmnd->pdu.ahssize) { - iscsi_conn_read_ahs(conn, cmnd); - conn->read_state = RX_AHS; - } else - conn->read_state = hdigest ? RX_INIT_HDIGEST : RX_INIT_DATA; - - if (conn->read_state != RX_AHS) - break; - case RX_AHS: - res = do_recv(conn, hdigest ? RX_INIT_HDIGEST : RX_INIT_DATA); - if (res <= 0 || conn->read_state != RX_INIT_HDIGEST) - break; - case RX_INIT_HDIGEST: - iscsi_conn_init_read(conn, &cmnd->hdigest, sizeof(u32)); - conn->read_state = RX_HDIGEST; - case RX_HDIGEST: - res = do_recv(conn, RX_CHECK_HDIGEST); - if (res <= 0 || conn->read_state != RX_CHECK_HDIGEST) - break; - case RX_CHECK_HDIGEST: - rx_hdigest(conn, RX_INIT_DATA); - if (conn->read_state != RX_INIT_DATA) - break; - case RX_INIT_DATA: - cmnd_rx_start(cmnd); - conn->read_state = cmnd->pdu.datasize ? RX_DATA : RX_END; - if (conn->read_state != RX_DATA) - break; - case RX_DATA: - res = do_recv(conn, ddigest ? RX_INIT_DDIGEST : RX_END); - if (res <= 0 || conn->read_state != RX_INIT_DDIGEST) - break; - case RX_INIT_DDIGEST: - iscsi_conn_init_read(conn, &cmnd->ddigest, sizeof(u32)); - conn->read_state = RX_DDIGEST; - case RX_DDIGEST: - res = do_recv(conn, RX_CHECK_DDIGEST); - if (res <= 0 || conn->read_state != RX_CHECK_DDIGEST) - break; - case RX_CHECK_DDIGEST: - rx_ddigest(conn, RX_END); - break; - default: - eprintk("%d %d %x\n", res, conn->read_state, cmnd_opcode(cmnd)); - assert(0); - } - - if (res <= 0) - return res; - - if (conn->read_state != RX_END) - goto next_state; - - if (conn->read_size) { - eprintk("%d %x %d\n", res, cmnd_opcode(cmnd), conn->read_size); - assert(0); - } - - cmnd_rx_end(cmnd); - if (conn->read_size) { - eprintk("%x %d\n", cmnd_opcode(cmnd), conn->read_size); - conn->read_state = RX_DATA; - return 1; - } - - conn->read_cmnd = NULL; - conn->read_state = RX_INIT_BHS; - - return 0; -} - -/* - * @locking: grabs the target's nthread_lock to protect it from races with - * iet_write_space() - */ -static void set_conn_wspace_wait(struct iscsi_conn *conn) -{ - struct network_thread_info *info = &conn->session->target->nthread_info; - struct sock *sk = conn->sock->sk; - - spin_lock_bh(&info->nthread_lock); - - if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk)) - set_bit(CONN_WSPACE_WAIT, &conn->state); - - spin_unlock_bh(&info->nthread_lock); -} - -/* This is taken from the Ardis code. */ -static int write_data(struct iscsi_conn *conn) -{ - mm_segment_t oldfs; - struct file *file; - struct socket *sock; - ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); - struct tio *tio; - struct iovec *iop; - int saved_size, size, sendsize; - int offset, idx; - int flags, res; - - file = conn->file; - saved_size = size = conn->write_size; - iop = conn->write_iop; - - if (iop) while (1) { - loff_t off = 0; - unsigned long count; - struct iovec *vec; - int rest; - - vec = iop; - for (count = 0; vec->iov_len; count++, vec++) - ; - oldfs = get_fs(); - set_fs(KERNEL_DS); - res = vfs_writev(file, (struct iovec __user *) iop, count, &off); - set_fs(oldfs); - dprintk(D_DATA, "%#Lx:%u: %d(%ld)\n", - (unsigned long long) conn->session->sid, conn->cid, - res, (long) iop->iov_len); - if (unlikely(res <= 0)) { - if (res == -EAGAIN || res == -EINTR) { - conn->write_iop = iop; - goto out_iov; - } - goto err; - } - - rest = res; - size -= res; - while (iop->iov_len <= rest && rest) { - rest -= iop->iov_len; - iop++; - } - iop->iov_base += rest; - iop->iov_len -= rest; - - if (!iop->iov_len) { - conn->write_iop = NULL; - if (size) - break; - goto out_iov; - } - } - - if (!(tio = conn->write_tcmnd)) { - eprintk("%s\n", "warning data missing!"); - return 0; - } - offset = conn->write_offset; - idx = offset >> PAGE_CACHE_SHIFT; - offset &= ~PAGE_CACHE_MASK; - - sock = conn->sock; - sendpage = sock->ops->sendpage ? : sock_no_sendpage; - flags = MSG_DONTWAIT; - - while (1) { - sendsize = PAGE_CACHE_SIZE - offset; - if (size <= sendsize) { - res = sendpage(sock, tio->pvec[idx], offset, size, flags); - dprintk(D_DATA, "%s %#Lx:%u: %d(%lu,%u,%u)\n", - sock->ops->sendpage ? "sendpage" : "writepage", - (unsigned long long ) conn->session->sid, conn->cid, - res, tio->pvec[idx]->index, offset, size); - if (unlikely(res <= 0)) { - if (res == -EAGAIN || res == -EINTR) { - goto out; - } - goto err; - } - if (res == size) { - conn->write_tcmnd = NULL; - conn->write_size = 0; - return saved_size; - } - offset += res; - size -= res; - continue; - } - - res = sendpage(sock, tio->pvec[idx], offset,sendsize, flags | MSG_MORE); - dprintk(D_DATA, "%s %#Lx:%u: %d(%lu,%u,%u)\n", - sock->ops->sendpage ? "sendpage" : "writepage", - (unsigned long long ) conn->session->sid, conn->cid, - res, tio->pvec[idx]->index, offset, sendsize); - if (unlikely(res <= 0)) { - if (res == -EAGAIN || res == -EINTR) { - goto out; - } - goto err; - } - if (res == sendsize) { - idx++; - offset = 0; - } else - offset += res; - size -= res; - } - out: - conn->write_offset = (idx << PAGE_CACHE_SHIFT) + offset; - out_iov: - conn->write_size = size; - if (res == -EAGAIN) { - set_conn_wspace_wait(conn); - if (saved_size == size) - return res; - } - - return saved_size - size; - - err: - eprintk("error %d at %#Lx:%u\n", res, - (unsigned long long) conn->session->sid, conn->cid); - return res; -} - -static void exit_tx(struct iscsi_conn *conn, int res) -{ - if (res > 0) - return; - - switch (res) { - case -EAGAIN: - case -ERESTARTSYS: - break; - default: - eprintk("%d %d %d\n", conn->write_size, conn->write_state, res); - conn_close(conn); - break; - } -} - -static int tx_ddigest(struct iscsi_cmnd *cmnd, int state) -{ - int res, rest = cmnd->conn->write_size; - struct msghdr msg = {.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT}; - struct kvec iov; - - iov.iov_base = (char *) (&cmnd->ddigest) + (sizeof(u32) - rest); - iov.iov_len = rest; - - res = kernel_sendmsg(cmnd->conn->sock, &msg, &iov, 1, rest); - - if (res > 0) { - cmnd->conn->write_size -= res; - if (!cmnd->conn->write_size) - cmnd->conn->write_state = state; - } else - exit_tx(cmnd->conn, res); - - return res; -} - -static void init_tx_hdigest(struct iscsi_cmnd *cmnd) -{ - struct iscsi_conn *conn = cmnd->conn; - struct iovec *iop; - - if (conn->hdigest_type & DIGEST_NONE) - return; - - digest_tx_header(cmnd); - - for (iop = conn->write_iop; iop->iov_len; iop++) - ; - iop->iov_base = &(cmnd->hdigest); - iop->iov_len = sizeof(u32); - conn->write_size += sizeof(u32); - iop++; - iop->iov_len = 0; - - return; -} - -enum tx_state { - TX_INIT, /* Must be zero. */ - TX_BHS_DATA, - TX_INIT_DDIGEST, - TX_DDIGEST, - TX_END, -}; - -static int do_send(struct iscsi_conn *conn, int state) -{ - int res; - - res = write_data(conn); - - if (res > 0) { - if (!conn->write_size) - conn->write_state = state; - } else - exit_tx(conn, res); - - return res; -} - -static int send(struct iscsi_conn *conn) -{ - struct iscsi_cmnd *cmnd = conn->write_cmnd; - int ddigest, res = 0; - - ddigest = conn->ddigest_type != DIGEST_NONE ? 1 : 0; - -next_state: - switch (conn->write_state) { - case TX_INIT: - assert(!cmnd); - cmnd = conn->write_cmnd = iscsi_get_send_cmnd(conn); - if (!cmnd) - return 0; - cmnd_tx_start(cmnd); - init_tx_hdigest(cmnd); - conn->write_state = TX_BHS_DATA; - case TX_BHS_DATA: - res = do_send(conn, ddigest && cmnd->pdu.datasize ? TX_INIT_DDIGEST : TX_END); - if (res <= 0 || conn->write_state != TX_INIT_DDIGEST) - break; - case TX_INIT_DDIGEST: - digest_tx_data(cmnd); - assert(!cmnd->conn->write_size); - cmnd->conn->write_size += sizeof(u32); - conn->write_state = TX_DDIGEST; - case TX_DDIGEST: - res = tx_ddigest(cmnd, TX_END); - break; - default: - eprintk("%d %d %x\n", res, conn->write_state, cmnd_opcode(cmnd)); - assert(0); - } - - if (res <= 0) - return res; - - if (conn->write_state != TX_END) - goto next_state; - - if (conn->write_size) { - eprintk("%d %x %u\n", res, cmnd_opcode(cmnd), conn->write_size); - assert(!conn->write_size); - } - cmnd_tx_end(cmnd); - cmnd_release(cmnd, 0); - conn->write_cmnd = NULL; - conn->write_state = TX_INIT; - - return 0; -} - -static void conn_nop_timeout(unsigned long data) -{ - struct iscsi_conn *conn = (struct iscsi_conn *)data; - - if (test_bit(CONN_ACTIVE, &conn->state)) - set_bit(CONN_NEED_NOP_IN, &conn->state); - - dprintk(D_THREAD, "conn %llu:%hu, NOP timer %p\n", conn->session->sid, - conn->cid, &conn->nop_timer); - - nthread_wakeup(conn->session->target); -} - -static void conn_reset_nop_timer(struct iscsi_conn *conn) -{ - struct iscsi_target *target = conn->session->target; - - if (target->trgt_param.nop_interval) - mod_timer(&conn->nop_timer, - jiffies + HZ * target->trgt_param.nop_interval); -} - -static void conn_start_nop_timer(struct iscsi_conn *conn) -{ - struct iscsi_target *target = conn->session->target; - - if (!target->trgt_param.nop_interval || timer_pending(&conn->nop_timer)) - return; - - conn->nop_timer.data = (unsigned long)conn; - conn->nop_timer.function = conn_nop_timeout; - - dprintk(D_THREAD, "conn %llu:%hu, NOP timer %p\n", conn->session->sid, - conn->cid, &conn->nop_timer); - - mod_timer(&conn->nop_timer, - jiffies + HZ * target->trgt_param.nop_interval); -} - -static void process_io(struct iscsi_conn *conn) -{ - struct iscsi_target *target = conn->session->target; - int res, wakeup = 0; - - res = recv(conn); - - if (is_data_available(conn) > 0 || res > 0) { - conn_reset_nop_timer(conn); - wakeup = 1; - } - - if (!test_bit(CONN_ACTIVE, &conn->state)) { - wakeup = 1; - goto out; - } - - if (test_bit(CONN_WSPACE_WAIT, &conn->state)) - goto out; - - res = send(conn); - - if (!list_empty(&conn->write_list) || conn->write_cmnd) { - conn_reset_nop_timer(conn); - wakeup = 1; - } - -out: - if (wakeup) - nthread_wakeup(target); - else if (test_and_clear_bit(CONN_NEED_NOP_IN, &conn->state)) { - send_nop_in(conn); - nthread_wakeup(target); - } else - conn_start_nop_timer(conn); - - return; -} - -static void close_conn(struct iscsi_conn *conn) -{ - struct iscsi_session *session = conn->session; - struct iscsi_target *target = conn->session->target; - struct iscsi_cmnd *cmnd; - - if (target->trgt_param.nop_interval) - del_timer_sync(&conn->nop_timer); - - conn->sock->ops->shutdown(conn->sock, 2); - - write_lock_bh(&conn->sock->sk->sk_callback_lock); - conn->sock->sk->sk_state_change = target->nthread_info.old_state_change; - conn->sock->sk->sk_data_ready = target->nthread_info.old_data_ready; - conn->sock->sk->sk_write_space = target->nthread_info.old_write_space; - write_unlock_bh(&conn->sock->sk->sk_callback_lock); - - fput(conn->file); - conn->file = NULL; - conn->sock = NULL; - - while (atomic_read(&conn->nr_busy_cmnds)) - yield(); - - while (!list_empty(&conn->pdu_list)) { - cmnd = list_entry(conn->pdu_list.next, struct iscsi_cmnd, conn_list); - - list_del_init(&cmnd->list); - cmnd_release(cmnd, 1); - } - - if (atomic_read(&conn->nr_cmnds)) { - eprintk("%u\n", atomic_read(&conn->nr_cmnds)); - list_for_each_entry(cmnd, &conn->pdu_list, conn_list) - eprintk("%x %x\n", cmnd_opcode(cmnd), cmnd_itt(cmnd)); - assert(0); - } - - event_send(target->tid, session->sid, conn->cid, E_CONN_CLOSE, 0); - conn_free(conn); - - if (list_empty(&session->conn_list)) { - if (session->done) - complete(session->done); - else - session_del(target, session->sid); - } -} - -static int istd(void *arg) -{ - struct iscsi_target *target = arg; - struct network_thread_info *info = &target->nthread_info; - struct iscsi_conn *conn, *tmp; - - __set_current_state(TASK_RUNNING); - do { - spin_lock_bh(&info->nthread_lock); - __set_current_state(TASK_INTERRUPTIBLE); - - if (!test_bit(D_DATA_READY, &info->flags)) { - spin_unlock_bh(&info->nthread_lock); - schedule(); - spin_lock_bh(&info->nthread_lock); - } - __set_current_state(TASK_RUNNING); - clear_bit(D_DATA_READY, &info->flags); - spin_unlock_bh(&info->nthread_lock); - - target_lock(target, 0); - list_for_each_entry_safe(conn, tmp, &info->active_conns, poll_list) { - if (test_bit(CONN_ACTIVE, &conn->state)) - process_io(conn); - else - close_conn(conn); - } - target_unlock(target); - - } while (!kthread_should_stop()); - - return 0; -} - -int nthread_init(struct iscsi_target *target) -{ - struct network_thread_info *info = &target->nthread_info; - - info->flags = 0; - info->task = NULL; - - info->old_state_change = NULL; - info->old_data_ready = NULL; - info->old_write_space = NULL; - - INIT_LIST_HEAD(&info->active_conns); - - spin_lock_init(&info->nthread_lock); - - return 0; -} - -int nthread_start(struct iscsi_target *target) -{ - int err = 0; - struct network_thread_info *info = &target->nthread_info; - struct task_struct *task; - - if (info->task) { - eprintk("Target (%u) already runs\n", target->tid); - return -EALREADY; - } - - task = kthread_run(istd, target, "istd%d", target->tid); - - if (IS_ERR(task)) - err = PTR_ERR(task); - else - info->task = task; - - return err; -} - -int nthread_stop(struct iscsi_target *target) -{ - int err; - struct network_thread_info *info = &target->nthread_info; - - if (!info->task) - return -ESRCH; - - err = kthread_stop(info->task); - - if (err < 0 && err != -EINTR) - return err; - - info->task = NULL; - - return 0; -} diff --git a/ubuntu/iscsitarget/null-io.c b/ubuntu/iscsitarget/null-io.c deleted file mode 100644 index 0b87507..0000000 --- a/ubuntu/iscsitarget/null-io.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Target device null I/O. - * (C) 2005 MING Zhang - * This code is licenced under the GPL. - * - * The nullio mode will not return any meaningful or previous written - * data. It is only for performance measurement purpose. - */ - -#include -#include -#include -#include - -#include "iscsi.h" -#include "iscsi_dbg.h" -#include "iotype.h" - -enum { - opt_blk_cnt, opt_ignore, opt_err, -}; - -static match_table_t tokens = { - /* alias for compatibility with existing setups and documentation */ - {opt_blk_cnt, "sectors=%u"}, - /* but actually it is the scsi block count, now that we can - * specify the block size. */ - {opt_blk_cnt, "blocks=%u"}, - {opt_ignore, "scsiid=%s"}, - {opt_ignore, "scsisn=%s"}, - {opt_ignore, "blocksize=%s"}, - {opt_ignore, "type=%s"}, - {opt_err, NULL}, -}; - -static int parse_nullio_params(struct iet_volume *volume, char *params) -{ - int err = 0; - char *p, *q; - - while ((p = strsep(¶ms, ",")) != NULL) { - substring_t args[MAX_OPT_ARGS]; - int token; - if (!*p) - continue; - iet_strtolower(p); - token = match_token(p, tokens, args); - switch (token) { - case opt_blk_cnt: - q = match_strdup(&args[0]); - if (!q) - return -ENOMEM; - volume->blk_cnt = simple_strtoull(q, NULL, 10); - kfree(q); - break; - case opt_ignore: - break; - default: - eprintk("Unknown %s\n", p); - return -EINVAL; - break; - } - } - return err; -} - -static void nullio_detach(struct iet_volume *lu) -{ -} - -static int nullio_attach(struct iet_volume *lu, char *args) -{ - int err = 0; - - if ((err = parse_nullio_params(lu, args)) < 0) { - eprintk("%d\n", err); - goto out; - } - - if (!lu->blk_shift) - lu->blk_shift = blksize_bits(IET_DEF_BLOCK_SIZE); - - /* defaults to 64 GiB */ - if (!lu->blk_cnt) - lu->blk_cnt = 1 << (36 - lu->blk_shift); - -out: - if (err < 0) - nullio_detach(lu); - return err; -} - -struct iotype nullio = -{ - .name = "nullio", - .attach = nullio_attach, - .detach = nullio_detach, -}; diff --git a/ubuntu/iscsitarget/param.c b/ubuntu/iscsitarget/param.c deleted file mode 100644 index 482d00c..0000000 --- a/ubuntu/iscsitarget/param.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * (C) 2005 FUJITA Tomonori - * - * This code is licenced under the GPL. - */ - -#include "iscsi.h" -#include "iscsi_dbg.h" -#include "digest.h" - -struct target_type *target_type_array[] = { - &disk_ops, -}; - -#define CHECK_PARAM(info, iparam, word, min, max) \ -do { \ - if (!info->partial || (info->partial & 1 << key_##word)) \ - if (iparam[key_##word] < min || \ - iparam[key_##word] > max) { \ - eprintk("%s: %u is out of range (%u %u)\n", \ - #word, iparam[key_##word], min, max); \ - iparam[key_##word] = min; \ - } \ -} while (0) - -#define SET_PARAM(param, info, iparam, word) \ -({ \ - int changed = 0; \ - if (!info->partial || (info->partial & 1 << key_##word)) { \ - if (param->word != iparam[key_##word]) \ - changed = 1; \ - param->word = iparam[key_##word]; \ - } \ - changed; \ -}) - -#define GET_PARAM(param, info, iparam, word) \ -do { \ - iparam[key_##word] = param->word; \ -} while (0) - -static void sess_param_check(struct iscsi_param_info *info) -{ - u32 *iparam = info->session_param; - - CHECK_PARAM(info, iparam, max_connections, 1, 65535); - CHECK_PARAM(info, iparam, max_recv_data_length, 512, - (u32) ((ISCSI_CONN_IOV_MAX - 1) * PAGE_CACHE_SIZE)); - CHECK_PARAM(info, iparam, max_xmit_data_length, 512, - (u32) ((ISCSI_CONN_IOV_MAX - 1) * PAGE_CACHE_SIZE)); - CHECK_PARAM(info, iparam, error_recovery_level, 0, 0); - CHECK_PARAM(info, iparam, data_pdu_inorder, 1, 1); - CHECK_PARAM(info, iparam, data_sequence_inorder, 1, 1); - - digest_alg_available(&iparam[key_header_digest]); - digest_alg_available(&iparam[key_data_digest]); - - CHECK_PARAM(info, iparam, ofmarker, 0, 0); - CHECK_PARAM(info, iparam, ifmarker, 0, 0); -} - -static void sess_param_set(struct iscsi_sess_param *param, struct iscsi_param_info *info) -{ - u32 *iparam = info->session_param; - - SET_PARAM(param, info, iparam, initial_r2t); - SET_PARAM(param, info, iparam, immediate_data); - SET_PARAM(param, info, iparam, max_connections); - SET_PARAM(param, info, iparam, max_recv_data_length); - SET_PARAM(param, info, iparam, max_xmit_data_length); - SET_PARAM(param, info, iparam, max_burst_length); - SET_PARAM(param, info, iparam, first_burst_length); - SET_PARAM(param, info, iparam, default_wait_time); - SET_PARAM(param, info, iparam, default_retain_time); - SET_PARAM(param, info, iparam, max_outstanding_r2t); - SET_PARAM(param, info, iparam, data_pdu_inorder); - SET_PARAM(param, info, iparam, data_sequence_inorder); - SET_PARAM(param, info, iparam, error_recovery_level); - SET_PARAM(param, info, iparam, header_digest); - SET_PARAM(param, info, iparam, data_digest); - SET_PARAM(param, info, iparam, ofmarker); - SET_PARAM(param, info, iparam, ifmarker); - SET_PARAM(param, info, iparam, ofmarkint); - SET_PARAM(param, info, iparam, ifmarkint); -} - -static void sess_param_get(struct iscsi_sess_param *param, struct iscsi_param_info *info) -{ - u32 *iparam = info->session_param; - - GET_PARAM(param, info, iparam, initial_r2t); - GET_PARAM(param, info, iparam, immediate_data); - GET_PARAM(param, info, iparam, max_connections); - GET_PARAM(param, info, iparam, max_recv_data_length); - GET_PARAM(param, info, iparam, max_xmit_data_length); - GET_PARAM(param, info, iparam, max_burst_length); - GET_PARAM(param, info, iparam, first_burst_length); - GET_PARAM(param, info, iparam, default_wait_time); - GET_PARAM(param, info, iparam, default_retain_time); - GET_PARAM(param, info, iparam, max_outstanding_r2t); - GET_PARAM(param, info, iparam, data_pdu_inorder); - GET_PARAM(param, info, iparam, data_sequence_inorder); - GET_PARAM(param, info, iparam, error_recovery_level); - GET_PARAM(param, info, iparam, header_digest); - GET_PARAM(param, info, iparam, data_digest); - GET_PARAM(param, info, iparam, ofmarker); - GET_PARAM(param, info, iparam, ifmarker); - GET_PARAM(param, info, iparam, ofmarkint); - GET_PARAM(param, info, iparam, ifmarkint); -} - -static void trgt_param_check(struct iscsi_param_info *info) -{ - u32 *iparam = info->target_param; - - CHECK_PARAM(info, iparam, wthreads, MIN_NR_WTHREADS, MAX_NR_WTHREADS); - CHECK_PARAM(info, iparam, target_type, 0, - (unsigned int) ARRAY_SIZE(target_type_array) - 1); - CHECK_PARAM(info, iparam, queued_cmnds, MIN_NR_QUEUED_CMNDS, - MAX_NR_QUEUED_CMNDS); - CHECK_PARAM(info, iparam, nop_interval, MIN_NOP_INTERVAL, - MAX_NOP_INTERVAL); - CHECK_PARAM(info, iparam, nop_timeout, MIN_NOP_TIMEOUT, - MAX_NOP_TIMEOUT); -} - -static void trgt_param_set(struct iscsi_target *target, struct iscsi_param_info *info) -{ - struct iscsi_trgt_param *param = &target->trgt_param; - u32 *iparam = info->target_param; - - if (!worker_thread_pool && - SET_PARAM(param, info, iparam, wthreads)) - wthread_start(target->wthread_info, - target->trgt_param.wthreads, target->tid); - SET_PARAM(param, info, iparam, target_type); - SET_PARAM(param, info, iparam, queued_cmnds); - SET_PARAM(param, info, iparam, nop_interval); - SET_PARAM(param, info, iparam, nop_timeout); -} - -static void trgt_param_get(struct iscsi_trgt_param *param, struct iscsi_param_info *info) -{ - u32 *iparam = info->target_param; - - GET_PARAM(param, info, iparam, wthreads); - GET_PARAM(param, info, iparam, target_type); - GET_PARAM(param, info, iparam, queued_cmnds); - GET_PARAM(param, info, iparam, nop_interval); - GET_PARAM(param, info, iparam, nop_timeout); -} - -static int trgt_param(struct iscsi_target *target, struct iscsi_param_info *info, int set) -{ - - if (set) { - trgt_param_check(info); - trgt_param_set(target, info); - } else - trgt_param_get(&target->trgt_param, info); - - return 0; -} - -static int sess_param(struct iscsi_target *target, struct iscsi_param_info *info, int set) -{ - struct iscsi_session *session = NULL; - struct iscsi_sess_param *param; - int err = -ENOENT; - - if (set) - sess_param_check(info); - - if (info->sid) { - if (!(session = session_lookup(target, info->sid))) - goto out; - param = &session->param; - } else { - param = &target->sess_param; - } - - if (set) { - sess_param_set(param, info); - show_param(param); - } else - sess_param_get(param, info); - - err = 0; -out: - return err; -} - -int iscsi_param_set(struct iscsi_target *target, struct iscsi_param_info *info, int set) -{ - int err; - - if (info->param_type == key_session) - err = sess_param(target, info, set); - else if (info->param_type == key_target) - err = trgt_param(target, info, set); - else - err = -EINVAL; - - return err; -} diff --git a/ubuntu/iscsitarget/session.c b/ubuntu/iscsitarget/session.c deleted file mode 100644 index a566d8b..0000000 --- a/ubuntu/iscsitarget/session.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2002-2003 Ardis Technolgies - * - * Released under the terms of the GNU GPL v2.0. - */ - -#include "iscsi.h" -#include "iscsi_dbg.h" - -struct iscsi_session *session_lookup(struct iscsi_target *target, u64 sid) -{ - struct iscsi_session *session; - - list_for_each_entry(session, &target->session_list, list) { - if (session->sid == sid) - return session; - } - return NULL; -} - -static struct iscsi_session * -iet_session_alloc(struct iscsi_target *target, struct session_info *info) -{ - int i; - struct iscsi_session *session; - struct iet_volume *vol; - - dprintk(D_SETUP, "%p %u %#Lx\n", target, target->tid, - (unsigned long long) info->sid); - - session = kzalloc(sizeof(*session), GFP_KERNEL); - if (!session) - return NULL; - - session->target = target; - session->sid = info->sid; - memcpy(&session->param, &target->sess_param, sizeof(session->param)); - session->max_queued_cmnds = target->trgt_param.queued_cmnds; - - session->exp_cmd_sn = info->exp_cmd_sn; - session->max_cmd_sn = info->max_cmd_sn; - - session->initiator = kstrdup(info->initiator_name, GFP_KERNEL); - if (!session->initiator) { - kfree(session); - return NULL; - } - - INIT_LIST_HEAD(&session->conn_list); - INIT_LIST_HEAD(&session->pending_list); - - spin_lock_init(&session->cmnd_hash_lock); - for (i = 0; i < ARRAY_SIZE(session->cmnd_hash); i++) - INIT_LIST_HEAD(&session->cmnd_hash[i]); - - spin_lock_init(&session->ua_hash_lock); - for (i = 0; i < ARRAY_SIZE(session->ua_hash); i++) - INIT_LIST_HEAD(&session->ua_hash[i]); - - list_for_each_entry(vol, &target->volumes, list) - /* power-on, reset, or bus device reset occurred */ - ua_establish_for_session(session, vol->lun, 0x29, 0x0); - - session->next_ttt = 1; - - spin_lock(&target->session_list_lock); - list_add(&session->list, &target->session_list); - spin_unlock(&target->session_list_lock); - - return session; -} - -static int session_free(struct iscsi_session *session) -{ - int i; - struct ua_entry *ua, *tmp; - struct list_head *l; - struct iscsi_target *target = session->target; - - dprintk(D_SETUP, "%#Lx\n", (unsigned long long) session->sid); - - spin_lock(&target->session_list_lock); - - assert(list_empty(&session->conn_list)); - - for (i = 0; i < ARRAY_SIZE(session->cmnd_hash); i++) { - if (!list_empty(&session->cmnd_hash[i])) - BUG(); - } - - for (i = 0; i < ARRAY_SIZE(session->ua_hash); i++) { - l = &session->ua_hash[i]; - list_for_each_entry_safe(ua, tmp, l, entry) { - list_del_init(&ua->entry); - ua_free(ua); - } - } - - list_del(&session->list); - - kfree(session->initiator); - kfree(session); - - spin_unlock(&target->session_list_lock); - - return 0; -} - -int session_add(struct iscsi_target *target, struct session_info *info) -{ - struct iscsi_session *session; - - session = session_lookup(target, info->sid); - if (session) - return -EEXIST; - - session = iet_session_alloc(target, info); - if (!session) - return -ENOMEM; - - return 0; -} - -int session_del(struct iscsi_target *target, u64 sid) -{ - struct iscsi_session *session; - struct iet_volume *volume; - - session = session_lookup(target, sid); - if (!session) - return -ENOENT; - - if (!list_empty(&session->conn_list)) { - DECLARE_COMPLETION_ONSTACK(done); - struct iscsi_conn *conn; - - session->done = &done; - list_for_each_entry(conn, &session->conn_list, list) - conn_close(conn); - - target_unlock(target); - wait_for_completion(&done); - target_lock(target, 0); - } - - list_for_each_entry(volume, &target->volumes, list){ - volume_release(volume, sid, 0); - } - - return session_free(session); -} - -static void iet_session_info_show(struct seq_file *seq, struct iscsi_target *target) -{ - struct iscsi_session *session; - - list_for_each_entry(session, &target->session_list, list) { - seq_printf(seq, "\tsid:%llu initiator:%s\n", - (unsigned long long) session->sid, session->initiator); - conn_info_show(seq, session); - } -} - -static int iet_session_seq_open(struct inode *inode, struct file *file) -{ - int res; - res = seq_open(file, &iet_seq_op); - if (!res) - ((struct seq_file *)file->private_data)->private = - iet_session_info_show; - return res; -} - -struct file_operations session_seq_fops = { - .owner = THIS_MODULE, - .open = iet_session_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; diff --git a/ubuntu/iscsitarget/target.c b/ubuntu/iscsitarget/target.c deleted file mode 100644 index 9065d16..0000000 --- a/ubuntu/iscsitarget/target.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (C) 2002-2003 Ardis Technolgies - * - * Released under the terms of the GNU GPL v2.0. - */ - -#include "iscsi.h" -#include "digest.h" -#include "iscsi_dbg.h" - -#define MAX_NR_TARGETS (1UL << 30) - -static LIST_HEAD(target_list); -static DEFINE_SEMAPHORE(target_list_sem); -static u32 next_target_id; -static u32 nr_targets; - -static struct iscsi_sess_param default_session_param = { - .initial_r2t = 1, - .immediate_data = 1, - .max_connections = 1, - .max_recv_data_length = 8192, - .max_xmit_data_length = 8192, - .max_burst_length = 262144, - .first_burst_length = 65536, - .default_wait_time = 2, - .default_retain_time = 20, - .max_outstanding_r2t = 1, - .data_pdu_inorder = 1, - .data_sequence_inorder = 1, - .error_recovery_level = 0, - .header_digest = DIGEST_NONE, - .data_digest = DIGEST_NONE, - .ofmarker = 0, - .ifmarker = 0, - .ofmarkint = 2048, - .ifmarkint = 2048, -}; - -static struct iscsi_trgt_param default_target_param = { - .wthreads = DEFAULT_NR_WTHREADS, - .target_type = 0, - .queued_cmnds = DEFAULT_NR_QUEUED_CMNDS, -}; - -inline int target_lock(struct iscsi_target *target, int interruptible) -{ - int err = 0; - - if (interruptible) - err = down_interruptible(&target->target_sem); - else - down(&target->target_sem); - - return err; -} - -inline void target_unlock(struct iscsi_target *target) -{ - up(&target->target_sem); -} - -static struct iscsi_target *__target_lookup_by_id(u32 id) -{ - struct iscsi_target *target; - - list_for_each_entry(target, &target_list, t_list) { - if (target->tid == id) - return target; - } - return NULL; -} - -static struct iscsi_target *__target_lookup_by_name(char *name) -{ - struct iscsi_target *target; - - list_for_each_entry(target, &target_list, t_list) { - if (!strcmp(target->name, name)) - return target; - } - return NULL; -} - -struct iscsi_target *target_lookup_by_id(u32 id) -{ - struct iscsi_target *target; - - down(&target_list_sem); - target = __target_lookup_by_id(id); - up(&target_list_sem); - - return target; -} - -static int target_thread_start(struct iscsi_target *target) -{ - int err; - - if ((err = nthread_start(target)) < 0) - return err; - - if (!worker_thread_pool) { - err = wthread_start(target->wthread_info, - target->trgt_param.wthreads, target->tid); - if (err) - nthread_stop(target); - } - - return err; -} - -static void target_thread_stop(struct iscsi_target *target) -{ - if (!worker_thread_pool) - wthread_stop(target->wthread_info); - - nthread_stop(target); -} - -static int iscsi_target_create(struct target_info *info, u32 tid) -{ - int err = -EINVAL, len; - char *name = info->name; - struct iscsi_target *target; - - dprintk(D_SETUP, "%u %s\n", tid, name); - - if (!(len = strlen(name))) { - eprintk("The length of the target name is zero %u\n", tid); - return err; - } - - if (!try_module_get(THIS_MODULE)) { - eprintk("Fail to get module %u\n", tid); - return err; - } - - target = kzalloc(sizeof(*target), GFP_KERNEL); - if (!target) { - err = -ENOMEM; - goto out; - } - - if (!worker_thread_pool) { - target->wthread_info = kmalloc(sizeof(struct worker_thread_info), GFP_KERNEL); - if (!target->wthread_info) { - err = -ENOMEM; - goto out; - } - } - - target->tid = info->tid = tid; - - memcpy(&target->sess_param, &default_session_param, sizeof(default_session_param)); - memcpy(&target->trgt_param, &default_target_param, sizeof(default_target_param)); - - strncpy(target->name, name, sizeof(target->name) - 1); - - sema_init(&target->target_sem, 1); - spin_lock_init(&target->session_list_lock); - - INIT_LIST_HEAD(&target->session_list); - INIT_LIST_HEAD(&target->volumes); - - atomic_set(&target->nr_volumes, 0); - - nthread_init(target); - - if (!worker_thread_pool) - wthread_init(target->wthread_info); - else - target->wthread_info = worker_thread_pool; - - - if ((err = target_thread_start(target)) < 0) { - target_thread_stop(target); - goto out; - } - - list_add(&target->t_list, &target_list); - - return 0; -out: - if (!worker_thread_pool) - kfree(target->wthread_info); - kfree(target); - module_put(THIS_MODULE); - - return err; -} - -int target_add(struct target_info *info) -{ - u32 tid = info->tid; - int err; - - err = down_interruptible(&target_list_sem); - if (err < 0) - return err; - - if (nr_targets > MAX_NR_TARGETS) { - err = -EBUSY; - goto out; - } - - if (__target_lookup_by_name(info->name) || - (tid && __target_lookup_by_id(tid))) { - err = -EEXIST; - goto out; - } - - if (!tid) { - do { - if (!++next_target_id) - ++next_target_id; - } while (__target_lookup_by_id(next_target_id)); - - tid = next_target_id; - } - - err = iscsi_target_create(info, tid); - if (!err) - nr_targets++; -out: - up(&target_list_sem); - - return err; -} - -static void target_destroy(struct iscsi_target *target) -{ - dprintk(D_SETUP, "%u\n", target->tid); - - target_thread_stop(target); - - while (!list_empty(&target->volumes)) { - struct iet_volume *volume; - volume = list_entry(target->volumes.next, struct iet_volume, list); - volume->l_state = IDEV_DEL; - iscsi_volume_destroy(volume); - } - - if (!worker_thread_pool) - kfree(target->wthread_info); - kfree(target); - - module_put(THIS_MODULE); -} - -/* @locking: target_list_sem must be locked */ -static int __target_del(struct iscsi_target *target) -{ - int err; - - target_lock(target, 0); - - if (!list_empty(&target->session_list)) { - struct iscsi_session *session; - - do { - session = list_entry(target->session_list.next, - struct iscsi_session, list); - err = session_del(target, session->sid); - if (err < 0) { - target_unlock(target); - return err; - } - } while (!list_empty(&target->session_list)); - } - - list_del(&target->t_list); - nr_targets--; - - target_unlock(target); - target_destroy(target); - - return 0; -} - -int target_del(u32 id) -{ - struct iscsi_target *target; - int err; - - err = down_interruptible(&target_list_sem); - if (err < 0) - return err; - - target = __target_lookup_by_id(id); - if (!target) { - err = -ENOENT; - goto out; - } - - err = __target_del(target); -out: - up(&target_list_sem); - - return err; -} - -void target_del_all(void) -{ - struct iscsi_target *target, *tmp; - int err; - - down(&target_list_sem); - - if (!list_empty(&target_list)) - iprintk("Removing all connections, sessions and targets\n"); - - list_for_each_entry_safe(target, tmp, &target_list, t_list) { - u32 tid = target->tid; - err =__target_del(target); - if (err) - eprintk("Error deleteing target %u: %d\n", tid, err); - } - - next_target_id = 0; - - up(&target_list_sem); -} - -static void *iet_seq_start(struct seq_file *m, loff_t *pos) -{ - int err; - - /* are you sure this is to be interruptible? */ - err = down_interruptible(&target_list_sem); - if (err < 0) - return ERR_PTR(err); - - return seq_list_start(&target_list, *pos); -} - -static void *iet_seq_next(struct seq_file *m, void *v, loff_t *pos) -{ - return seq_list_next(v, &target_list, pos); -} - -static void iet_seq_stop(struct seq_file *m, void *v) -{ - up(&target_list_sem); -} - -static int iet_seq_show(struct seq_file *m, void *p) -{ - iet_show_info_t *func = (iet_show_info_t *)m->private; - struct iscsi_target *target = - list_entry(p, struct iscsi_target, t_list); - int err; - - /* relly, interruptible? I'd think target_lock(target, 0) - * would be more appropriate. --lge */ - err = target_lock(target, 1); - if (err < 0) - return err; - - seq_printf(m, "tid:%u name:%s\n", target->tid, target->name); - - func(m, target); - - target_unlock(target); - - return 0; -} - -struct seq_operations iet_seq_op = { - .start = iet_seq_start, - .next = iet_seq_next, - .stop = iet_seq_stop, - .show = iet_seq_show, -}; diff --git a/ubuntu/iscsitarget/target_disk.c b/ubuntu/iscsitarget/target_disk.c deleted file mode 100644 index 1f7693c..0000000 --- a/ubuntu/iscsitarget/target_disk.c +++ /dev/null @@ -1,589 +0,0 @@ -/* - * (C) 2004 - 2005 FUJITA Tomonori - * This code is licenced under the GPL. - * - * heavily based on code from kernel/iscsi.c: - * Copyright (C) 2002-2003 Ardis Technolgies , - * licensed under the terms of the GNU GPL v2.0, - */ - -#include -#include - -#include "iscsi.h" -#include "iscsi_dbg.h" - -static int insert_disconnect_pg(u8 *ptr) -{ - unsigned char disconnect_pg[] = {0x02, 0x0e, 0x80, 0x80, 0x00, 0x0a, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - memcpy(ptr, disconnect_pg, sizeof(disconnect_pg)); - return sizeof(disconnect_pg); -} - -static int insert_caching_pg(u8 *ptr, int wcache, int rcache) -{ - unsigned char caching_pg[] = {0x08, 0x12, 0x10, 0x00, 0xff, 0xff, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; - - memcpy(ptr, caching_pg, sizeof(caching_pg)); - if (wcache) - ptr[2] |= 0x04; /* set WCE bit if we're caching writes */ - if (!rcache) - ptr[2] |= 0x01; /* Read Cache Disable */ - - return sizeof(caching_pg); -} - -static int insert_ctrl_m_pg(u8 *ptr) -{ - unsigned char ctrl_m_pg[] = {0x0a, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x4b}; - - memcpy(ptr, ctrl_m_pg, sizeof(ctrl_m_pg)); - return sizeof(ctrl_m_pg); -} - -static int insert_iec_m_pg(u8 *ptr) -{ - unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}; - - memcpy(ptr, iec_m_pg, sizeof(iec_m_pg)); - return sizeof(iec_m_pg); -} - -static int insert_format_m_pg(u8 *ptr, u32 sector_size) -{ - unsigned char format_m_pg[] = {0x03, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00}; - - memcpy(ptr, format_m_pg, sizeof(format_m_pg)); - ptr[12] = (sector_size >> 8) & 0xff; - ptr[13] = sector_size & 0xff; - return sizeof(format_m_pg); -} - -static int insert_geo_m_pg(u8 *ptr, u64 sec) -{ - unsigned char geo_m_pg[] = {0x04, 0x16, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00}; - u32 ncyl; - u32 n; - - /* assume 0xff heads, 15krpm. */ - memcpy(ptr, geo_m_pg, sizeof(geo_m_pg)); - ncyl = sec >> 14; /* 256 * 64 */ - memcpy(&n, ptr+1, sizeof(u32)); - n = n | cpu_to_be32(ncyl); - memcpy(ptr+1, &n, sizeof(u32)); - return sizeof(geo_m_pg); -} - -static void build_mode_sense_response(struct iscsi_cmnd *cmnd) -{ - struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); - struct tio *tio = cmnd->tio; - u8 *data, *scb = req->scb; - int len = 4, err = 0; - u8 pcode; - - /* changeable parameter mode pages are unsupported */ - if ((scb[2] & 0xc0) >> 6 == 0x1) - goto set_sense; - - pcode = req->scb[2] & 0x3f; - - assert(!tio); - tio = cmnd->tio = tio_alloc(1); - data = page_address(tio->pvec[0]); - assert(data); - clear_page(data); - - if (LUReadonly(cmnd->lun)) - data[2] = 0x80; - - if ((scb[1] & 0x8)) - data[3] = 0; - else { - data[3] = 8; - len += 8; - *(u32 *)(data + 4) = (cmnd->lun->blk_cnt >> 32) ? - cpu_to_be32(0xffffffff) : cpu_to_be32(cmnd->lun->blk_cnt); - *(u32 *)(data + 8) = cpu_to_be32(1 << cmnd->lun->blk_shift); - } - - switch (pcode) { - case 0x0: - break; - case 0x2: - len += insert_disconnect_pg(data + len); - break; - case 0x3: - len += insert_format_m_pg(data + len, 1 << cmnd->lun->blk_shift); - break; - case 0x4: - len += insert_geo_m_pg(data + len, cmnd->lun->blk_cnt); - break; - case 0x8: - len += insert_caching_pg(data + len, LUWCache(cmnd->lun), - LURCache(cmnd->lun)); - break; - case 0xa: - len += insert_ctrl_m_pg(data + len); - break; - case 0x1c: - len += insert_iec_m_pg(data + len); - break; - case 0x3f: - len += insert_disconnect_pg(data + len); - len += insert_format_m_pg(data + len, 1 << cmnd->lun->blk_shift); - len += insert_geo_m_pg(data + len, cmnd->lun->blk_cnt); - len += insert_caching_pg(data + len, LUWCache(cmnd->lun), - LURCache(cmnd->lun)); - len += insert_ctrl_m_pg(data + len); - len += insert_iec_m_pg(data + len); - break; - default: - err = -1; - } - - if (!err) { - data[0] = len - 1; - tio_set(tio, len, 0); - return; - } - - tio_put(tio); - cmnd->tio = NULL; - set_sense: - /* Invalid Field In CDB */ - iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x24, 0x0); -} - -static void build_inquiry_response(struct iscsi_cmnd *cmnd) -{ - struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); - struct tio *tio = cmnd->tio; - u8 *data; - u8 *scb = req->scb; - int err = -1; - - /* - * - CmdDt and EVPD both set or EVPD and Page Code set: illegal - * - CmdDt set: not supported - */ - if ((scb[1] & 0x3) > 0x1 || (!(scb[1] & 0x3) && scb[2])) - goto set_sense; - - assert(!tio); - tio = cmnd->tio = tio_alloc(1); - data = page_address(tio->pvec[0]); - assert(data); - clear_page(data); - - if (!(scb[1] & 0x3)) { - data[2] = 4; - data[3] = 0x52; - data[4] = 59; - data[7] = 0x02; - memset(data + 8, 0x20, 28); - memcpy(data + 8, - VENDOR_ID, min_t(size_t, strlen(VENDOR_ID), 8)); - memcpy(data + 16, - PRODUCT_ID, min_t(size_t, strlen(PRODUCT_ID), 16)); - memcpy(data + 32, - PRODUCT_REV, min_t(size_t, strlen(PRODUCT_REV), 4)); - data[58] = 0x03; - data[59] = 0x20; - data[60] = 0x09; - data[61] = 0x60; - data[62] = 0x03; - data[63] = 0x00; - tio_set(tio, 64, 0); - err = 0; - } else if (scb[1] & 0x1) { - /* EVPD bit set */ - if (scb[2] == 0x0) { - data[1] = 0x0; - data[3] = 3; - data[4] = 0x0; - data[5] = 0x80; - data[6] = 0x83; - tio_set(tio, 7, 0); - err = 0; - } else if (scb[2] == 0x80) { - u32 len = 4; - - if (cmnd->lun) { - if (strlen(cmnd->lun->scsi_sn) <= 16) - len = 16; - else - len = SCSI_SN_LEN; - } - - data[1] = 0x80; - data[3] = len; - memset(data + 4, 0x20, len); - if (cmnd->lun) { - size_t offset = len - - strlen(cmnd->lun->scsi_sn); - memcpy(data + 4 + offset, cmnd->lun->scsi_sn, - strlen(cmnd->lun->scsi_sn)); - } - tio_set(tio, len + 4, 0); - err = 0; - } else if (scb[2] == 0x83) { - u32 len = SCSI_ID_LEN + 8; - - data[1] = 0x83; - data[3] = len + 4; - data[4] = 0x1; - data[5] = 0x1; - data[7] = len; - if (cmnd->lun) { /* We need this ? */ - memset(data + 8, 0x00, 8); - memcpy(data + 8, VENDOR_ID, - min_t(size_t, strlen(VENDOR_ID), 8)); - memcpy(data + 16, cmnd->lun->scsi_id, - SCSI_ID_LEN); - } - tio_set(tio, len + 8, 0); - err = 0; - } - } - - if (!err) { - tio_set(tio, min_t(u8, tio->size, scb[4]), 0); - if (!cmnd->lun) - data[0] = TYPE_NO_LUN; - return; - } - - tio_put(tio); - cmnd->tio = NULL; - set_sense: - /* Invalid Field In CDB */ - iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x24, 0x0); -} - -static void build_report_luns_response(struct iscsi_cmnd *cmnd) -{ - struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); - struct tio *tio = cmnd->tio; - u32 *data, size, len; - struct iet_volume *lun; - int rest, idx = 0; - - size = (u32)req->scb[6] << 24 | (u32)req->scb[7] << 16 | - (u32)req->scb[8] << 8 | (u32)req->scb[9]; - if (size < 16) { - /* Invalid Field In CDB */ - iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x24, 0x0); - return; - } - - len = atomic_read(&cmnd->conn->session->target->nr_volumes) * 8; - size = min(size & ~(8 - 1), len + 8); - - assert(!tio); - tio = cmnd->tio = tio_alloc(get_pgcnt(size, 0)); - tio_set(tio, size, 0); - - data = page_address(tio->pvec[idx]); - assert(data); - *data++ = cpu_to_be32(len); - *data++ = 0; - size -= 8; - rest = PAGE_CACHE_SIZE - 8; - list_for_each_entry(lun, &cmnd->conn->session->target->volumes, list) { - if (lun->l_state != IDEV_RUNNING) - continue; - - *data++ = cpu_to_be32((0x3ff & lun->lun) << 16 | - ((lun->lun > 0xff) ? (0x1 << 30) : 0)); - *data++ = 0; - if ((size -= 8) == 0) - break; - if ((rest -= 8) == 0) { - idx++; - data = page_address(tio->pvec[idx]); - rest = PAGE_CACHE_SIZE; - } - } -} - -static void build_read_capacity_response(struct iscsi_cmnd *cmnd) -{ - struct tio *tio = cmnd->tio; - u32 *data; - - assert(!tio); - tio = cmnd->tio = tio_alloc(1); - data = page_address(tio->pvec[0]); - assert(data); - clear_page(data); - - data[0] = (cmnd->lun->blk_cnt >> 32) ? - cpu_to_be32(0xffffffff) : cpu_to_be32(cmnd->lun->blk_cnt - 1); - data[1] = cpu_to_be32(1U << cmnd->lun->blk_shift); - - tio_set(tio, 8, 0); -} - -static void build_request_sense_response(struct iscsi_cmnd *cmnd) -{ - struct tio *tio = cmnd->tio; - u8 *data; - - assert(!tio); - tio = cmnd->tio = tio_alloc(1); - data = page_address(tio->pvec[0]); - assert(data); - memset(data, 0, 18); - data[0] = 0xf0; - data[1] = 0; - data[2] = NO_SENSE; - data[7] = 10; - tio_set(tio, 18, 0); -} - -static void build_service_action_in_response(struct iscsi_cmnd *cmnd) -{ - struct tio *tio = cmnd->tio; - u32 *data; - u64 *data64; - - assert(!tio); - - /* only READ_CAPACITY_16 service action is currently supported */ - if ((cmnd_hdr(cmnd)->scb[1] & 0x1F) != 0x10) { - /* Invalid Field In CDB */ - iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x24, 0x0); - return; - } - - tio = cmnd->tio = tio_alloc(1); - data = page_address(tio->pvec[0]); - assert(data); - clear_page(data); - data64 = (u64*) data; - data64[0] = cpu_to_be64(cmnd->lun->blk_cnt - 1); - data[2] = cpu_to_be32(1UL << cmnd->lun->blk_shift); - - tio_set(tio, 12, 0); -} - -static void build_read_response(struct iscsi_cmnd *cmnd) -{ - struct tio *tio = cmnd->tio; - - assert(tio); - assert(cmnd->lun); - - if (tio_read(cmnd->lun, tio)) - /* Medium Error/Unrecovered Read Error */ - iscsi_cmnd_set_sense(cmnd, MEDIUM_ERROR, 0x11, 0x0); -} - -static void build_write_response(struct iscsi_cmnd *cmnd) -{ - int err; - struct tio *tio = cmnd->tio; - - assert(tio); - assert(cmnd->lun); - - list_del_init(&cmnd->list); - err = tio_write(cmnd->lun, tio); - if (!err && !LUWCache(cmnd->lun)) - err = tio_sync(cmnd->lun, tio); - - if (err) - /* Medium Error/Write Fault */ - iscsi_cmnd_set_sense(cmnd, MEDIUM_ERROR, 0x03, 0x0); -} - -static void build_sync_cache_response(struct iscsi_cmnd *cmnd) -{ - assert(cmnd->lun); - if (tio_sync(cmnd->lun, NULL)) - /* Medium Error/Write Fault */ - iscsi_cmnd_set_sense(cmnd, MEDIUM_ERROR, 0x03, 0x0); -} - -static void build_generic_response(struct iscsi_cmnd *cmnd) -{ - return; -} - -static void build_reserve_response(struct iscsi_cmnd *cmnd) -{ - switch (volume_reserve(cmnd->lun, cmnd->conn->session->sid)) { - case -ENOENT: - /* Logical Unit Not Supported (?) */ - iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x25, 0x0); - break; - case -EBUSY: - cmnd->status = SAM_STAT_RESERVATION_CONFLICT; - break; - default: - break; - } -} - -static void build_release_response(struct iscsi_cmnd *cmnd) -{ - int ret = volume_release(cmnd->lun, - cmnd->conn->session->sid, 0); - switch (ret) { - case -ENOENT: - /* Logical Unit Not Supported (?) */ - iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x25, 0x0); - break; - case -EBUSY: - cmnd->status = SAM_STAT_RESERVATION_CONFLICT; - break; - default: - break; - } -} - -static void build_reservation_conflict_response(struct iscsi_cmnd *cmnd) -{ - cmnd->status = SAM_STAT_RESERVATION_CONFLICT; -} - -static int disk_check_ua(struct iscsi_cmnd *cmnd) -{ - struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); - struct ua_entry *ua; - - if (cmnd->lun && ua_pending(cmnd->conn->session, cmnd->lun->lun)) { - switch(req->scb[0]){ - case INQUIRY: - case REQUEST_SENSE: - break; - case REPORT_LUNS: - ua = ua_get_match(cmnd->conn->session, - cmnd->lun->lun, - /* reported luns data has changed */ - 0x3f, 0x0e); - ua_free(ua); - break; - default: - ua = ua_get_first(cmnd->conn->session, cmnd->lun->lun); - iscsi_cmnd_set_sense(cmnd, UNIT_ATTENTION, ua->asc, - ua->ascq); - ua_free(ua); - send_scsi_rsp(cmnd, build_generic_response); - return 1; - } - } - return 0; -} - -static int disk_check_reservation(struct iscsi_cmnd *cmnd) -{ - struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); - - int ret = is_volume_reserved(cmnd->lun, - cmnd->conn->session->sid); - if (ret == -EBUSY) { - switch (req->scb[0]) { - case INQUIRY: - case RELEASE: - case REPORT_LUNS: - case REQUEST_SENSE: - case READ_CAPACITY: - /* allowed commands when reserved */ - break; - case SERVICE_ACTION_IN: - if ((cmnd_hdr(cmnd)->scb[1] & 0x1F) == 0x10) - break; - /* fall through */ - default: - /* return reservation conflict for all others */ - send_scsi_rsp(cmnd, - build_reservation_conflict_response); - return 1; - } - } - - return 0; -} - -static int disk_execute_cmnd(struct iscsi_cmnd *cmnd) -{ - struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); - - req->opcode &= ISCSI_OPCODE_MASK; - - if (disk_check_ua(cmnd)) - return 0; - - if (disk_check_reservation(cmnd)) - return 0; - - switch (req->scb[0]) { - case INQUIRY: - send_data_rsp(cmnd, build_inquiry_response); - break; - case REPORT_LUNS: - send_data_rsp(cmnd, build_report_luns_response); - break; - case READ_CAPACITY: - send_data_rsp(cmnd, build_read_capacity_response); - break; - case MODE_SENSE: - send_data_rsp(cmnd, build_mode_sense_response); - break; - case REQUEST_SENSE: - send_data_rsp(cmnd, build_request_sense_response); - break; - case SERVICE_ACTION_IN: - send_data_rsp(cmnd, build_service_action_in_response); - break; - case READ_6: - case READ_10: - case READ_16: - send_data_rsp(cmnd, build_read_response); - break; - case WRITE_6: - case WRITE_10: - case WRITE_16: - case WRITE_VERIFY: - send_scsi_rsp(cmnd, build_write_response); - break; - case SYNCHRONIZE_CACHE: - send_scsi_rsp(cmnd, build_sync_cache_response); - break; - case RESERVE: - send_scsi_rsp(cmnd, build_reserve_response); - break; - case RELEASE: - send_scsi_rsp(cmnd, build_release_response); - break; - case START_STOP: - case TEST_UNIT_READY: - case VERIFY: - case VERIFY_16: - send_scsi_rsp(cmnd, build_generic_response); - break; - default: - eprintk("%s\n", "we should not come here!"); - break; - } - - return 0; -} - -struct target_type disk_ops = -{ - .id = 0, - .execute_cmnd = disk_execute_cmnd, -}; diff --git a/ubuntu/iscsitarget/tio.c b/ubuntu/iscsitarget/tio.c deleted file mode 100644 index 4220391..0000000 --- a/ubuntu/iscsitarget/tio.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Target I/O. - * (C) 2005 FUJITA Tomonori - * This code is licenced under the GPL. - */ - -#include "iscsi.h" -#include "iscsi_dbg.h" -#include "iotype.h" - -static int tio_add_pages(struct tio *tio, int count) -{ - int i; - struct page *page; - - dprintk(D_GENERIC, "%p %d (%d)\n", tio, count, tio->pg_cnt); - - tio->pg_cnt = count; - - count *= sizeof(struct page *); - - do { - tio->pvec = kzalloc(count, GFP_KERNEL); - if (!tio->pvec) - yield(); - } while (!tio->pvec); - - for (i = 0; i < tio->pg_cnt; i++) { - do { - if (!(page = alloc_page(GFP_KERNEL))) - yield(); - } while (!page); - tio->pvec[i] = page; - } - return 0; -} - -static struct kmem_cache *tio_cache; - -struct tio *tio_alloc(int count) -{ - struct tio *tio; - - tio = kmem_cache_alloc(tio_cache, GFP_KERNEL | __GFP_NOFAIL); - - tio->pg_cnt = 0; - tio->idx = 0; - tio->offset = 0; - tio->size = 0; - tio->pvec = NULL; - - atomic_set(&tio->count, 1); - - if (count) - tio_add_pages(tio, count); - - return tio; -} - -static void tio_free(struct tio *tio) -{ - int i; - for (i = 0; i < tio->pg_cnt; i++) { - assert(tio->pvec[i]); - __free_page(tio->pvec[i]); - } - kfree(tio->pvec); - kmem_cache_free(tio_cache, tio); -} - -void tio_put(struct tio *tio) -{ - assert(atomic_read(&tio->count)); - if (atomic_dec_and_test(&tio->count)) - tio_free(tio); -} - -void tio_get(struct tio *tio) -{ - atomic_inc(&tio->count); -} - -void tio_set(struct tio *tio, u32 size, loff_t offset) -{ - tio->idx = offset >> PAGE_CACHE_SHIFT; - tio->offset = offset & ~PAGE_CACHE_MASK; - tio->size = size; -} - -int tio_read(struct iet_volume *lu, struct tio *tio) -{ - struct iotype *iot = lu->iotype; - assert(iot); - return iot->make_request ? iot->make_request(lu, tio, READ) : 0; -} - -int tio_write(struct iet_volume *lu, struct tio *tio) -{ - struct iotype *iot = lu->iotype; - assert(iot); - return iot->make_request ? iot->make_request(lu, tio, WRITE) : 0; -} - -int tio_sync(struct iet_volume *lu, struct tio *tio) -{ - struct iotype *iot = lu->iotype; - assert(iot); - return iot->sync ? iot->sync(lu, tio) : 0; -} - -int tio_init(void) -{ - tio_cache = KMEM_CACHE(tio, 0); - return tio_cache ? 0 : -ENOMEM; -} - -void tio_exit(void) -{ - if (tio_cache) - kmem_cache_destroy(tio_cache); -} diff --git a/ubuntu/iscsitarget/ua.c b/ubuntu/iscsitarget/ua.c deleted file mode 100644 index 97f1ba0..0000000 --- a/ubuntu/iscsitarget/ua.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * IET Unit Attention support - * - * Copyright (C) 2009 Xie Gang - * Copyright (C) 2009 Arne Redlich - * - * Released under the terms of the GNU GPL v2.0. - */ - -#include - -#include "iscsi.h" -#include "iscsi_dbg.h" - -#define ua_hashfn(lun) ((lun % UA_HASH_LEN)) - -static struct kmem_cache *ua_cache; - -int ua_init(void) -{ - ua_cache = KMEM_CACHE(ua_entry, 0); - if (!ua_cache) { - eprintk("%s", "Failed to create ua cache\n"); - return -ENOMEM; - } - - return 0; -} - -void ua_exit(void) -{ - if (ua_cache) - kmem_cache_destroy(ua_cache); -} - -/* sess->ua_hash_lock needs to be held */ -static struct ua_entry * ua_find_hash(struct iscsi_session *sess, u32 lun, - u8 asc, u8 ascq, int match) -{ - struct ua_entry *ua; - struct list_head *h = &sess->ua_hash[ua_hashfn(lun)]; - - list_for_each_entry(ua, h, entry) { - if (ua->lun == lun) { - if (!match) - return ua; - if (ua->asc == asc && ua->ascq == ascq) - return ua; - } - } - - return NULL; -} - -int ua_pending(struct iscsi_session *sess, u32 lun) -{ - struct ua_entry *ua; - - spin_lock(&sess->ua_hash_lock); - ua = ua_find_hash(sess, lun, 0, 0, 0); - spin_unlock(&sess->ua_hash_lock); - - dprintk_ua(ua, sess, lun); - - return ua ? 1 : 0; -} - -/* sess->ua_hash_lock needs to be held */ -static struct ua_entry * __ua_get_hash(struct iscsi_session *sess, u32 lun, - u8 asc, u8 ascq, int match) -{ - struct ua_entry *ua = ua_find_hash(sess, lun, asc, ascq, match); - - if (ua) - list_del_init(&ua->entry); - - return ua; -} - -struct ua_entry * ua_get_first(struct iscsi_session *sess, u32 lun) -{ - struct ua_entry *ua; - - spin_lock(&sess->ua_hash_lock); - ua = __ua_get_hash(sess, lun, 0, 0, 0); - spin_unlock(&sess->ua_hash_lock); - - dprintk_ua(ua, sess, lun); - - return ua; -} - -struct ua_entry * ua_get_match(struct iscsi_session *sess, u32 lun, - u8 asc, u8 ascq) -{ - struct ua_entry *ua; - - spin_lock(&sess->ua_hash_lock); - ua = __ua_get_hash(sess, lun, asc, ascq, 1); - spin_unlock(&sess->ua_hash_lock); - - dprintk_ua(ua, sess, lun); - - return ua; -} - -void ua_establish_for_session(struct iscsi_session *sess, u32 lun, - u8 asc, u8 ascq) -{ - struct list_head *l = &sess->ua_hash[ua_hashfn(lun)]; - struct ua_entry *ua = kmem_cache_alloc(ua_cache, GFP_ATOMIC); - struct ua_entry *e; - - if (!ua) { - eprintk("%s", "Failed to alloc ua"); - return; - } - - ua->asc = asc; - ua->ascq = ascq; - ua->lun = lun; - ua->session = sess; - INIT_LIST_HEAD(&ua->entry); - - spin_lock(&sess->ua_hash_lock); - /* One UA per occurrence of an event */ - list_for_each_entry(e, l, entry) { - if (e->session == sess && e->lun == lun && - e->asc == asc && e->ascq == ascq && - e->session->exp_cmd_sn == sess->exp_cmd_sn) { - spin_unlock(&sess->ua_hash_lock); - ua_free(ua); - return; - } - } - list_add_tail(&ua->entry, l); - spin_unlock(&sess->ua_hash_lock); - - dprintk_ua(ua, sess, lun); -} - -void ua_establish_for_other_sessions(struct iscsi_session *sess, u32 lun, - u8 asc, u8 ascq) -{ - struct list_head *l = &sess->target->session_list; - struct iscsi_session *s; - - spin_lock(&sess->target->session_list_lock); - list_for_each_entry(s, l, list) - if (s->sid != sess->sid) - ua_establish_for_session(s, lun, asc, ascq); - spin_unlock(&sess->target->session_list_lock); -} - -void ua_establish_for_all_sessions(struct iscsi_target *target, u32 lun, - u8 asc, u8 ascq) -{ - struct list_head *l = &target->session_list; - struct iscsi_session *s; - - spin_lock(&target->session_list_lock); - list_for_each_entry(s, l, list) - ua_establish_for_session(s, lun, asc, ascq); - spin_unlock(&target->session_list_lock); - -} - -void ua_free(struct ua_entry *ua) -{ - if (!ua) - return; - - dprintk_ua(ua, ua->session, ua->lun); - BUG_ON(!list_empty(&ua->entry)); - kmem_cache_free(ua_cache, ua); -} diff --git a/ubuntu/iscsitarget/volume.c b/ubuntu/iscsitarget/volume.c deleted file mode 100644 index 2c9a698..0000000 --- a/ubuntu/iscsitarget/volume.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Volume manager - * (C) 2004 - 2005 FUJITA Tomonori - * This code is licenced under the GPL. - */ - -#include -#include - -#include "iscsi.h" -#include "iscsi_dbg.h" -#include "iotype.h" - -struct iet_volume *volume_lookup(struct iscsi_target *target, u32 lun) -{ - struct iet_volume *volume; - - list_for_each_entry(volume, &target->volumes, list) { - if (volume->lun == lun) - return volume; - } - return NULL; -} - -enum { - opt_type, - opt_iomode, - opt_scsiid, - opt_scsisn, - opt_blk_size, - opt_err, -}; - -static match_table_t tokens = { - {opt_type, "type=%s"}, - {opt_iomode, "iomode=%s"}, - {opt_scsiid, "scsiid=%s"}, - {opt_scsisn, "scsisn=%s"}, - {opt_blk_size, "blocksize=%u"}, - {opt_err, NULL}, -}; - -static int set_scsiid(struct iet_volume *volume, const char *id) -{ - size_t len; - - if ((len = strlen(id)) > SCSI_ID_LEN) { - eprintk("SCSI ID too long, %zd provided, %u max\n", len, - SCSI_ID_LEN); - return -EINVAL; - } - - memcpy(volume->scsi_id, id, len); - - return 0; -} - -static int set_scsisn(struct iet_volume *volume, const char *sn) -{ - size_t len; - int i; - - if ((len = strlen(sn)) > SCSI_SN_LEN) { - eprintk("SCSI SN too long, %zd provided, %u max\n", len, - SCSI_SN_LEN); - return -EINVAL; - } - - for (i = 0; i < len; i++) { - if (!isascii(*(sn + i)) || !isprint(*(sn + i))) { - eprintk("invalid characters in SCSI SN, %s\n", - "only printable ascii characters allowed!"); - return -EINVAL; - } - } - - memcpy(volume->scsi_sn, sn, len); - - return 0; -} - -/* Generate a MD5 hash of the target IQN and LUN number */ -static void gen_scsiid(struct iet_volume *volume) -{ - struct hash_desc hash; - - hash.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); - hash.flags = 0; - - if (hash.tfm) { - struct scatterlist sg[2]; - unsigned int nbytes = 0; - - sg_init_table(sg, 2); - - sg_set_buf(&sg[0], volume->target->name, - strlen(volume->target->name)); - nbytes += strlen(volume->target->name); - - sg_set_buf(&sg[1], &volume->lun, sizeof(volume->lun)); - nbytes += sizeof(volume->lun); - - crypto_hash_init(&hash); - crypto_hash_update(&hash, sg, nbytes); - crypto_hash_final(&hash, volume->scsi_id); - - crypto_free_hash(hash.tfm); - } else { - /* If no MD5 available set ID to TID and LUN */ - memcpy(volume->scsi_id, &volume->target->tid, - sizeof(volume->target->tid)); - memcpy(volume->scsi_id + sizeof(volume->target->tid), - &volume->lun, sizeof(volume->lun)); - } - -} - -static int parse_volume_params(struct iet_volume *volume, char *params) -{ - int err = 0; - unsigned blk_sz; - substring_t args[MAX_OPT_ARGS]; - char *p, *argp = NULL, *buf = (char *) get_zeroed_page(GFP_USER); - - if (!buf) - return -ENOMEM; - - strncpy(buf, params, PAGE_CACHE_SIZE); - - while ((p = strsep(&buf, ",")) != NULL) { - int token; - - if (!*p) - continue; - iet_strtolower(p); - token = match_token(p, tokens, args); - switch (token) { - case opt_type: - argp = match_strdup(&args[0]); - if (!argp) { - err = -ENOMEM; - break; - } - if (!(volume->iotype = get_iotype(argp))) - err = -ENOENT; - kfree(argp); - break; - case opt_iomode: - argp = match_strdup(&args[0]); - if (!argp) { - err = -ENOMEM; - break; - } - if (!strcmp(argp, "ro")) - SetLUReadonly(volume); - else if (!strcmp(argp, "wb")) - SetLUWCache(volume); - else if (strcmp(argp, "wt")) - err = -EINVAL; - kfree(argp); - break; - case opt_scsiid: - argp = match_strdup(&args[0]); - if (!argp) { - err = -ENOMEM; - break; - } - err = set_scsiid(volume, argp); - kfree(argp); - break; - case opt_scsisn: - argp = match_strdup(&args[0]); - if (!argp) { - err = -ENOMEM; - break; - } - err = set_scsisn(volume, argp); - kfree(argp); - break; - case opt_blk_size: - argp = match_strdup(&args[0]); - if (!argp) { - err = -ENOMEM; - break; - } - blk_sz = simple_strtoull(argp, NULL, 10); - if (is_power_of_2(blk_sz) && - 512 <= blk_sz && blk_sz <= IET_MAX_BLOCK_SIZE) - volume->blk_shift = blksize_bits(blk_sz); - else { - eprintk("invalid BlockSize=%u\n", blk_sz); - err = -EINVAL; - } - kfree(argp); - break; - default: - break; - } - } - - if (!err && !volume->iotype && !(volume->iotype = get_iotype("fileio"))) { - eprintk("%s\n", "Cannot find fileio"); - err = -EINVAL; - } - - free_page((unsigned long) buf); - - return err; -} - -int volume_add(struct iscsi_target *target, struct volume_info *info) -{ - int ret; - struct iet_volume *volume; - char *args; - - volume = volume_lookup(target, info->lun); - if (volume) - return -EEXIST; - - if (info->lun > 0x3fff) - return -EINVAL; - - volume = kzalloc(sizeof(*volume), GFP_KERNEL); - if (!volume) - return -ENOMEM; - - volume->target = target; - volume->lun = info->lun; - - args = kzalloc(info->args_len + 1, GFP_KERNEL); - if (!args) { - ret = -ENOMEM; - goto free_volume; - } - - ret = copy_from_user(args, (void *)(unsigned long)info->args_ptr, - info->args_len); - if (ret) { - ret = -EFAULT; - goto free_args; - } - - ret = parse_volume_params(volume, args); - if (ret < 0) - goto free_args; - - ret = volume->iotype->attach(volume, args); - if (ret < 0) - goto free_args; - - if (!volume->scsi_id[0]) - gen_scsiid(volume); - - if (!volume->scsi_sn[0]) { - int i; - - for (i = 0; i < SCSI_ID_LEN; i++) - snprintf(volume->scsi_sn + (i * 2), 3, "%02x", - volume->scsi_id[i]); - } - - INIT_LIST_HEAD(&volume->queue.wait_list); - spin_lock_init(&volume->queue.queue_lock); - spin_lock_init(&volume->reserve_lock); - - volume->l_state = IDEV_RUNNING; - atomic_set(&volume->l_count, 0); - - list_add_tail(&volume->list, &target->volumes); - atomic_inc(&target->nr_volumes); - - kfree(args); - - return 0; -free_args: - kfree(args); -free_volume: - put_iotype(volume->iotype); - kfree(volume); - - return ret; -} - -void iscsi_volume_destroy(struct iet_volume *volume) -{ - assert(volume->l_state == IDEV_DEL); - assert(!atomic_read(&volume->l_count)); - - volume->iotype->detach(volume); - put_iotype(volume->iotype); - list_del(&volume->list); - kfree(volume); -} - -int iscsi_volume_del(struct iscsi_target *target, struct volume_info *info) -{ - struct iet_volume *volume; - - eprintk("%x %x\n", target->tid, info->lun); - if (!(volume = volume_lookup(target, info->lun))) - return -ENOENT; - - volume->l_state = IDEV_DEL; - atomic_dec(&target->nr_volumes); - if (!atomic_read(&volume->l_count)) - iscsi_volume_destroy(volume); - - return 0; -} - -struct iet_volume *volume_get(struct iscsi_target *target, u32 lun) -{ - struct iet_volume *volume; - - if ((volume = volume_lookup(target, lun))) { - if (volume->l_state == IDEV_RUNNING) - atomic_inc(&volume->l_count); - else - volume = NULL; - } - return volume; -} - -void volume_put(struct iet_volume *volume) -{ - if (atomic_dec_and_test(&volume->l_count) && volume->l_state == IDEV_DEL) - iscsi_volume_destroy(volume); -} - -int volume_reserve(struct iet_volume *volume, u64 sid) -{ - int err = 0; - - if (!volume) - return -ENOENT; - - spin_lock(&volume->reserve_lock); - if (volume->reserve_sid && volume->reserve_sid != sid) - err = -EBUSY; - else - volume->reserve_sid = sid; - - spin_unlock(&volume->reserve_lock); - return err; -} - -int is_volume_reserved(struct iet_volume *volume, u64 sid) -{ - int err = 0; - - if (!volume) - return -ENOENT; - - spin_lock(&volume->reserve_lock); - if (!volume->reserve_sid || volume->reserve_sid == sid) - err = 0; - else - err = -EBUSY; - - spin_unlock(&volume->reserve_lock); - return err; -} - -int volume_release(struct iet_volume *volume, u64 sid, int force) -{ - int err = 0; - - if (!volume) - return -ENOENT; - - spin_lock(&volume->reserve_lock); - - if (force || volume->reserve_sid == sid) - volume->reserve_sid = 0; - else - err = -EBUSY; - - spin_unlock(&volume->reserve_lock); - return err; -} - -static void iet_volume_info_show(struct seq_file *seq, struct iscsi_target *target) -{ - struct iet_volume *volume; - - list_for_each_entry(volume, &target->volumes, list) { - seq_printf(seq, "\tlun:%u state:%x iotype:%s", - volume->lun, volume->l_state, volume->iotype->name); - if (LUReadonly(volume)) - seq_printf(seq, " iomode:ro"); - else if (LUWCache(volume)) - seq_printf(seq, " iomode:wb"); - else - seq_printf(seq, " iomode:wt"); - - seq_printf(seq, " blocks:%llu blocksize:%u", - volume->blk_cnt, 1 << volume->blk_shift); - if (volume->iotype->show) - volume->iotype->show(volume, seq); - else - seq_printf(seq, "\n"); - } -} - -static int iet_volume_seq_open(struct inode *inode, struct file *file) -{ - int res; - res = seq_open(file, &iet_seq_op); - if (!res) - ((struct seq_file *)file->private_data)->private = - iet_volume_info_show; - return res; -} - -struct file_operations volume_seq_fops = { - .owner = THIS_MODULE, - .open = iet_volume_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; diff --git a/ubuntu/iscsitarget/wthread.c b/ubuntu/iscsitarget/wthread.c deleted file mode 100644 index f77138b..0000000 --- a/ubuntu/iscsitarget/wthread.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Worker thread. - * (C) 2004 - 2005 FUJITA Tomonori - * This code is licenced under the GPL. - */ - -#include - -#include "iscsi.h" -#include "iscsi_dbg.h" - -struct worker_thread_info *worker_thread_pool; - -void wthread_queue(struct iscsi_cmnd *cmnd) -{ - struct worker_thread_info *info = cmnd->conn->session->target->wthread_info; - - if (!list_empty(&cmnd->list)) { - struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); - eprintk("%x %p %x %x %x %x %lx %x\n", - cmnd_itt(cmnd), req, req->opcode, req->scb[0], cmnd->pdu.datasize, - be32_to_cpu(req->data_length), cmnd->flags, req->flags); - - if (cmnd->lun) - eprintk("%u\n", cmnd->lun->lun); - assert(list_empty(&cmnd->list)); - } - - spin_lock(&info->wthread_lock); - list_add_tail(&cmnd->list, &info->work_queue); - spin_unlock(&info->wthread_lock); - - atomic_inc(&cmnd->conn->nr_busy_cmnds); - - wake_up(&info->wthread_sleep); -} - -static struct iscsi_cmnd * get_ready_cmnd(struct worker_thread_info *info) -{ - struct iscsi_cmnd *cmnd = NULL; - - spin_lock(&info->wthread_lock); - if (!list_empty(&info->work_queue)) { - cmnd = list_entry(info->work_queue.next, struct iscsi_cmnd, list); - list_del_init(&cmnd->list); - - assert(cmnd->conn); - } - spin_unlock(&info->wthread_lock); - - return cmnd; -} - -static int cmnd_execute(struct iscsi_cmnd *cmnd) -{ - int type = cmnd->conn->session->target->trgt_param.target_type; - - assert(target_type_array[type]->execute_cmnd); - return target_type_array[type]->execute_cmnd(cmnd); -} - -static void copy_io_context(struct io_context **pdst, struct io_context **psrc) -{ - struct io_context *src = *psrc; - struct io_context *dst = *pdst; - - if (src) { - BUG_ON(atomic_long_read(&src->refcount) == 0); - atomic_long_inc(&src->refcount); - put_io_context(dst); - *pdst = src; - } -} - -static int worker_thread(void *arg) -{ - struct worker_thread *wt = (struct worker_thread *) arg; - struct worker_thread_info *info = wt->w_info; - struct iscsi_cmnd *cmnd; - struct iscsi_conn *conn; - DECLARE_WAITQUEUE(wait, current); - - get_io_context(GFP_KERNEL, -1); - - if (!current->io_context) - eprintk("%s\n", "Failed to get IO context"); - else if (info->wthread_ioc) - copy_io_context(¤t->io_context, &info->wthread_ioc); - else - info->wthread_ioc = current->io_context; - - add_wait_queue(&info->wthread_sleep, &wait); - - __set_current_state(TASK_RUNNING); - do { - while (!list_empty(&info->work_queue) && - (cmnd = get_ready_cmnd(info))) { - conn = cmnd->conn; - if (cmnd_tmfabort(cmnd)) - cmnd_release(cmnd, 1); - else - cmnd_execute(cmnd); - assert(conn); - atomic_dec(&conn->nr_busy_cmnds); - } - - set_current_state(TASK_INTERRUPTIBLE); - if (list_empty(&info->work_queue)) - schedule(); - - __set_current_state(TASK_RUNNING); - } while (!kthread_should_stop()); - - remove_wait_queue(&info->wthread_sleep, &wait); - - if (current->io_context) { - struct io_context *ioc = current->io_context; - - task_lock(current); - current->io_context = NULL; - task_unlock(current); - - put_io_context(ioc); - } - - return 0; -} - -static int start_one_worker_thread(struct worker_thread_info *info, u32 tid) -{ - struct worker_thread *wt; - struct task_struct *task; - - if (!(wt = kmalloc(sizeof(struct worker_thread), GFP_KERNEL))) - return -ENOMEM; - - wt->w_info = info; - task = kthread_create(worker_thread, wt, "istiod%d", tid); - if (IS_ERR(task)) { - kfree(wt); - return PTR_ERR(task); - } - - wt->w_task = task; - list_add(&wt->w_list, &info->wthread_list); - info->nr_running_wthreads++; - - wake_up_process(task); - - return 0; -} - -static int stop_one_worker_thread(struct worker_thread *wt) -{ - struct worker_thread_info *info = wt->w_info; - int err; - - assert(wt->w_task); - err = kthread_stop(wt->w_task); - - if (err < 0 && err != -EINTR) - return err; - - list_del(&wt->w_list); - kfree(wt); - info->nr_running_wthreads--; - - return 0; -} - -int wthread_init(struct worker_thread_info *info) -{ - spin_lock_init(&info->wthread_lock); - - info->nr_running_wthreads = 0; - info->wthread_ioc = NULL; - - INIT_LIST_HEAD(&info->work_queue); - INIT_LIST_HEAD(&info->wthread_list); - - init_waitqueue_head(&info->wthread_sleep); - - return 0; -} - -int wthread_start(struct worker_thread_info *info, int wthreads, u32 tid) -{ - int err = 0; - - while (info->nr_running_wthreads < wthreads) { - if ((err = start_one_worker_thread(info, tid)) < 0) { - eprintk("Fail to create a worker thread %d\n", err); - goto out; - } - } - - while (info->nr_running_wthreads > wthreads) { - struct worker_thread *wt; - wt = list_entry(info->wthread_list.next, struct worker_thread, w_list); - if ((err = stop_one_worker_thread(wt)) < 0) { - eprintk("Fail to stop a worker thread %d\n", err); - break; - } - } -out: - return err; -} - -int wthread_stop(struct worker_thread_info *info) -{ - struct worker_thread *wt, *tmp; - int err = 0; - - list_for_each_entry_safe(wt, tmp, &info->wthread_list, w_list) { - if ((err = stop_one_worker_thread(wt)) < 0) { - eprintk("Fail to stop a worker thread %d\n", err); - return err; - } - } - - return err; -} - -int wthread_module_init() -{ - int err; - - if (!worker_thread_pool_size) - return 0; - - worker_thread_pool = kmalloc(sizeof(struct worker_thread_info), - GFP_KERNEL); - if (!worker_thread_pool) - return -ENOMEM; - - wthread_init(worker_thread_pool); - - err = wthread_start(worker_thread_pool, worker_thread_pool_size, 0); - if (err) { - kfree(worker_thread_pool); - worker_thread_pool = NULL; - return err; - } - - iprintk("iscsi_trgt using worker thread pool; size = %ld\n", - worker_thread_pool_size); - - return 0; -} - -void wthread_module_exit() -{ - if (!worker_thread_pool_size) - return; - - wthread_stop(worker_thread_pool); - kfree(worker_thread_pool); -} -- 1.7.4.1