mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-25 07:51:28 +00:00
Small cleanups and improvements
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1565 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -618,8 +618,8 @@ as well.
|
||||
3. ISCSI initiators from pre-CentOS/RHEL 5 reported to have some
|
||||
performance problems. If you use it, it is strongly advised to upgrade.
|
||||
|
||||
4. Pay attention to have mpio_type option set correctly. See SCST core's
|
||||
README for more details.
|
||||
4. Pay attention to have io_grouping_type option set correctly. See SCST
|
||||
core's README for more details.
|
||||
|
||||
5. If you are going to use your target in an VM environment, for
|
||||
instance as a shared storage with VMware, make sure all your VMs
|
||||
@@ -629,6 +629,15 @@ connection. You can check it using SCST proc or sysfs interface. If you
|
||||
miss it, you can greatly loose performance of parallel access to your
|
||||
target from different VMs.
|
||||
|
||||
6. Many dual port network adapters are not able to transfer data
|
||||
simultaneousy on both ports, i.e. they transfer data via both ports on
|
||||
the same speed as via any single port. Thus, using such adapters in MPIO
|
||||
configuration can't improve performance. To allow MPIO to have double
|
||||
performance you should either use separate network adapters, or find a
|
||||
dual-port adapter capable to to transfer data simultaneousy on both
|
||||
ports. You can check it by running 2 iperf's through both ports in
|
||||
parallel.
|
||||
|
||||
|
||||
Compilation options
|
||||
-------------------
|
||||
|
||||
@@ -527,8 +527,8 @@ as well.
|
||||
3. ISCSI initiators built in pre-CentOS/RHEL 5 reported to have some
|
||||
performance problems. If you use it, it is strongly advised to upgrade.
|
||||
|
||||
4. Pay attention to have mpio_type option set correctly. See SCST core's
|
||||
README for more details.
|
||||
4. Pay attention to have io_grouping_type option set correctly. See SCST
|
||||
core's README for more details.
|
||||
|
||||
5. If you are going to use your target in an VM environment, for
|
||||
instance as a shared storage with VMware, make sure all your VMs
|
||||
@@ -538,6 +538,15 @@ connection. You can check it using SCST proc or sysfs interface. If you
|
||||
miss it, you can greatly loose performance of parallel access to your
|
||||
target from different VMs.
|
||||
|
||||
6. Many dual port network adapters are not able to transfer data
|
||||
simultaneousy on both ports, i.e. they transfer data via both ports on
|
||||
the same speed as via any single port. Thus, using such adapters in MPIO
|
||||
configuration can't improve performance. To allow MPIO to have double
|
||||
performance you should either use separate network adapters, or find a
|
||||
dual-port adapter capable to to transfer data simultaneousy on both
|
||||
ports. You can check it by running 2 iperf's through both ports in
|
||||
parallel.
|
||||
|
||||
|
||||
Compilation options
|
||||
-------------------
|
||||
|
||||
@@ -424,8 +424,8 @@ The resulting overall SCST sysfs hierarchy with initiator
|
||||
Performance advices
|
||||
-------------------
|
||||
|
||||
1. Pay attention to have mpio_type option set correctly. See SCST core's
|
||||
README for more details.
|
||||
1. Pay attention to have io_grouping_type option set correctly. See
|
||||
SCST core's README for more details.
|
||||
|
||||
2. If you are going to use your target in an VM environment, for
|
||||
instance as a shared storage with VMware, make sure all your VMs
|
||||
|
||||
165
scst/README
165
scst/README
@@ -628,6 +628,18 @@ Standard SCST dev handlers have at least the following common entries:
|
||||
- handler - if dev handler determined for this device, this link points
|
||||
to it. The handler can be not set for pass-through devices.
|
||||
|
||||
- threads_num - shows and allows to set number of threads in this device's
|
||||
threads pool. If 0 - no threads will be created, and global SCST
|
||||
threads pool will be used. If <0 - creation of the threads pool is
|
||||
prohibited.
|
||||
|
||||
- threads_pool_type - shows and allows to sets threads pool type.
|
||||
Possible values: "per_initiator" and "shared". When the value is
|
||||
"per_initiator" (default), each session from each initiator will use
|
||||
separate dedicated pool of threads. When the value is "shared", all
|
||||
sessions from all initiators will share the same per-device pool of
|
||||
threads. Valid only if threads_num attribute >0.
|
||||
|
||||
- type - SCSI type of this device
|
||||
|
||||
See below for more information about other entries of this subdirectory
|
||||
@@ -694,23 +706,28 @@ Every target should have at least the following entries:
|
||||
initiators security groups, so you can assign the addressing method
|
||||
on per-initiator basis.
|
||||
|
||||
- mpio_type - defines how I/O from sessions to this target are grouped
|
||||
together. This I/O grouping is very important for performance. If
|
||||
you have this attribute set in a wrong value, you can considerably
|
||||
decrease performance of your setup. Possible values: "enable",
|
||||
"disable" and "auto". When "enable" all I/O from all sessions will be
|
||||
grouped together. When "disable", I/O from different sessions will
|
||||
not be grouped together, i.e. all sessions will have separate
|
||||
dedicated group. When "auto" (default), all I/O from initiators with
|
||||
the same name (iSCSI initiator name, for instance) will be grouped
|
||||
together with a separate dedicated group for each initiator name. For
|
||||
iSCSI it works well, but other transports usually use different
|
||||
names, so using them in MPIO configurations, you should instead use
|
||||
value "enable". This attribute is also available in the initiators
|
||||
security groups, so you can assign the addressing method on
|
||||
per-initiator basis. Recommended practice is to create a separate
|
||||
initiator security group for each MPIO sessions and set mpio_type in
|
||||
"enable".
|
||||
- io_grouping_type - defines how I/O from sessions to this target are
|
||||
grouped together. This I/O grouping is very important for
|
||||
performance. By setting this attribute in a right value, you can
|
||||
considerably increase performance of your setup. This grouping is
|
||||
performed only if you use CFQ I/O scheduler on the target and for
|
||||
devices with threads_num >= 0 and, if threads_num > 0, with
|
||||
threads_pool_type "per_initiator". Possible values:
|
||||
"this_group_only", "never", "auto", or I/O group number >0. When the
|
||||
value is "this_group_only" all I/O from all sessions in this target
|
||||
will be grouped together. When the value is "never", I/O from
|
||||
different sessions will not be grouped together, i.e. all sessions in
|
||||
this target will have separate dedicated I/O groups. When the value
|
||||
is "auto" (default), all I/O from initiators with the same name
|
||||
(iSCSI initiator name, for instance) in all targets will be grouped
|
||||
together with a separate dedicated I/O group for each initiator name.
|
||||
For iSCSI this mode works well, but other transports usually use
|
||||
different initiator names for different sessions, so using such
|
||||
transports in MPIO configurations you should either use value
|
||||
"this_group_only", or an explicit I/O group number. This attribute is
|
||||
also available in the initiators security groups, so you can assign
|
||||
the I/O groupping on per-initiator basis. See below for more info how
|
||||
to use this attribute.
|
||||
|
||||
- rel_tgt_id - allows to read or write SCSI Relative Target Port
|
||||
Identifier attribute. This identifier is used to identify SCSI Target
|
||||
@@ -1098,18 +1115,6 @@ cache. The following parameters possible for vdisk_fileio:
|
||||
- removable - with this flag set the device is reported to remote
|
||||
initiators as removable.
|
||||
|
||||
- threads_num - sets number of threads in this device's threads
|
||||
pool. If 0 - no threads will be created, and global SCST threads pool
|
||||
will be used. If <0 - creation of the threads pool will be
|
||||
prohibited.
|
||||
|
||||
- threads_pool_type - sets threads pool type. Possible values:
|
||||
"per_initiator" and "shared". When "per_initiator" (default), each
|
||||
session from each initiator will use separate dedicated pool of
|
||||
threads. When "shared", all sessions from all initiators will share
|
||||
the same per-device pool of threads. Valid only if threads_num
|
||||
attribute >0.
|
||||
|
||||
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
|
||||
@@ -1202,22 +1207,19 @@ For example:
|
||||
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, threads_num,
|
||||
threads_pool_type, type, usn. See description of vdisk_fileio's device
|
||||
for description of those parameters.
|
||||
threads_pool_type, type, usn. See above 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, threads_num, threads_pool_type, type,
|
||||
usn. See description of vdisk_fileio's device for description of those
|
||||
parameters.
|
||||
usn. See above 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, threads_num, threads_pool_type, 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:
|
||||
t10_dev_id, threads_num, threads_pool_type, type, usn. See above
|
||||
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.
|
||||
@@ -1434,6 +1436,16 @@ fileio_tgt's README file for more details.
|
||||
Performance
|
||||
-----------
|
||||
|
||||
SCST from the very beginning has been designed and implemented to
|
||||
provide the best possible performance. Since there is no "one fit all"
|
||||
the best performance configuration for different setups and loads, SCST
|
||||
provides extensive set of settings to allow to tune it for the best
|
||||
performance in each particular case. You don't have to necessary use
|
||||
those settings. If you don't, SCST will do very good job to autotune for
|
||||
you, so the resulting performance will, in average, be better
|
||||
(sometimes, much better) than with other SCSI targets. But in some cases
|
||||
you can by manual tuning improve it even more.
|
||||
|
||||
Before doing any performance measurements note that performance results
|
||||
are very much dependent from your type of load, so it is crucial that
|
||||
you choose access mode (FILEIO, BLOCKIO, O_DIRECT, pass-through), which
|
||||
@@ -1459,15 +1471,70 @@ In order to get the maximum performance you should:
|
||||
- Disable in Makefile CONFIG_SCST_TRACING and CONFIG_SCST_DEBUG.
|
||||
|
||||
|
||||
IMPORTANT: Some of the above compilation options in the SCST SVN enabled by default,
|
||||
========= i.e. development version of SCST is optimized currently rather for
|
||||
development and bug hunting, than for performance.
|
||||
IMPORTANT: Some of the above compilation options in the SCST SVN enabled
|
||||
========= by default, i.e. the development version of SCST is optimized
|
||||
for development and bug hunting, not for performance. For it
|
||||
you can set the above options, except
|
||||
CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ, in the
|
||||
needed values by command "make debug2perf" performed in
|
||||
trunk/.
|
||||
|
||||
You can set the above options, except
|
||||
CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ, in the needed values
|
||||
using debug2perf root Makefile target.
|
||||
4. Make sure you have io_grouping_type option set correctly, especially
|
||||
in the following cases:
|
||||
|
||||
4. If you are going to use your target in an VM environment, for
|
||||
- Several initiators share your target's backstorage. It can be a
|
||||
shared LU using some cluster FS, like VMFS, as well as can be
|
||||
different LUs located on the same backstorage (RAID array). For
|
||||
instance, if you have 3 initiators and each of them using its own
|
||||
dedicated FILEIO device file from the same RAID-6 array on the
|
||||
target.
|
||||
|
||||
In this case for the best performance you should have
|
||||
io_grouping_type option set in value "never" in all the LUNs' targets
|
||||
and security groups.
|
||||
|
||||
- Your initiator connected to your target in MPIO mode. In this case for
|
||||
the best performance you should:
|
||||
|
||||
* Either connect all the sessions from the initiator to a single
|
||||
target or security group and have io_grouping_type option set in
|
||||
value "this_group_only" in the target or security group,
|
||||
|
||||
* Or, if it isn't possible to connect all the sessions from the
|
||||
initiator to a single target or security group, assign the same
|
||||
numeric io_grouping_type value for each target/security group this
|
||||
initiator connected to. The exact value itself doesn't matter,
|
||||
important only that all the targets/security groups use the same
|
||||
value.
|
||||
|
||||
Don't forget, io_grouping_type makes sense only if you use CFQ I/O
|
||||
scheduler on the target and for devices with threads_num >= 0 and, if
|
||||
threads_num > 0, with threads_pool_type "per_initiator".
|
||||
|
||||
You can check if in your setup io_grouping_type set correctly as well as
|
||||
if the "auto" io_grouping_type value works for you by tests like the
|
||||
following:
|
||||
|
||||
- For not MPIO case you can run single thread sequential reading, e.g.
|
||||
using buffered dd, from one initiator, then run the same single
|
||||
thread sequential reading from the second initiator in parallel. If
|
||||
io_grouping_type is set correctly the aggregate throughput measured
|
||||
on the target should only slightly decrease as well as all initiators
|
||||
should have nearly equal share of it. If io_grouping_type is not set
|
||||
correctly, the aggregate throughput and/or throughput on any
|
||||
initiator will decrease significantly, in 2 times or even more. For
|
||||
instance, you have 80MB/s single thread sequential reading from the
|
||||
target on any initiator. When then both initiators are reading in
|
||||
parallel you should see on the target aggregate throughput something
|
||||
like 70-75MB/s with correct io_grouping_type and something like
|
||||
35-40MB/s or 8-10MB/s on any initiator with incorrect.
|
||||
|
||||
- For the MPIO case it's quite easier. With incorrect io_grouping_type
|
||||
you simply won't see performance increase from adding the second
|
||||
session (assuming your hardware is capable to transfer data through
|
||||
both sessions in parallel), or can even see a performance decrease.
|
||||
|
||||
5. If you are going to use your target in an VM environment, for
|
||||
instance as a shared storage with VMware, make sure all your VMs
|
||||
connected to the target via *separate* sessions. For instance, for iSCSI
|
||||
it means that each VM has own connection to the target, not all VMs
|
||||
@@ -1477,7 +1544,7 @@ facilities, like NPIV for Fibre Channel, to make separate sessions for
|
||||
each VM. If you miss it, you can greatly loose performance of parallel
|
||||
access to your target from different VMs.
|
||||
|
||||
5. For other target and initiator software parts:
|
||||
6. For other target and initiator software parts:
|
||||
|
||||
- Make sure you applied on your kernel all available SCST patches.
|
||||
If for your kernel version this patch doesn't exist, it is strongly
|
||||
@@ -1538,7 +1605,7 @@ access to your target from different VMs.
|
||||
files, because it allows considerably better linear write throughput,
|
||||
than ext3.
|
||||
|
||||
6. For hardware on target.
|
||||
7. For hardware on target.
|
||||
|
||||
- Make sure that your target hardware (e.g. target FC or network card)
|
||||
and underlaying IO hardware (e.g. IO card, like SATA, SCSI or RAID to
|
||||
@@ -1555,7 +1622,7 @@ access to your target from different VMs.
|
||||
you have no choice, but PCI bus sharing, set in the BIOS PCI latency
|
||||
as low as possible.
|
||||
|
||||
7. If you use VDISK IO module in FILEIO mode, NV_CACHE option will
|
||||
8. If you use VDISK IO module in FILEIO mode, NV_CACHE option will
|
||||
provide you the best performance. But using it make sure you use a good
|
||||
UPS with ability to shutdown the target on the power failure.
|
||||
|
||||
@@ -1579,7 +1646,7 @@ IMPORTANT: If you use on initiator some versions of Windows (at least W2K)
|
||||
for VDISK FILEIO devices above.
|
||||
|
||||
|
||||
8. In some cases, for instance working with SSD devices, which consume 100%
|
||||
9. In some cases, for instance working with SSD devices, which consume 100%
|
||||
of a single CPU load for data transfers in their internal threads, to
|
||||
maximize IOPS it can be needed to assign for those threads dedicated
|
||||
CPUs using Linux CPU affinity facilities. No IRQ processing should be
|
||||
|
||||
@@ -558,6 +558,18 @@ Standard SCST dev handlers have at least the following common entries:
|
||||
- handler - if dev handler determined for this device, this link points
|
||||
to it. The handler can be not set for pass-through devices.
|
||||
|
||||
- threads_num - shows and allows to set number of threads in this device's
|
||||
threads pool. If 0 - no threads will be created, and global SCST
|
||||
threads pool will be used. If <0 - creation of the threads pool is
|
||||
prohibited.
|
||||
|
||||
- threads_pool_type - shows and allows to sets threads pool type.
|
||||
Possible values: "per_initiator" and "shared". When the value is
|
||||
"per_initiator" (default), each session from each initiator will use
|
||||
separate dedicated pool of threads. When the value is "shared", all
|
||||
sessions from all initiators will share the same per-device pool of
|
||||
threads. Valid only if threads_num attribute >0.
|
||||
|
||||
- type - SCSI type of this device
|
||||
|
||||
See below for more information about other entries of this subdirectory
|
||||
@@ -624,23 +636,28 @@ Every target should have at least the following entries:
|
||||
initiators security groups, so you can assign the addressing method
|
||||
on per-initiator basis.
|
||||
|
||||
- mpio_type - defines how I/O from sessions to this target are grouped
|
||||
together. This I/O grouping is very important for performance. If
|
||||
you have this attribute set in a wrong value, you can considerably
|
||||
decrease performance of your setup. Possible values: "enable",
|
||||
"disable" and "auto". When "enable" all I/O from all sessions will be
|
||||
grouped together. When "disable", I/O from different sessions will
|
||||
not be grouped together, i.e. all sessions will have separate
|
||||
dedicated group. When "auto" (default), all I/O from initiators with
|
||||
the same name (iSCSI initiator name, for instance) will be grouped
|
||||
together with a separate dedicated group for each initiator name. For
|
||||
iSCSI it works well, but other transports usually use different
|
||||
names, so using them in MPIO configurations, you should instead use
|
||||
value "enable". This attribute is also available in the initiators
|
||||
security groups, so you can assign the addressing method on
|
||||
per-initiator basis. Recommended practice is to create a separate
|
||||
initiator security group for each MPIO sessions and set mpio_type in
|
||||
"enable".
|
||||
- io_grouping_type - defines how I/O from sessions to this target are
|
||||
grouped together. This I/O grouping is very important for
|
||||
performance. By setting this attribute in a right value, you can
|
||||
considerably increase performance of your setup. This grouping is
|
||||
performed only if you use CFQ I/O scheduler on the target and for
|
||||
devices with threads_num >= 0 and, if threads_num > 0, with
|
||||
threads_pool_type "per_initiator". Possible values:
|
||||
"this_group_only", "never", "auto", or I/O group number >0. When the
|
||||
value is "this_group_only" all I/O from all sessions in this target
|
||||
will be grouped together. When the value is "never", I/O from
|
||||
different sessions will not be grouped together, i.e. all sessions in
|
||||
this target will have separate dedicated I/O groups. When the value
|
||||
is "auto" (default), all I/O from initiators with the same name
|
||||
(iSCSI initiator name, for instance) in all targets will be grouped
|
||||
together with a separate dedicated I/O group for each initiator name.
|
||||
For iSCSI this mode works well, but other transports usually use
|
||||
different initiator names for different sessions, so using such
|
||||
transports in MPIO configurations you should either use value
|
||||
"this_group_only", or an explicit I/O group number. This attribute is
|
||||
also available in the initiators security groups, so you can assign
|
||||
the I/O groupping on per-initiator basis. See below for more info how
|
||||
to use this attribute.
|
||||
|
||||
- rel_tgt_id - allows to read or write SCSI Relative Target Port
|
||||
Identifier attribute. This identifier is used to identify SCSI Target
|
||||
@@ -1029,18 +1046,6 @@ cache. The following parameters possible for vdisk_fileio:
|
||||
- removable - with this flag set the device is reported to remote
|
||||
initiators as removable.
|
||||
|
||||
- threads_num - sets number of threads in this device's threads
|
||||
pool. If 0 - no threads will be created, and global SCST threads pool
|
||||
will be used. If <0 - creation of the threads pool will be
|
||||
prohibited.
|
||||
|
||||
- threads_pool_type - sets threads pool type. Possible values:
|
||||
"per_initiator" and "shared". When "per_initiator" (default), each
|
||||
session from each initiator will use separate dedicated pool of
|
||||
threads. When "shared", all sessions from all initiators will share
|
||||
the same per-device pool of threads. Valid only if threads_num
|
||||
attribute >0.
|
||||
|
||||
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
|
||||
@@ -1133,22 +1138,19 @@ For example:
|
||||
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, threads_num,
|
||||
threads_pool_type, type, usn. See description of vdisk_fileio's device
|
||||
for description of those parameters.
|
||||
threads_pool_type, type, usn. See above 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, threads_num, threads_pool_type, type,
|
||||
usn. See description of vdisk_fileio's device for description of those
|
||||
parameters.
|
||||
usn. See above 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, threads_num, threads_pool_type, 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:
|
||||
t10_dev_id, threads_num, threads_pool_type, type, usn. See above
|
||||
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.
|
||||
@@ -1365,6 +1367,16 @@ fileio_tgt's README file for more details.
|
||||
Performance
|
||||
-----------
|
||||
|
||||
SCST from the very beginning has been designed and implemented to
|
||||
provide the best possible performance. Since there is no "one fit all"
|
||||
the best performance configuration for different setups and loads, SCST
|
||||
provides extensive set of settings to allow to tune it for the best
|
||||
performance in each particular case. You don't have to necessary use
|
||||
those settings. If you don't, SCST will do very good job to autotune for
|
||||
you, so the resulting performance will, in average, be better
|
||||
(sometimes, much better) than with other SCSI targets. But in some cases
|
||||
you can by manual tuning improve it even more.
|
||||
|
||||
Before doing any performance measurements note that performance results
|
||||
are very much dependent from your type of load, so it is crucial that
|
||||
you choose access mode (FILEIO, BLOCKIO, O_DIRECT, pass-through), which
|
||||
@@ -1390,15 +1402,70 @@ In order to get the maximum performance you should:
|
||||
- Disable in Makefile CONFIG_SCST_TRACING and CONFIG_SCST_DEBUG.
|
||||
|
||||
|
||||
IMPORTANT: Some of the above compilation options in the SCST SVN enabled by default,
|
||||
========= i.e. development version of SCST is optimized currently rather for
|
||||
development and bug hunting, than for performance.
|
||||
IMPORTANT: Some of the above compilation options in the SCST SVN enabled
|
||||
========= by default, i.e. the development version of SCST is optimized
|
||||
for development and bug hunting, not for performance. For it
|
||||
you can set the above options, except
|
||||
CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ, in the
|
||||
needed values by command "make debug2perf" performed in
|
||||
trunk/.
|
||||
|
||||
You can set the above options, except
|
||||
CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ, in the needed values
|
||||
using debug2perf root Makefile target.
|
||||
4. Make sure you have io_grouping_type option set correctly, especially
|
||||
in the following cases:
|
||||
|
||||
4. If you are going to use your target in an VM environment, for
|
||||
- Several initiators share your target's backstorage. It can be a
|
||||
shared LU using some cluster FS, like VMFS, as well as can be
|
||||
different LUs located on the same backstorage (RAID array). For
|
||||
instance, if you have 3 initiators and each of them using its own
|
||||
dedicated FILEIO device file from the same RAID-6 array on the
|
||||
target.
|
||||
|
||||
In this case for the best performance you should have
|
||||
io_grouping_type option set in value "never" in all the LUNs' targets
|
||||
and security groups.
|
||||
|
||||
- Your initiator connected to your target in MPIO mode. In this case for
|
||||
the best performance you should:
|
||||
|
||||
* Either connect all the sessions from the initiator to a single
|
||||
target or security group and have io_grouping_type option set in
|
||||
value "this_group_only" in the target or security group,
|
||||
|
||||
* Or, if it isn't possible to connect all the sessions from the
|
||||
initiator to a single target or security group, assign the same
|
||||
numeric io_grouping_type value for each target/security group this
|
||||
initiator connected to. The exact value itself doesn't matter,
|
||||
important only that all the targets/security groups use the same
|
||||
value.
|
||||
|
||||
Don't forget, io_grouping_type makes sense only if you use CFQ I/O
|
||||
scheduler on the target and for devices with threads_num >= 0 and, if
|
||||
threads_num > 0, with threads_pool_type "per_initiator".
|
||||
|
||||
You can check if in your setup io_grouping_type set correctly as well as
|
||||
if the "auto" io_grouping_type value works for you by tests like the
|
||||
following:
|
||||
|
||||
- For not MPIO case you can run single thread sequential reading, e.g.
|
||||
using buffered dd, from one initiator, then run the same single
|
||||
thread sequential reading from the second initiator in parallel. If
|
||||
io_grouping_type is set correctly the aggregate throughput measured
|
||||
on the target should only slightly decrease as well as all initiators
|
||||
should have nearly equal share of it. If io_grouping_type is not set
|
||||
correctly, the aggregate throughput and/or throughput on any
|
||||
initiator will decrease significantly, in 2 times or even more. For
|
||||
instance, you have 80MB/s single thread sequential reading from the
|
||||
target on any initiator. When then both initiators are reading in
|
||||
parallel you should see on the target aggregate throughput something
|
||||
like 70-75MB/s with correct io_grouping_type and something like
|
||||
35-40MB/s or 8-10MB/s on any initiator with incorrect.
|
||||
|
||||
- For the MPIO case it's quite easier. With incorrect io_grouping_type
|
||||
you simply won't see performance increase from adding the second
|
||||
session (assuming your hardware is capable to transfer data through
|
||||
both sessions in parallel), or can even see a performance decrease.
|
||||
|
||||
5. If you are going to use your target in an VM environment, for
|
||||
instance as a shared storage with VMware, make sure all your VMs
|
||||
connected to the target via *separate* sessions. For instance, for iSCSI
|
||||
it means that each VM has own connection to the target, not all VMs
|
||||
@@ -1408,7 +1475,7 @@ facilities, like NPIV for Fibre Channel, to make separate sessions for
|
||||
each VM. If you miss it, you can greatly loose performance of parallel
|
||||
access to your target from different VMs.
|
||||
|
||||
5. For other target and initiator software parts:
|
||||
6. For other target and initiator software parts:
|
||||
|
||||
- Make sure you applied on your kernel all available SCST patches.
|
||||
If for your kernel version this patch doesn't exist, it is strongly
|
||||
@@ -1469,7 +1536,7 @@ access to your target from different VMs.
|
||||
files, because it allows considerably better linear write throughput,
|
||||
than ext3.
|
||||
|
||||
6. For hardware on target.
|
||||
7. For hardware on target.
|
||||
|
||||
- Make sure that your target hardware (e.g. target FC or network card)
|
||||
and underlaying IO hardware (e.g. IO card, like SATA, SCSI or RAID to
|
||||
@@ -1486,7 +1553,7 @@ access to your target from different VMs.
|
||||
you have no choice, but PCI bus sharing, set in the BIOS PCI latency
|
||||
as low as possible.
|
||||
|
||||
7. If you use VDISK IO module in FILEIO mode, NV_CACHE option will
|
||||
8. If you use VDISK IO module in FILEIO mode, NV_CACHE option will
|
||||
provide you the best performance. But using it make sure you use a good
|
||||
UPS with ability to shutdown the target on the power failure.
|
||||
|
||||
@@ -1509,7 +1576,7 @@ IMPORTANT: If you use on initiator some versions of Windows (at least W2K)
|
||||
See also important notes about setting block sizes >512 bytes
|
||||
for VDISK FILEIO devices above.
|
||||
|
||||
8. In some cases, for instance working with SSD devices, which consume 100%
|
||||
9. In some cases, for instance working with SSD devices, which consume 100%
|
||||
of a single CPU load for data transfers in their internal threads, to
|
||||
maximize IOPS it can be needed to assign for those threads dedicated
|
||||
CPUs using Linux CPU affinity facilities. No IRQ processing should be
|
||||
|
||||
@@ -471,6 +471,24 @@ enum scst_exec_context {
|
||||
|
||||
#define SCST_TGT_DEV_CLUST_POOL 11
|
||||
|
||||
/*************************************************************
|
||||
** I/O groupping types. Changing them don't forget to change
|
||||
** the corresponding *_STR values in scst_const.h!
|
||||
*************************************************************/
|
||||
|
||||
/*
|
||||
* All initiators with the same name connected to this group will have
|
||||
* shared IO context, for each name own context. All initiators with
|
||||
* different names will have own IO context.
|
||||
*/
|
||||
#define SCST_IO_GROUPING_AUTO 0
|
||||
|
||||
/* All initiators connected to this group will have shared IO context */
|
||||
#define SCST_IO_GROUPING_THIS_GROUP_ONLY -1
|
||||
|
||||
/* Each initiator connected to this group will have own IO context */
|
||||
#define SCST_IO_GROUPING_NEVER -2
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
|
||||
/*************************************************************
|
||||
@@ -2065,25 +2083,6 @@ struct scst_acg_dev {
|
||||
struct kobject acg_dev_kobj;
|
||||
};
|
||||
|
||||
/*
|
||||
* ACG MPIO types. Changing them don't forget to change
|
||||
* the corresponding *_STR values in scst_const.h!
|
||||
*/
|
||||
enum scst_acg_mpio {
|
||||
/*
|
||||
* All initiators with the same name connected to this group will have
|
||||
* shared IO context, for each name own context. All initiators with
|
||||
* different names will have own IO context.
|
||||
*/
|
||||
SCST_ACG_MPIO_AUTO = 0,
|
||||
|
||||
/* All initiators connected to this group will have shared IO context */
|
||||
SCST_ACG_MPIO_ENABLE,
|
||||
|
||||
/* Each initiator connected to this group will have own IO context */
|
||||
SCST_ACG_MPIO_DISABLE,
|
||||
};
|
||||
|
||||
/*
|
||||
* ACG - access control group. Used to store group related
|
||||
* control information.
|
||||
@@ -2109,8 +2108,8 @@ struct scst_acg {
|
||||
struct proc_dir_entry *acg_proc_root;
|
||||
#endif
|
||||
|
||||
/* Type of MPIO initiators groupping */
|
||||
enum scst_acg_mpio acg_mpio_type;
|
||||
/* Type of I/O initiators groupping */
|
||||
int acg_io_grouping_type;
|
||||
|
||||
unsigned int acg_kobj_initialized:1;
|
||||
unsigned int in_tgt_acg_list:1;
|
||||
@@ -3785,13 +3784,6 @@ void scst_restore_token_str(char *prev_lexem, char *token_str);
|
||||
*/
|
||||
char *scst_get_next_token_str(char **input_str);
|
||||
|
||||
/*
|
||||
* Converts string presentation of threads pool type to enum.
|
||||
* Returns SCST_THREADS_POOL_TYPE_INVALID if the string is invalid.
|
||||
*/
|
||||
enum scst_dev_type_threads_pool_type scst_parse_threads_pool_type(
|
||||
const char *p, int len);
|
||||
|
||||
/* Initializes scst_cmd_threads structure */
|
||||
void scst_init_threads(struct scst_cmd_threads *cmd_threads);
|
||||
|
||||
|
||||
@@ -349,14 +349,15 @@ enum scst_cdb_flags {
|
||||
#define SCST_MAX_OTHER_TIMEOUT (14000 * HZ)
|
||||
|
||||
/*************************************************************
|
||||
** ACG MPIO attribute values. Must match scst_acg_mpio!
|
||||
** I/O grouping attribute string values. Must match constants
|
||||
** w/o '_STR' suffix!
|
||||
*************************************************************/
|
||||
#define SCST_ACG_MPIO_AUTO_STR "auto"
|
||||
#define SCST_ACG_MPIO_ENABLE_STR "enable"
|
||||
#define SCST_ACG_MPIO_DISABLE_STR "disable"
|
||||
#define SCST_IO_GROUPING_AUTO_STR "auto"
|
||||
#define SCST_IO_GROUPING_THIS_GROUP_ONLY_STR "this_group_only"
|
||||
#define SCST_IO_GROUPING_NEVER_STR "never"
|
||||
|
||||
/*************************************************************
|
||||
** Threads pool type attribute values.
|
||||
** Threads pool type attribute string values.
|
||||
** Must match scst_dev_type_threads_pool_type!
|
||||
*************************************************************/
|
||||
#define SCST_THREADS_POOL_PER_INITIATOR_STR "per_initiator"
|
||||
|
||||
@@ -220,9 +220,6 @@ struct scst_vdisk_dev {
|
||||
struct scst_device *dev;
|
||||
struct list_head vdev_list_entry;
|
||||
|
||||
int threads_num;
|
||||
enum scst_dev_type_threads_pool_type threads_pool_type;
|
||||
|
||||
struct mutex vdev_sysfs_mutex;
|
||||
struct scst_dev_type *vdev_devt;
|
||||
};
|
||||
@@ -447,8 +444,7 @@ static struct scst_dev_type vdisk_file_devtype = {
|
||||
.del_device = vdisk_del_device,
|
||||
.dev_attrs = vdisk_fileio_attrs,
|
||||
.add_device_parameters_help = "filename, blocksize, write_through, "
|
||||
"nv_cache, o_direct, read_only, removable, threads_num, "
|
||||
"threads_pool_type",
|
||||
"nv_cache, o_direct, read_only, removable",
|
||||
#endif
|
||||
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
||||
.default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
|
||||
@@ -484,7 +480,7 @@ static struct scst_dev_type vdisk_blk_devtype = {
|
||||
.del_device = vdisk_del_device,
|
||||
.dev_attrs = vdisk_blockio_attrs,
|
||||
.add_device_parameters_help = "filename, blocksize, read_only, "
|
||||
"removable, threads_num, threads_pool_type",
|
||||
"removable",
|
||||
#endif
|
||||
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
||||
.default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
|
||||
@@ -517,8 +513,7 @@ static struct scst_dev_type vdisk_null_devtype = {
|
||||
.add_device = vdisk_add_nullio_device,
|
||||
.del_device = vdisk_del_device,
|
||||
.dev_attrs = vdisk_nullio_attrs,
|
||||
.add_device_parameters_help = "blocksize, read_only, removable, "
|
||||
"threads_num, threads_pool_type",
|
||||
.add_device_parameters_help = "blocksize, read_only, removable",
|
||||
#endif
|
||||
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
||||
.default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
|
||||
@@ -552,7 +547,7 @@ static struct scst_dev_type vcdrom_devtype = {
|
||||
.add_device = vcdrom_add_device,
|
||||
.del_device = vcdrom_del_device,
|
||||
.dev_attrs = vcdrom_attrs,
|
||||
.add_device_parameters_help = "threads_num, threads_pool_type",
|
||||
.add_device_parameters_help = NULL,
|
||||
#endif
|
||||
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
||||
.default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
|
||||
@@ -700,8 +695,6 @@ static int vdisk_attach(struct scst_device *dev)
|
||||
virt_dev->dev = dev;
|
||||
|
||||
dev->rd_only = virt_dev->rd_only;
|
||||
dev->threads_num = virt_dev->threads_num;
|
||||
dev->threads_pool_type = virt_dev->threads_pool_type;
|
||||
|
||||
if (!virt_dev->cdrom_empty) {
|
||||
if (virt_dev->nullio)
|
||||
@@ -2961,8 +2954,6 @@ static int vdev_create(struct scst_dev_type *devt,
|
||||
spin_lock_init(&virt_dev->flags_lock);
|
||||
mutex_init(&virt_dev->vdev_sysfs_mutex);
|
||||
virt_dev->vdev_devt = devt;
|
||||
virt_dev->threads_num = devt->threads_num;
|
||||
virt_dev->threads_pool_type = devt->threads_pool_type;
|
||||
|
||||
virt_dev->rd_only = DEF_RD_ONLY;
|
||||
virt_dev->removable = DEF_REMOVABLE;
|
||||
@@ -3051,21 +3042,6 @@ static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
pp = scst_get_next_lexem(¶m);
|
||||
if (*pp == '\0') {
|
||||
PRINT_ERROR("Parameter %s value missed for device %s",
|
||||
p, virt_dev->name);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (scst_get_next_lexem(¶m)[0] != '\0') {
|
||||
PRINT_ERROR("Too many parameter's %s values (device %s)",
|
||||
p, virt_dev->name);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (allowed_params != NULL) {
|
||||
const char **a = allowed_params;
|
||||
bool allowed = false;
|
||||
@@ -3086,6 +3062,21 @@ static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev,
|
||||
}
|
||||
}
|
||||
|
||||
pp = scst_get_next_lexem(¶m);
|
||||
if (*pp == '\0') {
|
||||
PRINT_ERROR("Parameter %s value missed for device %s",
|
||||
p, virt_dev->name);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (scst_get_next_lexem(¶m)[0] != '\0') {
|
||||
PRINT_ERROR("Too many parameter's %s values (device %s)",
|
||||
p, virt_dev->name);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!strcasecmp("filename", p)) {
|
||||
if (*pp != '/') {
|
||||
PRINT_ERROR("Filename %s must be global "
|
||||
@@ -3102,16 +3093,6 @@ static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev,
|
||||
goto out;
|
||||
}
|
||||
continue;
|
||||
} else if (!strcasecmp("threads_pool_type", p)) {
|
||||
virt_dev->threads_pool_type = scst_parse_threads_pool_type(pp,
|
||||
strlen(pp));
|
||||
if (virt_dev->threads_pool_type == SCST_THREADS_POOL_TYPE_INVALID) {
|
||||
res = virt_dev->threads_pool_type;
|
||||
goto out;
|
||||
}
|
||||
TRACE_DBG("threads_pool_type %d",
|
||||
virt_dev->threads_pool_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
res = strict_strtoul(pp, 0, &val);
|
||||
@@ -3142,9 +3123,6 @@ static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev,
|
||||
} else if (!strcasecmp("removable", p)) {
|
||||
virt_dev->removable = val;
|
||||
TRACE_DBG("REMOVABLE %d", virt_dev->removable);
|
||||
} else if (!strcasecmp("threads_num", p)) {
|
||||
virt_dev->threads_num = val;
|
||||
TRACE_DBG("threads_num %d", virt_dev->threads_num);
|
||||
} else if (!strcasecmp("blocksize", p)) {
|
||||
virt_dev->block_size = val;
|
||||
virt_dev->block_shift = scst_calc_block_shift(
|
||||
@@ -3232,8 +3210,8 @@ out_destroy:
|
||||
static int vdev_blockio_add_device(const char *device_name, char *params)
|
||||
{
|
||||
int res = 0;
|
||||
const char *allowed_params[] = { "filename", "threads_pool_type",
|
||||
"read_only", "removable", "threads_num", "blocksize", NULL };
|
||||
const char *allowed_params[] = { "filename", "read_only", "removable",
|
||||
"blocksize", NULL };
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
@@ -3284,8 +3262,8 @@ out_destroy:
|
||||
static int vdev_nullio_add_device(const char *device_name, char *params)
|
||||
{
|
||||
int res = 0;
|
||||
const char *allowed_params[] = { "threads_pool_type",
|
||||
"read_only", "removable", "threads_num", "blocksize", NULL };
|
||||
const char *allowed_params[] = { "read_only", "removable",
|
||||
"blocksize", NULL };
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
@@ -3442,8 +3420,7 @@ out:
|
||||
static int __vcdrom_add_device(const char *device_name, char *params)
|
||||
{
|
||||
int res = 0;
|
||||
const char *allowed_params[] = { "threads_pool_type",
|
||||
"threads_num", NULL };
|
||||
const char *allowed_params[] = { NULL }; /* no params */
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -2278,8 +2278,11 @@ static struct io_context *scst_find_shared_io_context(
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
switch (acg->acg_mpio_type) {
|
||||
case SCST_ACG_MPIO_AUTO:
|
||||
TRACE_DBG("tgt_dev %s (acg %p, io_grouping_type %d)",
|
||||
tgt_dev->sess->initiator_name, acg, acg->acg_io_grouping_type);
|
||||
|
||||
switch (acg->acg_io_grouping_type) {
|
||||
case SCST_IO_GROUPING_AUTO:
|
||||
if (tgt_dev->sess->initiator_name == NULL)
|
||||
goto out;
|
||||
|
||||
@@ -2290,9 +2293,7 @@ static struct io_context *scst_find_shared_io_context(
|
||||
(t->active_cmd_threads == NULL))
|
||||
continue;
|
||||
|
||||
TRACE_DBG("t name %s (tgt_dev name %s)",
|
||||
t->sess->initiator_name,
|
||||
tgt_dev->sess->initiator_name);
|
||||
TRACE_DBG("t %s", t->sess->initiator_name);
|
||||
|
||||
/* We check other ACG's as well */
|
||||
|
||||
@@ -2302,27 +2303,37 @@ static struct io_context *scst_find_shared_io_context(
|
||||
}
|
||||
break;
|
||||
|
||||
case SCST_ACG_MPIO_ENABLE:
|
||||
case SCST_IO_GROUPING_THIS_GROUP_ONLY:
|
||||
list_for_each_entry(t, &tgt_dev->dev->dev_tgt_dev_list,
|
||||
dev_tgt_dev_list_entry) {
|
||||
if ((t == tgt_dev) || (t->active_cmd_threads == NULL))
|
||||
continue;
|
||||
|
||||
TRACE_DBG("t name %s (tgt_dev name %s)",
|
||||
t->sess->initiator_name,
|
||||
tgt_dev->sess->initiator_name);
|
||||
TRACE_DBG("t %s (acg %p)", t->sess->initiator_name,
|
||||
t->acg_dev->acg);
|
||||
|
||||
goto found;
|
||||
if (t->acg_dev->acg == acg)
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCST_ACG_MPIO_DISABLE:
|
||||
case SCST_IO_GROUPING_NEVER:
|
||||
goto out;
|
||||
|
||||
default:
|
||||
PRINT_CRIT_ERROR("Unknown MPIO type %d (acg %s)",
|
||||
acg->acg_mpio_type, acg->acg_name);
|
||||
sBUG();
|
||||
list_for_each_entry(t, &tgt_dev->dev->dev_tgt_dev_list,
|
||||
dev_tgt_dev_list_entry) {
|
||||
if ((t == tgt_dev) || (t->active_cmd_threads == NULL))
|
||||
continue;
|
||||
|
||||
TRACE_DBG("t %s (acg %p, io_grouping_type %d)",
|
||||
t->sess->initiator_name, t->acg_dev->acg,
|
||||
t->acg_dev->acg->acg_io_grouping_type);
|
||||
|
||||
if (t->acg_dev->acg->acg_io_grouping_type ==
|
||||
acg->acg_io_grouping_type)
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2333,10 +2344,11 @@ out:
|
||||
found:
|
||||
if (t->active_cmd_threads == &scst_main_cmd_threads) {
|
||||
res = t->tgt_dev_cmd_threads.io_context;
|
||||
TRACE_DBG("Going to share async IO context %p (t %p, ini %s, "
|
||||
"dev %s, cmd_threads %p)", res, t,
|
||||
t->sess->initiator_name, t->dev->virt_name,
|
||||
&t->tgt_dev_cmd_threads);
|
||||
TRACE_MGMT_DBG("Going to share async IO context %p (t %p, "
|
||||
"ini %s, dev %s, cmd_threads %p, grouping type %d)",
|
||||
res, t, t->sess->initiator_name, t->dev->virt_name,
|
||||
&t->tgt_dev_cmd_threads,
|
||||
t->acg_dev->acg->acg_io_grouping_type);
|
||||
} else {
|
||||
res = t->active_cmd_threads->io_context;
|
||||
if (res == NULL) {
|
||||
@@ -2346,10 +2358,11 @@ found:
|
||||
barrier();
|
||||
goto found;
|
||||
}
|
||||
TRACE_DBG("Going to share IO context %p (t %p, ini %s, "
|
||||
"dev %s, cmd_threads %p)", res, t,
|
||||
TRACE_MGMT_DBG("Going to share IO context %p (t %p, ini %s, "
|
||||
"dev %s, cmd_threads %p, grouping type %d)", res, t,
|
||||
t->sess->initiator_name, t->dev->virt_name,
|
||||
t->active_cmd_threads);
|
||||
t->active_cmd_threads,
|
||||
t->acg_dev->acg->acg_io_grouping_type);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
@@ -2374,7 +2387,6 @@ enum scst_dev_type_threads_pool_type scst_parse_threads_pool_type(const char *p,
|
||||
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_parse_threads_pool_type);
|
||||
|
||||
/* scst_mutex supposed to be held */
|
||||
int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev)
|
||||
@@ -2392,10 +2404,10 @@ int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev)
|
||||
|
||||
shared_io_context = scst_find_shared_io_context(tgt_dev);
|
||||
if (shared_io_context != NULL) {
|
||||
TRACE_DBG("Linking async io context %p for "
|
||||
"shared tgt_dev %p (cmd_threads %p, "
|
||||
"dev %s)", shared_io_context, tgt_dev,
|
||||
&tgt_dev->tgt_dev_cmd_threads,
|
||||
TRACE_MGMT_DBG("Linking async io context %p "
|
||||
"for shared tgt_dev %p (cmd_threads "
|
||||
"%p, dev %s)", shared_io_context,
|
||||
tgt_dev, &tgt_dev->tgt_dev_cmd_threads,
|
||||
tgt_dev->dev->virt_name);
|
||||
tgt_dev->tgt_dev_cmd_threads.io_context =
|
||||
ioc_task_link(shared_io_context);
|
||||
@@ -2406,9 +2418,10 @@ int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev)
|
||||
tgt_dev->tgt_dev_cmd_threads.io_context =
|
||||
ioc_task_link(get_io_context(GFP_KERNEL, -1));
|
||||
current->io_context = io_context;
|
||||
TRACE_DBG("Created async io context %p for "
|
||||
"not shared tgt_dev %p (cmd_threads %p, "
|
||||
"dev %s)", tgt_dev->tgt_dev_cmd_threads.io_context,
|
||||
TRACE_MGMT_DBG("Created async io context %p "
|
||||
"for not shared tgt_dev %p "
|
||||
"(cmd_threads %p, dev %s)",
|
||||
tgt_dev->tgt_dev_cmd_threads.io_context,
|
||||
tgt_dev, &tgt_dev->tgt_dev_cmd_threads,
|
||||
tgt_dev->dev->virt_name);
|
||||
}
|
||||
@@ -2428,7 +2441,7 @@ int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev)
|
||||
|
||||
shared_io_context = scst_find_shared_io_context(tgt_dev);
|
||||
if (shared_io_context != NULL) {
|
||||
TRACE_DBG("Linking io context %p for "
|
||||
TRACE_MGMT_DBG("Linking io context %p for "
|
||||
"shared tgt_dev %p (cmd_threads %p)",
|
||||
shared_io_context, tgt_dev,
|
||||
tgt_dev->active_cmd_threads);
|
||||
|
||||
@@ -222,6 +222,13 @@ static inline void scst_reset_io_context(struct scst_tgt_dev *tgt_dev,
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts string presentation of threads pool type to enum.
|
||||
* Returns SCST_THREADS_POOL_TYPE_INVALID if the string is invalid.
|
||||
*/
|
||||
extern enum scst_dev_type_threads_pool_type scst_parse_threads_pool_type(
|
||||
const char *p, int len);
|
||||
|
||||
extern int scst_add_threads(struct scst_cmd_threads *cmd_threads,
|
||||
struct scst_device *dev, struct scst_tgt_dev *tgt_dev, int num);
|
||||
extern void scst_del_threads(struct scst_cmd_threads *cmd_threads, int num);
|
||||
|
||||
@@ -112,10 +112,10 @@ static ssize_t scst_tgt_addr_method_show(struct kobject *kobj,
|
||||
static ssize_t scst_tgt_addr_method_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
static ssize_t scst_tgt_mpio_type_show(struct kobject *kobj,
|
||||
static ssize_t scst_tgt_io_grouping_type_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
char *buf);
|
||||
static ssize_t scst_tgt_mpio_type_store(struct kobject *kobj,
|
||||
static ssize_t scst_tgt_io_grouping_type_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
static ssize_t scst_ini_group_mgmt_show(struct kobject *kobj,
|
||||
@@ -145,10 +145,10 @@ static ssize_t scst_acg_addr_method_show(struct kobject *kobj,
|
||||
static ssize_t scst_acg_addr_method_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
static ssize_t scst_acg_mpio_type_show(struct kobject *kobj,
|
||||
static ssize_t scst_acg_io_grouping_type_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
char *buf);
|
||||
static ssize_t scst_acg_mpio_type_store(struct kobject *kobj,
|
||||
static ssize_t scst_acg_io_grouping_type_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
static ssize_t scst_acn_file_show(struct kobject *kobj,
|
||||
@@ -541,9 +541,10 @@ static struct kobj_attribute scst_tgt_addr_method =
|
||||
__ATTR(addr_method, S_IRUGO | S_IWUSR, scst_tgt_addr_method_show,
|
||||
scst_tgt_addr_method_store);
|
||||
|
||||
static struct kobj_attribute scst_tgt_mpio_type =
|
||||
__ATTR(mpio_type, S_IRUGO | S_IWUSR, scst_tgt_mpio_type_show,
|
||||
scst_tgt_mpio_type_store);
|
||||
static struct kobj_attribute scst_tgt_io_grouping_type =
|
||||
__ATTR(io_grouping_type, S_IRUGO | S_IWUSR,
|
||||
scst_tgt_io_grouping_type_show,
|
||||
scst_tgt_io_grouping_type_store);
|
||||
|
||||
static struct kobj_attribute scst_rel_tgt_id =
|
||||
__ATTR(rel_tgt_id, S_IRUGO | S_IWUSR, scst_rel_tgt_id_show,
|
||||
@@ -553,9 +554,10 @@ static struct kobj_attribute scst_acg_addr_method =
|
||||
__ATTR(addr_method, S_IRUGO | S_IWUSR, scst_acg_addr_method_show,
|
||||
scst_acg_addr_method_store);
|
||||
|
||||
static struct kobj_attribute scst_acg_mpio_type =
|
||||
__ATTR(mpio_type, S_IRUGO | S_IWUSR, scst_acg_mpio_type_show,
|
||||
scst_acg_mpio_type_store);
|
||||
static struct kobj_attribute scst_acg_io_grouping_type =
|
||||
__ATTR(io_grouping_type, S_IRUGO | S_IWUSR,
|
||||
scst_acg_io_grouping_type_show,
|
||||
scst_acg_io_grouping_type_store);
|
||||
|
||||
static ssize_t scst_tgt_enable_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
@@ -721,10 +723,10 @@ int scst_create_tgt_sysfs(struct scst_tgt *tgt)
|
||||
}
|
||||
|
||||
retval = sysfs_create_file(&tgt->tgt_kobj,
|
||||
&scst_tgt_mpio_type.attr);
|
||||
&scst_tgt_io_grouping_type.attr);
|
||||
if (retval != 0) {
|
||||
PRINT_ERROR("Can't add attribute %s for tgt %s",
|
||||
scst_tgt_mpio_type.attr.name, tgt->tgt_name);
|
||||
scst_tgt_io_grouping_type.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -840,6 +842,13 @@ static ssize_t scst_device_sysfs_threads_data_store(struct scst_device *dev,
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (dev->threads_num < 0) {
|
||||
PRINT_ERROR("Threads pool disabled for device %s",
|
||||
dev->virt_name);
|
||||
res = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((threads_num == dev->threads_num) &&
|
||||
(threads_pool_type == dev->threads_pool_type))
|
||||
goto out;
|
||||
@@ -1959,51 +1968,61 @@ static ssize_t scst_tgt_addr_method_store(struct kobject *kobj,
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t __scst_acg_mpio_type_show(struct scst_acg *acg, char *buf)
|
||||
static ssize_t __scst_acg_io_grouping_type_show(struct scst_acg *acg, char *buf)
|
||||
{
|
||||
int res;
|
||||
|
||||
switch (acg->acg_mpio_type) {
|
||||
case SCST_ACG_MPIO_AUTO:
|
||||
res = sprintf(buf, "auto\n");
|
||||
switch (acg->acg_io_grouping_type) {
|
||||
case SCST_IO_GROUPING_AUTO:
|
||||
res = sprintf(buf, "%s\n", SCST_IO_GROUPING_AUTO_STR);
|
||||
break;
|
||||
case SCST_ACG_MPIO_ENABLE:
|
||||
res = sprintf(buf, "enable\n%s\n", SCST_SYSFS_KEY_MARK);
|
||||
case SCST_IO_GROUPING_THIS_GROUP_ONLY:
|
||||
res = sprintf(buf, "%s\n%s\n",
|
||||
SCST_IO_GROUPING_THIS_GROUP_ONLY_STR,
|
||||
SCST_SYSFS_KEY_MARK);
|
||||
break;
|
||||
case SCST_ACG_MPIO_DISABLE:
|
||||
res = sprintf(buf, "disable\n%s\n", SCST_SYSFS_KEY_MARK);
|
||||
case SCST_IO_GROUPING_NEVER:
|
||||
res = sprintf(buf, "%s\n%s\n", SCST_IO_GROUPING_NEVER_STR,
|
||||
SCST_SYSFS_KEY_MARK);
|
||||
break;
|
||||
default:
|
||||
res = sprintf(buf, "Unknown\n");
|
||||
res = sprintf(buf, "%d\n%s\n", acg->acg_io_grouping_type,
|
||||
SCST_SYSFS_KEY_MARK);
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t __scst_acg_mpio_type_store(struct scst_acg *acg,
|
||||
static ssize_t __scst_acg_io_grouping_type_store(struct scst_acg *acg,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int res = count;
|
||||
enum scst_acg_mpio prev = acg->acg_mpio_type;
|
||||
int res = 0;
|
||||
int prev = acg->acg_io_grouping_type;
|
||||
struct scst_acg_dev *acg_dev;
|
||||
|
||||
if (strncasecmp(buf, SCST_ACG_MPIO_AUTO_STR,
|
||||
min_t(int, strlen(SCST_ACG_MPIO_AUTO_STR), count)) == 0)
|
||||
acg->acg_mpio_type = SCST_ACG_MPIO_AUTO;
|
||||
else if (strncasecmp(buf, SCST_ACG_MPIO_ENABLE_STR,
|
||||
min_t(int, strlen(SCST_ACG_MPIO_ENABLE_STR), count)) == 0)
|
||||
acg->acg_mpio_type = SCST_ACG_MPIO_ENABLE;
|
||||
else if (strncasecmp(buf, SCST_ACG_MPIO_DISABLE_STR,
|
||||
min_t(int, strlen(SCST_ACG_MPIO_DISABLE_STR), count)) == 0)
|
||||
acg->acg_mpio_type = SCST_ACG_MPIO_DISABLE;
|
||||
if (strncasecmp(buf, SCST_IO_GROUPING_AUTO_STR,
|
||||
min_t(int, strlen(SCST_IO_GROUPING_AUTO_STR), count)) == 0)
|
||||
acg->acg_io_grouping_type = SCST_IO_GROUPING_AUTO;
|
||||
else if (strncasecmp(buf, SCST_IO_GROUPING_THIS_GROUP_ONLY_STR,
|
||||
min_t(int, strlen(SCST_IO_GROUPING_THIS_GROUP_ONLY_STR), count)) == 0)
|
||||
acg->acg_io_grouping_type = SCST_IO_GROUPING_THIS_GROUP_ONLY;
|
||||
else if (strncasecmp(buf, SCST_IO_GROUPING_NEVER_STR,
|
||||
min_t(int, strlen(SCST_IO_GROUPING_NEVER_STR), count)) == 0)
|
||||
acg->acg_io_grouping_type = SCST_IO_GROUPING_NEVER;
|
||||
else {
|
||||
PRINT_ERROR("Unknown MPIO type %s", buf);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
long io_grouping_type;
|
||||
res = strict_strtoul(buf, 0, &io_grouping_type);
|
||||
if ((res != 0) || (io_grouping_type <= 0)) {
|
||||
PRINT_ERROR("Unknown or not allowed I/O grouping type "
|
||||
"%s", buf);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
acg->acg_io_grouping_type = io_grouping_type;
|
||||
}
|
||||
|
||||
if (prev == acg->acg_mpio_type)
|
||||
if (prev == acg->acg_io_grouping_type)
|
||||
goto out;
|
||||
|
||||
res = scst_suspend_activity(true);
|
||||
@@ -2034,7 +2053,7 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t scst_tgt_mpio_type_show(struct kobject *kobj,
|
||||
static ssize_t scst_tgt_io_grouping_type_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct scst_acg *acg;
|
||||
@@ -2043,10 +2062,10 @@ static ssize_t scst_tgt_mpio_type_show(struct kobject *kobj,
|
||||
tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
|
||||
acg = tgt->default_acg;
|
||||
|
||||
return __scst_acg_mpio_type_show(acg, buf);
|
||||
return __scst_acg_io_grouping_type_show(acg, buf);
|
||||
}
|
||||
|
||||
static ssize_t scst_tgt_mpio_type_store(struct kobject *kobj,
|
||||
static ssize_t scst_tgt_io_grouping_type_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int res;
|
||||
@@ -2056,8 +2075,13 @@ static ssize_t scst_tgt_mpio_type_store(struct kobject *kobj,
|
||||
tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
|
||||
acg = tgt->default_acg;
|
||||
|
||||
res = __scst_acg_mpio_type_store(acg, buf, count);
|
||||
res = __scst_acg_io_grouping_type_store(acg, buf, count);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
res = count;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
@@ -2117,10 +2141,10 @@ static int scst_create_acg_sysfs(struct scst_tgt *tgt,
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = sysfs_create_file(&acg->acg_kobj, &scst_acg_mpio_type.attr);
|
||||
retval = sysfs_create_file(&acg->acg_kobj, &scst_acg_io_grouping_type.attr);
|
||||
if (retval != 0) {
|
||||
PRINT_ERROR("Can't add tgt attr %s for tgt %s",
|
||||
scst_acg_mpio_type.attr.name, tgt->tgt_name);
|
||||
scst_acg_io_grouping_type.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -2175,17 +2199,17 @@ static ssize_t scst_acg_addr_method_store(struct kobject *kobj,
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t scst_acg_mpio_type_show(struct kobject *kobj,
|
||||
static ssize_t scst_acg_io_grouping_type_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct scst_acg *acg;
|
||||
|
||||
acg = container_of(kobj, struct scst_acg, acg_kobj);
|
||||
|
||||
return __scst_acg_mpio_type_show(acg, buf);
|
||||
return __scst_acg_io_grouping_type_show(acg, buf);
|
||||
}
|
||||
|
||||
static ssize_t scst_acg_mpio_type_store(struct kobject *kobj,
|
||||
static ssize_t scst_acg_io_grouping_type_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int res;
|
||||
@@ -2193,8 +2217,13 @@ static ssize_t scst_acg_mpio_type_store(struct kobject *kobj,
|
||||
|
||||
acg = container_of(kobj, struct scst_acg, acg_kobj);
|
||||
|
||||
res = __scst_acg_mpio_type_store(acg, buf, count);
|
||||
res = __scst_acg_io_grouping_type_store(acg, buf, count);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
res = count;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3762,7 +3762,7 @@ int scst_cmd_thread(void *arg)
|
||||
if (p_cmd_threads->io_context == NULL) {
|
||||
p_cmd_threads->io_context = ioc_task_link(
|
||||
get_io_context(GFP_KERNEL, -1));
|
||||
TRACE_DBG("Alloced new IO context %p "
|
||||
TRACE_MGMT_DBG("Alloced new IO context %p "
|
||||
"(p_cmd_threads %p)",
|
||||
p_cmd_threads->io_context,
|
||||
p_cmd_threads);
|
||||
@@ -3770,7 +3770,7 @@ int scst_cmd_thread(void *arg)
|
||||
put_io_context(current->io_context);
|
||||
current->io_context = ioc_task_link(
|
||||
p_cmd_threads->io_context);
|
||||
TRACE_DBG("Linked IO context %p "
|
||||
TRACE_MGMT_DBG("Linked IO context %p "
|
||||
"(p_cmd_threads %p)",
|
||||
p_cmd_threads->io_context,
|
||||
p_cmd_threads);
|
||||
|
||||
Reference in New Issue
Block a user