Small cleanups and improvements
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 26 Mar 2010 19:46:41 +0000 (19:46 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 26 Mar 2010 19:46:41 +0000 (19:46 +0000)
git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1565 d57e44dd-8a1f-0410-8b47-8ef2f437770f

12 files changed:
iscsi-scst/README
iscsi-scst/README_in-tree
qla2x00t/qla2x00-target/README
scst/README
scst/README_in-tree
scst/include/scst.h
scst/include/scst_const.h
scst/src/dev_handlers/scst_vdisk.c
scst/src/scst_lib.c
scst/src/scst_priv.h
scst/src/scst_sysfs.c
scst/src/scst_targ.c

index 6c0ebd5..d4e0684 100644 (file)
@@ -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
 -------------------
index 4aec409..68431d8 100644 (file)
@@ -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
 -------------------
index 575c5f0..5f6d8e0 100644 (file)
@@ -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
index 41dac95..2aedf0e 100644 (file)
@@ -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.
-
-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. If you are going to use your target in an VM environment, for
+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/.
+
+4. Make sure you have io_grouping_type option set correctly, especially
+in the following cases:
+
+ - 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
index 3905288..5b84531 100644 (file)
@@ -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.
-
-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. If you are going to use your target in an VM environment, for
+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/.
+
+4. Make sure you have io_grouping_type option set correctly, especially
+in the following cases:
+
+ - 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
index 9b4607e..bc53087 100644 (file)
@@ -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);
 
index 7c748e1..a58ce76 100644 (file)
@@ -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"
index 7d9e550..18aaab6 100644 (file)
@@ -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(&param);
-               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(&param)[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(&param);
+               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(&param)[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();
index e3e473f..e407180 100644 (file)
@@ -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);
index 91b8f28..fdca4ff 100644 (file)
@@ -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);
index 930f861..b73b730 100644 (file)
@@ -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;
 }
index af82a6f..39438ab 100644 (file)
@@ -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);