- Dev handler sysfs interface changed to match new unified rules

- Docs updated
 - Other minor fixes, improvements and cleanups



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1538 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2010-03-09 19:36:48 +00:00
parent 157a65737c
commit 256b25cc0f
25 changed files with 3283 additions and 1321 deletions
+86 -53
View File
@@ -31,7 +31,7 @@ See HOWTOs in the doc/ subdirectory.
Only vanilla kernels from kernel.org and RHEL/CentOS 5.2 kernels are
supported, but it should work on other (vendors') kernels, if you manage
to successfully compile on them. The main problem with vendor's kernels
is that they often contain patches, which will appear only in the next
is that they often contain patches, which appear only in the next
version of the vanilla kernel, therefore it's quite hard to track such
changes. Thus, if during compilation for some vendor's kernel your
compiler complains about redefinition of some symbol, you should either
@@ -87,7 +87,7 @@ functionality, which put_page_callback patch provides. For example,
Fedora or Gentoo use kernels, which, although have version number like
2.6.18, are greatly differ from the "vanilla" kernel 2.6.18,
maintained by Linus Torvalds for that the put_page_callback patch was
created. In this case I would recommend you either:
created. In this case it is recommended either:
- Search net/ in your kernel source for "put_page" and "get_page" functions.
If you find any in some place, except in net/sunrpc/svc.c and
@@ -108,14 +108,11 @@ Usage
See HOWTOs in the doc/ subdirectory.
In 2.0.0 usage of iscsi-scstd.conf as well as iscsi-scst-adm is
In 2.0.0 usage of iscsi-scstd.conf as well as iscsi-scst-adm utility is
obsolete. Use the sysfs interface facilities instead.
It is recommended to use TEST UNIT READY ("tur") command to check if
iSCSI-SCST target is alive.
IMPORTANT: In the procfs build all LUN information (access control)
========= MUST be configured BEFORE iscsi-scstd started!
iSCSI-SCST target is alive in MPIO configurations.
Also see SCST README file how to tune for the best performance.
@@ -128,8 +125,9 @@ Sysfs interface
Starting from 2.0.0 iSCSI-SCST has sysfs interface. You can switch to it
by running "make disable_proc". To switch back to the procfs interface
you should run "make enable_proc". The procfs interface from version
2.0.0 is obsolete and will be removed in one of the next versions.
you should run "make enable_proc". The procfs interface starting from
version 2.0.0 is obsolete and will be removed in one of the next
versions.
Root of SCST sysfs interface is /sys/kernel/scst_tgt. Root of iSCSI-SCST
is /sys/kernel/scst_tgt/targets/iscsi. It has the following entries:
@@ -168,9 +166,9 @@ is /sys/kernel/scst_tgt/targets/iscsi. It has the following entries:
per-target attributes. See content of this file for help how to use
it.
Each iSCSI-SCST attribute can contain in the last line mark "[key]". It
is automatically added mark used to allow scstadmin to see which
attributes it should save in the config file. You can ignore it.
Each iSCSI-SCST sysfs file (attribute) can contain in the last line mark
"[key]". It is automatically added mark used to allow scstadmin to see
which attributes it should save in the config file. You can ignore it.
Each target subdirectory contains the following entries:
@@ -192,16 +190,40 @@ Each target subdirectory contains the following entries:
the "mgmt" entry, see above.
- Entries defining default iSCSI parameters values used during iSCSI
parameters negotiation.
parameters negotiation. Only entries which can be changed or make
sense are listed there.
- QueuedCommands - defines maximum number of commands queued to any
session of this target.
session of this target. Default is 32 commands.
- RspTimeout - defines the maximum time in seconds a command can wait for
response from initiator, otherwise the corresponding connection will
be closed. For performance reasons it is implemented as a timer,
which once in RspTimeout time checks the oldest command waiting for
response and, if it's older than RspTimeout, then it closes the
connection. Hence, a stalled connection will be closed in time
between RspTimeout and 2*RspTimeout. Default is 30 seconds.
- NopInInterval - defines interval between NOP-In requests, which the
target will send on idle connections to check if the initiator is
still alive. If there is no NOP-Out reply from the initiator in
RspTimeout time, the corresponding connection will be closed. Default
is 30 seconds. If it's set to 0, then NOP-In requests are disabled.
- enabled - using this attribute you can enable or disable iSCSI-SCST
accept new connections to this target. It allows to finish
configuring it before it starts accepting new connections. 0 by
default.
- rel_tgt_id - allows to read or write SCSI Relative Target Port
Identifier attribute. This identifier is used to identify SCSI Target
Ports by some SCSI commands, mainly by Persistent Reservations
commands. This identifier must be unique among all SCST targets, but
for convenience SCST allows disabled targets to have not unique
rel_tgt_id. In this case SCST will not allow to enable this target
until rel_tgt_id becomes unique. This attribute initialized unique by
SCST by default.
- tid - TID of this target.
Subdirectory "sessions" contains one subdirectory for each connected
@@ -213,7 +235,8 @@ Each session subdirectory contains the following entries:
supports 1 connection per session, but the session subdirectory can
contain several connections: one active and other being closed.
- Entries defining negotiated iSCSI parameters.
- Entries defining negotiated iSCSI parameters. Only parameters which
can be changed or make sense are listed there.
- initiator_name - contains initiator name
@@ -246,18 +269,16 @@ parameters:
modprobe scst
modprobe scst_vdisk
echo "open disk1 /disk1 NV_CACHE" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
service iscsi-scst start
echo "add_target iqn.2006-10.net.vlnb:tgt" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
echo 1 >/sys/kernel/scst_tgt/targets/iscsi/enabled
Below is more advanced sample script, which configures more virtual
devices of various types, including virtual CDROM and 2 targets, one
with all default parameters, another one with some not default
@@ -271,11 +292,11 @@ authentication for discovery sessions and iSNS server with access control.
modprobe scst
modprobe scst_vdisk
echo "open disk1 /disk1 NV_CACHE" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "open disk2 /disk2 4096 NV_CACHE" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "open blockio /dev/sda5" >/sys/kernel/scst_tgt/handlers/vdisk_blockio/mgmt
echo "open nullio none" >/sys/kernel/scst_tgt/handlers/vdisk_nullio/mgmt
echo "open cdrom" >/sys/kernel/scst_tgt/handlers/vcdrom/mgmt
echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "add_device disk2 filename=/disk2; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "add_device blockio filename=/dev/sda5" >/sys/kernel/scst_tgt/handlers/vdisk_blockio/mgmt
echo "add_device nullio" >/sys/kernel/scst_tgt/handlers/vdisk_nullio/mgmt
echo "add_device cdrom" >/sys/kernel/scst_tgt/handlers/vcdrom/mgmt
service iscsi-scst start
@@ -288,27 +309,26 @@ echo "add_target iqn.2006-10.net.vlnb:tgt" >/sys/kernel/scst_tgt/targets/iscsi/m
echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
echo "add cdrom 1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
echo "add_target iqn.2006-10.net.vlnb:tgt1 \
IncomingUser1 joe2 12charsecret2; \
IncomingUser joe 12charsecret; \
OutgoingUser jim1 12charpasswd; \
InitialR2T No; \
ImmediateData Yes; \
MaxRecvDataSegmentLength 8192; \
MaxXmitDataSegmentLength 8192; \
MaxBurstLength 131072; \
FirstBurstLength 32768; \
MaxOutstandingR2T 1; \
HeaderDigest CRC32C,None; \
DataDigest CRC32C,None; \
QueuedCommands 8; \
" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
echo "add_target iqn.2006-10.net.vlnb:tgt1" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
echo "add_target_attribute iqn.2006-10.net.vlnb:tgt1 IncomingUser1 joe2 12charsecret2" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
echo "add_target_attribute iqn.2006-10.net.vlnb:tgt1 IncomingUser joe 12charsecret" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
echo "add_target_attribute iqn.2006-10.net.vlnb:tgt1 OutgoingUser jim1 12charpasswd" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
echo "No" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/InitialR2T
echo "Yes" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ImmediateData
echo "8192" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxRecvDataSegmentLength
echo "8192" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxXmitDataSegmentLength
echo "131072" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxBurstLength
echo "32768" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/FirstBurstLength
echo "1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxOutstandingR2T
echo "CRC32C,None" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/HeaderDigest
echo "CRC32C,None" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/DataDigest
echo "32" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/QueuedCommands
echo "add disk2 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/mgmt
echo "add nullio 26" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/mgmt
echo "create special_ini" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/mgmt
echo "add blockio 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/special_ini/luns/mgmt
echo "add blockio 0 read_only=1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/special_ini/luns/mgmt
echo "add iqn.2005-03.org.open-iscsi:cacdcd2520" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/special_ini/initiators/mgmt
echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
@@ -322,7 +342,7 @@ both iSCSI-SCST targets will look like:
/sys/kernel/scst_tgt
|-- devices
| |-- blockio
| | |-- block_size
| | |-- blocksize
| | |-- exported
| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/special_ini/luns/0
| | |-- filename
@@ -330,20 +350,21 @@ both iSCSI-SCST targets will look like:
| | |-- read_only
| | |-- removable
| | |-- resync_size
| | |-- size
| | |-- size_mb
| | |-- t10_dev_id
| | `-- type
| | |-- type
| | `-- usn
| |-- cdrom
| | |-- exported
| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/1
| | |-- filename
| | |-- handler -> ../../handlers/vcdrom
| | |-- removable
| | |-- size
| | |-- size_mb
| | |-- t10_dev_id
| | `-- type
| | |-- type
| | `-- usn
| |-- disk1
| | |-- block_size
| | |-- blocksize
| | |-- exported
| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/0
| | |-- filename
@@ -353,12 +374,13 @@ both iSCSI-SCST targets will look like:
| | |-- read_only
| | |-- removable
| | |-- resync_size
| | |-- size
| | |-- size_mb
| | |-- t10_dev_id
| | |-- type
| | |-- usn
| | `-- write_through
| |-- disk2
| | |-- block_size
| | |-- blocksize
| | |-- exported
| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/0
| | |-- filename
@@ -368,35 +390,42 @@ both iSCSI-SCST targets will look like:
| | |-- read_only
| | |-- removable
| | |-- resync_size
| | |-- size
| | |-- size_mb
| | |-- t10_dev_id
| | |-- type
| | |-- usn
| | `-- write_through
| `-- nullio
| |-- block_size
| |-- blocksize
| |-- exported
| | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/26
| |-- handler -> ../../handlers/vdisk_nullio
| |-- read_only
| |-- removable
| |-- size
| |-- size_mb
| |-- t10_dev_id
| `-- type
| |-- type
| `-- usn
|-- handlers
| |-- vcdrom
| | |-- cdrom -> ../../devices/cdrom
| | |-- mgmt
| | |-- trace_level
| | `-- type
| |-- vdisk_blockio
| | |-- blockio -> ../../devices/blockio
| | |-- mgmt
| | |-- trace_level
| | `-- type
| |-- vdisk_fileio
| | |-- disk1 -> ../../devices/disk1
| | |-- disk2 -> ../../devices/disk2
| | |-- mgmt
| | |-- trace_level
| | `-- type
| `-- vdisk_nullio
| |-- mgmt
| |-- nullio -> ../../devices/nullio
| |-- trace_level
| `-- type
|-- sgv
@@ -435,6 +464,7 @@ both iSCSI-SCST targets will look like:
| | | | |-- device -> ../../../../../devices/cdrom
| | | | `-- read_only
| | | `-- mgmt
| | |-- rel_tgt_id
| | |-- sessions
| | | `-- iqn.2005-03.org.open-iscsi:cacdcd2520
| | | |-- 10.170.75.2
@@ -454,6 +484,7 @@ both iSCSI-SCST targets will look like:
| | | |-- commands
| | | |-- force_close
| | | |-- initiator_name
| | | |-- luns -> ../../luns
| | | |-- reinstating
| | | `-- sid
| | `-- tid
@@ -491,6 +522,7 @@ both iSCSI-SCST targets will look like:
| | | | |-- device -> ../../../../../devices/nullio
| | | | `-- read_only
| | | `-- mgmt
| | |-- rel_tgt_id
| | |-- sessions
| | | `-- iqn.2005-03.org.open-iscsi:cacdcd2520
| | | |-- 10.170.75.2
@@ -510,6 +542,7 @@ both iSCSI-SCST targets will look like:
| | | |-- commands
| | | |-- force_close
| | | |-- initiator_name
| | | |-- luns -> ../../ini_group/special_ini/luns
| | | |-- reinstating
| | | `-- sid
| | `-- tid
@@ -568,7 +601,7 @@ http://virtualgeek.typepad.com/virtual_geek/2009/01/a-multivendor-post-to-help-o
It's about VMware, but its recommendations apply to other environments
as well.
3. ISCSI initiators built in pre-CentOS/RHEL 5 reported to have some
3. ISCSI initiators from pre-CentOS/RHEL 5 reported to have some
performance problems. If you use it, it is strongly advised to upgrade.
+80 -45
View File
@@ -17,11 +17,11 @@ Usage
See in http://scst.sourceforge.net/iscsi-scst-howto.txt how to configure
iSCSI-SCST.
In 2.0.0 usage of iscsi-scstd.conf as well as iscsi-scst-adm is
In 2.0.0 usage of iscsi-scstd.conf as well as iscsi-scst-adm utility is
obsolete. Use the sysfs interface facilities instead.
It is recommended to use TEST UNIT READY ("tur") command to check if
iSCSI-SCST target is alive.
iSCSI-SCST target is alive in MPIO configurations.
IMPORTANT: In the procfs build all LUN information (access control)
========= MUST be configured BEFORE iscsi-scstd started!
@@ -77,9 +77,9 @@ is /sys/kernel/scst_tgt/targets/iscsi. It has the following entries:
per-target attributes. See content of this file for help how to use
it.
Each iSCSI-SCST attribute can contain in the last line mark "[key]". It
is automatically added mark used to allow scstadmin to see which
attributes it should save in the config file. You can ignore it.
Each iSCSI-SCST sysfs file (attribute) can contain in the last line mark
"[key]". It is automatically added mark used to allow scstadmin to see
which attributes it should save in the config file. You can ignore it.
Each target subdirectory contains the following entries:
@@ -101,16 +101,40 @@ Each target subdirectory contains the following entries:
the "mgmt" entry, see above.
- Entries defining default iSCSI parameters values used during iSCSI
parameters negotiation.
parameters negotiation. Only entries which can be changed or make
sense are listed there.
- QueuedCommands - defines maximum number of commands queued to any
session of this target.
session of this target. Default is 32 commands.
- RspTimeout - defines the maximum time in seconds a command can wait for
response from initiator, otherwise the corresponding connection will
be closed. For performance reasons it is implemented as a timer,
which once in RspTimeout time checks the oldest command waiting for
response and, if it's older than RspTimeout, then it closes the
connection. Hence, a stalled connection will be closed in time
between RspTimeout and 2*RspTimeout. Default is 30 seconds.
- NopInInterval - defines interval between NOP-In requests, which the
target will send on idle connections to check if the initiator is
still alive. If there is no NOP-Out reply from the initiator in
RspTimeout time, the corresponding connection will be closed. Default
is 30 seconds. If it's set to 0, then NOP-In requests are disabled.
- enabled - using this attribute you can enable or disable iSCSI-SCST
accept new connections to this target. It allows to finish
configuring it before it starts accepting new connections. 0 by
default.
- rel_tgt_id - allows to read or write SCSI Relative Target Port
Identifier attribute. This identifier is used to identify SCSI Target
Ports by some SCSI commands, mainly by Persistent Reservations
commands. This identifier must be unique among all SCST targets, but
for convenience SCST allows disabled targets to have not unique
rel_tgt_id. In this case SCST will not allow to enable this target
until rel_tgt_id becomes unique. This attribute initialized unique by
SCST by default.
- tid - TID of this target.
Subdirectory "sessions" contains one subdirectory for each connected
@@ -122,7 +146,8 @@ Each session subdirectory contains the following entries:
supports 1 connection per session, but the session subdirectory can
contain several connections: one active and other being closed.
- Entries defining negotiated iSCSI parameters.
- Entries defining negotiated iSCSI parameters. Only parameters which
can be changed or make sense are listed there.
- initiator_name - contains initiator name
@@ -155,18 +180,16 @@ parameters:
modprobe scst
modprobe scst_vdisk
echo "open disk1 /disk1 NV_CACHE" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
service iscsi-scst start
echo "add_target iqn.2006-10.net.vlnb:tgt" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
echo 1 >/sys/kernel/scst_tgt/targets/iscsi/enabled
Below is more advanced sample script, which configures more virtual
devices of various types, including virtual CDROM and 2 targets, one
with all default parameters, another one with some not default
@@ -180,11 +203,11 @@ authentication for discovery sessions and iSNS server with access control.
modprobe scst
modprobe scst_vdisk
echo "open disk1 /disk1 NV_CACHE" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "open disk2 /disk2 4096 NV_CACHE" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "open blockio /dev/sda5" >/sys/kernel/scst_tgt/handlers/vdisk_blockio/mgmt
echo "open nullio none" >/sys/kernel/scst_tgt/handlers/vdisk_nullio/mgmt
echo "open cdrom" >/sys/kernel/scst_tgt/handlers/vcdrom/mgmt
echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "add_device disk2 filename=/disk2; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "add_device blockio filename=/dev/sda5" >/sys/kernel/scst_tgt/handlers/vdisk_blockio/mgmt
echo "add_device nullio" >/sys/kernel/scst_tgt/handlers/vdisk_nullio/mgmt
echo "add_device cdrom" >/sys/kernel/scst_tgt/handlers/vcdrom/mgmt
service iscsi-scst start
@@ -197,27 +220,26 @@ echo "add_target iqn.2006-10.net.vlnb:tgt" >/sys/kernel/scst_tgt/targets/iscsi/m
echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
echo "add cdrom 1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
echo "add_target iqn.2006-10.net.vlnb:tgt1 \
IncomingUser1 joe2 12charsecret2; \
IncomingUser joe 12charsecret; \
OutgoingUser jim1 12charpasswd; \
InitialR2T No; \
ImmediateData Yes; \
MaxRecvDataSegmentLength 8192; \
MaxXmitDataSegmentLength 8192; \
MaxBurstLength 131072; \
FirstBurstLength 32768; \
MaxOutstandingR2T 1; \
HeaderDigest CRC32C,None; \
DataDigest CRC32C,None; \
QueuedCommands 8; \
" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
echo "add_target iqn.2006-10.net.vlnb:tgt1" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
echo "add_target_attribute iqn.2006-10.net.vlnb:tgt1 IncomingUser1 joe2 12charsecret2" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
echo "add_target_attribute iqn.2006-10.net.vlnb:tgt1 IncomingUser joe 12charsecret" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
echo "add_target_attribute iqn.2006-10.net.vlnb:tgt1 OutgoingUser jim1 12charpasswd" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
echo "No" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/InitialR2T
echo "Yes" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ImmediateData
echo "8192" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxRecvDataSegmentLength
echo "8192" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxXmitDataSegmentLength
echo "131072" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxBurstLength
echo "32768" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/FirstBurstLength
echo "1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxOutstandingR2T
echo "CRC32C,None" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/HeaderDigest
echo "CRC32C,None" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/DataDigest
echo "32" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/QueuedCommands
echo "add disk2 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/mgmt
echo "add nullio 26" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/mgmt
echo "create special_ini" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/mgmt
echo "add blockio 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/special_ini/luns/mgmt
echo "add blockio 0 read_only=1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/special_ini/luns/mgmt
echo "add iqn.2005-03.org.open-iscsi:cacdcd2520" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/special_ini/initiators/mgmt
echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
@@ -231,7 +253,7 @@ both iSCSI-SCST targets will look like:
/sys/kernel/scst_tgt
|-- devices
| |-- blockio
| | |-- block_size
| | |-- blocksize
| | |-- exported
| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/special_ini/luns/0
| | |-- filename
@@ -239,20 +261,21 @@ both iSCSI-SCST targets will look like:
| | |-- read_only
| | |-- removable
| | |-- resync_size
| | |-- size
| | |-- size_mb
| | |-- t10_dev_id
| | `-- type
| | |-- type
| | `-- usn
| |-- cdrom
| | |-- exported
| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/1
| | |-- filename
| | |-- handler -> ../../handlers/vcdrom
| | |-- removable
| | |-- size
| | |-- size_mb
| | |-- t10_dev_id
| | `-- type
| | |-- type
| | `-- usn
| |-- disk1
| | |-- block_size
| | |-- blocksize
| | |-- exported
| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/0
| | |-- filename
@@ -262,12 +285,13 @@ both iSCSI-SCST targets will look like:
| | |-- read_only
| | |-- removable
| | |-- resync_size
| | |-- size
| | |-- size_mb
| | |-- t10_dev_id
| | |-- type
| | |-- usn
| | `-- write_through
| |-- disk2
| | |-- block_size
| | |-- blocksize
| | |-- exported
| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/0
| | |-- filename
@@ -277,35 +301,42 @@ both iSCSI-SCST targets will look like:
| | |-- read_only
| | |-- removable
| | |-- resync_size
| | |-- size
| | |-- size_mb
| | |-- t10_dev_id
| | |-- type
| | |-- usn
| | `-- write_through
| `-- nullio
| |-- block_size
| |-- blocksize
| |-- exported
| | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/26
| |-- handler -> ../../handlers/vdisk_nullio
| |-- read_only
| |-- removable
| |-- size
| |-- size_mb
| |-- t10_dev_id
| `-- type
| |-- type
| `-- usn
|-- handlers
| |-- vcdrom
| | |-- cdrom -> ../../devices/cdrom
| | |-- mgmt
| | |-- trace_level
| | `-- type
| |-- vdisk_blockio
| | |-- blockio -> ../../devices/blockio
| | |-- mgmt
| | |-- trace_level
| | `-- type
| |-- vdisk_fileio
| | |-- disk1 -> ../../devices/disk1
| | |-- disk2 -> ../../devices/disk2
| | |-- mgmt
| | |-- trace_level
| | `-- type
| `-- vdisk_nullio
| |-- mgmt
| |-- nullio -> ../../devices/nullio
| |-- trace_level
| `-- type
|-- sgv
@@ -344,6 +375,7 @@ both iSCSI-SCST targets will look like:
| | | | |-- device -> ../../../../../devices/cdrom
| | | | `-- read_only
| | | `-- mgmt
| | |-- rel_tgt_id
| | |-- sessions
| | | `-- iqn.2005-03.org.open-iscsi:cacdcd2520
| | | |-- 10.170.75.2
@@ -363,6 +395,7 @@ both iSCSI-SCST targets will look like:
| | | |-- commands
| | | |-- force_close
| | | |-- initiator_name
| | | |-- luns -> ../../luns
| | | |-- reinstating
| | | `-- sid
| | `-- tid
@@ -400,6 +433,7 @@ both iSCSI-SCST targets will look like:
| | | | |-- device -> ../../../../../devices/nullio
| | | | `-- read_only
| | | `-- mgmt
| | |-- rel_tgt_id
| | |-- sessions
| | | `-- iqn.2005-03.org.open-iscsi:cacdcd2520
| | | |-- 10.170.75.2
@@ -419,6 +453,7 @@ both iSCSI-SCST targets will look like:
| | | |-- commands
| | | |-- force_close
| | | |-- initiator_name
| | | |-- luns -> ../../ini_group/special_ini/luns
| | | |-- reinstating
| | | `-- sid
| | `-- tid
+161 -3
View File
@@ -1,5 +1,5 @@
Installing and using iSCSI-SCST with scstadmin
----------------------------------------------
==============================================
1. Download, build and install iSCSI-SCST.
@@ -121,8 +121,8 @@ the following commands:
/etc/init.d/iscsi-scst start
Installing and using iSCSI-SCST without using scstadmin
-------------------------------------------------------
Installing and using iSCSI-SCST without using scstadmin via /proc interface
===========================================================================
First repeat steps 1, 2 and 3 from the previous section but leave out
"scstadm scstadm_install" from the make command in step 1.
@@ -287,6 +287,164 @@ OFMarkInt=Reject
IFMarkInt=Reject
Installing and using iSCSI-SCST without using scstadmin via /sys interface
==========================================================================
First repeat steps 1, 2 and 3 from the first section but leave out
"scstadm scstadm_install" from the make command in step 1.
Next load the scst_disk and scst_vdisk kernel modules as follows:
modprobe scst_disk
modprobe scst_vdisk
The shell script /etc/init.d/iscsi-scst can now be used to start/stop/restart or
check the status of iSCSI-SCST.
Creating targets
----------------
echo "add_target iqn.2007-05.com.example:storage.iscsi-scst-1" > /sys/kernel/scst_tgt/targets/iscsi/mgmt
This will add target iqn.2007-05.com.example:storage.iscsi-scst-1.
Changing targets' parameters
----------------------------
echo "8192" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example\:storage.iscsi-scst-1/MaxRecvDataSegmentLength
This will change MaxRecvDataSegmentLength parameter of target
iqn.2007-05.com.example:storage.iscsi-scst-1 to 8192.
You can read it then by:
# cat /sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example\:storage.iscsi-scst-1/MaxRecvDataSegmentLength
8192
[key]
The mark "[key]" shows high level management tools, like scstadmin, that
this attribute has not default value. You can ignore it.
Add vdisk devices
-----------------
dd if=/dev/zero of=/disk1 bs=1M count=1024
This will create a backend file /disk1 for our future virtual device
disk1.
echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
This will add new FILEIO device disk1 with backend file /disk1 and
NV_CACHE option enabled.
Selecting devices to be used by SCST
------------------------------------
You can see the list of available devices:
# ls -1 /sys/kernel/scst_tgt/devices
0:0:0:0
1:0:0:0
3:0:0:0
3:0:0:1
3:0:0:2
3:0:0:3
3:0:0:4
3:0:0:5
3:0:0:6
3:0:0:7
2:0:0:0
4:0:0:0
4:0:0:5
4:0:0:6
4:0:0:7
4:0:0:8
4:0:0:9
4:0:1:0
4:0:1:1
4:0:1:2
4:0:1:3
4:0:1:4
5:0:0:0
5:0:0:5
5:0:0:6
5:0:0:7
5:0:0:8
5:0:0:9
5:0:1:0
5:0:1:1
5:0:1:2
5:0:1:3
5:0:1:4
disk1
Defining LUN masking
--------------------
In order to associate specific LUNs with target
iqn.2007-05.com.example:storage.iscsi-scst-1, do the following:
echo "add 4:0:0:8 0" > /sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example\:storage.iscsi-scst-1/luns/mgmt
This will assign the LUN 0 for pass-through device 4:0:0:8 to the target
iqn.2007-05.com.example:storage.iscsi-scst-1.
Note, you must have LUN 0 for each group. That's a SCSI requirement
(documented in SCST's README).
echo "add disk1 1 read_only=1" > /sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example\:storage.iscsi-scst-1/luns/mgmt
This will assign the read only LUN 1 for virtual device disk1 to the
target iqn.2007-05.com.example:storage.iscsi-scst-1.
Deleting a LUN from a group
---------------------------
Run the following command:
echo "del disk1" > /sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example\:storage.iscsi-scst-1/luns/mgmt
This will remove the LUN "disk1" from the target iqn.2007-05.com.example:storage.iscsi-scst-1.
For more information about LUN masking, refer to SCST README, section
"Access and devices visibility management (LUN masking)".
Enabling targets
----------------
After you created and configured target, you should enable it:
echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example\:storage.iscsi-scst-1/enabled
Then enable the iSCSI-SCST driver:
echo 1 >/sys/kernel/scst_tgt/targets/iscsi/enabled
Assigning targets to specific initiators
----------------------------------------
In order to assign targets to specific initiators, you need to have
/etc/initiators.allow and /etc/initiators.deny. You can find
example files in etc/initiators.allow and etc/initiators.deny.
Note that all targets are allowed to all initiators by default, so if
you want to use /etc/initiators.allow, you will need to have
/etc/initiators.deny that looks like this:
ALL ALL
This will deny all initiators expect for those defined in /etc/initiators.allow.
Bart Van Assche
Erez Zilber
Vladislav Bolkhovitin
+2 -3
View File
@@ -534,10 +534,9 @@ extern ssize_t iscsi_sysfs_send_event(uint32_t tid,
extern struct iscsi_target *target_lookup_by_id(u32);
extern int __add_target(struct iscsi_kern_target_info *);
extern int __del_target(u32 id);
extern ssize_t iscsi_sysfs_add_target(const char *target_name,
const char *params);
extern ssize_t iscsi_sysfs_add_target(const char *target_name, char *params);
extern ssize_t iscsi_sysfs_del_target(const char *target_name);
extern ssize_t iscsi_sysfs_mgmt_cmd(const char *cmd);
extern ssize_t iscsi_sysfs_mgmt_cmd(char *cmd);
extern void target_del_session(struct iscsi_target *target,
struct iscsi_session *session, int flags);
extern void target_del_all_sess(struct iscsi_target *target, int flags);
+2 -2
View File
@@ -547,7 +547,7 @@ bool iscsi_is_target_enabled(struct scst_tgt *scst_tgt)
return tgt->tgt_enabled;
}
ssize_t iscsi_sysfs_add_target(const char *target_name, const char *params)
ssize_t iscsi_sysfs_add_target(const char *target_name, char *params)
{
int res;
@@ -594,7 +594,7 @@ out:
return res;
}
ssize_t iscsi_sysfs_mgmt_cmd(const char *cmd)
ssize_t iscsi_sysfs_mgmt_cmd(char *cmd)
{
int res;
+2 -2
View File
@@ -642,7 +642,7 @@ static int initiator_match(u32 tid, int fd, char *filename)
p = buf;
while (!isblank(*p) && (*p != '\0'))
p++;
if (p == '\0')
if (*p == '\0')
continue;
*p = '\0';
@@ -830,7 +830,7 @@ int config_parse_main(const char *data, u32 cookie)
target = NULL;
p = config_sep_string(&q);
if (p == '\0') {
if (*p == '\0') {
log_error("Target name required on %s\n", q);
continue;
}
+1 -1
View File
@@ -330,7 +330,7 @@ static int handle_e_mgmt_cmd(int fd, const struct iscsi_kern_event *event)
}
res = handle_del_param(target, p, event->cookie);
} else {
log_error("Syntax error at %s", p);
log_error("Syntax error at %s", pp);
res = -EINVAL;
}
+272 -9
View File
@@ -17,7 +17,7 @@ Linux kernel 2.6.26 and higher. Sorry, kernels below 2.6.26 are not
supported, because it's too hard to backport used initiator driver to
older kernels.
NPIV is particulary supported by this driver. You can create virtual
NPIV is partially supported by this driver. You can create virtual
targets using standard Linux interface by echoing wwpn:wwnn into
/sys/class/fc_host/hostX/vport_create and work with them, but SCST core
will not see those virtual targets and, hence, provide the
@@ -80,16 +80,22 @@ subdirectory. The target driver will be installed in
uninstall'.
After the drivers are loaded and adapters successfully initialized by
the initiator driver, including firmware image load, the target mode
should be enabled via a sysfs interface on a per card basis. Under the
appropriate scsi_host there is an entry target_mode_enabled, where you
should write "1", like:
the initiator driver, including firmware image load, you should
configure exported devices using the corresponding interface of SCST
core. It is highly recommended to use scstadmin utility for that
purpose.
Then target mode should be enabled via a sysfs interface on a per card
basis. Under the appropriate scsi_host there is an entry
target_mode_enabled, where you should write "1", like:
echo "1" >/sys/class/scsi_host/host0/target_mode_enabled
Then you should configure exported devices using the corresponding
interface of SCST core. It is highly recommended to use scstadmin
utility for that purpose.
For the sysfs build you should instead
echo "1" >/sys/kernel/scst_tgt/targets/qla2x00t/target/enabled
See below for full description of the driver's sysfs interface.
You can find some installation and configuration HOWTOs in
http://scst.sourceforge.net/qla2x00t-howto.html and
@@ -113,6 +119,9 @@ this feature, it is reported in the kernel logs ("confirmed completion
supported" or not). No major performance degradation was noticed, if it
is enabled. Supported only for 23xx+. Disabled by default.
In the sysfs build it is moved in /sys/kernel/scst_tgt/targets/qla2x00t/target/
subdirectory, see the sysfs interface description below.
Class 2
-------
@@ -148,6 +157,260 @@ in/out in Makefile:
initiator to issue a retransmit request.
Sysfs interface
---------------
Starting from 2.0.0 this driver has sysfs interface. You can switch to
it by running "make disable_proc". To switch back to the procfs
interface you should run "make enable_proc". The procfs interface from
version 2.0.0 is obsolete and will be removed in one of the next
versions.
Root of SCST sysfs interface is /sys/kernel/scst_tgt. Root of this
driver is /sys/kernel/scst_tgt/targets/qla2x00t. It has the following
entries:
- None, one or more subdirectories for targets with name equal to port
names of the corresponding targets.
- trace_level - allows to enable and disable various tracing
facilities. See content of this file for help how to use it.
- version - read-only attribute, which allows to see version of
this driver and enabled optional features.
Each target subdirectory contains the following entries:
- host - link pointing on the corresponding scsi_host of the initiator
driver
- ini_group - subdirectory defining initiator groups for this target,
used to define per-initiator access control. See SCST core README for
more details.
- luns - subdirectory defining LUNs of this target. See SCST core
README for more details.
- sessions - subdirectory containing connected to this target sessions.
- enabled - using this attribute you can enable or disable target mode
of this FC port. It allows to finish configuring it before it starts
accepting new connections. 0 by default.
- explicit_confirmation - allows to enable explicit conformations, see
above.
- rel_tgt_id - allows to read or write SCSI Relative Target Port
Identifier attribute. This identifier is used to identify SCSI Target
Ports by some SCSI commands, mainly by Persistent Reservations
commands. This identifier must be unique among all SCST targets, but
for convenience SCST allows disabled targets to have not unique
rel_tgt_id. In this case SCST will not allow to enable this target
until rel_tgt_id becomes unique. This attribute initialized unique by
SCST by default.
Subdirectory "sessions" contains one subdirectory for each connected
session with name equal to port name of the connected initiator.
Each session subdirectory contains the following entries:
- initiator_name - contains initiator's port name
- active_commands - contains number of active, i.e. not yet or being
executed, SCSI commands in this session.
- commands - contains overall number of SCSI commands in this session.
Below is a sample script, which configures 1 virtual disk "disk1" using
/disk1 image for usage with 25:00:00:f0:98:87:92:f3 target. All
initiators connected to this target will see this device.
#!/bin/bash
modprobe scst
modprobe scst_vdisk
echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
modprobe qla2x00tgt
echo "add disk1 0" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
echo 1 >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/enabled
Below is more advanced sample script, which configures more virtual
devices of various types, including virtual CDROM. In this script
initiator 25:00:00:f0:99:87:94:a3 will see disk1 and disk2 devices, all
other initiators will see read only blockio, nullio and cdrom devices.
#!/bin/bash
modprobe scst
modprobe scst_vdisk
echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "add_device disk2 filename=/disk2; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "add_device blockio filename=/dev/sda5" >/sys/kernel/scst_tgt/handlers/vdisk_blockio/mgmt
echo "add_device nullio" >/sys/kernel/scst_tgt/handlers/vdisk_nullio/mgmt
echo "add_device cdrom" >/sys/kernel/scst_tgt/handlers/vcdrom/mgmt
modprobe qla2x00tgt
echo "add blockio 0 read_only=1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
echo "add nullio 1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
echo "add cdrom 2" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
echo "create 25:00:00:f0:99:87:94:a3" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_group/mgmt
echo "add disk1 0" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_group/25:00:00:f0:99:87:94:a3/luns/mgmt
echo "add disk2 1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_group/25:00:00:f0:99:87:94:a3/luns/mgmt
echo "add 25:00:00:f0:99:87:94:a3" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_group/25:00:00:f0:99:87:94:a3/initiators/mgmt
echo 1 >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/enabled
The resulting overall SCST sysfs hierarchy with initiator
25:00:00:f0:99:87:94:a3 connected will look like:
/sys/kernel/scst_tgt
|-- devices
| |-- blockio
| | |-- blocksize
| | |-- exported
| | | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/0
| | |-- filename
| | |-- handler -> ../../handlers/vdisk_blockio
| | |-- read_only
| | |-- removable
| | |-- resync_size
| | |-- size_mb
| | |-- t10_dev_id
| | |-- type
| | `-- usn
| |-- cdrom
| | |-- exported
| | | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/2
| | |-- filename
| | |-- handler -> ../../handlers/vcdrom
| | |-- size_mb
| | |-- t10_dev_id
| | |-- type
| | `-- usn
| |-- disk1
| | |-- blocksize
| | |-- exported
| | | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_group/25:00:00:f0:99:87:94:a3/luns/0
| | |-- filename
| | |-- handler -> ../../handlers/vdisk_fileio
| | |-- nv_cache
| | |-- o_direct
| | |-- read_only
| | |-- removable
| | |-- resync_size
| | |-- size_mb
| | |-- t10_dev_id
| | |-- type
| | |-- usn
| | `-- write_through
| |-- disk2
| | |-- blocksize
| | |-- exported
| | | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_group/25:00:00:f0:99:87:94:a3/luns/1
| | |-- filename
| | |-- handler -> ../../handlers/vdisk_fileio
| | |-- nv_cache
| | |-- o_direct
| | |-- read_only
| | |-- removable
| | |-- resync_size
| | |-- size_mb
| | |-- t10_dev_id
| | |-- type
| | |-- usn
| | `-- write_through
| `-- nullio
| |-- blocksize
| |-- exported
| | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/1
| |-- handler -> ../../handlers/vdisk_nullio
| |-- read_only
| |-- removable
| |-- size_mb
| |-- t10_dev_id
| |-- type
| `-- usn
|-- handlers
| |-- vcdrom
| | |-- cdrom -> ../../devices/cdrom
| | |-- mgmt
| | |-- trace_level
| | `-- type
| |-- vdisk_blockio
| | |-- blockio -> ../../devices/blockio
| | |-- mgmt
| | |-- trace_level
| | `-- type
| |-- vdisk_fileio
| | |-- disk1 -> ../../devices/disk1
| | |-- disk2 -> ../../devices/disk2
| | |-- mgmt
| | |-- trace_level
| | `-- type
| `-- vdisk_nullio
| |-- mgmt
| |-- nullio -> ../../devices/nullio
| |-- trace_level
| `-- type
|-- sgv
| |-- global_stats
| |-- sgv
| | `-- stats
| |-- sgv-clust
| | `-- stats
| `-- sgv-dma
| `-- stats
|-- targets
| `-- qla2x00t
| |-- 25:00:00:f0:98:87:92:f3
| | |-- enabled
| | |-- explicit_confirmation
| | |-- host -> ../../../../../class/scsi_host/host4
| | |-- ini_group
| | | |-- 25:00:00:f0:99:87:94:a3
| | | | |-- initiators
| | | | | |-- 25:00:00:f0:99:87:94:a3
| | | | | `-- mgmt
| | | | `-- luns
| | | | |-- 0
| | | | | |-- device -> ../../../../../../../devices/disk1
| | | | | `-- read_only
| | | | |-- 1
| | | | | |-- device -> ../../../../../../../devices/disk2
| | | | | `-- read_only
| | | | `-- mgmt
| | | `-- mgmt
| | |-- luns
| | | |-- 0
| | | | |-- device -> ../../../../../devices/blockio
| | | | `-- read_only
| | | |-- 1
| | | | |-- device -> ../../../../../devices/nullio
| | | | `-- read_only
| | | |-- 2
| | | | |-- device -> ../../../../../devices/cdrom
| | | | `-- read_only
| | | `-- mgmt
| | |-- rel_tgt_id
| | `-- sessions
| | `-- 25:00:00:f0:99:87:94:a3
| | |-- active_commands
| | |-- commands
| | |-- initiator_name
| | `-- luns -> ../../ini_group/25:00:00:f0:99:87:94:a3/luns
| |-- trace_level
| `-- version
|-- threads
|-- trace_level
`-- version
Credits
-------
@@ -162,6 +425,6 @@ initiator driver.
WWN-based authentification, a lot of useful suggestions, bug reports and
help in debugging.
* Ming Zhang <mingz@ele.uri.edu> for his fixes.
* Ming Zhang <mingz@ele.uri.edu> for fixes.
Vladislav Bolkhovitin <vst@vlnb.net>, http://scst.sourceforge.net
+5 -2
View File
@@ -1,9 +1,13 @@
Known issues and unimplemented features
---------------------------------------
- Allow to set port and node names through sysfs.
- Complete NPIV support. Particularly, SCST core should see all the virtual
targets and provide separate target-oriented access control for them.
- Minor "ToDo"'s spread in the code.
- If a Linux initiator asks for devices using INQUIRY command too soon
before the controller on the 23xx target is fully initialized in the
target mode, the initiator could receive garbage devices and the
@@ -15,8 +19,7 @@ Known issues and unimplemented features
"unknown or no device type", but the SCSI mid-level treats such
devices as real and adds them to the system. To avoid it, try to
leave the target enough time for initialization (some 10th seconds).
- Minor "ToDo"'s spread in the code.
With the latest firmware that might be fixed.
- On 23xx if on a tape with block size 0 we write block with size X
and then read it with bs <X the tape skips all blocks with size X
+105 -101
View File
@@ -140,7 +140,11 @@ static unsigned long q2t_trace_flag = Q2T_DEFAULT_LOG_FLAGS;
#endif
static struct scst_tgt_template tgt2x_template = {
#ifdef CONFIG_SCST_PROC
.name = "qla2x00tgt",
#else
.name = "qla2x00t",
#endif
.sg_tablesize = 0,
.use_clustering = 1,
#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
@@ -256,7 +260,7 @@ static inline int q2t_issue_marker(scsi_qla_host_t *ha, int ha_locked)
if (unlikely(ha->marker_needed != 0)) {
int rc = qla2x00_issue_marker(ha, ha_locked);
if (rc != QLA_SUCCESS) {
PRINT_ERROR("qla2x00tgt(%ld): issue_marker() "
PRINT_ERROR("qla2x00t(%ld): issue_marker() "
"failed", ha->instance);
}
return rc;
@@ -364,7 +368,7 @@ static int q2t_unreg_sess(struct q2t_sess *sess)
if (sess->deleted)
list_del(&sess->del_list_entry);
PRINT_INFO("qla2x00tgt(%ld): %ssession for loop_id %d deleted",
PRINT_INFO("qla2x00t(%ld): %ssession for loop_id %d deleted",
sess->tgt->ha->instance, sess->local ? "local " : "",
sess->loop_id);
@@ -410,7 +414,7 @@ static int q2t_reset(scsi_qla_host_t *ha, void *iocb, int mcmd)
break;
default:
PRINT_ERROR("qla2x00tgt(%ld): Not allowed "
PRINT_ERROR("qla2x00t(%ld): Not allowed "
"command %x in %s", ha->instance,
mcmd, __func__);
sess = NULL;
@@ -476,7 +480,7 @@ static void q2t_alloc_session_done(struct scst_session *scst_sess,
scsi_qla_host_t *ha = tgt->ha;
unsigned long flags;
PRINT_INFO("qla2x00tgt(%ld): Session initialization failed",
PRINT_INFO("qla2x00t(%ld): Session initialization failed",
ha->instance);
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -576,7 +580,7 @@ static struct q2t_sess *q2t_create_sess(scsi_qla_host_t *ha, fc_port_t *fcport,
sess = kzalloc(sizeof(*sess), GFP_KERNEL);
if (sess == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): session allocation failed, "
PRINT_ERROR("qla2x00t(%ld): session allocation failed, "
"all commands from port %02x:%02x:%02x:%02x:"
"%02x:%02x:%02x:%02x will be refused", ha->instance,
fcport->port_name[0], fcport->port_name[1],
@@ -597,7 +601,7 @@ static struct q2t_sess *q2t_create_sess(scsi_qla_host_t *ha, fc_port_t *fcport,
wwn_str = kmalloc(wwn_str_len, GFP_KERNEL);
if (wwn_str == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): Allocation of wwn_str failed. "
PRINT_ERROR("qla2x00t(%ld): Allocation of wwn_str failed. "
"All commands from port %02x:%02x:%02x:%02x:%02x:%02x:"
"%02x:%02x will be refused", ha->instance,
fcport->port_name[0], fcport->port_name[1],
@@ -618,7 +622,7 @@ static struct q2t_sess *q2t_create_sess(scsi_qla_host_t *ha, fc_port_t *fcport,
sess, q2t_alloc_session_done);
if (sess->scst_sess == NULL) {
PRINT_CRIT_ERROR("qla2x00tgt(%ld): scst_register_session() "
PRINT_CRIT_ERROR("qla2x00t(%ld): scst_register_session() "
"failed for host %ld (wwn %s, loop_id %d), all "
"commands from it will be refused", ha->instance,
ha->host_no, wwn_str, fcport->loop_id);
@@ -632,7 +636,7 @@ static struct q2t_sess *q2t_create_sess(scsi_qla_host_t *ha, fc_port_t *fcport,
tgt->sess_count++;
spin_unlock_irq(&ha->hardware_lock);
PRINT_INFO("qla2x00tgt(%ld): %ssession for wwn %s (loop_id %d, "
PRINT_INFO("qla2x00t(%ld): %ssession for wwn %s (loop_id %d, "
"s_id %x:%x:%x, confirmed completion %ssupported) added",
ha->instance, local ? "local " : "", wwn_str, fcport->loop_id,
sess->s_id.b.al_pa, sess->s_id.b.area, sess->s_id.b.domain,
@@ -685,7 +689,7 @@ static void q2t_fc_port_added(scsi_qla_host_t *ha, fc_port_t *fcport)
list_del(&sess->del_list_entry);
sess->deleted = 0;
PRINT_INFO("qla2x00tgt(%ld): session for port %02x:"
PRINT_INFO("qla2x00t(%ld): session for port %02x:"
"%02x:%02x:%02x:%02x:%02x:%02x:%02x (loop ID %d) "
"reappeared", ha->instance, fcport->port_name[0],
fcport->port_name[1], fcport->port_name[2],
@@ -694,7 +698,7 @@ static void q2t_fc_port_added(scsi_qla_host_t *ha, fc_port_t *fcport)
fcport->port_name[7], sess->loop_id);
TRACE_MGMT_DBG("Appeared sess %p", sess);
} else if (sess->local) {
TRACE(TRACE_MGMT, "qla2x00tgt(%ld): local session for "
TRACE(TRACE_MGMT, "qla2x00t(%ld): local session for "
"port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
"(loop ID %d) became global", ha->instance,
fcport->port_name[0], fcport->port_name[1],
@@ -750,7 +754,7 @@ static void q2t_fc_port_deleted(scsi_qla_host_t *ha, fc_port_t *fcport)
list_add_tail(&sess->del_list_entry, &tgt->del_sess_list);
sess->deleted = 1;
PRINT_INFO("qla2x00tgt(%ld): %ssession for port %02x:%02x:%02x:"
PRINT_INFO("qla2x00t(%ld): %ssession for port %02x:%02x:%02x:"
"%02x:%02x:%02x:%02x:%02x (loop ID %d) scheduled for "
"deletion in %d secs", ha->instance,
sess->local ? "local " : "",
@@ -897,7 +901,7 @@ static void q2x_modify_command_count(scsi_qla_host_t *ha, int cmd_count,
pkt = (modify_lun_entry_t *)qla2x00_req_pkt(ha);
if (pkt == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): %s failed: unable to allocate "
PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
"request packet", ha->instance, __func__);
goto out;
}
@@ -952,7 +956,7 @@ static void q2x_send_notify_ack(scsi_qla_host_t *ha, notify_entry_t *iocb,
ntfy = (nack_entry_t *)qla2x00_req_pkt(ha);
if (ntfy == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): %s failed: unable to allocate "
PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
"request packet", ha->instance, __func__);
goto out;
}
@@ -1016,7 +1020,7 @@ static void q24_send_abts_resp(scsi_qla_host_t *ha,
resp = (abts24_resp_entry_t *)qla2x00_req_pkt(ha);
if (resp == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): %s failed: unable to allocate "
PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
"request packet", ha->instance, __func__);
goto out;
}
@@ -1093,7 +1097,7 @@ static void q24_retry_term_exchange(scsi_qla_host_t *ha,
ctio = (ctio7_status1_entry_t *)qla2x00_req_pkt(ha);
if (ctio == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): %s failed: unable to allocate "
PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
"request packet", ha->instance, __func__);
goto out;
}
@@ -1140,7 +1144,7 @@ static void q24_handle_abts(scsi_qla_host_t *ha, abts24_recv_entry_t *abts)
TRACE_ENTRY();
if (le32_to_cpu(abts->fcp_hdr_le.parameter) & ABTS_PARAM_ABORT_SEQ) {
PRINT_ERROR("qla2x00tgt(%ld): ABTS: Abort Sequence not "
PRINT_ERROR("qla2x00t(%ld): ABTS: Abort Sequence not "
"supported", ha->instance);
goto out_err;
}
@@ -1148,19 +1152,19 @@ static void q24_handle_abts(scsi_qla_host_t *ha, abts24_recv_entry_t *abts)
tag = abts->exchange_addr_to_abort;
if (tag == ATIO_EXCHANGE_ADDRESS_UNKNOWN) {
TRACE_MGMT_DBG("qla2x00tgt(%ld): ABTS: Unknown Exchange "
TRACE_MGMT_DBG("qla2x00t(%ld): ABTS: Unknown Exchange "
"Address received", ha->instance);
goto out_err;
}
TRACE(TRACE_MGMT, "qla2x00tgt(%ld): task abort (s_id=%x:%x:%x, "
TRACE(TRACE_MGMT, "qla2x00t(%ld): task abort (s_id=%x:%x:%x, "
"tag=%d, param=%x)", ha->instance, abts->fcp_hdr_le.s_id[0],
abts->fcp_hdr_le.s_id[1], abts->fcp_hdr_le.s_id[2], tag,
le32_to_cpu(abts->fcp_hdr_le.parameter));
sess = q2t_find_sess_by_s_id_le(ha->tgt, abts->fcp_hdr_le.s_id);
if (sess == NULL) {
TRACE(TRACE_MGMT, "qla2x00tgt(%ld): task abort for unexisting "
TRACE(TRACE_MGMT, "qla2x00t(%ld): task abort for unexisting "
"session", ha->instance);
ha->tgt->tm_to_unknown = 1;
goto out_err;
@@ -1179,7 +1183,7 @@ static void q24_handle_abts(scsi_qla_host_t *ha, abts24_recv_entry_t *abts)
rc = scst_rx_mgmt_fn_tag(sess->scst_sess, SCST_ABORT_TASK, tag,
SCST_ATOMIC, mcmd);
if (rc != 0) {
PRINT_ERROR("qla2x00tgt(%ld): scst_rx_mgmt_fn_tag() failed: %d",
PRINT_ERROR("qla2x00t(%ld): scst_rx_mgmt_fn_tag() failed: %d",
ha->instance, rc);
goto out_err_free;
}
@@ -1216,7 +1220,7 @@ static void q24_send_task_mgmt_ctio(scsi_qla_host_t *ha,
ctio = (ctio7_status1_entry_t *)qla2x00_req_pkt(ha);
if (ctio == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): %s failed: unable to allocate "
PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
"request packet", ha->instance, __func__);
goto out;
}
@@ -1268,7 +1272,7 @@ static void q24_send_notify_ack(scsi_qla_host_t *ha,
nack = (nack24xx_entry_t *)qla2x00_req_pkt(ha);
if (nack == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): %s failed: unable to allocate "
PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
"request packet", ha->instance, __func__);
goto out;
}
@@ -1409,7 +1413,7 @@ out:
return res;
out_err:
PRINT_ERROR("qla2x00tgt(%ld): PCI mapping failed: sg_cnt=%d",
PRINT_ERROR("qla2x00t(%ld): PCI mapping failed: sg_cnt=%d",
prm->tgt->ha->instance, prm->cmd->sg_cnt);
res = -1;
goto out;
@@ -1801,7 +1805,7 @@ static int q2t_pre_xmit_response(struct q2t_cmd *cmd,
TRACE_ENTRY();
if (unlikely(cmd->aborted)) {
TRACE_MGMT_DBG("qla2x00tgt(%ld): terminating exchange "
TRACE_MGMT_DBG("qla2x00t(%ld): terminating exchange "
"for aborted cmd=%p (scst_cmd=%p, tag=%d)",
ha->instance, cmd, scst_cmd, cmd->tag);
@@ -2180,7 +2184,7 @@ static void q24_init_ctio_ret_entry(ctio7_status0_entry_t *ctio,
if (unlikely((prm->sense_buffer_len % 4) != 0)) {
static int q;
if (q < 10) {
PRINT_INFO("qla2x00tgt(%ld): %d bytes of sense "
PRINT_INFO("qla2x00t(%ld): %d bytes of sense "
"lost", prm->tgt->ha->instance,
prm->sense_buffer_len % 4);
q++;
@@ -2421,7 +2425,7 @@ static void q2x_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
ctio = (ctio_ret_entry_t *)qla2x00_req_pkt(ha);
if (ctio == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): %s failed: unable to allocate "
PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
"request packet", ha->instance, __func__);
goto out_unlock;
}
@@ -2430,7 +2434,7 @@ static void q2x_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
ctio->entry_count = 1;
if (cmd != NULL) {
if (cmd->state < Q2T_STATE_PROCESSED) {
PRINT_ERROR("qla2x00tgt(%ld): Terminating cmd %p with "
PRINT_ERROR("qla2x00t(%ld): Terminating cmd %p with "
"incorrect state %d", ha->instance, cmd,
cmd->state);
} else
@@ -2494,7 +2498,7 @@ static void q24_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
ctio = (ctio7_status1_entry_t *)qla2x00_req_pkt(ha);
if (ctio == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): %s failed: unable to allocate "
PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
"request packet", ha->instance, __func__);
goto out_unlock;
}
@@ -2504,7 +2508,7 @@ static void q24_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
if (cmd != NULL) {
ctio->common.nport_handle = cmd->loop_id;
if (cmd->state < Q2T_STATE_PROCESSED) {
PRINT_ERROR("qla2x00tgt(%ld): Terminating cmd %p with "
PRINT_ERROR("qla2x00t(%ld): Terminating cmd %p with "
"incorrect state %d", ha->instance, cmd,
cmd->state);
} else
@@ -2584,11 +2588,11 @@ static int q2t_prepare_srr_ctio(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
tgt->ctio_srr_id++;
TRACE_MGMT_DBG("qla2x00tgt(%ld): CTIO with SRR "
TRACE_MGMT_DBG("qla2x00t(%ld): CTIO with SRR "
"status received", ha->instance);
if (ctio == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): SRR CTIO, "
PRINT_ERROR("qla2x00t(%ld): SRR CTIO, "
"but ctio is NULL", ha->instance);
res = -EINVAL;
goto out;
@@ -2617,7 +2621,7 @@ static int q2t_prepare_srr_ctio(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
TRACE_MGMT_DBG("%s", "Scheduling srr work");
schedule_work(&tgt->srr_work);
} else {
PRINT_ERROR("qla2x00tgt(%ld): imm_srr_id "
PRINT_ERROR("qla2x00t(%ld): imm_srr_id "
"== ctio_srr_id (%d), but there is no "
"corresponding SRR IMM, deleting CTIO "
"SRR %p", ha->instance, tgt->ctio_srr_id,
@@ -2633,7 +2637,7 @@ static int q2t_prepare_srr_ctio(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
spin_unlock(&tgt->srr_lock);
} else {
struct srr_imm *ti;
PRINT_CRIT_ERROR("qla2x00tgt(%ld): Unable to "
PRINT_CRIT_ERROR("qla2x00t(%ld): Unable to "
"allocate SRR CTIO entry", ha->instance);
spin_lock(&tgt->srr_lock);
list_for_each_entry_safe(imm, ti, &tgt->srr_imm_list,
@@ -2722,13 +2726,13 @@ static struct q2t_cmd *q2t_ctio_to_cmd(scsi_qla_host_t *ha, uint32_t handle,
}
/* handle-1 is actually used */
if (unlikely(handle > MAX_OUTSTANDING_COMMANDS)) {
PRINT_ERROR("qla2x00tgt(%ld): Wrong handle %x "
PRINT_ERROR("qla2x00t(%ld): Wrong handle %x "
"received", ha->instance, handle);
goto out;
}
cmd = q2t_get_cmd(ha, handle);
if (unlikely(cmd == NULL)) {
PRINT_WARNING("qla2x00tgt(%ld): Suspicious: unable to "
PRINT_WARNING("qla2x00t(%ld): Suspicious: unable to "
"find the command with handle %x",
ha->instance, handle);
goto out;
@@ -2741,7 +2745,7 @@ static struct q2t_cmd *q2t_ctio_to_cmd(scsi_qla_host_t *ha, uint32_t handle,
if (IS_FWI2_CAPABLE(ha)) {
/* We can't get loop ID from CTIO7 */
PRINT_ERROR("qla2x00tgt(%ld): Wrong CTIO received: "
PRINT_ERROR("qla2x00t(%ld): Wrong CTIO received: "
"QLA24xx doesn't support NULL handles",
ha->instance);
goto out;
@@ -2753,7 +2757,7 @@ static struct q2t_cmd *q2t_ctio_to_cmd(scsi_qla_host_t *ha, uint32_t handle,
sess = q2t_find_sess_by_loop_id(ha->tgt, loop_id);
if (sess == NULL) {
PRINT_WARNING("qla2x00tgt(%ld): Suspicious: "
PRINT_WARNING("qla2x00t(%ld): Suspicious: "
"ctio_completion for non-existing session "
"(loop_id %d, tag %d)",
ha->instance, loop_id, tag);
@@ -2762,7 +2766,7 @@ static struct q2t_cmd *q2t_ctio_to_cmd(scsi_qla_host_t *ha, uint32_t handle,
scst_cmd = scst_find_cmd_by_tag(sess->scst_sess, tag);
if (scst_cmd == NULL) {
PRINT_WARNING("qla2x00tgt(%ld): Suspicious: unable to "
PRINT_WARNING("qla2x00t(%ld): Suspicious: unable to "
"find the command with tag %d (loop_id %d)",
ha->instance, tag, loop_id);
goto out;
@@ -2824,7 +2828,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, uint32_t handle,
case CTIO_INVALID_RX_ID:
/* They are OK */
TRACE(TRACE_MINOR_AND_MGMT_DBG,
"qla2x00tgt(%ld): CTIO with "
"qla2x00t(%ld): CTIO with "
"status %#x received, state %x, scst_cmd %p, "
"op %x (LIP_RESET=e, ABORTED=2, TARGET_RESET=17, "
"TIMEOUT=b, INVALID_RX_ID=8)", ha->instance,
@@ -2833,7 +2837,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, uint32_t handle,
case CTIO_PORT_LOGGED_OUT:
case CTIO_PORT_UNAVAILABLE:
PRINT_INFO("qla2x00tgt(%ld): CTIO with PORT LOGGED "
PRINT_INFO("qla2x00t(%ld): CTIO with PORT LOGGED "
"OUT (29) or PORT UNAVAILABLE (28) status %x "
"received (state %x, scst_cmd %p, op %x)",
ha->instance, status, cmd->state, scst_cmd,
@@ -2847,7 +2851,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, uint32_t handle,
goto out;
default:
PRINT_ERROR("qla2x00tgt(%ld): CTIO with error status "
PRINT_ERROR("qla2x00t(%ld): CTIO with error status "
"0x%x received (state %x, scst_cmd %p, op %x)",
ha->instance, status, cmd->state, scst_cmd,
scst_cmd->cdb[0]);
@@ -2885,7 +2889,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, uint32_t handle,
TRACE_MGMT_DBG("Aborted command %p (tag %d) finished", cmd,
cmd->tag);
} else {
PRINT_ERROR("qla2x00tgt(%ld): A command in state (%d) should "
PRINT_ERROR("qla2x00t(%ld): A command in state (%d) should "
"not return a CTIO complete", ha->instance, cmd->state);
}
@@ -2941,7 +2945,7 @@ static int q2x_do_send_cmd_to_scst(struct q2t_cmd *cmd)
SCST_ATOMIC);
if (cmd->scst_cmd == NULL) {
PRINT_ERROR("%s", "qla2x00tgt: scst_rx_cmd() failed");
PRINT_ERROR("%s", "qla2x00t: scst_rx_cmd() failed");
res = -EFAULT;
goto out;
}
@@ -2979,7 +2983,7 @@ static int q2x_do_send_cmd_to_scst(struct q2t_cmd *cmd)
cmd->scst_cmd->queue_type = SCST_CMD_QUEUE_UNTAGGED;
break;
default:
PRINT_ERROR("qla2x00tgt: unknown task code %x, use "
PRINT_ERROR("qla2x00t: unknown task code %x, use "
"ORDERED instead", atio->task_codes);
cmd->scst_cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
break;
@@ -3017,7 +3021,7 @@ static int q24_do_send_cmd_to_scst(struct q2t_cmd *cmd)
atio->fcp_cmnd.cdb, Q2T_MAX_CDB_LEN, SCST_ATOMIC);
if (cmd->scst_cmd == NULL) {
PRINT_ERROR("%s", "qla2x00tgt: scst_rx_cmd() failed");
PRINT_ERROR("%s", "qla2x00t: scst_rx_cmd() failed");
res = -EFAULT;
goto out;
}
@@ -3054,7 +3058,7 @@ static int q24_do_send_cmd_to_scst(struct q2t_cmd *cmd)
cmd->scst_cmd->queue_type = SCST_CMD_QUEUE_UNTAGGED;
break;
default:
PRINT_ERROR("qla2x00tgt: unknown task code %x, use "
PRINT_ERROR("qla2x00t: unknown task code %x, use "
"ORDERED instead", atio->fcp_cmnd.task_attr);
cmd->scst_cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
break;
@@ -3129,7 +3133,7 @@ static int q2t_send_cmd_to_scst(scsi_qla_host_t *ha, atio_t *atio)
atio7_entry_t *a = (atio7_entry_t *)atio;
sess = q2t_find_sess_by_s_id(tgt, a->fcp_hdr.s_id);
if (unlikely(sess == NULL)) {
TRACE_MGMT_DBG("qla2x00tgt(%ld): Unable to find "
TRACE_MGMT_DBG("qla2x00t(%ld): Unable to find "
"wwn login (s_id %x:%x:%x), trying to create "
"it manually", ha->instance,
a->fcp_hdr.s_id[0], a->fcp_hdr.s_id[1],
@@ -3140,7 +3144,7 @@ static int q2t_send_cmd_to_scst(scsi_qla_host_t *ha, atio_t *atio)
sess = q2t_find_sess_by_loop_id(tgt,
GET_TARGET_ID(ha, (atio_entry_t *)atio));
if (unlikely(sess == NULL)) {
TRACE_MGMT_DBG("qla2x00tgt(%ld): Unable to find "
TRACE_MGMT_DBG("qla2x00t(%ld): Unable to find "
"wwn login (loop_id=%d), trying to create it "
"manually", ha->instance,
GET_TARGET_ID(ha, (atio_entry_t *)atio));
@@ -3201,7 +3205,7 @@ static int q2t_issue_task_mgmt(struct q2t_sess *sess, uint8_t *lun,
mcmd = mempool_alloc(q2t_mgmt_cmd_mempool, GFP_ATOMIC);
if (mcmd == NULL) {
PRINT_CRIT_ERROR("qla2x00tgt(%ld): Allocation of management "
PRINT_CRIT_ERROR("qla2x00t(%ld): Allocation of management "
"command failed, some commands and their data could "
"leak", sess->tgt->ha->instance);
res = -ENOMEM;
@@ -3274,14 +3278,14 @@ static int q2t_issue_task_mgmt(struct q2t_sess *sess, uint8_t *lun,
break;
default:
PRINT_ERROR("qla2x00tgt(%ld): Unknown task mgmt fn 0x%x",
PRINT_ERROR("qla2x00t(%ld): Unknown task mgmt fn 0x%x",
sess->tgt->ha->instance, fn);
rc = -1;
break;
}
if (rc != 0) {
PRINT_ERROR("qla2x00tgt(%ld): scst_rx_mgmt_fn_lun() failed: %d",
PRINT_ERROR("qla2x00t(%ld): scst_rx_mgmt_fn_lun() failed: %d",
sess->tgt->ha->instance, rc);
res = -EFAULT;
goto out_free;
@@ -3332,7 +3336,7 @@ static int q2t_handle_task_mgmt(scsi_qla_host_t *ha, void *iocb)
}
if (sess == NULL) {
TRACE(TRACE_MGMT, "qla2x00tgt(%ld): task mgmt fn 0x%x for "
TRACE(TRACE_MGMT, "qla2x00t(%ld): task mgmt fn 0x%x for "
"non-existant session", ha->instance, fn);
tgt->tm_to_unknown = 1;
res = -ESRCH;
@@ -3362,7 +3366,7 @@ static int q2t_abort_task(scsi_qla_host_t *ha, notify_entry_t *iocb)
sess = q2t_find_sess_by_loop_id(ha->tgt, loop_id);
if (sess == NULL) {
TRACE(TRACE_MGMT, "qla2x00tgt(%ld): task abort for unexisting "
TRACE(TRACE_MGMT, "qla2x00t(%ld): task abort for unexisting "
"session", ha->instance);
ha->tgt->tm_to_unknown = 1;
res = -EFAULT;
@@ -3384,7 +3388,7 @@ static int q2t_abort_task(scsi_qla_host_t *ha, notify_entry_t *iocb)
rc = scst_rx_mgmt_fn_tag(sess->scst_sess, SCST_ABORT_TASK, tag,
SCST_ATOMIC, mcmd);
if (rc != 0) {
PRINT_ERROR("qla2x00tgt(%ld): scst_rx_mgmt_fn_tag() failed: %d",
PRINT_ERROR("qla2x00t(%ld): scst_rx_mgmt_fn_tag() failed: %d",
ha->instance, rc);
res = -EFAULT;
goto out_free;
@@ -3432,7 +3436,7 @@ static int q24_handle_els(scsi_qla_host_t *ha, notify24xx_entry_t *iocb)
}
default:
PRINT_ERROR("qla2x00tgt(%ld): Unsupported ELS command %x "
PRINT_ERROR("qla2x00t(%ld): Unsupported ELS command %x "
"received", ha->instance, iocb->status_subcode);
res = q2t_reset(ha, iocb, Q2T_NEXUS_LOSS_SESS);
break;
@@ -3484,7 +3488,7 @@ static int q2t_cut_cmd_data_head(struct q2t_cmd *cmd, unsigned int offset)
}
}
if (first_sg == -1) {
PRINT_ERROR("qla2x00tgt(%ld): Wrong offset %d, buf length %d",
PRINT_ERROR("qla2x00t(%ld): Wrong offset %d, buf length %d",
cmd->tgt->ha->instance, offset, cmd->bufflen);
res = -EINVAL;
goto out;
@@ -3497,7 +3501,7 @@ static int q2t_cut_cmd_data_head(struct q2t_cmd *cmd, unsigned int offset)
sg = kmalloc(cnt * sizeof(sg[0]), GFP_KERNEL);
if (sg == NULL) {
PRINT_CRIT_ERROR("qla2x00tgt(%ld): Unable to allocate cut "
PRINT_CRIT_ERROR("qla2x00t(%ld): Unable to allocate cut "
"SG (len %zd)", cmd->tgt->ha->instance,
cnt * sizeof(sg[0]));
res = -ENOMEM;
@@ -3574,7 +3578,7 @@ static inline int q2t_srr_adjust_data(struct q2t_cmd *cmd,
*xmit_type = Q2T_XMIT_ALL;
if (rel_offs < 0) {
PRINT_ERROR("qla2x00tgt(%ld): SRR rel_offs (%d) "
PRINT_ERROR("qla2x00t(%ld): SRR rel_offs (%d) "
"< 0", cmd->tgt->ha->instance, rel_offs);
res = -1;
} else if (rel_offs == cmd->bufflen)
@@ -3618,7 +3622,7 @@ static void q24_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
spin_unlock_irq(&ha->hardware_lock);
__q24_xmit_response(cmd, xmit_type);
} else {
PRINT_ERROR("qla2x00tgt(%ld): SRR for in data for cmd "
PRINT_ERROR("qla2x00t(%ld): SRR for in data for cmd "
"without them (tag %d, SCSI status %d), "
"reject", ha->instance, cmd->tag,
scst_cmd_get_status(cmd->scst_cmd));
@@ -3641,7 +3645,7 @@ static void q24_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
spin_unlock_irq(&ha->hardware_lock);
__q2t_rdy_to_xfer(cmd);
} else {
PRINT_ERROR("qla2x00tgt(%ld): SRR for out data for cmd "
PRINT_ERROR("qla2x00t(%ld): SRR for out data for cmd "
"without them (tag %d, SCSI status %d), "
"reject", ha->instance, cmd->tag,
scst_cmd_get_status(cmd->scst_cmd));
@@ -3649,7 +3653,7 @@ static void q24_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
}
break;
default:
PRINT_ERROR("qla2x00tgt(%ld): Unknown srr_ui value %x",
PRINT_ERROR("qla2x00t(%ld): Unknown srr_ui value %x",
ha->instance, ntfy->srr_ui);
goto out_unmap_reject;
}
@@ -3716,7 +3720,7 @@ static void q2x_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
spin_unlock_irq(&ha->hardware_lock);
__q2x_xmit_response(cmd, xmit_type);
} else {
PRINT_ERROR("qla2x00tgt(%ld): SRR for in data for cmd "
PRINT_ERROR("qla2x00t(%ld): SRR for in data for cmd "
"without them (tag %d, SCSI status %d), "
"reject", ha->instance, cmd->tag,
scst_cmd_get_status(cmd->scst_cmd));
@@ -3739,7 +3743,7 @@ static void q2x_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
spin_unlock_irq(&ha->hardware_lock);
__q2t_rdy_to_xfer(cmd);
} else {
PRINT_ERROR("qla2x00tgt(%ld): SRR for out data for cmd "
PRINT_ERROR("qla2x00t(%ld): SRR for out data for cmd "
"without them (tag %d, SCSI status %d), "
"reject", ha->instance, cmd->tag,
scst_cmd_get_status(cmd->scst_cmd));
@@ -3747,7 +3751,7 @@ static void q2x_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
}
break;
default:
PRINT_ERROR("qla2x00tgt(%ld): Unknown srr_ui value %x",
PRINT_ERROR("qla2x00t(%ld): Unknown srr_ui value %x",
ha->instance, ntfy->srr_ui);
goto out_unmap_reject;
}
@@ -3829,7 +3833,7 @@ restart:
if (i->srr_id == sctio->srr_id) {
list_del(&i->srr_list_entry);
if (imm) {
PRINT_ERROR("qla2x00tgt(%ld): There must "
PRINT_ERROR("qla2x00t(%ld): There must "
"be only one IMM SRR per CTIO SRR "
"(IMM SRR %p, id %d, CTIO %p",
ha->instance, i, i->srr_id, sctio);
@@ -3893,7 +3897,7 @@ static void q2t_prepare_srr_imm(scsi_qla_host_t *ha, void *iocb)
tgt->imm_srr_id++;
TRACE(TRACE_MGMT, "qla2x00tgt(%ld): SRR received", ha->instance);
TRACE(TRACE_MGMT, "qla2x00t(%ld): SRR received", ha->instance);
imm = kzalloc(sizeof(*imm), GFP_ATOMIC);
if (imm != NULL) {
@@ -3920,7 +3924,7 @@ static void q2t_prepare_srr_imm(scsi_qla_host_t *ha, void *iocb)
TRACE_MGMT_DBG("%s", "Scheduling srr work");
schedule_work(&tgt->srr_work);
} else {
TRACE(TRACE_MGMT, "qla2x00tgt(%ld): imm_srr_id "
TRACE(TRACE_MGMT, "qla2x00t(%ld): imm_srr_id "
"== ctio_srr_id (%d), but there is no "
"corresponding SRR CTIO, deleting IMM "
"SRR %p", ha->instance, tgt->ctio_srr_id,
@@ -3937,7 +3941,7 @@ static void q2t_prepare_srr_imm(scsi_qla_host_t *ha, void *iocb)
} else {
struct srr_ctio *ts;
PRINT_CRIT_ERROR("qla2x00tgt(%ld): Unable to allocate SRR IMM "
PRINT_CRIT_ERROR("qla2x00t(%ld): Unable to allocate SRR IMM "
"entry, SRR request will be rejected", ha->instance);
/* IRQ is already OFF */
@@ -4061,7 +4065,7 @@ static void q2t_handle_imm_notify(scsi_qla_host_t *ha, void *iocb)
break;
case IMM_NTFY_GLBL_LOGO:
PRINT_ERROR("qla2x00tgt(%ld): Link failure detected",
PRINT_ERROR("qla2x00t(%ld): Link failure detected",
ha->instance);
/* I_T nexus loss */
qla2x00_mark_all_devices_lost(ha, 1);
@@ -4070,7 +4074,7 @@ static void q2t_handle_imm_notify(scsi_qla_host_t *ha, void *iocb)
break;
case IMM_NTFY_IOCB_OVERFLOW:
PRINT_ERROR("qla2x00tgt(%ld): Cannot provide requested "
PRINT_ERROR("qla2x00t(%ld): Cannot provide requested "
"capability (IOCB overflowed the immediate notify "
"resource count)", ha->instance);
break;
@@ -4084,7 +4088,7 @@ static void q2t_handle_imm_notify(scsi_qla_host_t *ha, void *iocb)
break;
case IMM_NTFY_RESOURCE:
PRINT_ERROR("qla2x00tgt(%ld): Out of resources, host %ld",
PRINT_ERROR("qla2x00t(%ld): Out of resources, host %ld",
ha->instance, ha->host_no);
break;
@@ -4105,7 +4109,7 @@ static void q2t_handle_imm_notify(scsi_qla_host_t *ha, void *iocb)
break;
default:
PRINT_ERROR("qla2x00tgt(%ld): Received unknown immediate "
PRINT_ERROR("qla2x00t(%ld): Received unknown immediate "
"notify status %x", ha->instance, status);
break;
}
@@ -4135,7 +4139,7 @@ static void q2x_send_busy(scsi_qla_host_t *ha, atio_entry_t *atio)
ctio = (ctio_ret_entry_t *)qla2x00_req_pkt(ha);
if (ctio == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): %s failed: unable to allocate "
PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
"request packet", ha->instance, __func__);
goto out;
}
@@ -4190,7 +4194,7 @@ static void q24_send_busy(scsi_qla_host_t *ha, atio7_entry_t *atio,
ctio = (ctio7_status1_entry_t *)qla2x00_req_pkt(ha);
if (ctio == NULL) {
PRINT_ERROR("qla2x00tgt(%ld): %s failed: unable to allocate "
PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
"request packet", ha->instance, __func__);
goto out;
}
@@ -4254,7 +4258,7 @@ static void q24_atio_pkt(scsi_qla_host_t *ha, atio7_entry_t *atio)
case ATIO_TYPE7:
if (unlikely(atio->entry_count > 1) ||
unlikely(atio->fcp_cmnd.add_cdb_len != 0)) {
PRINT_ERROR("qla2x00tgt(%ld): Multi entry ATIO7 IOCBs "
PRINT_ERROR("qla2x00t(%ld): Multi entry ATIO7 IOCBs "
"(%d), ie with CDBs>16 bytes (%d), are not "
"supported", ha->instance, atio->entry_count,
atio->fcp_cmnd.add_cdb_len);
@@ -4274,7 +4278,7 @@ static void q24_atio_pkt(scsi_qla_host_t *ha, atio7_entry_t *atio)
sizeof(atio->fcp_cmnd.cdb));
if (unlikely(atio->exchange_addr ==
ATIO_EXCHANGE_ADDRESS_UNKNOWN)) {
TRACE(TRACE_OUT_OF_MEM, "qla2x00tgt(%ld): ATIO_TYPE7 "
TRACE(TRACE_OUT_OF_MEM, "qla2x00t(%ld): ATIO_TYPE7 "
"received with UNKNOWN exchange address, "
"sending QUEUE_FULL", ha->instance);
q24_send_busy(ha, atio, SAM_STAT_TASK_SET_FULL);
@@ -4292,7 +4296,7 @@ static void q24_atio_pkt(scsi_qla_host_t *ha, atio7_entry_t *atio)
q24_send_term_exchange(ha, NULL, atio, 1);
#endif
} else {
PRINT_INFO("qla2x00tgt(%ld): Unable to send "
PRINT_INFO("qla2x00t(%ld): Unable to send "
"command to SCST, sending BUSY status",
ha->instance);
q24_send_busy(ha, atio, SAM_STAT_BUSY);
@@ -4304,7 +4308,7 @@ static void q24_atio_pkt(scsi_qla_host_t *ha, atio7_entry_t *atio)
{
notify_entry_t *pkt = (notify_entry_t *)atio;
if (unlikely(pkt->entry_status != 0)) {
PRINT_ERROR("qla2x00tgt(%ld): Received ATIO packet %x "
PRINT_ERROR("qla2x00t(%ld): Received ATIO packet %x "
"with error status %x", ha->instance,
pkt->entry_type, pkt->entry_status);
break;
@@ -4315,7 +4319,7 @@ static void q24_atio_pkt(scsi_qla_host_t *ha, atio7_entry_t *atio)
}
default:
PRINT_ERROR("qla2x00tgt(%ld): Received unknown ATIO atio "
PRINT_ERROR("qla2x00t(%ld): Received unknown ATIO atio "
"type %x", ha->instance, atio->entry_type);
break;
}
@@ -4351,7 +4355,7 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, response_t *pkt)
*/
if (unlikely(pkt->entry_status != 0)) {
PRINT_ERROR("qla2x00tgt(%ld): Received response packet %x "
PRINT_ERROR("qla2x00t(%ld): Received response packet %x "
"with error status %x", ha->instance, pkt->entry_type,
pkt->entry_status);
switch (pkt->entry_type) {
@@ -4396,7 +4400,7 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, response_t *pkt)
TRACE_BUFFER("Incoming ATIO packet data", atio,
REQUEST_ENTRY_SIZE);
if (atio->status != __constant_cpu_to_le16(ATIO_CDB_VALID)) {
PRINT_ERROR("qla2x00tgt(%ld): ATIO with error "
PRINT_ERROR("qla2x00t(%ld): ATIO with error "
"status %x received", ha->instance,
le16_to_cpu(atio->status));
break;
@@ -4413,7 +4417,7 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, response_t *pkt)
q2x_send_term_exchange(ha, NULL, atio, 1);
#endif
} else {
PRINT_INFO("qla2x00tgt(%ld): Unable to send "
PRINT_INFO("qla2x00t(%ld): Unable to send "
"command to SCST, sending BUSY status",
ha->instance);
q2x_send_busy(ha, atio);
@@ -4461,12 +4465,12 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, response_t *pkt)
RESPONSE_ENTRY_SIZE);
tgt->notify_ack_expected--;
if (entry->status != __constant_cpu_to_le16(NOTIFY_ACK_SUCCESS)) {
PRINT_ERROR("qla2x00tgt(%ld): NOTIFY_ACK "
PRINT_ERROR("qla2x00t(%ld): NOTIFY_ACK "
"failed %x", ha->instance,
le16_to_cpu(entry->status));
}
} else {
PRINT_ERROR("qla2x00tgt(%ld): Unexpected NOTIFY_ACK "
PRINT_ERROR("qla2x00t(%ld): Unexpected NOTIFY_ACK "
"received", ha->instance);
}
break;
@@ -4504,13 +4508,13 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, response_t *pkt)
*/
q24_retry_term_exchange(ha, entry);
} else
PRINT_ERROR("qla2x00tgt(%ld): ABTS_RESP_24XX "
PRINT_ERROR("qla2x00t(%ld): ABTS_RESP_24XX "
"failed %x (subcode %x:%x)", ha->instance,
entry->compl_status, entry->error_subcode1,
entry->error_subcode2);
}
} else {
PRINT_ERROR("qla2x00tgt(%ld): Unexpected ABTS_RESP_24XX "
PRINT_ERROR("qla2x00t(%ld): Unexpected ABTS_RESP_24XX "
"received", ha->instance);
}
break;
@@ -4530,12 +4534,12 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, response_t *pkt)
entry->command_count);
tgt->modify_lun_expected--;
if (entry->status != MODIFY_LUN_SUCCESS) {
PRINT_ERROR("qla2x00tgt(%ld): MODIFY_LUN "
PRINT_ERROR("qla2x00t(%ld): MODIFY_LUN "
"failed %x", ha->instance,
entry->status);
}
} else {
PRINT_ERROR("qla2x00tgt(%ld): Unexpected MODIFY_LUN "
PRINT_ERROR("qla2x00t(%ld): Unexpected MODIFY_LUN "
"received", (ha != NULL) ? (long)ha->instance : -1);
}
break;
@@ -4555,7 +4559,7 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, response_t *pkt)
"error: %#x", entry->status);
entry->status = ENABLE_LUN_SUCCESS;
} else if (entry->status != ENABLE_LUN_SUCCESS) {
PRINT_ERROR("qla2x00tgt(%ld): ENABLE_LUN "
PRINT_ERROR("qla2x00t(%ld): ENABLE_LUN "
"failed %x", ha->instance, entry->status);
qla_clear_tgt_mode(ha);
} /* else success */
@@ -4563,7 +4567,7 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, response_t *pkt)
}
default:
PRINT_ERROR("qla2x00tgt(%ld): Received unknown response pkt "
PRINT_ERROR("qla2x00t(%ld): Received unknown response pkt "
"type %x", ha->instance, pkt->entry_type);
break;
}
@@ -4945,7 +4949,7 @@ static void q2t_on_hw_pending_cmd_timeout(struct scst_cmd *scst_cmd)
TRACE_MGMT_DBG("Force finishing aborted cmd %p (tag %d)",
cmd, cmd->tag);
} else {
PRINT_ERROR("qla2x00tgt(%ld): A command in state (%d) should "
PRINT_ERROR("qla2x00t(%ld): A command in state (%d) should "
"not be HW pending", ha->instance, cmd->state);
goto out_unlock;
}
@@ -5008,7 +5012,7 @@ static int q2t_add_target(scsi_qla_host_t *ha)
kfree(wwn);
if (!tgt->scst_tgt) {
PRINT_ERROR("qla2x00tgt(%ld): scst_register() "
PRINT_ERROR("qla2x00t(%ld): scst_register() "
"failed for host %ld(%p)", ha->instance,
ha->host_no, ha);
res = -ENOMEM;
@@ -5026,7 +5030,7 @@ static int q2t_add_target(scsi_qla_host_t *ha)
tgt->datasegs_per_cont = DATASEGS_PER_CONT_24XX;
} else {
if (ha->flags.enable_64bit_addressing) {
PRINT_INFO("qla2x00tgt(%ld): 64 Bit PCI "
PRINT_INFO("qla2x00t(%ld): 64 Bit PCI "
"addressing enabled", ha->instance);
tgt->tgt_enable_64bit_addr = 1;
/* 3 is reserved */
@@ -5035,7 +5039,7 @@ static int q2t_add_target(scsi_qla_host_t *ha)
tgt->datasegs_per_cmd = DATASEGS_PER_COMMAND64;
tgt->datasegs_per_cont = DATASEGS_PER_CONT64;
} else {
PRINT_INFO("qla2x00tgt(%ld): Using 32 Bit "
PRINT_INFO("qla2x00t(%ld): Using 32 Bit "
"PCI addressing", ha->instance);
sg_tablesize =
QLA_MAX_SG32(ha->request_q_length - 3);
@@ -5071,7 +5075,7 @@ static int q2t_remove_target(scsi_qla_host_t *ha)
TRACE_ENTRY();
if ((ha->q2t_tgt == NULL) || (ha->tgt != NULL)) {
PRINT_ERROR("qla2x00tgt(%ld): Can't remove "
PRINT_ERROR("qla2x00t(%ld): Can't remove "
"existing target", ha->instance);
}
@@ -5114,18 +5118,18 @@ static int q2t_host_action(scsi_qla_host_t *ha,
fc_port_t *fcport;
if (qla_tgt_mode_enabled(ha)) {
PRINT_INFO("qla2x00tgt(%ld): Target mode already "
PRINT_INFO("qla2x00t(%ld): Target mode already "
"enabled", ha->instance);
break;
}
if ((ha->q2t_tgt == NULL) || (ha->tgt != NULL)) {
PRINT_ERROR("qla2x00tgt(%ld): Can't enable target mode "
PRINT_ERROR("qla2x00t(%ld): Can't enable target mode "
"for not existing target", ha->instance);
break;
}
PRINT_INFO("qla2x00tgt(%ld): Enabling target mode",
PRINT_INFO("qla2x00t(%ld): Enabling target mode",
ha->instance);
spin_lock_irq(&ha->hardware_lock);
@@ -5143,12 +5147,12 @@ static int q2t_host_action(scsi_qla_host_t *ha,
case DISABLE_TARGET_MODE:
if (!qla_tgt_mode_enabled(ha)) {
PRINT_INFO("qla2x00tgt(%ld): Target mode already "
PRINT_INFO("qla2x00t(%ld): Target mode already "
"disabled", ha->instance);
break;
}
PRINT_INFO("qla2x00tgt(%ld): Disabling target mode",
PRINT_INFO("qla2x00t(%ld): Disabling target mode",
ha->instance);
sBUG_ON(ha->tgt == NULL);
@@ -5157,7 +5161,7 @@ static int q2t_host_action(scsi_qla_host_t *ha,
break;
default:
PRINT_ERROR("qla2x00tgt(%ld): %s: unsupported action %d",
PRINT_ERROR("qla2x00t(%ld): %s: unsupported action %d",
ha->instance, __func__, action);
res = -EINVAL;
break;
+527 -21
View File
@@ -86,7 +86,7 @@ will loose this performance benefit.
3. readahead-2.6.X.patch. This patch fixes problem in Linux readahead
subsystem and greatly improves performance for software RAIDs. See
http://sourceforge.net/mailarchive/forum.php?thread_name=a0272b440906030714g67eabc5k8f847fb1e538cc62%40mail.gmail.com&forum_name=scst-devel
thread for more details.
thread for more details. It is included in the mainstream kernel 2.6.33.
4. readahead-context-2.6.X.patch. This is backported from 2.6.31 version
of the context readahead patch http://lkml.org/lkml/2009/4/12/9, big
@@ -176,7 +176,7 @@ Usage in failover mode
----------------------
It is recommended to use TEST UNIT READY ("tur") command to check if
SCST target is alive.
SCST target is alive in MPIO configurations.
Device handlers
@@ -311,7 +311,8 @@ in/out in Makefile:
- CONFIG_SCST_MEASURE_LATENCY - if defined, provides in /proc/scsi_tgt/latency
file average commands processing latency. You can clear already
measured results by writing 0 in this file. Note, you need a
measured results by writing 0 in this file. For the sysfs build you
can find those results in /sys/kernel/scst_tgt and below. Note, you need a
non-preemptible kernel to have correct results.
HIGHMEM kernel configurations are fully supported, but not recommended
@@ -347,12 +348,14 @@ Module scst supports the following parameters:
default it is approximately TotalMem/4.
SCST /proc commands
---------------------
SCST /proc interface
--------------------
For communications with user space programs SCST provides proc-based
interface in /proc/scsi_tgt directory. It contains the following
entries:
interface in /proc/scsi_tgt directory. This interface is available in
the procfs build only. Starting from version 2.0.0 it is obsolete and
will be removed in one of the next versions. It contains the following
entries.
- "help" file, which provides online help for SCST commands
@@ -406,8 +409,8 @@ will assign device handler "dev_disk" to real device sitting on host 1,
channel 0, ID 1, LUN 0.
Access and devices visibility management (LUN masking)
------------------------------------------------------
Access and devices visibility management (LUN masking) - /proc interface
------------------------------------------------------------------------
Access and devices visibility management allows for an initiator or
group of initiators to see different devices with different LUNs
@@ -581,11 +584,325 @@ initiators or add new devices to old groups, but not altering existing
LUNs in them.
SCST sysfs interface
--------------------
Starting from 2.0.0 SCST has sysfs interface. You can switch to it by
running "make disable_proc". To switch back to the procfs interface you
should run "make enable_proc".
Root of SCST sysfs interface is /sys/kernel/scst_tgt. It has the
following entries:
- devices - this is a root subdirectory for all SCST devices
- handlers - this is a root subdirectory for all SCST dev handlers
- sgv - this is a root subdirectory for all SCST SGV caches
- targets - this is a root subdirectory for all SCST targets
- threads - allows to read and set number of global SCST I/O threads.
Those threads used with async. dev handlers, for instance, vdisk
BLOCKIO or NULLIO.
- trace_level - allows to enable and disable various tracing
facilities. See content of this file for help how to use it.
- version - read-only attribute, which allows to see version of
SCST and enabled optional features.
Each SCST sysfs file (attribute) can contain in the last line mark
"[key]". It is automatically added mark used to allow scstadmin to see
which attributes it should save in the config file. You can ignore it.
"Devices" subdirectory contains subdirectories for each SCST devices.
Content of each device's subdirectory is dev handler specific. See
documentation for your dev handlers for more info about it as well as
SysfsRules file for more info about common to all dev handlers rules.
Standard SCST dev handlers have at least the following common entries:
- exported - subdirectory containing links to all LUNs where this
device was exported.
- handler - if dev handler determined for this device, this link points
to it. The handler can be not set for pass-through devices.
- type - SCSI type of this device
See below for more information about other entries of this subdirectory
of the standard SCST dev handlers.
"Handlers" subdirectory contains subdirectories for each SCST dev
handler.
Content of each handler's subdirectory is dev handler specific. See
documentation for your dev handlers for more info about it as well as
SysfsRules file for more info about common to all dev handlers rules.
Standard SCST dev handlers have at least the following common entries:
- pass_through - if exists, it contains 1 and this dev handler is a
pass-through dev handler.
- trace_level - allows to enable and disable various tracing
facilities. See content of this file for help how to use it.
- type - SCSI type of devices served by this dev handler.
See below for more information about other entries of this subdirectory
of the standard SCST dev handlers.
"Sgv" subdirectory contains statistic information of SCST SGV caches. It
has the following entries:
- None, one or more subdirectories for each existing SGV cache.
- global_stats - file containing global SGV caches statistics.
Each SGV cache's subdirectory has the following item:
- stats - file containing statistics for this SGV caches.
"Targets" subdirectory contains subdirectories for each SCST target.
Content of each target's subdirectory is target specific. See
documentation for your target for more info about it as well as
SysfsRules file for more info about common to all dev handlers rules.
Every target should have at least the following entries:
- ini_group - subdirectory, which contains and allows to define
initiator-oriented access control information, see below.
- luns - subdirectory, which contains list of available LUNs in the
target-oriented access control and allows to define it, see below.
- sessions - subdirectory containing connected to this target sessions.
- enabled - using this attribute you can enable or disable this target/
It allows to finish configuring it before it starts accepting new
connections. 0 by default.
- rel_tgt_id - allows to read or write SCSI Relative Target Port
Identifier attribute. This identifier is used to identify SCSI Target
Ports by some SCSI commands, mainly by Persistent Reservations
commands. This identifier must be unique among all SCST targets, but
for convenience SCST allows disabled targets to have not unique
rel_tgt_id. In this case SCST will not allow to enable this target
until rel_tgt_id becomes unique. This attribute initialized unique by
SCST by default.
Subdirectory "sessions" contains one subdirectory for each connected
session with name equal to name of the connected initiator.
Each session subdirectory contains the following entries:
- initiator_name - contains initiator name
- force_close - optional write-only attribute, which allows to force
close this session.
- active_commands - contains number of active, i.e. not yet or being
executed, SCSI commands in this session.
- commands - contains overall number of SCSI commands in this session.
- other target driver specific attributes and subdirectories.
See below description of the VDISK's sysfs interface for samples.
Access and devices visibility management (LUN masking) - sysfs interface
------------------------------------------------------------------------
Access and devices visibility management allows for an initiator or
group of initiators to see different devices with different LUNs
with necessary access permissions.
SCST supports two modes of access control:
1. Target-oriented. In this mode you define for each target a default
set of LUNs, which are accessible to all initiators, connected to that
target. This is a regular access control mode, which people usually mean
thinking about access control in general. For instance, in IET this is
the only supported mode.
2. Initiator-oriented. In this mode you define which LUNs are accessible
for each initiator. In this mode you should create for each set of one
or more initiators, which should access to the same set of devices with
the same LUNs, a separate security group, then add to it devices and
names of allowed initiator(s).
Both modes can be used simultaneously. In this case the
initiator-oriented mode has higher priority, than the target-oriented,
i.e. initiators are at first searched in all defined security groups for
this target and, if none matches, the default target's set of LUNs is
used. This set of LUNs might be empty, then the initiator will not see
any LUNs from the target.
You can at any time find out which set of LUNs each session is assigned
to by looking where link
/sys/kernel/scst_tgt/targets/target_driver/target_name/sessions/initiator_name/luns
points to.
To configure the target-oriented access control SCST provides the
following interface. Each target's sysfs subdirectory
(/sys/kernel/scst_tgt/targets/target_driver/target_name) has "luns"
subdirectory. This subdirectory contains the list of already defined
target-oriented access control LUNs for this target as well as file
"mgmt". This file has the following commands, which you can send to it,
for instance, using "echo" shell command. You can always get a small
help about supported commands by looking inside this file. "Parameters"
are one or more param_name=value pairs separated by ';'.
- "add H:C:I:L lun [parameters]" - adds a pass-through device with
host:channel:id:lun with LUN "lun". Optionally, the device could be
marked as read only by using parameter "read_only". The recommended
way to find out H:C:I:L numbers is use of lsscsi utility.
- "replace H:C:I:L lun [parameters]" - replaces by pass-through device
with host:channel:id:lun existing with LUN "lun" device with
generation of INQUIRY DATA HAS CHANGED Unit Attention. If the old
device doesn't exist, this command acts as the "add" command.
Optionally, the device could be marked as read only by using
parameter "read_only". The recommended way to find out H:C:I:L
numbers is use of lsscsi utility.
- "del H:C:I:L" - deletes a pass-through device with host:channel:id:lun
The recommended way to find out H:C:I:L numbers is use of lsscsi
utility.
- "add VNAME lun [parameters]" - adds a virtual device with name VNAME
with LUN "lun". Optionally, the device could be marked as read only
by using parameter "read_only".
- "replace VNAME lun [parameters]" - replaces by virtual device
with name VNAME existing with LUN "lun" device with generation of
INQUIRY DATA HAS CHANGED Unit Attention. If the old device doesn't
exist, this command acts as the "add" command. Optionally, the device
could be marked as read only by using parameter "read_only".
- "del VNAME" - deletes a virtual device with name VNAME.
- "clear" - clears the list of devices
To configure the initiator-oriented access control SCST provides the
following interface. Each target's sysfs subdirectory
(/sys/kernel/scst_tgt/targets/target_driver/target_name) has "ini_group"
subdirectory. This subdirectory contains the list of already defined
security groups for this target as well as file "mgmt". This file has
the following commands, which you can send to it, for instance, using
"echo" shell command. You can always get a small help about supported
commands by looking inside this file.
- "create GROUP_NAME" - creates a new security group.
- "del GROUP_NAME" - deletes a new security group.
Each security group's subdirectory contains 2 subdirectories: initiators
and luns.
Each "initiators" subdirectory contains list of added to this groups
initiator as well as as well as file "mgmt". This file has the following
commands, which you can send to it, for instance, using "echo" shell
command. You can always get a small help about supported commands by
looking inside this file.
- "add INITIATOR_NAME" - adds initiator with name INITIATOR_NAME to the
group.
- "del INITIATOR_NAME" - deletes initiator with name INITIATOR_NAME
from the group.
- "move INITIATOR_NAME DEST_GROUP_NAME" moves initiator with name
INITIATOR_NAME from the current group to group with name
DEST_GROUP_NAME.
- "clear" - deletes all initiators from this group.
For "add" and "del" commands INITIATOR_NAME can be a simple DOS-type
patterns, containing '*' and '?' symbols. '*' means match all any
symbols, '?' means match only any single symbol. For instance,
"blah.xxx" will match "bl?h.*".
Each "luns" subdirectory contains the list of already defined LUNs for
this group as well as file "mgmt". Content of this file as well as list
of available in it commands is fully identical to the "luns"
sybdirectory of the target-oriented access control.
Examples:
- echo "create INI" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/mgmt -
creates security group INI for target iqn.2006-10.net.vlnb:tgt1.
- echo "add 2:0:1:0 11" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/INI/luns/mgmt -
adds a pass-through device sitting on host 2, channel 0, ID 1, LUN 0
to group with name INI as LUN 11.
- echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/INI/luns/mgmt -
adds a virtual disk with name disk1 to group with name INI as LUN 0.
- echo "add 21:*:e0:?b:83:*" >/sys/kernel/scst_tgt/targets/21:00:00:a0:8c:54:52:12/ini_group/INI/initiators/mgmt -
adds a pattern to group with name INI to Fibre Channel target with
WWN 21:00:00:a0:8c:54:52:12, which matches WWNs of Fibre Channel
initiator ports.
Consider you need to have an iSCSI target with name
"iqn.2007-05.com.example:storage.disk1.sys1.xyz", which should export
virtual device "dev1" with LUN 0 and virtual device "dev2" with LUN 1,
but initiator with name
"iqn.2007-05.com.example:storage.disk1.spec_ini.xyz" should see only
virtual device "dev2" read only with LUN 0. To achieve that you should
do the following commands:
# echo "iqn.2007-05.com.example:storage.disk1.sys1.xyz" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
# echo "add dev1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/luns/mgmt
# echo "add dev2 1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/luns/mgmt
# echo "create SPEC_INI" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_group/mgmt
# echo "add dev2 0 read_only=1" \
>/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_group/SPEC_INI/luns/mgmt
# echo "iqn.2007-05.com.example:storage.disk1.spec_ini.xyz" \
>/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_group/SPEC_INI/initiators/mgmt
For Fibre Channel or SAS in the above example you should use target's
and initiator ports WWNs instead of iSCSI names.
It is highly recommended to use scstadmin utility instead of described
in this section low level interface.
IMPORTANT
=========
There must be LUN 0 in each set of LUNs, i.e. LUs numeration must not
start from, e.g., 1. Otherwise you will see no devices on remote
initiators and SCST core will write into the kernel log message: "tgt_dev
for LUN 0 not found, command to unexisting LU?"
IMPORTANT
=========
All the access control must be fully configured BEFORE the corresponding
target is enabled! When you enable a target, it will immediately start
accepting new connections, hence creating new sessions, and those new
sessions will be assigned to security groups according to the
*currently* configured access control settings. For instance, to
the default target's set of LUNs, instead of "HOST004" group as you may
need, because "HOST004" doesn't exist yet. So, one must configure all
the security groups before new connections from the initiators are
created, i.e. before the target enabled.
VDISK device handler
--------------------
/proc interface
~~~~~~~~~~~~~~~
This interface starting from version 2.0.0 is obsolete and will be
removed in one of the next versions.
After loading VDISK device handler creates in /proc/scsi_tgt/
subdirectories "vdisk" and "vcdrom". They have similar layout:
subdirectories "vdisk" and "vcdrom". They have the following layout:
- "trace_level" and "type" files as described above
@@ -665,16 +982,206 @@ mode is used.
For example, "echo "open disk1 /vdisks/disk1" >/proc/scsi_tgt/vdisk/vdisk"
will open file /vdisks/disk1 as virtual FILEIO disk with name "disk1".
Also the VDISK handler has module parameter "num_threads", which
specifies count of I/O threads for each VDISK's device. If you have a
workload, which tends to produce rather random accesses (e.g. DB-like),
you should increase this count to a bigger value, like 32. If you have a
rather sequential workload, you should decrease it to a lower value,
like number of CPUs on the target or even 1. Due to some limitations of
Linux I/O subsystem, increasing number of I/O threads leads to
performance drop, especially with deadline scheduler, so decreasing it
can improve sequential performance. The default provides a good
compromise between random and sequential accesses.
/sys interface
~~~~~~~~~~~~~~
Starting from 2.0.0 VDISK device handler has sysfs interface. You can
switch to it by running "make disable_proc". To switch back to the
procfs interface you should run "make enable_proc". The procfs interface
starting from version 2.0.0 is obsolete and will be removed in one of
the next versions.
VDISK has 4 built-in dev handlers: vdisk_fileio, vdisk_blockio,
vdisk_nullio and vcdrom. Roots of their sysfs interface are
/sys/kernel/scst_tgt/handlers/handler_name, e.g. for vdisk_fileio:
/sys/kernel/scst_tgt/handlers/vdisk_fileio. Each root has the following
entries:
- None, one or more links to devices with name equal to names
of the corresponding devices.
- trace_level - allows to enable and disable various tracing
facilities. See content of this file for help how to use it.
- mgmt - main management entry, which allows to add/delete VDISK
devices with the corresponding type.
The "mgmt" file has the following commands, which you can send to it,
for instance, using "echo" shell command. You can always get a small
help about supported commands by looking inside this file. "Parameters"
are one or more param_name=value pairs separated by ';'.
- echo "add_device device_name [parameters]" - adds a virtual device
with name device_name and specified parameters (see below)
- echo "del_device device_name" - deletes a virtual device with name
device_name.
Handler vdisk_fileio provides FILEIO mode to create virtual devices.
This mode uses as backend files and accesses to them using regular
read()/write() file calls. This allows to use full power of Linux page
cache. The following parameters possible for vdisk_fileio:
- filename - specifies path and file name of the backend file. The path
must be absolute.
- blocksize - specifies block size used by this virtual device. The
block size must be power of 2 and >= 512 bytes. Default is 512.
- write_through - disables write back caching. Note, this option
has sense only if you also *manually* disable write-back cache in
*all* your backstorage devices and make sure it's actually disabled,
since many devices are known to lie about this mode to get better
benchmark results. Default is 0.
- read_only - read only. Default is 0.
- o_direct - disables both read and write caching. This mode isn't
currently fully implemented, you should use user space fileio_tgt
program in O_DIRECT mode instead (see below).
- nv_cache - enables "non-volatile cache" mode. In this mode it is
assumed that the target has a GOOD UPS with ability to cleanly
shutdown target in case of power failure and it is software/hardware
bugs free, i.e. all data from the target's cache are guaranteed
sooner or later to go to the media. Hence all data synchronization
with media operations, like SYNCHRONIZE_CACHE, are ignored in order
to bring more performance. Also in this mode target reports to
initiators that the corresponding device has write-through cache to
disable all write-back cache workarounds used by initiators. Use with
extreme caution, since in this mode after a crash of the target
journaled file systems don't guarantee the consistency after journal
recovery, therefore manual fsck MUST be ran. Note, that since usually
the journal barrier protection (see "IMPORTANT" note below) turned
off, enabling NV_CACHE could change nothing from data protection
point of view, since no data synchronization with media operations
will go from the initiator. This option overrides "write_through"
option. Disabled by default.
- removable - with this flag set the device is reported to remote
initiators as removable.
Handler vdisk_blockio provides BLOCKIO mode to create virtual devices.
This mode performs direct block I/O with a block device, bypassing the
page cache for all operations. This mode works ideally with high-end
storage HBAs and for applications that either do not need caching
between application and disk or need the large block throughput. See
below for more info.
The following parameters possible for vdisk_blockio: filename,
blocksize, read_only, removable. See vdisk_fileio above for description
of those parameters.
Handler vdisk_nullio provides NULLIO mode to create virtual devices. In
this mode no real I/O is done, but success returned to initiators.
Intended to be used for performance measurements at the same way as
"*_perf" handlers. The following parameters possible for vdisk_nullio:
blocksize, read_only, removable. See vdisk_fileio above for description
of those parameters.
Handler vcdrom allows emulation of a virtual CDROM device using an ISO
file as backend. It doesn't have any parameters.
For example:
echo "add_device disk1 filename=/disk1; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
will create a FILEIO virtual device disk1 with backend file /disk1
with block size 4K and NV_CACHE enabled.
Each vdisk_fileio's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name:
- filename - contains path and file name of the backend file.
- blocksize - contains block size used by this virtual device.
- write_through - contains status of write back caching of this virtual
device.
- read_only - contains read only status of this virtual device.
- o_direct - contains O_DIRECT status of this virtual device.
- nv_cache - contains NV_CACHE status of this virtual device.
- removable - contains removable status of this virtual device.
- size_mb - contains size of this virtual device in MB.
- t10_dev_id - contains and allows to set T10 vendor specific
identifier for Device Identification VPD page (0x83) of INQUIRY data.
By default VDISK handler always generates t10_dev_id for every new
created device at creation time based on the device name and
scst_vdisk_ID scst_vdisk.ko module parameter (see below).
- usn - contains the virtual device's serial number of INQUIRY data. It
is created at the device creation time based on the device name and
scst_vdisk_ID scst_vdisk.ko module parameter (see below).
- type - contains SCSI type of this virtual device.
- resync_size - write only attribute, which makes vdisk_fileio to
rescan size of the backend file. It is usful if you changed it, for
instance, if you resized it.
For example:
/sys/kernel/scst_tgt/devices/disk1
|-- blocksize
|-- exported
| |-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/0
| |-- export1 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_group/INI/luns/0
| |-- export2 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/0
| |-- export3 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/INI1/luns/0
| |-- export4 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/INI2/luns/0
|-- filename
|-- handler -> ../../handlers/vdisk_fileio
|-- nv_cache
|-- o_direct
|-- read_only
|-- removable
|-- resync_size
|-- size_mb
|-- t10_dev_id
|-- type
|-- usn
`-- write_through
Each vdisk_blockio's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name: blocksize, filename,
read_only, removable, resync_size, size_mb, t10_dev_id, type, usn. See
description of vdisk_fileio's device for description of those parameters.
Each vdisk_nullio's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name: blocksize, read_only,
removable, size_mb, t10_dev_id, type, usn. See description
of vdisk_fileio's device for description of those parameters.
Each vcdrom's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name: filename, size_mb,
t10_dev_id, type, usn. See description of vdisk_fileio's device for
description of those parameters. Exception is filename attribute. For
vcdrom it is writable. Writing to it allows to virtually insert or
change virtual CD media in the virtual CDROM device. For example:
- echo "/image.iso" >/sys/kernel/scst_tgt/devices/cdrom/filename - will
insert file /image.iso as virtual media to the virtual CDROM cdrom.
- echo "" >/sys/kernel/scst_tgt/devices/cdrom/filename - will remove
"media" from the virtual CDROM cdrom.
Additionally to the sysfs/procfs interface VDISK handler has module
parameter "num_threads", which specifies count of I/O threads for each
VDISK's device. If you have a workload, which tends to produce rather
random accesses (e.g. DB-like), you should increase this count to a
bigger value, like 32. If you have a rather sequential workload, you
should decrease it to a lower value, like number of CPUs on the target
or even 1. Due to some limitations of Linux I/O subsystem, increasing
number of I/O threads too much leads to sequential performance drop,
especially with deadline scheduler, so decreasing it can improve
sequential performance. The default provides a good compromise between
random and sequential accesses.
You shouldn't be afraid to have too many VDISK I/O threads if you have
many VDISK devices. Kernel threads consume very little amount of
@@ -704,7 +1211,6 @@ CAUTION: If you partitioned/formatted your device with block size X, *NEVER*
IMPORTANT: By default for performance reasons VDISK FILEIO devices use write
========= back caching policy. This is generally safe from the consistence of
journaled file systems, laying over them, point of view, but
your unsaved cached data will be lost in case of
power/hardware/software failure, so you must supply your
+544 -26
View File
@@ -37,6 +37,7 @@ In addition, SCST supports advanced per-initiator access and devices
visibility management, so different initiators could see different set
of devices with different access permissions. See below for details.
Installation
------------
@@ -98,7 +99,7 @@ Usage in failover mode
----------------------
It is recommended to use TEST UNIT READY ("tur") command to check if
SCST target is alive.
SCST target is alive in MPIO configurations.
Device handlers
@@ -145,6 +146,7 @@ NOTE: Since "perf" device handlers on READ operations don't touch the
was allocated, without even being zeroed. Thus, "perf" device
handlers impose some security risk, so use them with caution.
Compilation options
-------------------
@@ -232,7 +234,8 @@ your favorite kernel configuration Makefile target, e.g. "make xconfig":
- CONFIG_SCST_MEASURE_LATENCY - if defined, provides in /proc/scsi_tgt/latency
file average commands processing latency. You can clear already
measured results by writing 0 in this file. Note, you need a
measured results by writing 0 in this file. For the sysfs build you
can find those results in /sys/kernel/scst_tgt and below. Note, you need a
non-preemptible kernel to have correct results.
HIGHMEM kernel configurations are fully supported, but not recommended
@@ -254,6 +257,7 @@ For changing VMSPLIT option (CONFIG_VMSPLIT to be precise) you should in
memory you have. If it is less than 800MB, you may not touch this
option at all.
Module parameters
-----------------
@@ -266,12 +270,15 @@ Module scst supports the following parameters:
consumed by the SCST commands for data buffers at any given time. By
default it is approximately TotalMem/4.
SCST /proc commands
---------------------
SCST /proc interface
--------------------
For communications with user space programs SCST provides proc-based
interface in /proc/scsi_tgt directory. It contains the following
entries:
interface in /proc/scsi_tgt directory. This interface is available in
the procfs build only. Starting from version 2.0.0 it is obsolete and
will be removed in one of the next versions. It contains the following
entries.
- "help" file, which provides online help for SCST commands
@@ -324,8 +331,9 @@ For example, "echo "assign 1:0:1:0 dev_disk" >/proc/scsi_tgt/scsi_tgt"
will assign device handler "dev_disk" to real device sitting on host 1,
channel 0, ID 1, LUN 0.
Access and devices visibility management (LUN masking)
------------------------------------------------------
Access and devices visibility management (LUN masking) - /proc interface
------------------------------------------------------------------------
Access and devices visibility management allows for an initiator or
group of initiators to see different devices with different LUNs
@@ -403,15 +411,15 @@ following files and directories under /proc/scsi_tgt:
H:C:I:L numbers is use of lsscsi utility.
- "add V_NAME lun [READ_ONLY]" to /proc/scsi_tgt/groups/GROUP_NAME/devices adds
device with virtual name "V_NAME" with LUN "lun" in group
"GROUP_NAME". Optionally, the device could be marked as read only.
device with virtual name "V_NAME" with LUN "lun" in group "GROUP_NAME".
Optionally, the device could be marked as read only.
- "replace V_NAME lun [READ_ONLY]" to /proc/scsi_tgt/groups/GROUP_NAME/devices
replaces by device with virtual name "V_NAME" existing with LUN
"lun" device in group "GROUP_NAME" with generation of INQUIRY DATA
HAS CHANGED Unit Attention. If the old device doesn't exist, this
command acts as the "add" command. Optionally, the device could be
marked as read only.
command acts as the "add" command. Optionally, the device could
be marked as read only.
- "del V_NAME" to /proc/scsi_tgt/groups/GROUP_NAME/devices deletes device with
virtual name "V_NAME" from group "GROUP_NAME"
@@ -471,8 +479,8 @@ IMPORTANT
There must be LUN 0 in each security group, i.e. LUs numeration must not
start from, e.g., 1. Otherwise you will see no devices on remote
initiators and SCST core will write into the kernel log message:
"tgt_dev for LUN 0 not found, command to unexisting LU?"
initiators and SCST core will write into the kernel log message: "tgt_dev
for LUN 0 not found, command to unexisting LU?"
IMPORTANT
=========
@@ -498,11 +506,326 @@ target driver load and then only add new devices to new groups for new
initiators or add new devices to old groups, but not altering existing
LUNs in them.
SCST sysfs interface
--------------------
Starting from 2.0.0 SCST has sysfs interface. You can switch to it by
running "make disable_proc". To switch back to the procfs interface you
should run "make enable_proc".
Root of SCST sysfs interface is /sys/kernel/scst_tgt. It has the
following entries:
- devices - this is a root subdirectory for all SCST devices
- handlers - this is a root subdirectory for all SCST dev handlers
- sgv - this is a root subdirectory for all SCST SGV caches
- targets - this is a root subdirectory for all SCST targets
- threads - allows to read and set number of global SCST I/O threads.
Those threads used with async. dev handlers, for instance, vdisk
BLOCKIO or NULLIO.
- trace_level - allows to enable and disable various tracing
facilities. See content of this file for help how to use it.
- version - read-only attribute, which allows to see version of
SCST and enabled optional features.
Each SCST sysfs file (attribute) can contain in the last line mark
"[key]". It is automatically added mark used to allow scstadmin to see
which attributes it should save in the config file. You can ignore it.
"Devices" subdirectory contains subdirectories for each SCST devices.
Content of each device's subdirectory is dev handler specific. See
documentation for your dev handlers for more info about it as well as
SysfsRules file for more info about common to all dev handlers rules.
Standard SCST dev handlers have at least the following common entries:
- exported - subdirectory containing links to all LUNs where this
device was exported.
- handler - if dev handler determined for this device, this link points
to it. The handler can be not set for pass-through devices.
- type - SCSI type of this device
See below for more information about other entries of this subdirectory
of the standard SCST dev handlers.
"Handlers" subdirectory contains subdirectories for each SCST dev
handler.
Content of each handler's subdirectory is dev handler specific. See
documentation for your dev handlers for more info about it as well as
SysfsRules file for more info about common to all dev handlers rules.
Standard SCST dev handlers have at least the following common entries:
- pass_through - if exists, it contains 1 and this dev handler is a
pass-through dev handler.
- trace_level - allows to enable and disable various tracing
facilities. See content of this file for help how to use it.
- type - SCSI type of devices served by this dev handler.
See below for more information about other entries of this subdirectory
of the standard SCST dev handlers.
"Sgv" subdirectory contains statistic information of SCST SGV caches. It
has the following entries:
- None, one or more subdirectories for each existing SGV cache.
- global_stats - file containing global SGV caches statistics.
Each SGV cache's subdirectory has the following item:
- stats - file containing statistics for this SGV caches.
"Targets" subdirectory contains subdirectories for each SCST target.
Content of each target's subdirectory is target specific. See
documentation for your target for more info about it as well as
SysfsRules file for more info about common to all dev handlers rules.
Every target should have at least the following entries:
- ini_group - subdirectory, which contains and allows to define
initiator-oriented access control information, see below.
- luns - subdirectory, which contains list of available LUNs in the
target-oriented access control and allows to define it, see below.
- sessions - subdirectory containing connected to this target sessions.
- enabled - using this attribute you can enable or disable this target/
It allows to finish configuring it before it starts accepting new
connections. 0 by default.
- rel_tgt_id - allows to read or write SCSI Relative Target Port
Identifier attribute. This identifier is used to identify SCSI Target
Ports by some SCSI commands, mainly by Persistent Reservations
commands. This identifier must be unique among all SCST targets, but
for convenience SCST allows disabled targets to have not unique
rel_tgt_id. In this case SCST will not allow to enable this target
until rel_tgt_id becomes unique. This attribute initialized unique by
SCST by default.
Subdirectory "sessions" contains one subdirectory for each connected
session with name equal to name of the connected initiator.
Each session subdirectory contains the following entries:
- initiator_name - contains initiator name
- force_close - optional write-only attribute, which allows to force
close this session.
- active_commands - contains number of active, i.e. not yet or being
executed, SCSI commands in this session.
- commands - contains overall number of SCSI commands in this session.
- other target driver specific attributes and subdirectories.
See below description of the VDISK's sysfs interface for samples.
Access and devices visibility management (LUN masking) - sysfs interface
------------------------------------------------------------------------
Access and devices visibility management allows for an initiator or
group of initiators to see different devices with different LUNs
with necessary access permissions.
SCST supports two modes of access control:
1. Target-oriented. In this mode you define for each target a default
set of LUNs, which are accessible to all initiators, connected to that
target. This is a regular access control mode, which people usually mean
thinking about access control in general. For instance, in IET this is
the only supported mode.
2. Initiator-oriented. In this mode you define which LUNs are accessible
for each initiator. In this mode you should create for each set of one
or more initiators, which should access to the same set of devices with
the same LUNs, a separate security group, then add to it devices and
names of allowed initiator(s).
Both modes can be used simultaneously. In this case the
initiator-oriented mode has higher priority, than the target-oriented,
i.e. initiators are at first searched in all defined security groups for
this target and, if none matches, the default target's set of LUNs is
used. This set of LUNs might be empty, then the initiator will not see
any LUNs from the target.
You can at any time find out which set of LUNs each session is assigned
to by looking where link
/sys/kernel/scst_tgt/targets/target_driver/target_name/sessions/initiator_name/luns
points to.
To configure the target-oriented access control SCST provides the
following interface. Each target's sysfs subdirectory
(/sys/kernel/scst_tgt/targets/target_driver/target_name) has "luns"
subdirectory. This subdirectory contains the list of already defined
target-oriented access control LUNs for this target as well as file
"mgmt". This file has the following commands, which you can send to it,
for instance, using "echo" shell command. You can always get a small
help about supported commands by looking inside this file. "Parameters"
are one or more param_name=value pairs separated by ';'.
- "add H:C:I:L lun [parameters]" - adds a pass-through device with
host:channel:id:lun with LUN "lun". Optionally, the device could be
marked as read only by using parameter "read_only". The recommended
way to find out H:C:I:L numbers is use of lsscsi utility.
- "replace H:C:I:L lun [parameters]" - replaces by pass-through device
with host:channel:id:lun existing with LUN "lun" device with
generation of INQUIRY DATA HAS CHANGED Unit Attention. If the old
device doesn't exist, this command acts as the "add" command.
Optionally, the device could be marked as read only by using
parameter "read_only". The recommended way to find out H:C:I:L
numbers is use of lsscsi utility.
- "del H:C:I:L" - deletes a pass-through device with host:channel:id:lun
The recommended way to find out H:C:I:L numbers is use of lsscsi
utility.
- "add VNAME lun [parameters]" - adds a virtual device with name VNAME
with LUN "lun". Optionally, the device could be marked as read only
by using parameter "read_only".
- "replace VNAME lun [parameters]" - replaces by virtual device
with name VNAME existing with LUN "lun" device with generation of
INQUIRY DATA HAS CHANGED Unit Attention. If the old device doesn't
exist, this command acts as the "add" command. Optionally, the device
could be marked as read only by using parameter "read_only".
- "del VNAME" - deletes a virtual device with name VNAME.
- "clear" - clears the list of devices
To configure the initiator-oriented access control SCST provides the
following interface. Each target's sysfs subdirectory
(/sys/kernel/scst_tgt/targets/target_driver/target_name) has "ini_group"
subdirectory. This subdirectory contains the list of already defined
security groups for this target as well as file "mgmt". This file has
the following commands, which you can send to it, for instance, using
"echo" shell command. You can always get a small help about supported
commands by looking inside this file.
- "create GROUP_NAME" - creates a new security group.
- "del GROUP_NAME" - deletes a new security group.
Each security group's subdirectory contains 2 subdirectories: initiators
and luns.
Each "initiators" subdirectory contains list of added to this groups
initiator as well as as well as file "mgmt". This file has the following
commands, which you can send to it, for instance, using "echo" shell
command. You can always get a small help about supported commands by
looking inside this file.
- "add INITIATOR_NAME" - adds initiator with name INITIATOR_NAME to the
group.
- "del INITIATOR_NAME" - deletes initiator with name INITIATOR_NAME
from the group.
- "move INITIATOR_NAME DEST_GROUP_NAME" moves initiator with name
INITIATOR_NAME from the current group to group with name
DEST_GROUP_NAME.
- "clear" - deletes all initiators from this group.
For "add" and "del" commands INITIATOR_NAME can be a simple DOS-type
patterns, containing '*' and '?' symbols. '*' means match all any
symbols, '?' means match only any single symbol. For instance,
"blah.xxx" will match "bl?h.*".
Each "luns" subdirectory contains the list of already defined LUNs for
this group as well as file "mgmt". Content of this file as well as list
of available in it commands is fully identical to the "luns"
sybdirectory of the target-oriented access control.
Examples:
- echo "create INI" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/mgmt -
creates security group INI for target iqn.2006-10.net.vlnb:tgt1.
- echo "add 2:0:1:0 11" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/INI/luns/mgmt -
adds a pass-through device sitting on host 2, channel 0, ID 1, LUN 0
to group with name INI as LUN 11.
- echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/INI/luns/mgmt -
adds a virtual disk with name disk1 to group with name INI as LUN 0.
- echo "add 21:*:e0:?b:83:*" >/sys/kernel/scst_tgt/targets/21:00:00:a0:8c:54:52:12/ini_group/INI/initiators/mgmt -
adds a pattern to group with name INI to Fibre Channel target with
WWN 21:00:00:a0:8c:54:52:12, which matches WWNs of Fibre Channel
initiator ports.
Consider you need to have an iSCSI target with name
"iqn.2007-05.com.example:storage.disk1.sys1.xyz", which should export
virtual device "dev1" with LUN 0 and virtual device "dev2" with LUN 1,
but initiator with name
"iqn.2007-05.com.example:storage.disk1.spec_ini.xyz" should see only
virtual device "dev2" read only with LUN 0. To achieve that you should
do the following commands:
# echo "iqn.2007-05.com.example:storage.disk1.sys1.xyz" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
# echo "add dev1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/luns/mgmt
# echo "add dev2 1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/luns/mgmt
# echo "create SPEC_INI" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_group/mgmt
# echo "add dev2 0 read_only=1" \
>/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_group/SPEC_INI/luns/mgmt
# echo "iqn.2007-05.com.example:storage.disk1.spec_ini.xyz" \
>/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_group/SPEC_INI/initiators/mgmt
For Fibre Channel or SAS in the above example you should use target's
and initiator ports WWNs instead of iSCSI names.
It is highly recommended to use scstadmin utility instead of described
in this section low level interface.
IMPORTANT
=========
There must be LUN 0 in each set of LUNs, i.e. LUs numeration must not
start from, e.g., 1. Otherwise you will see no devices on remote
initiators and SCST core will write into the kernel log message: "tgt_dev
for LUN 0 not found, command to unexisting LU?"
IMPORTANT
=========
All the access control must be fully configured BEFORE the corresponding
target is enabled! When you enable a target, it will immediately start
accepting new connections, hence creating new sessions, and those new
sessions will be assigned to security groups according to the
*currently* configured access control settings. For instance, to
the default target's set of LUNs, instead of "HOST004" group as you may
need, because "HOST004" doesn't exist yet. So, one must configure all
the security groups before new connections from the initiators are
created, i.e. before the target enabled.
VDISK device handler
--------------------
/proc interface
~~~~~~~~~~~~~~~
This interface starting from version 2.0.0 is obsolete and will be
removed in one of the next versions.
After loading VDISK device handler creates in /proc/scsi_tgt/
subdirectories "vdisk" and "vcdrom". They have similar layout:
subdirectories "vdisk" and "vcdrom". They have the following layout:
- "trace_level" and "type" files as described above
@@ -582,16 +905,207 @@ mode is used.
For example, "echo "open disk1 /vdisks/disk1" >/proc/scsi_tgt/vdisk/vdisk"
will open file /vdisks/disk1 as virtual FILEIO disk with name "disk1".
Also the VDISK handler has module parameter "num_threads", which
specifies count of I/O threads for each VDISK's device. If you have a
workload, which tends to produce rather random accesses (e.g. DB-like),
you should increase this count to a bigger value, like 32. If you have a
rather sequential workload, you should decrease it to a lower value,
like number of CPUs on the target or even 1. Due to some limitations of
Linux I/O subsystem, increasing number of I/O threads leads to
performance drop, especially with deadline scheduler, so decreasing it
can improve sequential performance. The default provides a good
compromise between random and sequential accesses.
/sys interface
~~~~~~~~~~~~~~
Starting from 2.0.0 VDISK device handler has sysfs interface. You can
switch to it by running "make disable_proc". To switch back to the
procfs interface you should run "make enable_proc". The procfs interface
starting from version 2.0.0 is obsolete and will be removed in one of
the next versions.
VDISK has 4 built-in dev handlers: vdisk_fileio, vdisk_blockio,
vdisk_nullio and vcdrom. Roots of their sysfs interface are
/sys/kernel/scst_tgt/handlers/handler_name, e.g. for vdisk_fileio:
/sys/kernel/scst_tgt/handlers/vdisk_fileio. Each root has the following
entries:
- None, one or more links to devices with name equal to names
of the corresponding devices.
- trace_level - allows to enable and disable various tracing
facilities. See content of this file for help how to use it.
- mgmt - main management entry, which allows to add/delete VDISK
devices with the corresponding type.
The "mgmt" file has the following commands, which you can send to it,
for instance, using "echo" shell command. You can always get a small
help about supported commands by looking inside this file. "Parameters"
are one or more param_name=value pairs separated by ';'.
- echo "add_device device_name [parameters]" - adds a virtual device
with name device_name and specified parameters (see below)
- echo "del_device device_name" - deletes a virtual device with name
device_name.
Handler vdisk_fileio provides FILEIO mode to create virtual devices.
This mode uses as backend files and accesses to them using regular
read()/write() file calls. This allows to use full power of Linux page
cache. The following parameters possible for vdisk_fileio:
- filename - specifies path and file name of the backend file. The path
must be absolute.
- blocksize - specifies block size used by this virtual device. The
block size must be power of 2 and >= 512 bytes. Default is 512.
- write_through - disables write back caching. Note, this option
has sense only if you also *manually* disable write-back cache in
*all* your backstorage devices and make sure it's actually disabled,
since many devices are known to lie about this mode to get better
benchmark results. Default is 0.
- read_only - read only. Default is 0.
- o_direct - disables both read and write caching. This mode isn't
currently fully implemented, you should use user space fileio_tgt
program in O_DIRECT mode instead (see below).
- nv_cache - enables "non-volatile cache" mode. In this mode it is
assumed that the target has a GOOD UPS with ability to cleanly
shutdown target in case of power failure and it is software/hardware
bugs free, i.e. all data from the target's cache are guaranteed
sooner or later to go to the media. Hence all data synchronization
with media operations, like SYNCHRONIZE_CACHE, are ignored in order
to bring more performance. Also in this mode target reports to
initiators that the corresponding device has write-through cache to
disable all write-back cache workarounds used by initiators. Use with
extreme caution, since in this mode after a crash of the target
journaled file systems don't guarantee the consistency after journal
recovery, therefore manual fsck MUST be ran. Note, that since usually
the journal barrier protection (see "IMPORTANT" note below) turned
off, enabling NV_CACHE could change nothing from data protection
point of view, since no data synchronization with media operations
will go from the initiator. This option overrides "write_through"
option. Disabled by default.
- removable - with this flag set the device is reported to remote
initiators as removable.
Handler vdisk_blockio provides BLOCKIO mode to create virtual devices.
This mode performs direct block I/O with a block device, bypassing the
page cache for all operations. This mode works ideally with high-end
storage HBAs and for applications that either do not need caching
between application and disk or need the large block throughput. See
below for more info.
The following parameters possible for vdisk_blockio: filename,
blocksize, read_only, removable. See vdisk_fileio above for description
of those parameters.
Handler vdisk_nullio provides NULLIO mode to create virtual devices. In
this mode no real I/O is done, but success returned to initiators.
Intended to be used for performance measurements at the same way as
"*_perf" handlers. The following parameters possible for vdisk_nullio:
blocksize, read_only, removable. See vdisk_fileio above for description
of those parameters.
Handler vcdrom allows emulation of a virtual CDROM device using an ISO
file as backend. It doesn't have any parameters.
For example:
echo "add_device disk1 filename=/disk1; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
will create a FILEIO virtual device disk1 with backend file /disk1
with block size 4K and NV_CACHE enabled.
Each vdisk_fileio's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name:
- filename - contains path and file name of the backend file.
- blocksize - contains block size used by this virtual device.
- write_through - contains status of write back caching of this virtual
device.
- read_only - contains read only status of this virtual device.
- o_direct - contains O_DIRECT status of this virtual device.
- nv_cache - contains NV_CACHE status of this virtual device.
- removable - contains removable status of this virtual device.
- size_mb - contains size of this virtual device in MB.
- t10_dev_id - contains and allows to set T10 vendor specific
identifier for Device Identification VPD page (0x83) of INQUIRY data.
By default VDISK handler always generates t10_dev_id for every new
created device at creation time based on the device name and
scst_vdisk_ID scst_vdisk.ko module parameter (see below).
- usn - contains the virtual device's serial number of INQUIRY data. It
is created at the device creation time based on the device name and
scst_vdisk_ID scst_vdisk.ko module parameter (see below).
- type - contains SCSI type of this virtual device.
- resync_size - write only attribute, which makes vdisk_fileio to
rescan size of the backend file. It is usful if you changed it, for
instance, if you resized it.
For example:
/sys/kernel/scst_tgt/devices/disk1
|-- blocksize
|-- exported
| |-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/0
| |-- export1 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_group/INI/luns/0
| |-- export2 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/0
| |-- export3 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/INI1/luns/0
| |-- export4 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_group/INI2/luns/0
|-- filename
|-- handler -> ../../handlers/vdisk_fileio
|-- nv_cache
|-- o_direct
|-- read_only
|-- removable
|-- resync_size
|-- size_mb
|-- t10_dev_id
|-- type
|-- usn
`-- write_through
Each vdisk_blockio's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name: blocksize, filename,
read_only, removable, resync_size, size_mb, t10_dev_id, type, usn. See
description of vdisk_fileio's device for description of those parameters.
Each vdisk_nullio's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name: blocksize, read_only,
removable, size_mb, t10_dev_id, type, usn. See description
of vdisk_fileio's device for description of those parameters.
Each vcdrom's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name: filename, size_mb,
t10_dev_id, type, usn. See description of vdisk_fileio's device for
description of those parameters. Exception is filename attribute. For
vcdrom it is writable. Writing to it allows to virtually insert or
change virtual CD media in the virtual CDROM device. For example:
- echo "/image.iso" >/sys/kernel/scst_tgt/devices/cdrom/filename - will
insert file /image.iso as virtual media to the virtual CDROM cdrom.
- echo "" >/sys/kernel/scst_tgt/devices/cdrom/filename - will remove
"media" from the virtual CDROM cdrom.
Additionally to the sysfs/procfs interface VDISK handler has module
parameter "num_threads", which specifies count of I/O threads for each
VDISK's device. If you have a workload, which tends to produce rather
random accesses (e.g. DB-like), you should increase this count to a
bigger value, like 32. If you have a rather sequential workload, you
should decrease it to a lower value, like number of CPUs on the target
or even 1. Due to some limitations of Linux I/O subsystem, increasing
number of I/O threads too much leads to sequential performance drop,
especially with deadline scheduler, so decreasing it can improve
sequential performance. The default provides a good compromise between
random and sequential accesses.
You shouldn't be afraid to have too many VDISK I/O threads if you have
many VDISK devices. Kernel threads consume very little amount of
@@ -621,7 +1135,6 @@ CAUTION: If you partitioned/formatted your device with block size X, *NEVER*
IMPORTANT: By default for performance reasons VDISK FILEIO devices use write
========= back caching policy. This is generally safe from the consistence of
journaled file systems, laying over them, point of view, but
your unsaved cached data will be lost in case of
power/hardware/software failure, so you must supply your
@@ -679,6 +1192,7 @@ IMPORTANT: Some disk and partition table management utilities don't support
size device, the block size stops matter, any program will
work with files on such file system.
BLOCKIO VDISK mode
------------------
@@ -710,6 +1224,7 @@ IMPORTANT: Since data in BLOCKIO and FILEIO modes are not consistent between
========= them, if you try to use a device in both those modes simultaneously,
you will almost instantly corrupt your data on that device.
Pass-through mode
-----------------
@@ -742,6 +1257,7 @@ Another way to solve this issue is to build SG entries with more than 1
page each. See the following patch as an example:
http://scst.sf.net/sgv_big_order_alloc.diff
User space mode using scst_user dev handler
-------------------------------------------
@@ -754,6 +1270,7 @@ loads it could be significantly faster, than the regular FILEIO access.
All the words about BLOCKIO from above apply to O_DIRECT as well. See
fileio_tgt's README file for more details.
Performance
-----------
@@ -998,6 +1515,7 @@ or initiator-target link, you can increase SCST_MAX_TGT_DEV_COMMANDS in
scst_priv.h to 64. Usually initiators don't try to push more commands on
the target.
Credits
-------
+76 -6
View File
@@ -848,7 +848,7 @@ struct scst_tgt_template {
*
* MUST HAVE if virtual targets are supported.
*/
ssize_t (*add_target) (const char *target_name, const char *params);
ssize_t (*add_target) (const char *target_name, char *params);
/*
* This function deletes a virtual target. See comment for add_target
@@ -861,11 +861,11 @@ struct scst_tgt_template {
/*
* This function called if not "add_target" or "del_target" command is
* sent to the mgmt entry (see comment for add_target above). In this
* case the command passed in this function as is in a string form.
* case the command passed to this function as is in a string form.
*
* OPTIONAL.
*/
ssize_t (*mgmt_cmd) (const char *cmd);
ssize_t (*mgmt_cmd) (char *cmd);
/*
* Name of the template. Must be unique to identify
@@ -907,6 +907,9 @@ struct scst_tgt_template {
/* Optional help string for mgmt_cmd commands */
const char *mgmt_cmd_help;
/* Optional help string for add_target parameters */
const char *add_target_parameters_help;
/** Private, must be inited to 0 by memset() **/
/* List of targets per template, protected by scst_mutex */
@@ -937,6 +940,9 @@ struct scst_dev_type {
/* SCSI type of the supported device. MUST HAVE */
int type;
/* True, if this dev handler is a pass-through dev handler */
unsigned pass_through:1;
/*
* True, if corresponding function supports execution in
* the atomic (non-sleeping) context
@@ -946,12 +952,12 @@ struct scst_dev_type {
unsigned dev_done_atomic:1;
#ifdef CONFIG_SCST_PROC
/* Set, if no /proc files should be automatically created by SCST */
/* True, if no /proc files should be automatically created by SCST */
unsigned no_proc:1;
#endif
/*
* Should be set, if exec() is synchronous. This is a hint to SCST core
* Should be true, if exec() is synchronous. This is a hint to SCST core
* to optimize commands order management.
*/
unsigned exec_sync:1;
@@ -1070,6 +1076,43 @@ struct scst_dev_type {
int (*read_proc) (struct seq_file *seq, struct scst_dev_type *dev_type);
int (*write_proc) (char *buffer, char **start, off_t offset,
int length, int *eof, struct scst_dev_type *dev_type);
#else
/*
* This function adds a virtual device.
*
* If both add_device and del_device callbacks defined, then this
* dev handler supposed to support adding/deleting virtual devices.
* In this case an "mgmt" entry will be created in the sysfs root for
* this handler. The "mgmt" entry will support 2 commands: "add_device"
* and "del_device", for which the corresponding callbacks will be called.
* Also dev handler can define own commands for the "mgmt" entry, see
* mgmt_cmd and mgmt_cmd_help below.
*
* This approach allows uniform devices management to simplify external
* management tools like scstadmin. See README for more details.
*
* Either both add_device and del_device must be defined, or none.
*
* MUST HAVE if virtual devices are supported.
*/
ssize_t (*add_device) (const char *device_name, char *params);
/*
* This function deletes a virtual device. See comment for add_device
* above.
*
* MUST HAVE if virtual devices are supported.
*/
ssize_t (*del_device) (const char *device_name);
/*
* This function called if not "add_device" or "del_device" command is
* sent to the mgmt entry (see comment for add_device above). In this
* case the command passed to this function as is in a string form.
*
* OPTIONAL.
*/
ssize_t (*mgmt_cmd) (char *cmd);
#endif
/*
@@ -1094,10 +1137,16 @@ struct scst_dev_type {
/* Optional local trace table */
struct scst_trace_log *trace_tbl;
#ifndef CONFIG_SCST_PROC
/* Optional local trace table help string */
const char *trace_tbl_help;
#ifndef CONFIG_SCST_PROC
/* Optional help string for mgmt_cmd commands */
const char *mgmt_cmd_help;
/* Optional help string for add_device parameters */
const char *add_device_parameters_help;
/* Optional sysfs attributes */
const struct attribute **devt_attrs;
@@ -3644,4 +3693,25 @@ int scst_wait_info_completion(struct scst_sysfs_user_info *info,
#endif /* CONFIG_SCST_PROC */
/*
* This function returns pointer to the next lexem from token_str skipping
* spaces and '=' character and using them then as a delimeter. Content
* of token_str is modified by setting '\0' at the delimeter's position.
*/
char *scst_get_next_lexem(char **token_str);
/*
* This function restores token_str modified by scst_get_next_lexem() to the
* previous value before scst_get_next_lexem() was called. Prev_lexem is
* a pointer to lexem returned by scst_get_next_lexem().
*/
void scst_restore_token_str(char *prev_lexem, char *token_str);
/*
* This function returns pointer to the next token strings from input_str
* using '\n', ';' and '\0' as a delimeter. Content of input_str is
* modified by setting '\0' at the delimeter's position.
*/
char *scst_get_next_token_str(char **input_str);
#endif /* __SCST_H */
+1
View File
@@ -42,6 +42,7 @@ static int cdrom_done(struct scst_cmd *);
static struct scst_dev_type cdrom_devtype = {
.name = CDROM_NAME,
.type = TYPE_ROM,
.pass_through = 1,
.parse_atomic = 1,
.dev_done_atomic = 1,
.attach = cdrom_attach,
+1
View File
@@ -38,6 +38,7 @@ static int changer_parse(struct scst_cmd *);
static struct scst_dev_type changer_devtype = {
.name = CHANGER_NAME,
.type = TYPE_MEDIUM_CHANGER,
.pass_through = 1,
.parse_atomic = 1,
/* .dev_done_atomic = 1, */
.attach = changer_attach,
+2
View File
@@ -48,6 +48,7 @@ static int disk_exec(struct scst_cmd *cmd);
static struct scst_dev_type disk_devtype = {
.name = DISK_NAME,
.type = TYPE_DISK,
.pass_through = 1,
.parse_atomic = 1,
.dev_done_atomic = 1,
.exec_atomic = 1,
@@ -64,6 +65,7 @@ static struct scst_dev_type disk_devtype = {
static struct scst_dev_type disk_devtype_perf = {
.name = DISK_PERF_NAME,
.type = TYPE_DISK,
.pass_through = 1,
.parse_atomic = 1,
.dev_done_atomic = 1,
.exec_atomic = 1,
+2
View File
@@ -48,6 +48,7 @@ static int modisk_exec(struct scst_cmd *);
static struct scst_dev_type modisk_devtype = {
.name = MODISK_NAME,
.type = TYPE_MOD,
.pass_through = 1,
.parse_atomic = 1,
.dev_done_atomic = 1,
.exec_atomic = 1,
@@ -64,6 +65,7 @@ static struct scst_dev_type modisk_devtype = {
static struct scst_dev_type modisk_devtype_perf = {
.name = MODISK_PERF_NAME,
.type = TYPE_MOD,
.pass_through = 1,
.parse_atomic = 1,
.dev_done_atomic = 1,
.exec_atomic = 1,
+1
View File
@@ -38,6 +38,7 @@ static int processor_parse(struct scst_cmd *);
static struct scst_dev_type processor_devtype = {
.name = PROCESSOR_NAME,
.type = TYPE_PROCESSOR,
.pass_through = 1,
.parse_atomic = 1,
/* .dev_done_atomic = 1,*/
.attach = processor_attach,
+1
View File
@@ -38,6 +38,7 @@ static int raid_parse(struct scst_cmd *);
static struct scst_dev_type raid_devtype = {
.name = RAID_NAME,
.type = TYPE_RAID,
.pass_through = 1,
.parse_atomic = 1,
/* .dev_done_atomic = 1,*/
.attach = raid_attach,
+2
View File
@@ -53,6 +53,7 @@ static int tape_exec(struct scst_cmd *);
static struct scst_dev_type tape_devtype = {
.name = TAPE_NAME,
.type = TYPE_TAPE,
.pass_through = 1,
.parse_atomic = 1,
.dev_done_atomic = 1,
.exec_atomic = 1,
@@ -69,6 +70,7 @@ static struct scst_dev_type tape_devtype = {
static struct scst_dev_type tape_devtype_perf = {
.name = TAPE_PERF_NAME,
.type = TYPE_TAPE,
.pass_through = 1,
.parse_atomic = 1,
.dev_done_atomic = 1,
.exec_atomic = 1,
File diff suppressed because it is too large Load Diff
+55 -1
View File
@@ -28,6 +28,7 @@
#include <linux/unistd.h>
#include <linux/string.h>
#include <asm/kmap_types.h>
#include <linux/ctype.h>
#include "scst.h"
#include "scst_priv.h"
@@ -5825,6 +5826,59 @@ out:
return;
}
char *scst_get_next_lexem(char **token_str)
{
char *p = *token_str;
char *q;
static const char blank = '\0';
if ((token_str == NULL) || (*token_str == NULL))
return (char *)&blank;
for (p = *token_str; (*p != '\0') && (isspace(*p) || (*p == '=')); p++)
;
for (q = p; (*q != '\0') && !isspace(*q) && (*q != '='); q++)
;
if (*q != '\0')
*q++ = '\0';
*token_str = q;
return p;
}
EXPORT_SYMBOL(scst_get_next_lexem);
void scst_restore_token_str(char *prev_lexem, char *token_str)
{
if (&prev_lexem[strlen(prev_lexem)] != token_str)
prev_lexem[strlen(prev_lexem)] = ' ';
return;
}
EXPORT_SYMBOL(scst_restore_token_str);
char *scst_get_next_token_str(char **input_str)
{
char *p = *input_str;
int i = 0;
while ((p[i] != '\n') && (p[i] != ';') && (p[i] != '\0'))
i++;
if (i == 0)
return NULL;
if (p[i] == '\0')
*input_str = &p[i];
else
*input_str = &p[i+1];
p[i] = '\0';
return p;
}
EXPORT_SYMBOL(scst_get_next_token_str);
static void __init scst_scsi_op_list_init(void)
{
int i;
@@ -5907,7 +5961,7 @@ unsigned long scst_random(void)
return rv;
}
EXPORT_SYMBOL(scst_random);
#endif
#endif /* CONFIG_SCST_DEBUG */
#ifdef CONFIG_SCST_DEBUG_TM
+31 -2
View File
@@ -737,7 +737,7 @@ EXPORT_SYMBOL(scst_resume_activity);
static int scst_register_device(struct scsi_device *scsidp)
{
int res = 0;
struct scst_device *dev;
struct scst_device *dev, *d;
struct scst_dev_type *dt;
TRACE_ENTRY();
@@ -766,6 +766,14 @@ static int scst_register_device(struct scsi_device *scsidp)
snprintf(dev->virt_name, 50, "%d:%d:%d:%d", scsidp->host->host_no,
scsidp->channel, scsidp->id, scsidp->lun);
list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
if (strcmp(d->virt_name, dev->virt_name) == 0) {
PRINT_ERROR("Device %s already exists", dev->virt_name);
res = -EEXIST;
goto out_free_dev;
}
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
dev->rq_disk = alloc_disk(1);
if (dev->rq_disk == NULL) {
@@ -893,6 +901,19 @@ static int scst_dev_handler_check(struct scst_dev_type *dev_handler)
goto out;
}
#ifndef CONFIG_SCST_PROC
if (((dev_handler->add_device != NULL) &&
(dev_handler->del_device == NULL)) ||
((dev_handler->add_device == NULL) &&
(dev_handler->del_device != NULL))) {
PRINT_ERROR("Dev handler %s must either define both "
"add_device() and del_device(), or none.",
dev_handler->name);
res = -EINVAL;
goto out;
}
#endif
if (dev_handler->exec == NULL) {
#ifdef CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
dev_handler->exec_atomic = 1;
@@ -913,7 +934,7 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
const char *dev_name)
{
int res, rc;
struct scst_device *dev = NULL;
struct scst_device *dev;
TRACE_ENTRY();
@@ -934,6 +955,14 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
if (res != 0)
goto out;
list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
if (strcmp(dev->virt_name, dev_name) == 0) {
PRINT_ERROR("Device %s already exists", dev_name);
res = -EEXIST;
goto out;
}
}
res = scst_suspend_activity(true);
if (res != 0)
goto out;
+2 -6
View File
@@ -726,13 +726,9 @@ void scst_check_debug_sn(struct scst_cmd *cmd);
static inline void scst_check_debug_sn(struct scst_cmd *cmd) {}
#endif
/*
* It deals with comparing 32 bit unsigned ints and worry about wraparound
* (automatic with unsigned arithmetic). Borrowed from net/tcp.h.
*/
static inline int scst_sn_before(__u32 seq1, __u32 seq2)
static inline int scst_sn_before(uint32_t seq1, uint32_t seq2)
{
return (__s32)(seq1-seq2) < 0;
return (int32_t)(seq1-seq2) < 0;
}
bool scst_is_relative_target_port_id_unique(uint16_t id, struct scst_tgt *t);
+384 -87
View File
@@ -118,9 +118,6 @@ static ssize_t scst_rel_tgt_id_show(struct kobject *kobj,
static ssize_t scst_rel_tgt_id_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count);
static ssize_t scst_acg_luns_mgmt_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf);
static ssize_t scst_acg_luns_mgmt_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count);
@@ -217,13 +214,21 @@ static ssize_t scst_tgtt_mgmt_show(struct kobject *kobj,
"%s"
"\n"
"where parameters are one or more "
"param_name=value pairs separated by ';'\n";
"param_name=value pairs separated by ';'\n"
"%s%s";
struct scst_tgt_template *tgtt;
tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
return sprintf(buf, help, (tgtt->mgmt_cmd_help != NULL) ?
tgtt->mgmt_cmd_help : "");
if (tgtt->add_target_parameters_help != NULL)
return sprintf(buf, help,
(tgtt->mgmt_cmd_help) ? tgtt->mgmt_cmd_help : "",
"\nThe following parameters available: ",
tgtt->add_target_parameters_help);
else
return sprintf(buf, help,
(tgtt->mgmt_cmd_help) ? tgtt->mgmt_cmd_help : "",
"", "");
}
static ssize_t scst_tgtt_mgmt_store(struct kobject *kobj,
@@ -231,7 +236,7 @@ static ssize_t scst_tgtt_mgmt_store(struct kobject *kobj,
const char *buf, size_t count)
{
int res;
char *buffer, *p, *target_name;
char *buffer, *p, *pp, *target_name;
struct scst_tgt_template *tgtt;
TRACE_ENTRY();
@@ -246,62 +251,38 @@ static ssize_t scst_tgtt_mgmt_store(struct kobject *kobj,
memcpy(buffer, buf, count);
buffer[count] = '\0';
p = buffer;
p = buffer;
if (p[strlen(p) - 1] == '\n')
p[strlen(p) - 1] = '\0';
pp = buffer;
if (pp[strlen(pp) - 1] == '\n')
pp[strlen(pp) - 1] = '\0';
if (strncasecmp("add_target ", p, 11) == 0) {
p += 11;
p = scst_get_next_lexem(&pp);
while (isspace(*p) && *p != '\0')
p++;
if (p == '\0')
goto out_syntax_err;
target_name = p;
while (!isspace(*p) && *p != '\0')
p++;
if (*p != '\0') {
*p = '\0';
p++;
if (strcasecmp("add_target", p) == 0) {
target_name = scst_get_next_lexem(&pp);
if (*target_name == '\0') {
PRINT_ERROR("%s", "Target name required");
res = -EINVAL;
goto out_free;
}
res = tgtt->add_target(target_name, pp);
} else if (strcasecmp("del_target", p) == 0) {
target_name = scst_get_next_lexem(&pp);
if (*target_name == '\0') {
PRINT_ERROR("%s", "Target name required");
res = -EINVAL;
goto out_free;
}
while (isspace(*p) && *p != '\0')
p++;
res = tgtt->add_target(target_name, p);
} else if (strncasecmp("del_target ", p, 11) == 0) {
p += 11;
while (isspace(*p) && *p != '\0')
p++;
if (p == '\0')
p = scst_get_next_lexem(&pp);
if (*p != '\0')
goto out_syntax_err;
target_name = p;
while (!isspace(*p) && *p != '\0')
p++;
if (*p != '\0') {
*p = '\0';
p++;
while (isspace(*p) && *p != '\0')
p++;
if (*p != '\0')
goto out_syntax_err;
}
res = tgtt->del_target(target_name);
} else if (tgtt->mgmt_cmd != NULL)
} else if (tgtt->mgmt_cmd != NULL) {
scst_restore_token_str(p, pp);
res = tgtt->mgmt_cmd(buffer);
else {
} else {
PRINT_ERROR("Unknown action \"%s\"", p);
res = -EINVAL;
goto out_free;
@@ -521,7 +502,7 @@ static struct kobj_attribute scst_luns_mgmt =
scst_luns_mgmt_store);
static struct kobj_attribute scst_acg_luns_mgmt =
__ATTR(mgmt, S_IRUGO | S_IWUSR, scst_acg_luns_mgmt_show,
__ATTR(mgmt, S_IRUGO | S_IWUSR, scst_luns_mgmt_show,
scst_acg_luns_mgmt_store);
static struct kobj_attribute scst_acg_ini_mgmt =
@@ -814,6 +795,14 @@ int scst_create_devt_dev_sysfs(struct scst_device *dev)
goto out;
}
retval = sysfs_create_link(&dev->handler->devt_kobj,
&dev->dev_kobj, dev->virt_name);
if (retval != 0) {
PRINT_ERROR("Can't create handler link for dev %s",
dev->virt_name);
goto out;
}
pattr = dev->handler->dev_attrs;
if (pattr != NULL) {
while (*pattr != NULL) {
@@ -852,6 +841,7 @@ void scst_devt_dev_sysfs_put(struct scst_device *dev)
}
sysfs_remove_link(&dev->dev_kobj, "handler");
sysfs_remove_link(&dev->handler->devt_kobj, dev->virt_name);
out:
TRACE_EXIT();
@@ -1206,6 +1196,13 @@ restart:
}
}
if (sess->acg == sess->tgt->default_acg)
retval = sysfs_create_link(&sess->sess_kobj,
sess->tgt->tgt_luns_kobj, "luns");
else
retval = sysfs_create_link(&sess->sess_kobj,
sess->acg->luns_kobj, "luns");
out_free:
if (name != sess->initiator_name)
kfree(name);
@@ -1260,8 +1257,10 @@ static ssize_t scst_lun_rd_only_show(struct kobject *kobj,
acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
return sprintf(buf, "%d\n",
(acg_dev->rd_only || acg_dev->dev->rd_only) ? 1 : 0);
if (acg_dev->rd_only || acg_dev->dev->rd_only)
return sprintf(buf, "%d\n%s\n", 1, SCST_SYSFS_KEY_MARK);
else
return sprintf(buf, "%d\n", 0);
}
static struct kobj_attribute lun_options_attr =
@@ -1464,12 +1463,49 @@ static ssize_t __scst_luns_mgmt_store(struct scst_acg *acg,
while (isspace(*e) && *e != '\0')
e++;
if (*e != '\0') {
if ((strncasecmp("READ_ONLY", e, 9) == 0) &&
(isspace(e[9]) || (e[9] == '\0')))
read_only = 1;
else {
PRINT_ERROR("Unknown option \"%s\"", e);
while (1) {
char *pp;
unsigned long val;
char *param = scst_get_next_token_str(&e);
if (param == NULL)
break;
p = scst_get_next_lexem(&param);
if (*p == '\0') {
PRINT_ERROR("Syntax error at %s (device %s)",
param, dev->virt_name);
res = -EINVAL;
goto out_free_up;
}
pp = scst_get_next_lexem(&param);
if (*pp == '\0') {
PRINT_ERROR("Parameter %s value missed for device %s",
p, dev->virt_name);
res = -EINVAL;
goto out_free_up;
}
if (scst_get_next_lexem(&param)[0] != '\0') {
PRINT_ERROR("Too many parameter's %s values (device %s)",
p, dev->virt_name);
res = -EINVAL;
goto out_free_up;
}
res = strict_strtoul(pp, 0, &val);
if (res != 0) {
PRINT_ERROR("strict_strtoul() for %s failed: %d "
"(device %s)", pp, res, dev->virt_name);
goto out_free_up;
}
if (!strcasecmp("read_only", p)) {
read_only = val;
TRACE_DBG("READ ONLY %d", read_only);
} else {
PRINT_ERROR("Unknown parameter %s (device %s)",
p, dev->virt_name);
res = -EINVAL;
goto out_free_up;
}
@@ -1578,16 +1614,19 @@ static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
static char *help = "Usage: echo \"add|del H:C:I:L lun [READ_ONLY]\" "
static char *help = "Usage: echo \"add|del H:C:I:L lun [parameters]\" "
">mgmt\n"
" echo \"add|del VNAME lun [READ_ONLY]\" "
" echo \"add|del VNAME lun [parameters]\" "
">mgmt\n"
" echo \"replace H:C:I:L lun [READ_ONLY]\" "
" echo \"replace H:C:I:L lun [parameters]\" "
">mgmt\n"
" echo \"replace VNAME lun [READ_ONLY]\" "
" echo \"replace VNAME lun [parameters]\" "
">mgmt\n"
" echo \"clear\" "
">mgmt\n";
" echo \"clear\" >mgmt\n"
"\n"
"where parameters are one or more "
"param_name=value pairs separated by ';'\n"
"\nThe following parameters available: read_only.";
return sprintf(buf, help);
}
@@ -1984,24 +2023,6 @@ static ssize_t scst_acn_file_show(struct kobject *kobj,
attr->attr.name);
}
static ssize_t scst_acg_luns_mgmt_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
static char *help = "Usage: echo \"add|del H:C:I:L lun [READ_ONLY]\" "
">mgmt\n"
" echo \"add|del VNAME lun [READ_ONLY]\" "
">mgmt\n"
" echo \"replace H:C:I:L lun [READ_ONLY]\" "
">mgmt\n"
" echo \"replace VNAME lun [READ_ONLY]\" "
">mgmt\n"
" echo \"clear\" "
">mgmt\n";
return sprintf(buf, help);
}
static ssize_t scst_acg_luns_mgmt_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
@@ -2835,6 +2856,256 @@ static struct kobj_type scst_devt_ktype = {
.default_attrs = scst_devt_default_attrs,
};
static ssize_t scst_devt_mgmt_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
char *help = "Usage: echo \"add_device device_name [parameters]\" "
">mgmt\n"
" echo \"del_device device_name\" >mgmt\n"
"%s"
"\n"
"where parameters are one or more "
"param_name=value pairs separated by ';'\n"
"%s%s";
struct scst_dev_type *devt;
devt = container_of(kobj, struct scst_dev_type, devt_kobj);
if (devt->add_device_parameters_help != NULL)
return sprintf(buf, help,
(devt->mgmt_cmd_help) ? devt->mgmt_cmd_help : "",
"\nThe following parameters available: ",
devt->add_device_parameters_help);
else
return sprintf(buf, help,
(devt->mgmt_cmd_help) ? devt->mgmt_cmd_help : "",
"", "");
}
static ssize_t scst_devt_mgmt_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
int res;
char *buffer, *p, *pp, *device_name;
struct scst_dev_type *devt;
TRACE_ENTRY();
devt = container_of(kobj, struct scst_dev_type, devt_kobj);
buffer = kzalloc(count+1, GFP_KERNEL);
if (buffer == NULL) {
res = -ENOMEM;
goto out;
}
memcpy(buffer, buf, count);
buffer[count] = '\0';
pp = buffer;
if (pp[strlen(pp) - 1] == '\n')
pp[strlen(pp) - 1] = '\0';
p = scst_get_next_lexem(&pp);
if (strcasecmp("add_device", p) == 0) {
device_name = scst_get_next_lexem(&pp);
if (*device_name == '\0') {
PRINT_ERROR("%s", "Device name required");
res = -EINVAL;
goto out_free;
}
res = devt->add_device(device_name, pp);
} else if (strcasecmp("del_device", p) == 0) {
device_name = scst_get_next_lexem(&pp);
if (*device_name == '\0') {
PRINT_ERROR("%s", "Device name required");
res = -EINVAL;
goto out_free;
}
p = scst_get_next_lexem(&pp);
if (*p != '\0')
goto out_syntax_err;
res = devt->del_device(device_name);
} else if (devt->mgmt_cmd != NULL) {
scst_restore_token_str(p, pp);
res = devt->mgmt_cmd(buffer);
} else {
PRINT_ERROR("Unknown action \"%s\"", p);
res = -EINVAL;
goto out_free;
}
if (res == 0)
res = count;
out_free:
kfree(buffer);
out:
TRACE_EXIT_RES(res);
return res;
out_syntax_err:
PRINT_ERROR("Syntax error on \"%s\"", p);
res = -EINVAL;
goto out_free;
}
static struct kobj_attribute scst_devt_mgmt =
__ATTR(mgmt, S_IRUGO | S_IWUSR, scst_devt_mgmt_show,
scst_devt_mgmt_store);
static ssize_t scst_devt_pass_through_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "1");
}
static struct kobj_attribute scst_devt_pass_through =
__ATTR(pass_through, S_IRUGO, scst_devt_pass_through_show, NULL);
static ssize_t scst_devt_pass_through_mgmt_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
char *help = "Usage: echo \"assign H:C:I:L\" >mgmt\n"
" echo \"unassign H:C:I:L\" >mgmt\n";
return sprintf(buf, help);
}
static ssize_t scst_devt_pass_through_mgmt_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t count)
{
int res;
char *buffer, *p, *pp, *action;
struct scst_dev_type *devt;
unsigned long host, channel, id, lun;
struct scst_device *d, *dev = NULL;
TRACE_ENTRY();
devt = container_of(kobj, struct scst_dev_type, devt_kobj);
buffer = kzalloc(count+1, GFP_KERNEL);
if (buffer == NULL) {
res = -ENOMEM;
goto out;
}
memcpy(buffer, buf, count);
buffer[count] = '\0';
pp = buffer;
if (pp[strlen(pp) - 1] == '\n')
pp[strlen(pp) - 1] = '\0';
action = scst_get_next_lexem(&pp);
p = scst_get_next_lexem(&pp);
if (*p == '\0') {
PRINT_ERROR("%s", "Device required");
res = -EINVAL;
goto out_free;
}
;
if (*scst_get_next_lexem(&pp) != '\0') {
PRINT_ERROR("%s", "Too many parameters");
res = -EINVAL;
goto out_syntax_err;
}
host = simple_strtoul(p, &p, 0);
if ((host == ULONG_MAX) || (*p != ':'))
goto out_syntax_err;
p++;
channel = simple_strtoul(p, &p, 0);
if ((channel == ULONG_MAX) || (*p != ':'))
goto out_syntax_err;
p++;
id = simple_strtoul(p, &p, 0);
if ((channel == ULONG_MAX) || (*p != ':'))
goto out_syntax_err;
p++;
lun = simple_strtoul(p, &p, 0);
if (lun == ULONG_MAX)
goto out_syntax_err;
TRACE_DBG("Dev %ld:%ld:%ld:%ld", host, channel, id, lun);
if (mutex_lock_interruptible(&scst_mutex) != 0) {
res = -EINTR;
goto out_free;
}
list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
if ((d->virt_id == 0) &&
d->scsi_dev->host->host_no == host &&
d->scsi_dev->channel == channel &&
d->scsi_dev->id == id &&
d->scsi_dev->lun == lun) {
dev = d;
TRACE_DBG("Dev %p (%ld:%ld:%ld:%ld) found",
dev, host, channel, id, lun);
break;
}
}
if (dev == NULL) {
PRINT_ERROR("Device %ld:%ld:%ld:%ld not found",
host, channel, id, lun);
res = -EINVAL;
goto out_unlock;
}
if (dev->scsi_dev->type != devt->type) {
PRINT_ERROR("Type %d of device %s differs from type "
"%d of dev handler %s", dev->type,
dev->virt_name, devt->type, devt->name);
res = -EINVAL;
goto out_unlock;
}
if (strcasecmp("assign", action) == 0)
res = scst_assign_dev_handler(dev, devt);
else if (strcasecmp("deassign", action) == 0) {
if (dev->handler != devt) {
PRINT_ERROR("Device %s is not assigned to handler %s",
dev->virt_name, devt->name);
res = -EINVAL;
goto out_unlock;
}
res = scst_assign_dev_handler(dev, &scst_null_devtype);
} else {
PRINT_ERROR("Unknown action \"%s\"", action);
res = -EINVAL;
goto out_unlock;
}
if (res == 0)
res = count;
out_unlock:
mutex_unlock(&scst_mutex);
out_free:
kfree(buffer);
out:
TRACE_EXIT_RES(res);
return res;
out_syntax_err:
PRINT_ERROR("Syntax error on \"%s\"", p);
res = -EINVAL;
goto out_free;
}
static struct kobj_attribute scst_devt_pass_through_mgmt =
__ATTR(mgmt, S_IRUGO | S_IWUSR, scst_devt_pass_through_mgmt_show,
scst_devt_pass_through_mgmt_store);
int scst_create_devt_sysfs(struct scst_dev_type *devt)
{
int retval;
@@ -2864,6 +3135,32 @@ int scst_create_devt_sysfs(struct scst_dev_type *devt)
* it will be done by the _put function() called by the caller.
*/
if (devt->add_device != NULL) {
retval = sysfs_create_file(&devt->devt_kobj,
&scst_devt_mgmt.attr);
if (retval != 0) {
PRINT_ERROR("Can't add mgmt attr for dev handler %s",
devt->name);
goto out;
}
} else if (devt->pass_through) {
retval = sysfs_create_file(&devt->devt_kobj,
&scst_devt_pass_through_mgmt.attr);
if (retval != 0) {
PRINT_ERROR("Can't add mgmt attr for dev handler %s",
devt->name);
goto out;
}
retval = sysfs_create_file(&devt->devt_kobj,
&scst_devt_pass_through.attr);
if (retval != 0) {
PRINT_ERROR("Can't add pass_through attr for dev "
"handler %s", devt->name);
goto out;
}
}
pattr = devt->devt_attrs;
if (pattr != NULL) {
while (*pattr != NULL) {