Commit 38567333 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-post-merge-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-post-merge-2.6:
  [SCSI] target: Add LIO target core v4.0.0-rc6
  [SCSI] sd,sr: kill compat SDEV_MEDIA_CHANGE event
  [SCSI] sd: implement sd_check_events()
parents de23be5f c66ac9db
This diff is collapsed.
>>>>>>>>>> The TCM v4 fabric module script generator <<<<<<<<<<
Greetings all,
This document is intended to be a mini-HOWTO for using the tcm_mod_builder.py
script to generate a brand new functional TCM v4 fabric .ko module of your very own,
that once built can be immediately be loaded to start access the new TCM/ConfigFS
fabric skeleton, by simply using:
modprobe $TCM_NEW_MOD
mkdir -p /sys/kernel/config/target/$TCM_NEW_MOD
This script will create a new drivers/target/$TCM_NEW_MOD/, and will do the following
*) Generate new API callers for drivers/target/target_core_fabric_configs.c logic
->make_nodeacl(), ->drop_nodeacl(), ->make_tpg(), ->drop_tpg()
->make_wwn(), ->drop_wwn(). These are created into $TCM_NEW_MOD/$TCM_NEW_MOD_configfs.c
*) Generate basic infrastructure for loading/unloading LKMs and TCM/ConfigFS fabric module
using a skeleton struct target_core_fabric_ops API template.
*) Based on user defined T10 Proto_Ident for the new fabric module being built,
the TransportID / Initiator and Target WWPN related handlers for
SPC-3 persistent reservation are automatically generated in $TCM_NEW_MOD/$TCM_NEW_MOD_fabric.c
using drivers/target/target_core_fabric_lib.c logic.
*) NOP API calls for all other Data I/O path and fabric dependent attribute logic
in $TCM_NEW_MOD/$TCM_NEW_MOD_fabric.c
tcm_mod_builder.py depends upon the mandatory '-p $PROTO_IDENT' and '-m
$FABRIC_MOD_name' parameters, and actually running the script looks like:
target:/mnt/sdb/lio-core-2.6.git/Documentation/target# python tcm_mod_builder.py -p iSCSI -m tcm_nab5000
tcm_dir: /mnt/sdb/lio-core-2.6.git/Documentation/target/../../
Set fabric_mod_name: tcm_nab5000
Set fabric_mod_dir:
/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000
Using proto_ident: iSCSI
Creating fabric_mod_dir:
/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000
Writing file:
/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/tcm_nab5000_base.h
Using tcm_mod_scan_fabric_ops:
/mnt/sdb/lio-core-2.6.git/Documentation/target/../../include/target/target_core_fabric_ops.h
Writing file:
/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/tcm_nab5000_fabric.c
Writing file:
/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/tcm_nab5000_fabric.h
Writing file:
/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/tcm_nab5000_configfs.c
Writing file:
/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/Kbuild
Writing file:
/mnt/sdb/lio-core-2.6.git/Documentation/target/../../drivers/target/tcm_nab5000/Kconfig
Would you like to add tcm_nab5000to drivers/target/Kbuild..? [yes,no]: yes
Would you like to add tcm_nab5000to drivers/target/Kconfig..? [yes,no]: yes
At the end of tcm_mod_builder.py. the script will ask to add the following
line to drivers/target/Kbuild:
obj-$(CONFIG_TCM_NAB5000) += tcm_nab5000/
and the same for drivers/target/Kconfig:
source "drivers/target/tcm_nab5000/Kconfig"
*) Run 'make menuconfig' and select the new CONFIG_TCM_NAB5000 item:
<M> TCM_NAB5000 fabric module
*) Build using 'make modules', once completed you will have:
target:/mnt/sdb/lio-core-2.6.git# ls -la drivers/target/tcm_nab5000/
total 1348
drwxr-xr-x 2 root root 4096 2010-10-05 03:23 .
drwxr-xr-x 9 root root 4096 2010-10-05 03:22 ..
-rw-r--r-- 1 root root 282 2010-10-05 03:22 Kbuild
-rw-r--r-- 1 root root 171 2010-10-05 03:22 Kconfig
-rw-r--r-- 1 root root 49 2010-10-05 03:23 modules.order
-rw-r--r-- 1 root root 738 2010-10-05 03:22 tcm_nab5000_base.h
-rw-r--r-- 1 root root 9096 2010-10-05 03:22 tcm_nab5000_configfs.c
-rw-r--r-- 1 root root 191200 2010-10-05 03:23 tcm_nab5000_configfs.o
-rw-r--r-- 1 root root 40504 2010-10-05 03:23 .tcm_nab5000_configfs.o.cmd
-rw-r--r-- 1 root root 5414 2010-10-05 03:22 tcm_nab5000_fabric.c
-rw-r--r-- 1 root root 2016 2010-10-05 03:22 tcm_nab5000_fabric.h
-rw-r--r-- 1 root root 190932 2010-10-05 03:23 tcm_nab5000_fabric.o
-rw-r--r-- 1 root root 40713 2010-10-05 03:23 .tcm_nab5000_fabric.o.cmd
-rw-r--r-- 1 root root 401861 2010-10-05 03:23 tcm_nab5000.ko
-rw-r--r-- 1 root root 265 2010-10-05 03:23 .tcm_nab5000.ko.cmd
-rw-r--r-- 1 root root 459 2010-10-05 03:23 tcm_nab5000.mod.c
-rw-r--r-- 1 root root 23896 2010-10-05 03:23 tcm_nab5000.mod.o
-rw-r--r-- 1 root root 22655 2010-10-05 03:23 .tcm_nab5000.mod.o.cmd
-rw-r--r-- 1 root root 379022 2010-10-05 03:23 tcm_nab5000.o
-rw-r--r-- 1 root root 211 2010-10-05 03:23 .tcm_nab5000.o.cmd
*) Load the new module, create a lun_0 configfs group, and add new TCM Core
IBLOCK backstore symlink to port:
target:/mnt/sdb/lio-core-2.6.git# insmod drivers/target/tcm_nab5000.ko
target:/mnt/sdb/lio-core-2.6.git# mkdir -p /sys/kernel/config/target/nab5000/iqn.foo/tpgt_1/lun/lun_0
target:/mnt/sdb/lio-core-2.6.git# cd /sys/kernel/config/target/nab5000/iqn.foo/tpgt_1/lun/lun_0/
target:/sys/kernel/config/target/nab5000/iqn.foo/tpgt_1/lun/lun_0# ln -s /sys/kernel/config/target/core/iblock_0/lvm_test0 nab5000_port
target:/sys/kernel/config/target/nab5000/iqn.foo/tpgt_1/lun/lun_0# cd -
target:/mnt/sdb/lio-core-2.6.git# tree /sys/kernel/config/target/nab5000/
/sys/kernel/config/target/nab5000/
|-- discovery_auth
|-- iqn.foo
| `-- tpgt_1
| |-- acls
| |-- attrib
| |-- lun
| | `-- lun_0
| | |-- alua_tg_pt_gp
| | |-- alua_tg_pt_offline
| | |-- alua_tg_pt_status
| | |-- alua_tg_pt_write_md
| | `-- nab5000_port -> ../../../../../../target/core/iblock_0/lvm_test0
| |-- np
| `-- param
`-- version
target:/mnt/sdb/lio-core-2.6.git# lsmod
Module Size Used by
tcm_nab5000 3935 4
iscsi_target_mod 193211 0
target_core_stgt 8090 0
target_core_pscsi 11122 1
target_core_file 9172 2
target_core_iblock 9280 1
target_core_mod 228575 31
tcm_nab5000,iscsi_target_mod,target_core_stgt,target_core_pscsi,target_core_file,target_core_iblock
libfc 73681 0
scsi_debug 56265 0
scsi_tgt 8666 1 target_core_stgt
configfs 20644 2 target_core_mod
----------------------------------------------------------------------
Future TODO items:
*) Add more T10 proto_idents
*) Make tcm_mod_dump_fabric_ops() smarter and generate function pointer
defs directly from include/target/target_core_fabric_ops.h:struct target_core_fabric_ops
structure members.
October 5th, 2010
Nicholas A. Bellinger <nab@linux-iscsi.org>
......@@ -26,6 +26,8 @@ source "drivers/ata/Kconfig"
source "drivers/md/Kconfig"
source "drivers/target/Kconfig"
source "drivers/message/fusion/Kconfig"
source "drivers/firewire/Kconfig"
......
......@@ -46,6 +46,7 @@ obj-y += macintosh/
obj-$(CONFIG_IDE) += ide/
obj-$(CONFIG_SCSI) += scsi/
obj-$(CONFIG_ATA) += ata/
obj-$(CONFIG_TARGET_CORE) += target/
obj-$(CONFIG_MTD) += mtd/
obj-$(CONFIG_SPI) += spi/
obj-y += net/
......
......@@ -990,30 +990,51 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
static void set_media_not_present(struct scsi_disk *sdkp)
{
if (sdkp->media_present)
sdkp->device->changed = 1;
if (sdkp->device->removable) {
sdkp->media_present = 0;
sdkp->capacity = 0;
sdkp->device->changed = 1;
}
}
static int media_not_present(struct scsi_disk *sdkp,
struct scsi_sense_hdr *sshdr)
{
if (!scsi_sense_valid(sshdr))
return 0;
/* not invoked for commands that could return deferred errors */
switch (sshdr->sense_key) {
case UNIT_ATTENTION:
case NOT_READY:
/* medium not present */
if (sshdr->asc == 0x3A) {
set_media_not_present(sdkp);
return 1;
}
}
return 0;
}
/**
* sd_media_changed - check if our medium changed
* sd_check_events - check media events
* @disk: kernel device descriptor
* @clearing: disk events currently being cleared
*
* Returns 0 if not applicable or no change; 1 if change
* Returns mask of DISK_EVENT_*.
*
* Note: this function is invoked from the block subsystem.
**/
static int sd_media_changed(struct gendisk *disk)
static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
{
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdp = sdkp->device;
struct scsi_sense_hdr *sshdr = NULL;
int retval;
SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_media_changed\n"));
if (!sdp->removable)
return 0;
SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_check_events\n"));
/*
* If the device is offline, don't send any commands - just pretend as
......@@ -1043,40 +1064,32 @@ static int sd_media_changed(struct gendisk *disk)
sshdr);
}
if (retval) {
/* failed to execute TUR, assume media not present */
if (host_byte(retval)) {
set_media_not_present(sdkp);
goto out;
}
if (media_not_present(sdkp, sshdr))
goto out;
/*
* For removable scsi disk we have to recognise the presence
* of a disk in the drive. This is kept in the struct scsi_disk
* struct and tested at open ! Daniel Roche (dan@lectra.fr)
* of a disk in the drive.
*/
if (!sdkp->media_present)
sdp->changed = 1;
sdkp->media_present = 1;
out:
/*
* Report a media change under the following conditions:
*
* Medium is present now and wasn't present before.
* Medium wasn't present before and is present now.
* Medium was present at all times, but it changed while
* we weren't looking (sdp->changed is set).
* sdp->changed is set under the following conditions:
*
* If there was no medium before and there is no medium now then
* don't report a change, even if a medium was inserted and removed
* while we weren't looking.
* Medium present state has changed in either direction.
* Device has indicated UNIT_ATTENTION.
*/
retval = (sdkp->media_present != sdkp->previous_state ||
(sdkp->media_present && sdp->changed));
if (retval)
sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL);
sdkp->previous_state = sdkp->media_present;
/* sdp->changed indicates medium was changed or is not present */
sdp->changed = !sdkp->media_present;
kfree(sshdr);
retval = sdp->changed ? DISK_EVENT_MEDIA_CHANGE : 0;
sdp->changed = 0;
return retval;
}
......@@ -1169,7 +1182,7 @@ static const struct block_device_operations sd_fops = {
#ifdef CONFIG_COMPAT
.compat_ioctl = sd_compat_ioctl,
#endif
.media_changed = sd_media_changed,
.check_events = sd_check_events,
.revalidate_disk = sd_revalidate_disk,
.unlock_native_capacity = sd_unlock_native_capacity,
};
......@@ -1312,23 +1325,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
return good_bytes;
}
static int media_not_present(struct scsi_disk *sdkp,
struct scsi_sense_hdr *sshdr)
{
if (!scsi_sense_valid(sshdr))
return 0;
/* not invoked for commands that could return deferred errors */
if (sshdr->sense_key != NOT_READY &&
sshdr->sense_key != UNIT_ATTENTION)
return 0;
if (sshdr->asc != 0x3A) /* medium not present */
return 0;
set_media_not_present(sdkp);
return 1;
}
/*
* spinup disk - called only in sd_revalidate_disk()
*/
......@@ -1503,7 +1499,7 @@ static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
*/
if (sdp->removable &&
sense_valid && sshdr->sense_key == NOT_READY)
sdp->changed = 1;
set_media_not_present(sdkp);
/*
* We used to set media_present to 0 here to indicate no media
......@@ -2389,8 +2385,10 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
gd->driverfs_dev = &sdp->sdev_gendev;
gd->flags = GENHD_FL_EXT_DEVT;
if (sdp->removable)
if (sdp->removable) {
gd->flags |= GENHD_FL_REMOVABLE;
gd->events |= DISK_EVENT_MEDIA_CHANGE;
}
add_disk(gd);
sd_dif_config_host(sdkp);
......@@ -2472,7 +2470,6 @@ static int sd_probe(struct device *dev)
sdkp->disk = gd;
sdkp->index = index;
atomic_set(&sdkp->openers, 0);
sdkp->previous_state = 1;
if (!sdp->request_queue->rq_timeout) {
if (sdp->type != TYPE_MOD)
......
......@@ -55,7 +55,6 @@ struct scsi_disk {
u8 media_present;
u8 write_prot;
u8 protection_type;/* Data Integrity Field */
unsigned previous_state : 1;
unsigned ATO : 1; /* state of disk ATO bit */
unsigned WCE : 1; /* state of disk WCE bit */
unsigned RCD : 1; /* state of disk RCD bit, unused */
......
......@@ -249,10 +249,6 @@ static unsigned int sr_check_events(struct cdrom_device_info *cdi,
cd->device->changed = 0;
}
/* for backward compatibility */
if (events & DISK_EVENT_MEDIA_CHANGE)
sdev_evt_send_simple(cd->device, SDEV_EVT_MEDIA_CHANGE,
GFP_KERNEL);
return events;
}
......
menuconfig TARGET_CORE
tristate "Generic Target Core Mod (TCM) and ConfigFS Infrastructure"
depends on SCSI && BLOCK
select CONFIGFS_FS
default n
help
Say Y or M here to enable the TCM Storage Engine and ConfigFS enabled
control path for target_core_mod. This includes built-in TCM RAMDISK
subsystem logic for virtual LUN 0 access
if TARGET_CORE
config TCM_IBLOCK
tristate "TCM/IBLOCK Subsystem Plugin for Linux/BLOCK"
help
Say Y here to enable the TCM/IBLOCK subsystem plugin for non-buffered
access to Linux/Block devices using BIO
config TCM_FILEIO
tristate "TCM/FILEIO Subsystem Plugin for Linux/VFS"
help
Say Y here to enable the TCM/FILEIO subsystem plugin for buffered
access to Linux/VFS struct file or struct block_device
config TCM_PSCSI
tristate "TCM/pSCSI Subsystem Plugin for Linux/SCSI"
help
Say Y here to enable the TCM/pSCSI subsystem plugin for non-buffered
passthrough access to Linux/SCSI device
endif
EXTRA_CFLAGS += -I$(srctree)/drivers/target/ -I$(srctree)/drivers/scsi/
target_core_mod-y := target_core_configfs.o \
target_core_device.o \
target_core_fabric_configfs.o \
target_core_fabric_lib.o \
target_core_hba.o \
target_core_pr.o \
target_core_alua.o \
target_core_scdb.o \
target_core_tmr.o \
target_core_tpg.o \
target_core_transport.o \
target_core_cdb.o \
target_core_ua.o \
target_core_rd.o \
target_core_mib.o
obj-$(CONFIG_TARGET_CORE) += target_core_mod.o
# Subsystem modules
obj-$(CONFIG_TCM_IBLOCK) += target_core_iblock.o
obj-$(CONFIG_TCM_FILEIO) += target_core_file.o
obj-$(CONFIG_TCM_PSCSI) += target_core_pscsi.o
This diff is collapsed.
#ifndef TARGET_CORE_ALUA_H
#define TARGET_CORE_ALUA_H
/*
* INQUIRY response data, TPGS Field
*
* from spc4r17 section 6.4.2 Table 135
*/
#define TPGS_NO_ALUA 0x00
#define TPGS_IMPLICT_ALUA 0x10
#define TPGS_EXPLICT_ALUA 0x20
/*
* ASYMMETRIC ACCESS STATE field
*
* from spc4r17 section 6.27 Table 245
*/
#define ALUA_ACCESS_STATE_ACTIVE_OPTMIZED 0x0
#define ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED 0x1
#define ALUA_ACCESS_STATE_STANDBY 0x2
#define ALUA_ACCESS_STATE_UNAVAILABLE 0x3
#define ALUA_ACCESS_STATE_OFFLINE 0xe
#define ALUA_ACCESS_STATE_TRANSITION 0xf
/*
* REPORT_TARGET_PORT_GROUP STATUS CODE
*
* from spc4r17 section 6.27 Table 246
*/
#define ALUA_STATUS_NONE 0x00
#define ALUA_STATUS_ALTERED_BY_EXPLICT_STPG 0x01
#define ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA 0x02
/*
* From spc4r17, Table D.1: ASC and ASCQ Assignement
*/
#define ASCQ_04H_ALUA_STATE_TRANSITION 0x0a
#define ASCQ_04H_ALUA_TG_PT_STANDBY 0x0b
#define ASCQ_04H_ALUA_TG_PT_UNAVAILABLE 0x0c
#define ASCQ_04H_ALUA_OFFLINE 0x12
/*
* Used as the default for Active/NonOptimized delay (in milliseconds)
* This can also be changed via configfs on a per target port group basis..
*/
#define ALUA_DEFAULT_NONOP_DELAY_MSECS 100
#define ALUA_MAX_NONOP_DELAY_MSECS 10000 /* 10 seconds */
/*
* Used for implict and explict ALUA transitional delay, that is disabled
* by default, and is intended to be used for debugging client side ALUA code.
*/
#define ALUA_DEFAULT_TRANS_DELAY_MSECS 0
#define ALUA_MAX_TRANS_DELAY_MSECS 30000 /* 30 seconds */
/*
* Used by core_alua_update_tpg_primary_metadata() and
* core_alua_update_tpg_secondary_metadata()
*/
#define ALUA_METADATA_PATH_LEN 512
/*
* Used by core_alua_update_tpg_secondary_metadata()
*/
#define ALUA_SECONDARY_METADATA_WWN_LEN 256
extern struct kmem_cache *t10_alua_lu_gp_cache;
extern struct kmem_cache *t10_alua_lu_gp_mem_cache;
extern struct kmem_cache *t10_alua_tg_pt_gp_cache;
extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
extern int core_emulate_report_target_port_groups(struct se_cmd *);
extern int core_emulate_set_target_port_groups(struct se_cmd *);
extern int core_alua_check_nonop_delay(struct se_cmd *);
extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *,
struct se_device *, struct se_port *,
struct se_node_acl *, int, int);
extern char *core_alua_dump_status(int);
extern struct t10_alua_lu_gp *core_alua_allocate_lu_gp(const char *, int);
extern int core_alua_set_lu_gp_id(struct t10_alua_lu_gp *, u16);
extern void core_alua_free_lu_gp(struct t10_alua_lu_gp *);
extern void core_alua_free_lu_gp_mem(struct se_device *);
extern struct t10_alua_lu_gp *core_alua_get_lu_gp_by_name(const char *);
extern void core_alua_put_lu_gp_from_name(struct t10_alua_lu_gp *);
extern void __core_alua_attach_lu_gp_mem(struct t10_alua_lu_gp_member *,
struct t10_alua_lu_gp *);
extern void __core_alua_drop_lu_gp_mem(struct t10_alua_lu_gp_member *,
struct t10_alua_lu_gp *);
extern void core_alua_drop_lu_gp_dev(struct se_device *);
extern struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(
struct se_subsystem_dev *, const char *, int);
extern int core_alua_set_tg_pt_gp_id(struct t10_alua_tg_pt_gp *, u16);
extern struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem(
struct se_port *);
extern void core_alua_free_tg_pt_gp(struct t10_alua_tg_pt_gp *);
extern void core_alua_free_tg_pt_gp_mem(struct se_port *);
extern void __core_alua_attach_tg_pt_gp_mem(struct t10_alua_tg_pt_gp_member *,
struct t10_alua_tg_pt_gp *);
extern ssize_t core_alua_show_tg_pt_gp_info(struct se_port *, char *);
extern ssize_t core_alua_store_tg_pt_gp_info(struct se_port *, const char *,
size_t);
extern ssize_t core_alua_show_access_type(struct t10_alua_tg_pt_gp *, char *);
extern ssize_t core_alua_store_access_type(struct t10_alua_tg_pt_gp *,
const char *, size_t);
extern ssize_t core_alua_show_nonop_delay_msecs(struct t10_alua_tg_pt_gp *,
char *);
extern ssize_t core_alua_store_nonop_delay_msecs(struct t10_alua_tg_pt_gp *,
const char *, size_t);
extern ssize_t core_alua_show_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
char *);
extern ssize_t core_alua_store_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
const char *, size_t);
extern ssize_t core_alua_show_preferred_bit(struct t10_alua_tg_pt_gp *,
char *);
extern ssize_t core_alua_store_preferred_bit(struct t10_alua_tg_pt_gp *,
const char *, size_t);
extern ssize_t core_alua_show_offline_bit(struct se_lun *, char *);
extern ssize_t core_alua_store_offline_bit(struct se_lun *, const char *,
size_t);
extern ssize_t core_alua_show_secondary_status(struct se_lun *, char *);
extern ssize_t core_alua_store_secondary_status(struct se_lun *,
const char *, size_t);
extern ssize_t core_alua_show_secondary_write_metadata(struct se_lun *,
char *);
extern ssize_t core_alua_store_secondary_write_metadata(struct se_lun *,
const char *, size_t);
extern int core_setup_alua(struct se_device *, int);
#endif /* TARGET_CORE_ALUA_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#ifndef TARGET_CORE_FILE_H
#define TARGET_CORE_FILE_H
#define FD_VERSION "4.0"
#define FD_MAX_DEV_NAME 256
/* Maximum queuedepth for the FILEIO HBA */
#define FD_HBA_QUEUE_DEPTH 256
#define FD_DEVICE_QUEUE_DEPTH 32
#define FD_MAX_DEVICE_QUEUE_DEPTH 128
#define FD_BLOCKSIZE 512
#define FD_MAX_SECTORS 1024
#define RRF_EMULATE_CDB 0x01
#define RRF_GOT_LBA 0x02
struct fd_request {
struct se_task fd_task;
/* SCSI CDB from iSCSI Command PDU */
unsigned char fd_scsi_cdb[TCM_MAX_COMMAND_SIZE];
/* FILEIO device */
struct fd_dev *fd_dev;
} ____cacheline_aligned;
#define FBDF_HAS_PATH 0x01
#define FBDF_HAS_SIZE 0x02
#define FDBD_USE_BUFFERED_IO 0x04
struct fd_dev {
u32 fbd_flags;
unsigned char fd_dev_name[FD_MAX_DEV_NAME];
/* Unique Ramdisk Device ID in Ramdisk HBA */
u32 fd_dev_id;
/* Number of SG tables in sg_table_array */
u32 fd_table_count;
u32 fd_queue_depth;
u32 fd_block_size;
unsigned long long fd_dev_size;
struct file *fd_file;
/* FILEIO HBA device is connected to */
struct fd_host *fd_host;
} ____cacheline_aligned;
struct fd_host {
u32 fd_host_dev_id_count;
/* Unique FILEIO Host ID */
u32 fd_host_id;
} ____cacheline_aligned;
#endif /* TARGET_CORE_FILE_H */
/*******************************************************************************
* Filename: target_core_hba.c
*
* This file copntains the iSCSI HBA Transport related functions.
*
* Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc.
* Copyright (c) 2005, 2006, 2007 SBE, Inc.
* Copyright (c) 2007-2010 Rising Tide Systems
* Copyright (c) 2008-2010 Linux-iSCSI.org
*
* Nicholas A. Bellinger <nab@kernel.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
******************************************************************************/
#include <linux/net.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <linux/in.h>
#include <net/sock.h>
#include <net/tcp.h>
#include <target/target_core_base.h>
#include <target/target_core_device.h>
#include <target/target_core_device.h>
#include <target/target_core_tpg.h>
#include <target/target_core_transport.h>
#include "target_core_hba.h"
static LIST_HEAD(subsystem_list);
static DEFINE_MUTEX(subsystem_mutex);
int transport_subsystem_register(struct se_subsystem_api *sub_api)
{
struct se_subsystem_api *s;
INIT_LIST_HEAD(&sub_api->sub_api_list);
mutex_lock(&subsystem_mutex);
list_for_each_entry(s, &subsystem_list, sub_api_list) {
if (!(strcmp(s->name, sub_api->name))) {
printk(KERN_ERR "%p is already registered with"
" duplicate name %s, unable to process"
" request\n", s, s->name);
mutex_unlock(&subsystem_mutex);
return -EEXIST;
}
}
list_add_tail(&sub_api->sub_api_list, &subsystem_list);
mutex_unlock(&subsystem_mutex);
printk(KERN_INFO "TCM: Registered subsystem plugin: %s struct module:"
" %p\n", sub_api->name, sub_api->owner);
return 0;
}
EXPORT_SYMBOL(transport_subsystem_register);
void transport_subsystem_release(struct se_subsystem_api *sub_api)
{
mutex_lock(&subsystem_mutex);
list_del(&sub_api->sub_api_list);
mutex_unlock(&subsystem_mutex);
}
EXPORT_SYMBOL(transport_subsystem_release);
static struct se_subsystem_api *core_get_backend(const char *sub_name)
{
struct se_subsystem_api *s;
mutex_lock(&subsystem_mutex);
list_for_each_entry(s, &subsystem_list, sub_api_list) {
if (!strcmp(s->name, sub_name))
goto found;
}
mutex_unlock(&subsystem_mutex);
return NULL;
found:
if (s->owner && !try_module_get(s->owner))
s = NULL;
mutex_unlock(&subsystem_mutex);
return s;
}
struct se_hba *
core_alloc_hba(const char *plugin_name, u32 plugin_dep_id, u32 hba_flags)
{
struct se_hba *hba;
int ret = 0;
hba = kzalloc(sizeof(*hba), GFP_KERNEL);
if (!hba) {
printk(KERN_ERR "Unable to allocate struct se_hba\n");
return ERR_PTR(-ENOMEM);
}
INIT_LIST_HEAD(&hba->hba_dev_list);
spin_lock_init(&hba->device_lock);
spin_lock_init(&hba->hba_queue_lock);
mutex_init(&hba->hba_access_mutex);
hba->hba_index = scsi_get_new_index(SCSI_INST_INDEX);
hba->hba_flags |= hba_flags;
atomic_set(&hba->max_queue_depth, 0);
atomic_set(&hba->left_queue_depth, 0);
hba->transport = core_get_backend(plugin_name);
if (!hba->transport) {
ret = -EINVAL;
goto out_free_hba;
}
ret = hba->transport->attach_hba(hba, plugin_dep_id);
if (ret < 0)
goto out_module_put;
spin_lock(&se_global->hba_lock);
hba->hba_id = se_global->g_hba_id_counter++;
list_add_tail(&hba->hba_list, &se_global->g_hba_list);
spin_unlock(&se_global->hba_lock);
printk(KERN_INFO "CORE_HBA[%d] - Attached HBA to Generic Target"
" Core\n", hba->hba_id);
return hba;
out_module_put:
if (hba->transport->owner)
module_put(hba->transport->owner);
hba->transport = NULL;
out_free_hba:
kfree(hba);
return ERR_PTR(ret);
}
int
core_delete_hba(struct se_hba *hba)
{
struct se_device *dev, *dev_tmp;
spin_lock(&hba->device_lock);
list_for_each_entry_safe(dev, dev_tmp, &hba->hba_dev_list, dev_list) {
se_clear_dev_ports(dev);
spin_unlock(&hba->device_lock);
se_release_device_for_hba(dev);
spin_lock(&hba->device_lock);
}
spin_unlock(&hba->device_lock);
hba->transport->detach_hba(hba);
spin_lock(&se_global->hba_lock);
list_del(&hba->hba_list);
spin_unlock(&se_global->hba_lock);
printk(KERN_INFO "CORE_HBA[%d] - Detached HBA from Generic Target"
" Core\n", hba->hba_id);
if (hba->transport->owner)
module_put(hba->transport->owner);
hba->transport = NULL;
kfree(hba);
return 0;
}
#ifndef TARGET_CORE_HBA_H
#define TARGET_CORE_HBA_H
extern struct se_hba *core_alloc_hba(const char *, u32, u32);
extern int core_delete_hba(struct se_hba *);
#endif /* TARGET_CORE_HBA_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#ifndef TARGET_CORE_SCDB_H
#define TARGET_CORE_SCDB_H
extern void split_cdb_XX_6(unsigned long long, u32 *, unsigned char *);
extern void split_cdb_XX_10(unsigned long long, u32 *, unsigned char *);
extern void split_cdb_XX_12(unsigned long long, u32 *, unsigned char *);
extern void split_cdb_XX_16(unsigned long long, u32 *, unsigned char *);
extern void split_cdb_XX_32(unsigned long long, u32 *, unsigned char *);
#endif /* TARGET_CORE_SCDB_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment