mirror of
https://github.com/SCST-project/scst.git
synced 2026-07-19 22:42:38 +00:00
- 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:
+86
-53
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
+938
-951
File diff suppressed because it is too large
Load Diff
+55
-1
@@ -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 *)␣
|
||||
|
||||
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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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(¶m);
|
||||
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(¶m);
|
||||
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(¶m)[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) {
|
||||
|
||||
Reference in New Issue
Block a user