* [PATCH 0/8] Address recent SCST comments
@ 2010-12-27 13:35 Bart Van Assche
  2010-12-27 13:36 ` [PATCH 1/8] [SCSI] scst: Split sysfs type attribute Bart Van Assche
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Bart Van Assche @ 2010-12-27 13:35 UTC (permalink / raw)
  To: linux-scsi
  Cc: scst-devel, Greg Kroah-Hartman, Konrad Rzeszutek Wilk,
	Vladislav Bolkhovitin, Richard Sharpe
The paches in this patch series address the following issues:
- Make sure that all SCST sysfs attributes have only one value per file.
- Remove the '[key]' marker from sysfs files since it is nonstandard.
- Replace the symbolic constant SCST_SYSFS_BLOCK_SIZE by PAGE_SIZE.
- Improved the robustness of the sysfs parsing code.
- Fixed the errors in the online documentation of /sys/devices/scst/mgmt.
- Correct the version number of the SCST core.
- Update the documentation in Documentation/ABI/stable according to the above
  changes.
- Made the SCST sysfs documentation more clear. All comments formulated by Greg
  and Konrad about the documentation in Documentation/ABI/stable should have been
  addressed.
Notes:
- In case anyone starts wondering why set commands were introduced instead of
  making sysfs files writeable: the reason behind this is to avoid lock inversion.
- While examining how SCST has been configured via the sysfs interface is
  straightforward, configuring SCST via sysfs can be tedious. There exists a
  user space tool that allows to save a configuration to disk and to restore
  a configuration, even without restarting SCST. The source code of that tool
  can be obtained as follows:
  svn co https://scst.svn.sourceforge.net/svnroot/scst/branches/sysfs-tree-changes/scstadmin
  An example of a configuration file generated by the scstadmin tool:
# Automatically generated by SCST Configurator v2.0.0.
HANDLER vdisk_fileio {
	DEVICE disk01 {
		filename /dev/vdisk1
		nv_cache 1
	}
	DEVICE disk02 {
		filename /dev/vdisk2
		nv_cache 1
	}
	DEVICE disk03 {
		filename /dev/vdisk3
		nv_cache 1
	}
	DEVICE disk04 {
		filename /dev/vdisk4
		nv_cache 1
	}
}
HANDLER vdisk_nullio {
	DEVICE disk05
	DEVICE disk06
	DEVICE disk07
}
TARGET_DRIVER ib_srpt {
	TARGET ib_srpt_target_0 {
		rel_tgt_id 1
		enabled 1
		LUN 0 disk01
		LUN 1 disk02
		LUN 2 disk03
		LUN 3 disk04
		LUN 4 disk05
		LUN 5 disk06
		
		GROUP initiator1 {
			INITIATOR 0x00000000000000000002c9030005f34b
			INITIATOR 0x00000000000000000002c9030005f34c
			LUN 0 disk01
			LUN 1 disk02
			LUN 2 disk03
			LUN 3 disk04
			LUN 4 disk05
			LUN 5 disk06
			LUN 6 disk07
		}
	}
	TARGET ib_srpt_target_1 {
		rel_tgt_id 2
		enabled 1
		LUN 0 disk01
		LUN 1 disk02
		LUN 2 disk03
		LUN 3 disk04
		LUN 4 disk05
		LUN 5 disk06
	}
}
^ permalink raw reply	[flat|nested] 10+ messages in thread
* [PATCH 1/8] [SCSI] scst: Split sysfs type attribute
  2010-12-27 13:35 [PATCH 0/8] Address recent SCST comments Bart Van Assche
@ 2010-12-27 13:36 ` Bart Van Assche
  2010-12-27 13:37 ` [PATCH 2/8] [SCSI] scst: Split version and stats attributes Bart Van Assche
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Bart Van Assche @ 2010-12-27 13:36 UTC (permalink / raw)
  To: linux-scsi
  Cc: scst-devel, Greg Kroah-Hartman, Konrad Rzeszutek Wilk,
	Vladislav Bolkhovitin, Richard Sharpe
The device 'type' sysfs attribute contains two values: the SCSI
peripheral device type as a number and its textual description. Split
this sysfs attribute into two attributes such that both satisfy the
"one value per file" rule. Also, fix a potential out-of-bounds access
of the array scst_dev_handler_types.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Vladislav Bolkhovitin <vst@vlnb.net>
---
 .../ABI/stable/sysfs-devices-scst_tgt_dev          |    8 +++-
 Documentation/ABI/stable/sysfs-driver-scst_tgt_dev |   12 +++--
 drivers/scst/scst_sysfs.c                          |   46 ++++++++++++++-----
 3 files changed, 49 insertions(+), 17 deletions(-)
diff --git a/Documentation/ABI/stable/sysfs-devices-scst_tgt_dev b/Documentation/ABI/stable/sysfs-devices-scst_tgt_dev
index cfa791e..a7d5070 100644
--- a/Documentation/ABI/stable/sysfs-devices-scst_tgt_dev
+++ b/Documentation/ABI/stable/sysfs-devices-scst_tgt_dev
@@ -118,7 +118,13 @@ What:		/sys/bus/scst_tgt_dev/device/*/type
 Date:		December 2010
 Contact:	Bart Van Assche <bvanassche@acm.org>
 Description:
-		SCSI type of this device. Read-only.
+		SCSI type of this device as a number. Read-only.
+
+What:		/sys/bus/scst_tgt_dev/device/*/type_description
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		SCSI type of this device as a textual description. Read-only.
 
 What:		/sys/bus/scst_tgt_dev/device/*/usn
 Date:		December 2010
diff --git a/Documentation/ABI/stable/sysfs-driver-scst_tgt_dev b/Documentation/ABI/stable/sysfs-driver-scst_tgt_dev
index c79aee0..2787c4d 100644
--- a/Documentation/ABI/stable/sysfs-driver-scst_tgt_dev
+++ b/Documentation/ABI/stable/sysfs-driver-scst_tgt_dev
@@ -20,8 +20,12 @@ What:		/sys/bus/scst_tgt_dev/drivers/*/type
 Date:		December 2010
 Contact:	Bart Van Assche <bvanassche@acm.org>
 Description:
-		SCSI type of the devices managed by this driver. Read-only.
-		An example:
+		SCSI type of the devices managed by this driver as a number.
+		Read-only.
 
-		$ cat /sys/bus/scst_tgt_dev/drivers/vcdrom/type
-		5 - CD-ROM device
+What:		/sys/bus/scst_tgt_dev/drivers/*/type_description
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		SCSI type of the devices managed by this driver as a textual
+		description. Read-only.
diff --git a/drivers/scst/scst_sysfs.c b/drivers/scst/scst_sysfs.c
index 3901f20..23cba83 100644
--- a/drivers/scst/scst_sysfs.c
+++ b/drivers/scst/scst_sysfs.c
@@ -1091,16 +1091,22 @@ void scst_tgt_sysfs_put(struct scst_tgt *tgt)
 static ssize_t scst_dev_sysfs_type_show(struct device *device,
 				struct device_attribute *attr, char *buf)
 {
-	int pos;
 	struct scst_device *dev;
 
 	dev = scst_dev_to_dev(device);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", dev->type);
+}
 
-	pos = sprintf(buf, "%d - %s\n", dev->type,
-		(unsigned)dev->type > ARRAY_SIZE(scst_dev_handler_types) ?
-		      "unknown" : scst_dev_handler_types[dev->type]);
+static ssize_t scst_dev_sysfs_type_description_show(struct device *device,
+				struct device_attribute *attr, char *buf)
+{
+	struct scst_device *dev;
+	const char *descr;
 
-	return pos;
+	dev = scst_dev_to_dev(device);
+	descr = (unsigned)dev->type < ARRAY_SIZE(scst_dev_handler_types) ?
+		scst_dev_handler_types[dev->type] : "unknown";
+	return scnprintf(buf, PAGE_SIZE, "%s\n", descr);
 }
 
 static int scst_process_dev_sysfs_threads_data_store(
@@ -1265,8 +1271,13 @@ static const struct device_attribute *dev_thread_attr[] = {
 static const struct device_attribute scst_dev_sysfs_type_attr =
 	__ATTR(type, S_IRUGO, scst_dev_sysfs_type_show, NULL);
 
+static const struct device_attribute scst_dev_sysfs_type_description_attr =
+	__ATTR(type_description, S_IRUGO, scst_dev_sysfs_type_description_show,
+	       NULL);
+
 static const struct device_attribute *scst_devt_dev_attrs[] = {
 	&scst_dev_sysfs_type_attr,
+	&scst_dev_sysfs_type_description_attr,
 	NULL
 };
 
@@ -2852,23 +2863,34 @@ out:
 
 static ssize_t scst_devt_type_show(struct device_driver *drv, char *buf)
 {
-	int pos;
 	struct scst_dev_type *devt;
 
 	devt = scst_drv_to_devt(drv);
-
-	pos = sprintf(buf, "%d - %s\n", devt->type,
-		(unsigned)devt->type > ARRAY_SIZE(scst_dev_handler_types) ?
-			"unknown" : scst_dev_handler_types[devt->type]);
-
-	return pos;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", devt->type);
 }
 
 static const struct driver_attribute scst_devt_type_attr =
 	__ATTR(type, S_IRUGO, scst_devt_type_show, NULL);
 
+static ssize_t scst_devt_type_description_show(struct device_driver *drv,
+					       char *buf)
+{
+	struct scst_dev_type *devt;
+	const char *descr;
+
+	devt = scst_drv_to_devt(drv);
+	descr = (unsigned)devt->type < ARRAY_SIZE(scst_dev_handler_types) ?
+		scst_dev_handler_types[devt->type] : "unknown";
+	return scnprintf(buf, PAGE_SIZE, "%s\n", descr);
+}
+
+static const struct driver_attribute scst_devt_type_description_attr =
+	__ATTR(type_description, S_IRUGO, scst_devt_type_description_show,
+	       NULL);
+
 static const struct driver_attribute *scst_devt_default_attrs[] = {
 	&scst_devt_type_attr,
+	&scst_devt_type_description_attr,
 	NULL
 };
 
-- 
1.7.1
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH 2/8] [SCSI] scst: Split version and stats attributes
  2010-12-27 13:35 [PATCH 0/8] Address recent SCST comments Bart Van Assche
  2010-12-27 13:36 ` [PATCH 1/8] [SCSI] scst: Split sysfs type attribute Bart Van Assche
@ 2010-12-27 13:37 ` Bart Van Assche
  2010-12-27 13:38 ` [PATCH 3/8] [SCSI] scst: Remove [key] marker from sysfs files Bart Van Assche
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Bart Van Assche @ 2010-12-27 13:37 UTC (permalink / raw)
  To: linux-scsi
  Cc: scst-devel, Greg Kroah-Hartman, Konrad Rzeszutek Wilk,
	Vladislav Bolkhovitin, Richard Sharpe
Split the scst_local 'stats' sysfs attribute into three attributes such
that the "one value per file" rule is honered. The three new attributes
are: aborts, device_resets and target_resets. Export the scst_local
release date via the module information instead of sysfs. Remove the
build options from the 'version' attribute of scst_local and scst since
this duplicates information already available in the kernel .config.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Vladislav Bolkhovitin <vst@vlnb.net>
Cc: Richard Sharpe <realrichardsharpe@gmail.com>
---
 Documentation/ABI/stable/sysfs-driver-scst_target  |    9 +---
 .../ABI/stable/sysfs-driver-scst_target-scst_local |   23 ++++++---
 drivers/scst/scst_local/scst_local.c               |   49 +++++++++++--------
 drivers/scst/scst_sysfs.c                          |   47 +------------------
 4 files changed, 47 insertions(+), 81 deletions(-)
diff --git a/Documentation/ABI/stable/sysfs-driver-scst_target b/Documentation/ABI/stable/sysfs-driver-scst_target
index 0c2b6a1..ca8944a 100644
--- a/Documentation/ABI/stable/sysfs-driver-scst_target
+++ b/Documentation/ABI/stable/sysfs-driver-scst_target
@@ -48,12 +48,7 @@ What:		/sys/bus/scst_target/drivers/*/version
 Date:		December 2010
 Contact:	Bart Van Assche <bvanassche@acm.org>
 Description:
-		Target driver version and build options. The driver version
-		and build date appear on the first line separated by a
-		slash and the build options appear on subsequent
-		lines. Read-only. An example:
+		Target driver version. Read-only. An example:
 
 		$ cat /sys/bus/scst_target/drivers/scst_local/version
-		1.0.0/20100910
-		TRACING
-		DEBUG
+		1.0.0
diff --git a/Documentation/ABI/stable/sysfs-driver-scst_target-scst_local b/Documentation/ABI/stable/sysfs-driver-scst_target-scst_local
index 56e50f7..3ea28dc 100644
--- a/Documentation/ABI/stable/sysfs-driver-scst_target-scst_local
+++ b/Documentation/ABI/stable/sysfs-driver-scst_target-scst_local
@@ -1,11 +1,20 @@
-What:		/sys/bus/scst_target/drivers/scst_local/stats
+What:		/sys/bus/scst_target/drivers/scst_local/aborts
 Date:		December 2010
 Contact:	Richard Sharpe <realrichardsharpe@gmail.com>
 Description:
-		Statistics about processing of SCSI commands received via the
-		Linux SCSI initiator: the number of SCSI commands that have
-		been aborted, the number of SCSI device resets and the number
-		of SCSI target resets. Read-only. An example:
+		Number of SCSI commands that have been aborted by the SCSI
+		initiator. Read-only.
 
-		# cat /sys/bus/scst_target/drivers/scst_local/stats
-		Aborts: 0, Device Resets: 0, Target Resets: 0
+What:		/sys/bus/scst_target/drivers/scst_local/device_resets
+Date:		December 2010
+Contact:	Richard Sharpe <realrichardsharpe@gmail.com>
+Description:
+		Number of SCSI device resets that have been performed by the
+		SCSI initiator. Read-only.
+
+What:		/sys/bus/scst_target/drivers/scst_local/target_resets
+Date:		December 2010
+Contact:	Richard Sharpe <realrichardsharpe@gmail.com>
+Description:
+		Number of SCSI target resets that have been performed by the
+		SCSI initiator. Read-only.
diff --git a/drivers/scst/scst_local/scst_local.c b/drivers/scst/scst_local/scst_local.c
index 14c8fd9..b0c989a 100644
--- a/drivers/scst/scst_local/scst_local.c
+++ b/drivers/scst/scst_local/scst_local.c
@@ -54,7 +54,7 @@ static unsigned long scst_local_trace_flag = SCST_LOCAL_DEFAULT_LOG_FLAGS;
 #define FALSE 0
 
 #define SCST_LOCAL_VERSION "1.0.0"
-static const char *scst_local_version_date = "20100910";
+#define SCST_LOCAL_VERSION_DATE "20100910"
 
 /* Some statistics */
 static atomic_t num_aborts = ATOMIC_INIT(0);
@@ -128,6 +128,7 @@ MODULE_AUTHOR("Richard Sharpe, Vladislav Bolkhovitin + ideas from SCSI_DEBUG");
 MODULE_DESCRIPTION("SCSI+SCST local adapter driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(SCST_LOCAL_VERSION);
+MODULE_INFO(release_date, SCST_LOCAL_VERSION_DATE);
 
 static int scst_local_get_sas_transport_id(struct scst_local_sess *sess,
 	uint8_t **transport_id, int *len)
@@ -222,38 +223,44 @@ out:
 
 static ssize_t scst_local_version_show(struct device_driver *drv, char *buf)
 {
-	sprintf(buf, "%s/%s\n", SCST_LOCAL_VERSION, scst_local_version_date);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", SCST_LOCAL_VERSION);
+}
 
-#ifdef CONFIG_SCST_EXTRACHECKS
-	strcat(buf, "EXTRACHECKS\n");
-#endif
+static struct driver_attribute scst_local_version_attr =
+	__ATTR(version, S_IRUGO, scst_local_version_show, NULL);
 
-#ifdef CONFIG_SCST_TRACING
-	strcat(buf, "TRACING\n");
-#endif
+static ssize_t scst_local_aborts_show(struct device_driver *drv, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%u\n", atomic_read(&num_aborts));
+}
 
-#ifdef CONFIG_SCST_DEBUG
-	strcat(buf, "DEBUG\n");
-#endif
-	return strlen(buf);
+static struct driver_attribute scst_local_aborts_attr =
+	__ATTR(aborts, S_IRUGO, scst_local_aborts_show, NULL);
+
+static ssize_t scst_local_device_resets_show(struct device_driver *drv,
+					     char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%u\n", atomic_read(&num_dev_resets));
 }
 
-static struct driver_attribute scst_local_version_attr =
-	__ATTR(version, S_IRUGO, scst_local_version_show, NULL);
+static struct driver_attribute scst_local_device_resets_attr =
+	__ATTR(device_resets, S_IRUGO, scst_local_device_resets_show, NULL);
 
-static ssize_t scst_local_stats_show(struct device_driver *drv, char *buf)
+static ssize_t scst_local_target_resets_show(struct device_driver *drv,
+					     char *buf)
 {
-	return sprintf(buf, "Aborts: %d, Device Resets: %d, Target Resets: %d",
-		atomic_read(&num_aborts), atomic_read(&num_dev_resets),
-		atomic_read(&num_target_resets));
+	return scnprintf(buf, PAGE_SIZE, "%u\n",
+			 atomic_read(&num_target_resets));
 }
 
-static struct driver_attribute scst_local_stats_attr =
-	__ATTR(stats, S_IRUGO, scst_local_stats_show, NULL);
+static struct driver_attribute scst_local_target_resets_attr =
+	__ATTR(target_resets, S_IRUGO, scst_local_target_resets_show, NULL);
 
 static const struct driver_attribute *scst_local_tgtt_attrs[] = {
 	&scst_local_version_attr,
-	&scst_local_stats_attr,
+	&scst_local_aborts_attr,
+	&scst_local_device_resets_attr,
+	&scst_local_target_resets_attr,
 	NULL,
 };
 
diff --git a/drivers/scst/scst_sysfs.c b/drivers/scst/scst_sysfs.c
index 23cba83..05344cc 100644
--- a/drivers/scst/scst_sysfs.c
+++ b/drivers/scst/scst_sysfs.c
@@ -3611,52 +3611,7 @@ out:
 static ssize_t scst_version_show(struct device *device,
 				 struct device_attribute *attr, char *buf)
 {
-	sprintf(buf, "%s\n", SCST_VERSION_STRING);
-
-#ifdef CONFIG_SCST_STRICT_SERIALIZING
-	strcat(buf, "STRICT_SERIALIZING\n");
-#endif
-
-#ifdef CONFIG_SCST_EXTRACHECKS
-	strcat(buf, "EXTRACHECKS\n");
-#endif
-
-#ifdef CONFIG_SCST_TRACING
-	strcat(buf, "TRACING\n");
-#endif
-
-#ifdef CONFIG_SCST_DEBUG
-	strcat(buf, "DEBUG\n");
-#endif
-
-#ifdef CONFIG_SCST_DEBUG_TM
-	strcat(buf, "DEBUG_TM\n");
-#endif
-
-#ifdef CONFIG_SCST_DEBUG_RETRY
-	strcat(buf, "DEBUG_RETRY\n");
-#endif
-
-#ifdef CONFIG_SCST_DEBUG_OOM
-	strcat(buf, "DEBUG_OOM\n");
-#endif
-
-#ifdef CONFIG_SCST_DEBUG_SN
-	strcat(buf, "DEBUG_SN\n");
-#endif
-
-#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
-	strcat(buf, "USE_EXPECTED_VALUES\n");
-#endif
-
-#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
-	strcat(buf, "TEST_IO_IN_SIRQ\n");
-#endif
-
-#ifdef CONFIG_SCST_STRICT_SECURITY
-	strcat(buf, "STRICT_SECURITY\n");
-#endif
-	return strlen(buf);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", SCST_VERSION_STRING);
 }
 
 static struct device_attribute scst_mgmt_attr =
-- 
1.7.1
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH 3/8] [SCSI] scst: Remove [key] marker from sysfs files
  2010-12-27 13:35 [PATCH 0/8] Address recent SCST comments Bart Van Assche
  2010-12-27 13:36 ` [PATCH 1/8] [SCSI] scst: Split sysfs type attribute Bart Van Assche
  2010-12-27 13:37 ` [PATCH 2/8] [SCSI] scst: Split version and stats attributes Bart Van Assche
@ 2010-12-27 13:38 ` Bart Van Assche
  2010-12-27 13:39 ` [PATCH 4/8] [SCSI] scst: Substitute SCST_SYSFS_BLOCK_SIZE Bart Van Assche
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Bart Van Assche @ 2010-12-27 13:38 UTC (permalink / raw)
  To: linux-scsi
  Cc: scst-devel, Greg Kroah-Hartman, Konrad Rzeszutek Wilk,
	Vladislav Bolkhovitin, Richard Sharpe
While the '[key]' marker on the second line of sysfs files is convenient
for user-space tools that save the SCST state (e.g. scstadmin) to find
out whether or not a value is a default value, remove this marker to make
the contents of sysfs files created by SCST uniform with other sysfs
files.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Vladislav Bolkhovitin <vst@vlnb.net>
---
 .../ABI/stable/sysfs-devices-scst_tgt_dev          |    1 -
 Documentation/scst/SysfsRules                      |  160 --------------------
 drivers/scst/dev_handlers/scst_vdisk.c             |   62 ++------
 drivers/scst/scst_local/scst_local.c               |   10 +-
 drivers/scst/scst_sysfs.c                          |   66 +++------
 include/scst/scst_const.h                          |    2 -
 6 files changed, 34 insertions(+), 267 deletions(-)
 delete mode 100644 Documentation/scst/SysfsRules
diff --git a/Documentation/ABI/stable/sysfs-devices-scst_tgt_dev b/Documentation/ABI/stable/sysfs-devices-scst_tgt_dev
index a7d5070..2048875 100644
--- a/Documentation/ABI/stable/sysfs-devices-scst_tgt_dev
+++ b/Documentation/ABI/stable/sysfs-devices-scst_tgt_dev
@@ -24,7 +24,6 @@ Description:
 
 		# cat /sys/devices/disk01/filename
 		/dev/sdc
-		[key]
 
 What:		/sys/bus/scst_tgt_dev/device/*/nv_cache
 Date:		December 2010
diff --git a/Documentation/scst/SysfsRules b/Documentation/scst/SysfsRules
deleted file mode 100644
index 5790511..0000000
--- a/Documentation/scst/SysfsRules
+++ /dev/null
@@ -1,160 +0,0 @@
-		SCST SYSFS interface rules
-		==========================
-
-This document explains the rules SCST target drivers, device handlers and
-management utilities must adhere to. These rules make it possible for a
-user space tool like scstadmin to save and restore the entire state of the
-SCST core, target drivers and device handlers.
-
-If the last line of a modifiable sysfs attribute contains the text "[key]",
-this means the value of that attribute is not the default value of that
-attribute. That text is added by SCST when such an attribute is read but
-must not be added when modifying an SCST sysfs attribute.
-
-I. Rules for target drivers
-===========================
-
-The SCST core creates a directory for each target driver (struct
-scst_tgt_template) in /sys/bus/scst_target. And for each SCSI target (struct
-scst_tgt) the SCST core creates a directory in /sys/bus/scst_target/devices/.
-
-There are two types of SCSI targets, namely hardware and virtual.  Hardware
-targets are targets corresponding to a hardware entity, e.g. a port of a Fibre
-Channel adapter or an InfiniBand HCA. Virtual targets can be added and removed
-dynamically and do not have a one-to-one correspondence to hardware. As an
-example, iSCSI targets and NPIV Fibre Channel targets are virtual targets.
-
-Virtual targets are created and removed via the commands "add_target" and
-"del_target" respectively.
-
-A target driver that supports both hardware targets and virtual targets
-(e.g. an FC adapter that supports NPIV) must mark each hardware target with
-"hw_target" (see further).
-
-Querying the current state
---------------------------
-
-Querying the current state is possible by reading individual sysfs attributes.
-As an example, querying the state of the SCST core, all device drivers and
-target drivers is possible as follows:
-
-# find /sys/devices/scst /sys/bus/scst_target /sys/bus/scst_tgt_dev -type f -perm -u+r | xargs head
-
-Modifying the current state
----------------------------
-
-If a sysfs attribute has write permission, it can be modified by writing a new
-value into that attribute. Many management actions though happen via the
-"mgmt" attribute of the SCST device itself. The documentation of the syntax of
-the management commands can be revealed by reading that attribute. An example:
-
-# cd /sys/devices/scst
-# cat mgmt
-[ ... ]
-# cat /sys/devices/disk01/threads_num
-6
-[key]
-# echo "in device/disk01 set_threads_num 1" >mgmt
-# cat /sys/devices/disk01/threads_num
-1
-[key]
-
-
-II. Rules for device handlers
-=============================
-
-There are two types of device handlers: parent device handlers and child
-device handlers. The child device handlers depend on their parent device
-handler.
-
-The SCST core creates a directory for each parent device handler (struct
-scst_dev_type where the parent member equals NULL) in
-/sys/bus/scst_tgt_dev/driver. Parent device handlers can have one or more
-subdirectories for child device handlers.
-
-Only one level is allowed in the parent/child hierarchy. Parent device
-handlers that support child device handlers must not handle devices themselves.
-
-In this document child device handlers and parent device handlers without
-child device handlers will be called "end level device handlers".
-
-For each device (struct scst_device) the SCST core creates a directory in
-/sys/bus/scst_tgt_dev.
-
-Device handler attributes
--------------------------
-
-The following attributes may be supported for a device handler:
-
-1. "trace_level" - Allows to query and/or modify the log level for a device
-handler.
-
-2. "add_device_parameters" - Parameters supported by the add_device command.
-
-3. "driver_attributes" - Attributes supported by the add_attribute and
-del_attribute commands.
-
-4. "device_attributes" - Attributes supported by the add_device_attribute and
-del_device_attribute commands.
-
-5. "type" - SCSI device type. A number followed by a description, e.g.:
-
-# cat /sys/bus/scst_tgt_dev/drivers/vcdrom/type
-5 - CD-ROM device
-
-
-Device attributes
------------------
-
-The following attributes may be supported for a device:
-
-1. blocksize - Native SCSI block size of this device.
-
-2. filename - For virtual devices, the path of the associated file or device.
-An example:
-
-# cat /sys/devices/disk01/filename
-/dev/sdc
-[key]
-
-3. nv_cache - Whether or not the device has a non-volatile cache. SCST uses
-this information to decide whether or not it is safe to acknowledge writes
-early to the initiator. Setting this attribute to 1 for a device that neither
-has a non-volatile cache nor an UPS will decrease I/O latency but may result
-in data loss in case of a power failure.
-
-4. o_direct - For virtual devices that use file I/O, whether to use
-non-buffered (direct) I/O or buffered (asynchronous) I/O. In direct I/O mode
-both read and write caching is disabled.
-
-5. read_only - For virtual devices, whether or not to deny write commands.
-
-6. removable - For virtual devices, whether or not the underlying storage
-medium is removable.
-
-7. resync_size - For virtual devices, writing to this attribute will update
-the internally cached device size.
-
-8. size_mb - For virtual devices, the internally cached size in MB of the
-underlying storage device.
-
-9. t10_dev_id - SCSI device ID associated with the virtual device. This is the
-ID reported via the Device Identification page (0x83) of the INQUIRY command.
-
-10. thin_provisioned - Whether or not the virtual device supports thin
-provisioning.
-
-11. threads_num - Number of threads that exist in the thread pool that is
-used for processing SCSI commands for this device.
-
-12. threads_pool_type - Whether to use a distinct thread pool per initiator
-("per_initiator") or one thread pool for all initiators accessing this device
-("shared").
-
-13. type - SCSI type of this device.
-
-14. usn - Unique serial number as reported in the SCSI INQUIRY response.
-
-15. write_through - Allows to disable write-back caching for virtual devices.
-
-See also the SCST core README for more information about those attributes.
diff --git a/drivers/scst/dev_handlers/scst_vdisk.c b/drivers/scst/dev_handlers/scst_vdisk.c
index 0700c60..cb41962 100644
--- a/drivers/scst/dev_handlers/scst_vdisk.c
+++ b/drivers/scst/dev_handlers/scst_vdisk.c
@@ -532,7 +532,7 @@ static char *__vdev_get_filename(struct scst_vdisk_dev *virt_dev)
 	if (virt_dev->filename != NULL)
 		return virt_dev->filename;
 	else
-		return "none";
+		return "";
 }
 
 static void vdev_set_filename(struct scst_vdisk_dev *virt_dev, char *n)
@@ -3788,115 +3788,80 @@ static ssize_t vdev_sysfs_size_show(struct device *device,
 static ssize_t vdisk_sysfs_blocksize_show(struct device *device,
 				struct device_attribute *attr, char *buf)
 {
-	int pos = 0;
 	struct scst_device *dev;
 	struct scst_vdisk_dev *virt_dev;
 
 	dev = scst_dev_to_dev(device);
 	virt_dev = dev->dh_priv;
-
-	pos = sprintf(buf, "%d\n%s", (int)virt_dev->block_size,
-		(virt_dev->block_size == DEF_DISK_BLOCKSIZE) ? "" :
-			SCST_SYSFS_KEY_MARK "\n");
-	return pos;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", (int)virt_dev->block_size);
 }
 
 static ssize_t vdisk_sysfs_rd_only_show(struct device *device,
 				struct device_attribute *attr, char *buf)
 {
-	int pos = 0;
 	struct scst_device *dev;
 	struct scst_vdisk_dev *virt_dev;
 
 	dev = scst_dev_to_dev(device);
 	virt_dev = dev->dh_priv;
-
-	pos = sprintf(buf, "%d\n%s", virt_dev->rd_only ? 1 : 0,
-		(virt_dev->rd_only == DEF_RD_ONLY) ? "" :
-			SCST_SYSFS_KEY_MARK "");
-	return pos;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", virt_dev->rd_only ? 1 : 0);
 }
 
 static ssize_t vdisk_sysfs_wt_show(struct device *device,
 				   struct device_attribute *attr, char *buf)
 {
-	int pos = 0;
 	struct scst_device *dev;
 	struct scst_vdisk_dev *virt_dev;
 
 	dev = scst_dev_to_dev(device);
 	virt_dev = dev->dh_priv;
-
-	pos = sprintf(buf, "%d\n%s", virt_dev->wt_flag ? 1 : 0,
-		(virt_dev->wt_flag == DEF_WRITE_THROUGH) ? "" :
-			SCST_SYSFS_KEY_MARK "");
-	return pos;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", virt_dev->wt_flag ? 1 : 0);
 }
 
 static ssize_t vdisk_sysfs_tp_show(struct device *device,
 				   struct device_attribute *attr, char *buf)
 {
-	int pos = 0;
 	struct scst_device *dev;
 	struct scst_vdisk_dev *virt_dev;
 
 	dev = scst_dev_to_dev(device);
 	virt_dev = dev->dh_priv;
-
-	pos = sprintf(buf, "%d\n%s", virt_dev->thin_provisioned ? 1 : 0,
-		(virt_dev->thin_provisioned == DEF_THIN_PROVISIONED) ? "" :
-			SCST_SYSFS_KEY_MARK "");
-	return pos;
+	return scnprintf(buf, PAGE_SIZE, "%d\n",
+			 virt_dev->thin_provisioned ? 1 : 0);
 }
 
 static ssize_t vdisk_sysfs_nv_cache_show(struct device *device,
 	struct device_attribute *attr, char *buf)
 {
-	int pos = 0;
 	struct scst_device *dev;
 	struct scst_vdisk_dev *virt_dev;
 
 	dev = scst_dev_to_dev(device);
 	virt_dev = dev->dh_priv;
-
-	pos = sprintf(buf, "%d\n%s", virt_dev->nv_cache ? 1 : 0,
-		(virt_dev->nv_cache == DEF_NV_CACHE) ? "" :
-			SCST_SYSFS_KEY_MARK "");
-	return pos;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", virt_dev->nv_cache ? 1 : 0);
 }
 
 static ssize_t vdisk_sysfs_o_direct_show(struct device *device,
 	struct device_attribute *attr, char *buf)
 {
-	int pos = 0;
 	struct scst_device *dev;
 	struct scst_vdisk_dev *virt_dev;
 
 	dev = scst_dev_to_dev(device);
 	virt_dev = dev->dh_priv;
-
-	pos = sprintf(buf, "%d\n%s", virt_dev->o_direct_flag ? 1 : 0,
-		(virt_dev->o_direct_flag == DEF_O_DIRECT) ? "" :
-			SCST_SYSFS_KEY_MARK "");
-	return pos;
+	return scnprintf(buf, PAGE_SIZE, "%d\n",
+			 virt_dev->o_direct_flag ? 1 : 0);
 }
 
 static ssize_t vdisk_sysfs_removable_show(struct device *device,
 				struct device_attribute *attr, char *buf)
 {
-	int pos;
 	struct scst_device *dev;
 	struct scst_vdisk_dev *virt_dev;
 
 	dev = scst_dev_to_dev(device);
 	virt_dev = dev->dh_priv;
-
-	pos = sprintf(buf, "%d\n", virt_dev->removable ? 1 : 0);
-
-	if ((virt_dev->dev->type != TYPE_ROM) &&
-	    (virt_dev->removable != DEF_REMOVABLE))
-		pos += sprintf(&buf[pos], "%s\n", SCST_SYSFS_KEY_MARK);
-	return pos;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", virt_dev->removable ? 1 : 0);
 }
 
 static ssize_t vdev_sysfs_filename_show(struct device *device,
@@ -3912,9 +3877,7 @@ static ssize_t vdev_sysfs_filename_show(struct device *device,
 	res = mutex_lock_interruptible(&virt_dev->filename_mutex);
 	if (res)
 		goto out;
-	res = snprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n%s",
-		       __vdev_get_filename(virt_dev),
-		       virt_dev->filename ? SCST_SYSFS_KEY_MARK "\n" : "");
+	res = scnprintf(buf, PAGE_SIZE, "%s\n", __vdev_get_filename(virt_dev));
 	mutex_unlock(&virt_dev->filename_mutex);
 
 out:
@@ -4003,8 +3966,7 @@ static ssize_t vdev_sysfs_t10_dev_id_show(struct device *device,
 	virt_dev = dev->dh_priv;
 
 	read_lock_bh(&vdisk_t10_dev_id_rwlock);
-	pos = sprintf(buf, "%s\n%s", virt_dev->t10_dev_id,
-		virt_dev->t10_dev_id_set ? SCST_SYSFS_KEY_MARK "\n" : "");
+	pos = scnprintf(buf, PAGE_SIZE, "%s\n", virt_dev->t10_dev_id);
 	read_unlock_bh(&vdisk_t10_dev_id_rwlock);
 	return pos;
 }
diff --git a/drivers/scst/scst_local/scst_local.c b/drivers/scst/scst_local/scst_local.c
index b0c989a..a3804cb 100644
--- a/drivers/scst/scst_local/scst_local.c
+++ b/drivers/scst/scst_local/scst_local.c
@@ -285,10 +285,10 @@ static ssize_t scst_local_scsi_transport_version_show(struct device *dev,
 		goto out_up;
 
 	if (tgt->scsi_transport_version != 0)
-		res = sprintf(buf, "0x%x\n%s", tgt->scsi_transport_version,
-			SCST_SYSFS_KEY_MARK "\n");
+		res = scnprintf(buf, PAGE_SIZE, "0x%x\n",
+				tgt->scsi_transport_version);
 	else
-		res = sprintf(buf, "0x%x\n", 0x0BE0); /* SAS */
+		res = scnprintf(buf, PAGE_SIZE, "0x%x\n", 0x0BE0); /* SAS */
 
 out_up:
 	up_read(&scst_local_exit_rwsem);
@@ -350,9 +350,7 @@ static ssize_t scst_local_phys_transport_version_show(struct device *dev,
 	if (!tgt)
 		goto out_up;
 
-	res = sprintf(buf, "0x%x\n%s", tgt->phys_transport_version,
-			(tgt->phys_transport_version != 0) ?
-				SCST_SYSFS_KEY_MARK "\n" : "");
+	res = scnprintf(buf, PAGE_SIZE, "0x%x\n", tgt->phys_transport_version);
 
 out_up:
 	up_read(&scst_local_exit_rwsem);
diff --git a/drivers/scst/scst_sysfs.c b/drivers/scst/scst_sysfs.c
index 05344cc..da325f5 100644
--- a/drivers/scst/scst_sysfs.c
+++ b/drivers/scst/scst_sysfs.c
@@ -500,9 +500,6 @@ static ssize_t __scst_acg_addr_method_show(struct scst_acg *acg, char *buf)
 		break;
 	}
 
-	if (acg->addr_method != acg->tgt->tgtt->preferred_addr_method)
-		res += sprintf(&buf[res], "%s\n", SCST_SYSFS_KEY_MARK);
-
 	return res;
 }
 
@@ -568,17 +565,16 @@ static ssize_t __scst_acg_io_grouping_type_show(struct scst_acg *acg, char *buf)
 		res = sprintf(buf, "%s\n", SCST_IO_GROUPING_AUTO_STR);
 		break;
 	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);
+		res = scnprintf(buf, PAGE_SIZE, "%s\n",
+				SCST_IO_GROUPING_THIS_GROUP_ONLY_STR);
 		break;
 	case SCST_IO_GROUPING_NEVER:
-		res = sprintf(buf, "%s\n%s\n", SCST_IO_GROUPING_NEVER_STR,
-			SCST_SYSFS_KEY_MARK);
+		res = scnprintf(buf, PAGE_SIZE, "%s\n",
+				SCST_IO_GROUPING_NEVER_STR);
 		break;
 	default:
-		res = sprintf(buf, "%d\n%s\n", acg->acg_io_grouping_type,
-			SCST_SYSFS_KEY_MARK);
+		res = scnprintf(buf, PAGE_SIZE, "%d\n",
+				acg->acg_io_grouping_type);
 		break;
 	}
 
@@ -698,10 +694,6 @@ static ssize_t __scst_acg_cpu_mask_show(struct scst_acg *acg, char *buf)
 
 	res = cpumask_scnprintf(buf, PAGE_SIZE, &acg->acg_cpu_mask);
 	res += scnprintf(buf + res, PAGE_SIZE - res, "\n");
-	if (!cpus_equal(acg->acg_cpu_mask, default_cpu_mask))
-		res += scnprintf(buf + res, PAGE_SIZE - res, "%s",
-				 SCST_SYSFS_KEY_MARK "\n");
-
 	return res;
 }
 
@@ -839,13 +831,9 @@ static ssize_t scst_rel_tgt_id_show(struct device *device,
 				    struct device_attribute *attr, char *buf)
 {
 	struct scst_tgt *tgt;
-	int res;
 
 	tgt = scst_dev_to_tgt(device);
-
-	res = sprintf(buf, "%d\n%s", tgt->rel_tgt_id,
-		(tgt->rel_tgt_id != 0) ? SCST_SYSFS_KEY_MARK "\n" : "");
-	return res;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", tgt->rel_tgt_id);
 }
 
 static int scst_process_rel_tgt_id_store(struct scst_tgt *tgt,
@@ -1176,15 +1164,10 @@ out:
 static ssize_t scst_dev_sysfs_threads_num_show(struct device *device,
 					struct device_attribute *attr, char *buf)
 {
-	int pos;
 	struct scst_device *dev;
 
 	dev = scst_dev_to_dev(device);
-
-	pos = sprintf(buf, "%d\n%s", dev->threads_num,
-		(dev->threads_num != dev->handler->threads_num) ?
-			SCST_SYSFS_KEY_MARK "\n" : "");
-	return pos;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", dev->threads_num);
 }
 
 static ssize_t scst_dev_set_threads_num(struct scst_device *dev, long newtn)
@@ -1224,17 +1207,15 @@ static ssize_t scst_dev_sysfs_threads_pool_type_show(struct device *device,
 
 	switch (dev->threads_pool_type) {
 	case SCST_THREADS_POOL_PER_INITIATOR:
-		pos = sprintf(buf, "%s\n%s", SCST_THREADS_POOL_PER_INITIATOR_STR,
-			(dev->threads_pool_type != dev->handler->threads_pool_type) ?
-				SCST_SYSFS_KEY_MARK "\n" : "");
+		pos = scnprintf(buf, PAGE_SIZE, "%s\n",
+				SCST_THREADS_POOL_PER_INITIATOR_STR);
 		break;
 	case SCST_THREADS_POOL_SHARED:
-		pos = sprintf(buf, "%s\n%s", SCST_THREADS_POOL_SHARED_STR,
-			(dev->threads_pool_type != dev->handler->threads_pool_type) ?
-				SCST_SYSFS_KEY_MARK "\n" : "");
+		pos = scnprintf(buf, PAGE_SIZE, "%s\n",
+				SCST_THREADS_POOL_SHARED_STR);
 		break;
 	default:
-		pos = sprintf(buf, "Unknown\n");
+		pos = scnprintf(buf, PAGE_SIZE, "Unknown\n");
 		break;
 	}
 
@@ -2051,11 +2032,8 @@ static ssize_t scst_lun_rd_only_show(struct kobject *kobj,
 	struct scst_acg_dev *acg_dev;
 
 	acg_dev = scst_kobj_to_acg_dev(kobj);
-
-	if (acg_dev->rd_only || acg_dev->dev->rd_only)
-		return sprintf(buf, "%d\n%s\n", 1, SCST_SYSFS_KEY_MARK);
-	else
-		return sprintf(buf, "%d\n", 0);
+	return scnprintf(buf, PAGE_SIZE, "%d\n",
+			 acg_dev->rd_only || acg_dev->dev->rd_only);
 }
 
 static struct kobj_attribute lun_options_attr =
@@ -3514,12 +3492,8 @@ out:
 static ssize_t scst_threads_show(struct device *device,
 				 struct device_attribute *attr, char *buf)
 {
-	int count;
-
-	count = sprintf(buf, "%d\n%s", scst_main_cmd_threads.nr_threads,
-		(scst_main_cmd_threads.nr_threads != scst_threads) ?
-			SCST_SYSFS_KEY_MARK "\n" : "");
-	return count;
+	return scnprintf(buf, PAGE_SIZE, "%d\n",
+			 scst_main_cmd_threads.nr_threads);
 }
 
 static int scst_process_threads_store(int newtn)
@@ -3580,11 +3554,7 @@ out:
 static ssize_t scst_setup_id_show(struct device *device,
 				  struct device_attribute *attr, char *buf)
 {
-	int count;
-
-	count = sprintf(buf, "0x%x\n%s\n", scst_setup_id,
-		(scst_setup_id == 0) ? "" : SCST_SYSFS_KEY_MARK);
-	return count;
+	return scnprintf(buf, PAGE_SIZE, "0x%x\n", scst_setup_id);
 }
 
 static ssize_t scst_setup_id_store(struct device *device,
diff --git a/include/scst/scst_const.h b/include/scst/scst_const.h
index b7b06ea..d1dadfa 100644
--- a/include/scst/scst_const.h
+++ b/include/scst/scst_const.h
@@ -385,8 +385,6 @@ enum scst_cdb_flags {
 
 #define TID_COMMON_SIZE				24
 
-#define SCST_SYSFS_KEY_MARK			"[key]"
-
 #define SCST_MIN_REL_TGT_ID			1
 #define SCST_MAX_REL_TGT_ID			65535
 
-- 
1.7.1
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH 4/8] [SCSI] scst: Substitute SCST_SYSFS_BLOCK_SIZE
  2010-12-27 13:35 [PATCH 0/8] Address recent SCST comments Bart Van Assche
                   ` (2 preceding siblings ...)
  2010-12-27 13:38 ` [PATCH 3/8] [SCSI] scst: Remove [key] marker from sysfs files Bart Van Assche
@ 2010-12-27 13:39 ` Bart Van Assche
  2010-12-27 13:39 ` [PATCH 5/8] [SCSI] scst: Improve sysfs parsing robustness Bart Van Assche
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Bart Van Assche @ 2010-12-27 13:39 UTC (permalink / raw)
  To: linux-scsi
  Cc: scst-devel, Greg Kroah-Hartman, Konrad Rzeszutek Wilk,
	Vladislav Bolkhovitin, Richard Sharpe
Replace all instances of SCST_SYSFS_BLOCK_SIZE by PAGE_SIZE and remove the
symbolic constant SCST_SYSFS_BLOCK_SIZE.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Vladislav Bolkhovitin <vst@vlnb.net>
---
 drivers/scst/scst_sysfs.c |   54 +++++++++++++++++++-------------------------
 include/scst/scst_const.h |    2 -
 2 files changed, 23 insertions(+), 33 deletions(-)
diff --git a/drivers/scst/scst_sysfs.c b/drivers/scst/scst_sysfs.c
index da325f5..ed10475 100644
--- a/drivers/scst/scst_sysfs.c
+++ b/drivers/scst/scst_sysfs.c
@@ -1531,7 +1531,7 @@ static ssize_t scst_tgt_dev_latency_show(struct kobject *kobj,
 		processed_cmds_wr = latency_stat->processed_cmds_wr;
 		processed_cmds_rd = latency_stat->processed_cmds_rd;
 
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
 			 "%-5s %-9s %-15lu ", "Write", scst_io_size_names[i],
 			(unsigned long)processed_cmds_wr);
 		if (processed_cmds_wr == 0)
@@ -1543,8 +1543,7 @@ static ssize_t scst_tgt_dev_latency_show(struct kobject *kobj,
 			(unsigned long)scst_time_wr,
 			(unsigned long)latency_stat->max_scst_time_wr,
 			(unsigned long)latency_stat->scst_time_wr);
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
-			"%-47s", buf);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s", buf);
 
 		do_div(tgt_time_wr, processed_cmds_wr);
 		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
@@ -1552,8 +1551,7 @@ static ssize_t scst_tgt_dev_latency_show(struct kobject *kobj,
 			(unsigned long)tgt_time_wr,
 			(unsigned long)latency_stat->max_tgt_time_wr,
 			(unsigned long)latency_stat->tgt_time_wr);
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
-			"%-47s", buf);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s", buf);
 
 		do_div(dev_time_wr, processed_cmds_wr);
 		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
@@ -1561,10 +1559,9 @@ static ssize_t scst_tgt_dev_latency_show(struct kobject *kobj,
 			(unsigned long)dev_time_wr,
 			(unsigned long)latency_stat->max_dev_time_wr,
 			(unsigned long)latency_stat->dev_time_wr);
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
-			"%-47s\n", buf);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s\n", buf);
 
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
 			"%-5s %-9s %-15lu ", "Read", scst_io_size_names[i],
 			(unsigned long)processed_cmds_rd);
 		if (processed_cmds_rd == 0)
@@ -1576,8 +1573,7 @@ static ssize_t scst_tgt_dev_latency_show(struct kobject *kobj,
 			(unsigned long)scst_time_rd,
 			(unsigned long)latency_stat->max_scst_time_rd,
 			(unsigned long)latency_stat->scst_time_rd);
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
-			"%-47s", buf);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s", buf);
 
 		do_div(tgt_time_rd, processed_cmds_rd);
 		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
@@ -1585,8 +1581,7 @@ static ssize_t scst_tgt_dev_latency_show(struct kobject *kobj,
 			(unsigned long)tgt_time_rd,
 			(unsigned long)latency_stat->max_tgt_time_rd,
 			(unsigned long)latency_stat->tgt_time_rd);
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
-			"%-47s", buf);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s", buf);
 
 		do_div(dev_time_rd, processed_cmds_rd);
 		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
@@ -1594,8 +1589,7 @@ static ssize_t scst_tgt_dev_latency_show(struct kobject *kobj,
 			(unsigned long)dev_time_rd,
 			(unsigned long)latency_stat->max_dev_time_rd,
 			(unsigned long)latency_stat->dev_time_rd);
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
-			"%-47s\n", buf);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s\n", buf);
 	}
 	return res;
 }
@@ -1671,7 +1665,7 @@ static ssize_t scst_sess_latency_show(struct kobject *kobj,
 	sess = scst_kobj_to_sess(kobj);
 
 	res = 0;
-	res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+	res += scnprintf(&buffer[res], PAGE_SIZE - res,
 		"%-15s %-15s %-46s %-46s %-46s\n",
 		"T-L names", "Total commands", "SCST latency",
 		"Target latency", "Dev latency (min/avg/max/all ns)");
@@ -1695,7 +1689,7 @@ static ssize_t scst_sess_latency_show(struct kobject *kobj,
 		processed_cmds_wr = latency_stat->processed_cmds_wr;
 		processed_cmds_rd = latency_stat->processed_cmds_rd;
 
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
 			"%-5s %-9s %-15lu ",
 			"Write", scst_io_size_names[i],
 			(unsigned long)processed_cmds_wr);
@@ -1708,7 +1702,7 @@ static ssize_t scst_sess_latency_show(struct kobject *kobj,
 			(unsigned long)scst_time_wr,
 			(unsigned long)latency_stat->max_scst_time_wr,
 			(unsigned long)latency_stat->scst_time_wr);
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
 			"%-47s", buf);
 
 		do_div(tgt_time_wr, processed_cmds_wr);
@@ -1717,7 +1711,7 @@ static ssize_t scst_sess_latency_show(struct kobject *kobj,
 			(unsigned long)tgt_time_wr,
 			(unsigned long)latency_stat->max_tgt_time_wr,
 			(unsigned long)latency_stat->tgt_time_wr);
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
 			"%-47s", buf);
 
 		do_div(dev_time_wr, processed_cmds_wr);
@@ -1726,10 +1720,10 @@ static ssize_t scst_sess_latency_show(struct kobject *kobj,
 			(unsigned long)dev_time_wr,
 			(unsigned long)latency_stat->max_dev_time_wr,
 			(unsigned long)latency_stat->dev_time_wr);
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
 			"%-47s\n", buf);
 
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
 			"%-5s %-9s %-15lu ",
 			"Read", scst_io_size_names[i],
 			(unsigned long)processed_cmds_rd);
@@ -1742,7 +1736,7 @@ static ssize_t scst_sess_latency_show(struct kobject *kobj,
 			(unsigned long)scst_time_rd,
 			(unsigned long)latency_stat->max_scst_time_rd,
 			(unsigned long)latency_stat->scst_time_rd);
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
 			"%-47s", buf);
 
 		do_div(tgt_time_rd, processed_cmds_rd);
@@ -1751,7 +1745,7 @@ static ssize_t scst_sess_latency_show(struct kobject *kobj,
 			(unsigned long)tgt_time_rd,
 			(unsigned long)latency_stat->max_tgt_time_rd,
 			(unsigned long)latency_stat->tgt_time_rd);
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
 			"%-47s", buf);
 
 		do_div(dev_time_rd, processed_cmds_rd);
@@ -1760,7 +1754,7 @@ static ssize_t scst_sess_latency_show(struct kobject *kobj,
 			(unsigned long)dev_time_rd,
 			(unsigned long)latency_stat->max_dev_time_rd,
 			(unsigned long)latency_stat->dev_time_rd);
-		res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
 			"%-47s\n", buf);
 	}
 
@@ -1769,7 +1763,7 @@ static ssize_t scst_sess_latency_show(struct kobject *kobj,
 	dev_time = sess->dev_time;
 	processed_cmds = sess->processed_cmds;
 
-	res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+	res += scnprintf(&buffer[res], PAGE_SIZE - res,
 		"\n%-15s %-16d", "Overall ", processed_cmds);
 
 	if (processed_cmds == 0)
@@ -1781,7 +1775,7 @@ static ssize_t scst_sess_latency_show(struct kobject *kobj,
 		(unsigned long)scst_time,
 		(unsigned long)sess->max_scst_time,
 		(unsigned long)sess->scst_time);
-	res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+	res += scnprintf(&buffer[res], PAGE_SIZE - res,
 		"%-47s", buf);
 
 	do_div(tgt_time, processed_cmds);
@@ -1790,7 +1784,7 @@ static ssize_t scst_sess_latency_show(struct kobject *kobj,
 		(unsigned long)tgt_time,
 		(unsigned long)sess->max_tgt_time,
 		(unsigned long)sess->tgt_time);
-	res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+	res += scnprintf(&buffer[res], PAGE_SIZE - res,
 		"%-47s", buf);
 
 	do_div(dev_time, processed_cmds);
@@ -1799,7 +1793,7 @@ static ssize_t scst_sess_latency_show(struct kobject *kobj,
 		(unsigned long)dev_time,
 		(unsigned long)sess->max_dev_time,
 		(unsigned long)sess->dev_time);
-	res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
+	res += scnprintf(&buffer[res], PAGE_SIZE - res,
 		"%-47s\n\n", buf);
 
 	spin_unlock_bh(&sess->lat_lock);
@@ -1937,8 +1931,7 @@ static ssize_t scst_sess_sysfs_initiator_name_show(struct kobject *kobj,
 
 	sess = scst_kobj_to_sess(kobj);
 
-	return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n",
-		sess->initiator_name);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", sess->initiator_name);
 }
 
 static struct kobj_attribute session_initiator_name_attr =
@@ -2588,8 +2581,7 @@ out:
 static ssize_t scst_acn_file_show(struct kobject *kobj,
 	struct kobj_attribute *attr, char *buf)
 {
-	return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n",
-		attr->attr.name);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", attr->attr.name);
 }
 
 int scst_acn_sysfs_create(struct scst_acn *acn)
diff --git a/include/scst/scst_const.h b/include/scst/scst_const.h
index d1dadfa..ac446fa 100644
--- a/include/scst/scst_const.h
+++ b/include/scst/scst_const.h
@@ -379,8 +379,6 @@ enum scst_cdb_flags {
 /*************************************************************
  ** Misc constants
  *************************************************************/
-#define SCST_SYSFS_BLOCK_SIZE			PAGE_SIZE
-
 #define SCST_PR_DIR				"/var/lib/scst/pr"
 
 #define TID_COMMON_SIZE				24
-- 
1.7.1
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH 5/8] [SCSI] scst: Improve sysfs parsing robustness
  2010-12-27 13:35 [PATCH 0/8] Address recent SCST comments Bart Van Assche
                   ` (3 preceding siblings ...)
  2010-12-27 13:39 ` [PATCH 4/8] [SCSI] scst: Substitute SCST_SYSFS_BLOCK_SIZE Bart Van Assche
@ 2010-12-27 13:39 ` Bart Van Assche
  2010-12-27 13:40 ` [PATCH 6/8] [SCSI] scst: Fix online documentation Bart Van Assche
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Bart Van Assche @ 2010-12-27 13:39 UTC (permalink / raw)
  To: linux-scsi
  Cc: scst-devel, Greg Kroah-Hartman, Konrad Rzeszutek Wilk,
	Vladislav Bolkhovitin, Richard Sharpe
Improve the robustness of the code for parsing management commands
received via the sysfs file /sys/devices/scst/mgmt. Allow several spaces
between parameters where only a single space was allowed, and consistenly
ignore trailing newlines.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 drivers/scst/scst_sysfs.c |   85 ++++++++++++++++++++++++--------------------
 1 files changed, 46 insertions(+), 39 deletions(-)
diff --git a/drivers/scst/scst_sysfs.c b/drivers/scst/scst_sysfs.c
index ed10475..525f368 100644
--- a/drivers/scst/scst_sysfs.c
+++ b/drivers/scst/scst_sysfs.c
@@ -937,20 +937,24 @@ out_free:
 
 static int scst_process_tgt_mgmt_store(char *cmd, struct scst_tgt *tgt)
 {
+	char *arg, *tail;
 	int res;
 
 	res = -EINVAL;
+	arg = cmd;
+	cmd = scst_get_next_lexem(&arg);
+	tail = arg;
+	scst_get_next_lexem(&tail);
 	if (strcmp(cmd, "enable") == 0)
 		res = scst_process_tgt_enable_store(tgt, true);
 	else if (strcmp(cmd, "disable") == 0)
 		res = scst_process_tgt_enable_store(tgt, false);
-	else if (strncmp(cmd, "set_cpu_mask ", 13) == 0) {
+	else if (strcmp(cmd, "set_cpu_mask") == 0) {
 		cpumask_t *cpumask;
 
 		BUG_ON(!tgt->default_acg);
 
-		res = scst_alloc_and_parse_cpumask(&cpumask, cmd + 13,
-						   strlen(cmd + 13));
+		res = scst_alloc_and_parse_cpumask(&cpumask, arg, strlen(arg));
 		if (res)
 			goto out;
 		res = __scst_acg_process_cpu_mask_store(tgt, tgt->default_acg,
@@ -1264,20 +1268,25 @@ static const struct device_attribute *scst_devt_dev_attrs[] = {
 
 static int scst_process_dev_mgmt_store(char *cmd, struct scst_device *dev)
 {
+	char *arg, *tail;
 	int res;
 
 	res = -EINVAL;
-	if (strncmp(cmd, "set_filename ", 13) == 0) {
+	arg = cmd;
+	cmd = scst_get_next_lexem(&arg);
+	tail = arg;
+	scst_get_next_lexem(&tail);
+	if (strcmp(cmd, "set_filename") == 0) {
 		res = -EPERM;
 		if (!dev->handler->set_filename)
 			goto out;
-		res = dev->handler->set_filename(dev, cmd + 13);
-	} else if (strncmp(cmd, "set_threads_num ", 16) == 0) {
+		res = dev->handler->set_filename(dev, arg);
+	} else if (strcmp(cmd, "set_threads_num") == 0) {
 		long num_threads;
 
-		res = strict_strtol(cmd + 16, 0, &num_threads);
+		res = strict_strtol(arg, 0, &num_threads);
 		if (res) {
-			PRINT_ERROR("Bad thread count %s", cmd + 16);
+			PRINT_ERROR("Bad thread count %s", arg);
 			goto out;
 		}
 		if (num_threads < 0) {
@@ -1285,13 +1294,12 @@ static int scst_process_dev_mgmt_store(char *cmd, struct scst_device *dev)
 			goto out;
 		}
 		res = scst_dev_set_threads_num(dev, num_threads);
-	} else if (strncmp(cmd, "set_thread_pool_type ", 21) == 0) {
+	} else if (strcmp(cmd, "set_thread_pool_type") == 0) {
 		enum scst_dev_type_threads_pool_type newtpt;
 
-		newtpt = scst_parse_threads_pool_type(cmd + 21,
-						      strlen(cmd + 21));
+		newtpt = scst_parse_threads_pool_type(arg, strlen(arg));
 		if (newtpt == SCST_THREADS_POOL_TYPE_INVALID) {
-			PRINT_ERROR("Invalid thread pool type %s", cmd + 21);
+			PRINT_ERROR("Invalid thread pool type %s", arg);
 			goto out;
 		}
 		res = scst_dev_set_thread_pool_type(dev, newtpt);
@@ -2095,16 +2103,20 @@ out_del:
  ** ini_groups directory implementation.
  **/
 
-static int scst_process_acg_mgmt_store(const char *cmd, struct scst_acg *acg)
+static int scst_process_acg_mgmt_store(char *cmd, struct scst_acg *acg)
 {
+	char *arg, *tail;
 	int res;
 
 	res = -EINVAL;
-	if (strncmp(cmd, "set_cpu_mask ", 13) == 0) {
+	arg = cmd;
+	cmd = scst_get_next_lexem(&arg);
+	tail = arg;
+	scst_get_next_lexem(&tail);
+	if (strcmp(cmd, "set_cpu_mask") == 0) {
 		cpumask_t *cpumask;
 
-		res = scst_alloc_and_parse_cpumask(&cpumask, cmd + 13,
-						   strlen(cmd + 13));
+		res = scst_alloc_and_parse_cpumask(&cpumask, arg, strlen(arg));
 		if (res)
 			goto out;
 		res = __scst_acg_process_cpu_mask_store(acg->tgt, acg, cpumask);
@@ -3390,7 +3402,7 @@ static ssize_t scst_mgmt_store(struct device *device,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	ssize_t res;
-	char *buffer, *path, *path_end, *cmd;
+	char *buffer, *path, *cmd, *tail;
 	enum mgmt_path_type mgmt_path_type;
 	struct scst_dev_type *devt;
 	struct scst_device *dev;
@@ -3409,19 +3421,13 @@ static ssize_t scst_mgmt_store(struct device *device,
 		goto out;
 
 	res = -EINVAL;
-	if (strncmp(buffer, "in ", 3) != 0)
+	path = buffer;
+	cmd = scst_get_next_lexem(&path);
+	if (strcmp(cmd, "in") != 0)
 		goto out;
 
-	path = buffer + 3;
-	while (*path && isspace((u8)*path))
-		path++;
-	path_end = path;
-	while (*path_end && !isspace((u8)*path_end))
-		path_end++;
-	*path_end++ = '\0';
-	cmd = path_end;
-	while (*cmd && isspace((u8)*cmd))
-		cmd++;
+	tail = path;
+	scst_get_next_lexem(&tail);
 
 	res = scst_suspend_activity(true);
 	if (res)
@@ -3437,36 +3443,37 @@ static ssize_t scst_mgmt_store(struct device *device,
 	res = -EINVAL;
 	switch (mgmt_path_type) {
 	case DEVICE_PATH:
-		res = scst_process_dev_mgmt_store(cmd, dev);
+		res = scst_process_dev_mgmt_store(tail, dev);
 		break;
 	case DEVICE_TYPE_PATH:
 		if (devt->add_device)
-			res = scst_process_devt_mgmt_store(cmd, devt);
+			res = scst_process_devt_mgmt_store(tail, devt);
 		else
-			res = scst_process_devt_pass_through_mgmt_store(cmd,
+			res = scst_process_devt_pass_through_mgmt_store(tail,
 									devt);
 		break;
 	case TARGET_TEMPLATE_PATH:
-		res = scst_process_tgtt_mgmt_store(cmd, tgtt);
+		res = scst_process_tgtt_mgmt_store(tail, tgtt);
 		break;
 	case TARGET_PATH:
-		res = scst_process_tgt_mgmt_store(cmd, tgt);
+		res = scst_process_tgt_mgmt_store(tail, tgt);
 		break;
 	case TARGET_LUNS_PATH:
-		res = __scst_process_luns_mgmt_store(cmd, tgt, tgt->default_acg,
-						     true);
+		res = __scst_process_luns_mgmt_store(tail, tgt,
+						     tgt->default_acg, true);
 		break;
 	case TARGET_INI_GROUPS_PATH:
-		res = scst_process_ini_group_mgmt_store(cmd, tgt);
+		res = scst_process_ini_group_mgmt_store(tail, tgt);
 		break;
 	case ACG_PATH:
-		res = scst_process_acg_mgmt_store(cmd, acg);
+		res = scst_process_acg_mgmt_store(tail, acg);
 		break;
 	case ACG_LUNS_PATH:
-		res = __scst_process_luns_mgmt_store(cmd, acg->tgt, acg, false);
+		res = __scst_process_luns_mgmt_store(tail, acg->tgt, acg,
+						     false);
 		break;
 	case ACG_INITIATOR_GROUPS_PATH:
-		res = scst_process_acg_ini_mgmt_store(cmd, acg->tgt, acg);
+		res = scst_process_acg_ini_mgmt_store(tail, acg->tgt, acg);
 		break;
 	case PATH_NOT_RECOGNIZED:
 		break;
-- 
1.7.1
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH 6/8] [SCSI] scst: Fix online documentation
  2010-12-27 13:35 [PATCH 0/8] Address recent SCST comments Bart Van Assche
                   ` (4 preceding siblings ...)
  2010-12-27 13:39 ` [PATCH 5/8] [SCSI] scst: Improve sysfs parsing robustness Bart Van Assche
@ 2010-12-27 13:40 ` Bart Van Assche
  2010-12-27 13:43 ` [PATCH 8/8] Make SCST sysfs documentation more complete Bart Van Assche
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Bart Van Assche @ 2010-12-27 13:40 UTC (permalink / raw)
  To: linux-scsi
  Cc: scst-devel, Greg Kroah-Hartman, Konrad Rzeszutek Wilk,
	Vladislav Bolkhovitin, Richard Sharpe
Fix an error in the online documentation of /sys/devices/scst/mgmt,
reorder it and make that documentation more consistent.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 drivers/scst/scst_sysfs.c |   37 +++++++++++++++++--------------------
 1 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/drivers/scst/scst_sysfs.c b/drivers/scst/scst_sysfs.c
index 525f368..aadb066 100644
--- a/drivers/scst/scst_sysfs.c
+++ b/drivers/scst/scst_sysfs.c
@@ -3217,21 +3217,21 @@ static ssize_t scst_mgmt_show(struct device *device,
 {
 	ssize_t count;
 	static const char help[] =
-/* device/<dev>/filename */
-"in device/<dev> <dev_cmd>\n"
 /* scst_devt_mgmt or scst_devt_pass_through_mgmt */
 "in device_driver/<devt> <devt_cmd>\n"
+/* device/<dev>/filename */
+"in device/<dev> <dev_cmd>\n"
 /* scst_tgtt_mgmt */
 "in target_driver/<tgtt> <tgtt_cmd>\n"
 /* scst_tgt_mgmt */
-"in target_driver/<tgtt>/<target>/luns <tgt_cmd>\n"
+"in target_driver/<tgtt>/<target> <tgt_cmd>\n"
 /* scst_luns_mgmt */
 "in target_driver/<tgtt>/<target>/luns <luns_cmd>\n"
 /* scst_ini_group_mgmt */
 "in target_driver/<tgtt>/<target>/ini_groups <acg_mgmt_cmd>\n"
 "in target_driver/<tgtt>/<target>/ini_groups/<acg> <acg_cmd>\n"
 /* scst_acg_luns_mgmt */
-"in target_driver/<tgtt>/<target>/ini_groups/<acg>/luns <luns_cmd>\n"
+"in target_driver/<tgtt>/<target>/ini_groups/<acg>/luns <lun_cmd>\n"
 /* scst_acg_ini_mgmt */
 "in target_driver/<tgtt>/<target>/ini_groups/<acg>/initiators <acg_ini_cmd>\n"
 "\n"
@@ -3243,12 +3243,12 @@ static ssize_t scst_mgmt_show(struct device *device,
 "\n"
 "devt_cmd syntax:\n"
 "\n"
-"add_device device_name [parameters]\n"
-"del_device device_name\n"
+"add_device <device_name> [<parameters>]\n"
+"del_device <device_name>\n"
 "add_attribute <attribute> <value>\n"
 "del_attribute <attribute> <value>\n"
-"add_device_attribute device_name <attribute> <value>\n"
-"del_device_attribute device_name <attribute> <value>\n"
+"add_device_attribute <device_name> <attribute> <value>\n"
+"del_device_attribute <device_name> <attribute> <value>\n"
 "\n"
 "devt_cmd syntax for pass-through device types:\n"
 "\n"
@@ -3257,12 +3257,9 @@ static ssize_t scst_mgmt_show(struct device *device,
 "\n"
 "tgtt_cmd syntax:\n"
 "\n"
-"add_target target_name [parameters]\n"
-"del_target target_name\n"
-"add_attribute <attribute> <value>\n"
-"del_attribute <attribute> <value>\n"
-"add_target_attribute target_name <attribute> <value>\"\n"
-"del_target_attribute target_name <attribute> <value>\"\n"
+"add_target <target_name> [<parameters>]\n"
+"del_target <target_name>\n"
+"<target-driver-specific-command-and-parameters>\n"
 "\n"
 "where parameters is one or more <name>=<value> pairs separated by ';'\n"
 "\n"
@@ -3272,13 +3269,13 @@ static ssize_t scst_mgmt_show(struct device *device,
 "disable\n"
 "set_cpu_mask <mask>\n"
 "\n"
-"luns_cmd syntax:\n"
+"lun_cmd syntax:\n"
 "\n"
-"add|del H:C:I:L lun [parameters]\n"
-"add VNAME lun [parameters]\n"
-"del lun\n"
-"replace H:C:I:L lun [parameters]\n"
-"replace VNAME lun [parameters]\n"
+"add|del H:C:I:L <lun> [<parameters>]\n"
+"add <vname> <lun> [<parameters>]\n"
+"del <lun>\n"
+"replace H:C:I:L <lun> [<parameters>]\n"
+"replace <vname> <lun> [<parameters>]\n"
 "clear\n"
 "\n"
 "where parameters is either 'read_only' or empty.\n"
-- 
1.7.1
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH 8/8] Make SCST sysfs documentation more complete
  2010-12-27 13:35 [PATCH 0/8] Address recent SCST comments Bart Van Assche
                   ` (5 preceding siblings ...)
  2010-12-27 13:40 ` [PATCH 6/8] [SCSI] scst: Fix online documentation Bart Van Assche
@ 2010-12-27 13:43 ` Bart Van Assche
  2010-12-27 13:46 ` [PATCH 7/8] [SCSI] scst: Correct SCST core version number Bart Van Assche
  2010-12-28 17:23 ` [PATCH 0/8] Address recent SCST comments Bart Van Assche
  8 siblings, 0 replies; 10+ messages in thread
From: Bart Van Assche @ 2010-12-27 13:43 UTC (permalink / raw)
  To: linux-scsi
  Cc: scst-devel, Greg Kroah-Hartman, Konrad Rzeszutek Wilk,
	Vladislav Bolkhovitin, Richard Sharpe
Since the previous time the SCST sysfs documentation has been posted, detailed
documentation about /sys/devices/scst/mgmt has been added and the
documentation of several sysfs attributes has been made more clear.
Note: this patch contains the entire SCST sysfs documentation since it has
been generated as follows:
git diff origin/master..scst Documentation/ABI/stable
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 sysfs-devices-scst                   |  318 +++++++++++++++++++++++++++++++++++
 sysfs-devices-scst_target            |  226 ++++++++++++++++++++++++
 sysfs-devices-scst_target-scst_local |   23 ++
 sysfs-devices-scst_tgt_dev           |  217 +++++++++++++++++++++++
 sysfs-driver-scst_target             |   55 ++++++
 sysfs-driver-scst_target-scst_local  |   20 ++
 sysfs-driver-scst_tgt_dev            |   51 +++++
 7 files changed, 910 insertions(+)
diff --git a/Documentation/ABI/stable/sysfs-devices-scst b/Documentation/ABI/stable/sysfs-devices-scst
new file mode 100644
index 0000000..e25d1a4
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-devices-scst
@@ -0,0 +1,318 @@
+What:		/sys/devices/scst/mgmt
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Interface through which SCST management commands can be
+		issued. Read-write. Brief documentation of the syntax of these
+		commands can be obtained by reading this file (e.g. cat
+		/sys/devices/scst/mgmt). Detailed information is available
+		below.
+
+What:		/sys/devices/scst/setup_id
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		SCST setup ID. Allows to identify otherwise identical SCST
+		setups on different systems. As an example, the
+		vdisk device handler uses this to generate the T10 vendor
+		specific identifier ID and USN of virtual devices. Must be
+		set before any virtual devices are created. Read-write.
+
+What:		/sys/devices/scst/sgv/global_stats
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Global SGV (scatter/gather vector) cache statistics. Read-only.
+		An example:
+
+		$ cat sgv/global_stats
+		Inactive/active pages			0/0
+		Hi/lo watermarks [pages]		62208/0
+		Hi watermark releases/failures		0/0
+		Other allocs				0
+
+What:		/sys/devices/scst/sgv/sgv/stats
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Statistics for the regular SGV cache. Read-only.
+
+What:		/sys/devices/scst/sgv/sgv-clust/stats
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Statistics for the clustering SGV cache. Read-only.
+
+What:		/sys/devices/scst/sgv/sgv-dma/stats
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Statistics for the DMA SGV cache. Read-only.
+
+What:		/sys/devices/scst/threads
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Number of global I/O threads. The global I/O threads are used
+		by asynchronous device handlers or when explicitly configured
+		(i.e. when threads_num has been set to zero). Read-write.
+
+What:		/sys/devices/scst/version
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		SCST version number. Read-only. An example:
+
+		$ cat /sys/devices/scst/version
+		2.0.0
+
+-------------------------------------------------------------------------------
+
+
+Issuing management commands via /sys/devices/scst/mgmt
+
+
+1 Device driver commands
+========================
+
+1.1 Managing virtual devices
+----------------------------
+
+The syntax for creating a virtual device is as follows:
+
+echo "in device_driver/<devt> add_device <device_name> [<parameters>]" \
+  >/sys/devices/scst/mgmt
+
+where <devt> is the name of a virtual device handler and <parameters> is a
+semicolon-separated list of <name>=<value> pairs. The supported parameters are
+enumerated in the add_device_parameters file of each virtual device
+driver. E.g. for vdisk_fileio the parameters supported at device creation time
+are:
+
+$ cat /sys/bus/scst_tgt_dev/drivers/vdisk_fileio/add_device_parameters
+filename
+blocksize
+write_through
+nv_cache
+o_direct
+read_only
+removable
+thin_provisioned
+
+An example of how to create a vdisk_fileio device with NV-cache and thin
+provisioning enabled:
+
+echo "in device_driver/vdisk_fileio add_device disk01 filename=/home/exported-storage;nv_cache=1;thin_provisioned=1" >/sys/devices/scst/mgmt
+
+Removing virtual devices is possible via the del_device command. An example:
+
+echo "in device_driver/vdisk_fileio del_device disk01" >/sys/devices/scst/mgmt
+
+The remaining commands (add_attribute, del_attribute, add_device_attribute and
+del_device_attribute) allow to add or remove dynamically sysfs files for
+virtual devices and their drivers. There are not yet any virtual devices or
+virtual device drivers that allow this.
+
+1.2 Managing pass-through devices
+---------------------------------
+
+SCST supports SCSI pass-through. Before a LUN number can be assigned to a SCSI
+device, a device handler has to be assigned via the add_device command:
+
+echo "in device_driver/<devt> add_device H:C:I:L" >/sys/devices/scst/mgmt
+
+The syntax for disabling SCSI passthrough is similar:
+
+echo "in device_driver/<devt> del_device H:C:I:L" >/sys/devices/scst/mgmt
+
+In the above <devt> is the name of a pass-through handler and H:C:I:L is a
+quadruplet identifying a local SCSI device. An example:
+
+echo "in device_driver/dev_disk add_device 2:0:0:0" >/sys/devices/scst/mgmt
+echo "in device_driver/dev_disk del_device 2:0:0:0" >/sys/devices/scst/mgmt
+
+A list with the names of all currently loaded virtual and pass-through drivers
+can be obtained as follows:
+
+$ ls /sys/bus/scst_tgt_dev/drivers
+dev_cdrom    dev_disk_perf    dev_processor  dev_tape_perf  vdisk_fileio
+dev_changer  dev_modisk       dev_raid       vcdrom         vdisk_nullio
+dev_disk     dev_modisk_perf  dev_tape       vdisk_blockio
+
+
+2 Device management commands
+============================
+
+The syntax of device management commands is as follows:
+
+echo "in device/<dev> <dev_cmd>" >/sys/devices/scst/mgmt
+
+where <dev> is a device name and <dev_cmd> is one of:
+
+set_filename <filename>
+set_threads_num <n>
+set_thread_pool_type <thread_pool_type>
+
+These commands are documented in
+Documentation/ABI/stable/sysfs-devices-scst_tgt_dev.
+
+
+3 Target driver commands
+========================
+
+3.1 Adding and removing targets
+-------------------------------
+
+Adding and removing targets dynamically is possible with the add_target and
+remove_target commands. This is supported by scst_local but not by ib_srpt. An
+example for scst_local:
+
+# echo "in target_driver/scst_local add_target tgt2 session_name=tgt2_sess" >/sys/devices/scst/mgmt
+# ls /sys/bus/scst_target/drivers/scst_local/tgt2/sessions
+tgt2_sess
+# echo "in target_driver/scst_local del_target tgt2" >/sys/devices/scst/mgmt
+# ls /sys/bus/scst_target/drivers/scst_local/tgt2/sessions
+ls: cannot access /sys/bus/scst_target/drivers/scst_local/tgt2/sessions: No such file or directory
+
+3.2 Driver-specific commands
+----------------------------
+
+Each driver can define additional commands. As an example, the scst_local
+driver supports the add_session and del_session commands. See also the
+driver-specific documentation for more information.
+
+
+4 Target commands
+=================
+
+The following target commands are supported via /sys/devices/scst/mgmt:
+enable, disable and set_cpu_mask. These commands are documented in
+Documentation/ABI/stable/sysfs-devices-scst_target.
+
+
+5 Target LUN commands
+=====================
+
+The syntax of the commands for managing the set of LUNs associated with a
+target is as follows:
+
+in target_driver/<tgtt>/<target>/luns <lun_cmd>
+
+where lun_cmd is one of:
+
+add|del H:C:I:L <lun> [<parameters>]
+add <vname> <lun> [<parameters>]
+del <lun>
+replace H:C:I:L <lun> [<parameters>]
+replace <vname> <lun> [<parameters>]
+clear
+
+and where <vname> is the name of a virtual device, <lun> is a LUN number and
+<parameters> is a semicolon-separated list of parameters. Currently the only
+supported parameter is the parameter called "read_only" (either 0 or 1).
+
+# echo "in target_driver/ib_srpt/ib_srpt_target_0/luns clear" >/sys/devices/scst/mgmt
+# echo "in target_driver/ib_srpt/ib_srpt_target_0/luns add disk01 0" >/sys/devices/scst/mgmt
+# readlink /sys/bus/scst_target/drivers/ib_srpt/ib_srpt_target_0/luns/0/device
+../../../disk01
+# echo "in target_driver/ib_srpt/ib_srpt_target_0/luns replace disk02 0" >/sys/devices/scst/mgmt
+# readlink /sys/bus/scst_target/drivers/ib_srpt/ib_srpt_target_0/luns/0/device
+../../../disk02
+
+
+6 Access control group commands
+===============================
+
+6.1 Access control group creation and removal
+---------------------------------------------
+
+A list of zero or more access control groups (ACGs) can be associated with
+each target. ACGs allow to define which initiator has access to which LUNs.
+The syntax for creating and removing ACGs is:
+
+in target_driver/<tgtt>/<target>/ini_groups <acg_mgmt_cmd>
+
+where <acg_mgmt_cmd> is one of:
+
+create <group_name>
+del <group_name>
+
+An example:
+
+# echo "in target_driver/ib_srpt/ib_srpt_target_0/ini_groups create group1" >/sys/devices/scst/mgmt
+# ls /sys/bus/scst_target/drivers/ib_srpt/ib_srpt_target_0/ini_groups
+group1
+
+6.2 Access control group properties
+-----------------------------------
+
+The access control group CPU mask can be modified via the set_cpu_mask
+command. See also Documentation/ABI/stable/sysfs-devices-scst_target for more
+information.
+
+6.3 Managing ACG LUNs
+---------------------
+
+The syntax of the commands for managing the LUNs associated with an ACG is as
+follows:
+
+in target_driver/<tgtt>/<target>/ini_groups/<acg>/luns <lun_cmd>
+
+add|del H:C:I:L <lun> [<parameters>]
+add <vname> <lun> [<parameters>]
+del <lun>
+replace H:C:I:L <lun> [<parameters>]
+replace <vname> <lun> [<parameters>]
+clear
+
+See also section 5 for more information about these commands. An example:
+
+# echo "in target_driver/ib_srpt/ib_srpt_target_0/ini_groups/group1/luns add disk01 0" >/sys/devices/scst/mgmt
+# readlink /sys/bus/scst_target/drivers/ib_srpt/ib_srpt_target_0/ini_groups/group1/luns/0/device
+../../../disk01
+
+6.4 Associating initiators with an ACG
+--------------------------------------
+
+The syntax of the commands for manipulating the list of initiators associated
+with an ACG is as follows:
+
+in target_driver/<tgtt>/<target>/ini_groups/<acg>/initiators <acg_ini_cmd>
+
+where <acg_ini_cmd> is one of:
+
+add <initiator_name>
+del <initiator_name>
+move <initiator_name> <dest_group_name>
+clear
+
+These commands allow to add an initiator name to the initiator name list of an
+ACG, remove an initiator name from that list, move an initatior name from one
+ACG to another or to clear that initiator name list entirely. For the "add"
+and "del" commands the initiator name may be a pattern instead of a literal
+initator name. The following wildcard characters are supported:
+- '*' matches any substring.
+- '?' matches any character.
+- '!' at the start of a pattern will cause the pattern to match with every
+  initiator name that does not match with the subsequent pattern.
+As an example, the pattern "!abc*" will match with every initiator name that
+does not start with the sequence "abc".
+
+Below one can find an example for the target driver ib_srpt. For the SRP
+protocol initiator names are 128-bit hexadecimal numbers (a HCA port GUID).
+Associating the ACG called "group1" with the two HCA ports with GUIDs $port1
+and $port2 is possible as follows:
+
+# port1="0x00000000000000000002c9030005f34b"
+# port2="0x00000000000000000002c9030005f34c"
+# echo "in target_driver/ib_srpt/ib_srpt_target_0/ini_groups/group1/initiators add $port1" >/sys/devices/scst/mgmt
+# echo "in target_driver/ib_srpt/ib_srpt_target_0/ini_groups/group1/initiators add $port2" >/sys/devices/scst/mgmt
+# ls /sys/bus/scst_target/drivers/ib_srpt/ib_srpt_target_0/ini_groups/group1/initiators
+0x00000000000000000002c9030005f34b 0x00000000000000000002c9030005f34c
+
+The cumulative effect of the commands shown as examples in sections 6.1, 6.3
+and this section is that the initiator identified by GUID $ini1 and only that
+initiator will see the LUNs defined in the ACG with name "group1". If no other
+ACGs have been defined, all other initiators that log in to the same target
+will see the LUNs associated with the target itself. Making a LUN available to
+some hosts and not available to other hosts is also called LUN masking.
diff --git a/Documentation/ABI/stable/sysfs-devices-scst_target b/Documentation/ABI/stable/sysfs-devices-scst_target
new file mode 100644
index 0000000..2d3a388
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-devices-scst_target
@@ -0,0 +1,226 @@
+What:		/sys/bus/scst_target/devices/*/addr_method
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		LUN addressing method used by this target when e.g. responding
+		to a REPORT_LUNS command. One of the values PERIPHERAL, FLAT
+		or LUN. Read-write. While most initiators work well with the
+		default addressing method (PERIPHERAL), some initiators need
+		the FLAT addressing method (HP/UX) or LUN addressing (AIX).
+		Note: the LUN addressing method can also be configured for a
+		security group. That allows to define the LUN addressing
+		method on a per-initiator basis. See also SAM-4, section 4.6,
+		Logical Unit Numbers.
+
+What:		/sys/bus/scst_target/devices/*/cpu_mask
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Target-specific CPU mask in hexadecimal format. While this
+		file is read-only, changing the CPU mask is possible via
+		the set_cpu_mask command. As an example, the commands below
+		show how to make scst_local use any CPU for processing SCSI
+		commands except CPUs 0, 1, 2 or 3:
+
+		# cat /sys/bus/scst_target/devices/scst_local_tgt/cpu_mask
+		ffffffff,ffffffff
+		# echo "in target_driver/scst_local/scst_local_tgt set_cpu_mask ffffffff,fffffff0" >/sys/devices/scst/mgmt
+		# cat /sys/bus/scst_target/devices/scst_local_tgt/cpu_mask
+		ffffffff,fffffff0
+
+What:		/sys/bus/scst_target/devices/*/force_close
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		If this file exists, writing any data to this file will
+		forcibly close all sessions associated with a target.
+		Write-only.
+
+What:		/sys/bus/scst_target/devices/*/enabled
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Whether a target is currently enabled ("1") or disabled ("0").
+		No new connections are accepted for a
+		target that is in the disabled state. Defaults to disabled
+		("0"). This allows to configure a target before any connections
+		are accepted. Read-only. Notes:
+		- Enabling a target is only allowed if its relative target
+		  port identifier is unique.
+		- Enabling or disabling a target is possible via the SCST
+		  device. An example:
+
+		$ echo "in target_driver/ib_srpt/ib_srpt_target_0 disable" >/sys/devices/scst/mgmt
+		$ cat /sys/devices/ib_srpt_target_0/enabled
+		0
+		$ echo "in target_driver/ib_srpt/ib_srpt_target_0 enable" >/sys/devices/scst/mgmt
+		$ cat /sys/devices/ib_srpt_target_0/enabled
+
+What:		/sys/bus/scst_target/devices/*/hw_target
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Allows to distinguish hardware and virtual targets. The value
+		1 means that there is a one-to-one correspondence between this
+		target and a hardware entity, and the value 0 means that there
+		is no such one-to-one correspondence. This file only exists
+		when the target driver supports both hardware and virtual
+		targets. Read-only.
+
+What:		/sys/bus/scst_target/devices/*/ini_groups/<acg>/addr_method
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		LUN addressing method for this ACG (access control group).
+		Read-write.
+
+What:		/sys/bus/scst_target/devices/*/ini_groups/<acg>/cpu_mask
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		CPU mask associated with this ACG. Read-only. Modifying this
+		CPU mask is possible via the set_cpu_mask command. An example:
+
+		# cat /sys/bus/scst_target/devices/scst_local_tgt/ini_groups/group1/cpu_mask
+		ffffffff,ffffffff
+		# echo "in target_driver/scst_local/scst_local_tgt/ini_groups/group1 set_cpu_mask 1" >/sys/devices/scst/mgmt
+		# cat /sys/bus/scst_target/devices/scst_local_tgt/ini_groups/group1/cpu_mask
+		00000000,00000001
+
+What:		/sys/bus/scst_target/devices/*/ini_groups/<acg>/initiators/<ini>
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Name of an initiator associated with this ACG. The contents
+		of this file is the same as the filename. Read-only.
+
+What:		/sys/bus/scst_target/devices/*/ini_groups/<acg>/initiators/luns/parameters
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Names of the parameters supported when adding a LUN to an ACG,
+		one per line. Read-only.
+
+What:		/sys/bus/scst_target/devices/*/ini_groups/<acg>/initiators/luns/<number>/device
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Soft link to the SCST device associated with this LUN. An
+		example:
+		$ readlink /sys/bus/scst_target/devices/scst_local_tgt/ini_groups/group1/luns/0/device
+		../../../../../disk01
+
+What:		/sys/bus/scst_target/devices/*/ini_groups/<acg>/initiators/luns/<number>/read_only
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Whether the LUN has been exported read-only ("1") or
+		read-write ("0"). This file is read-only.
+
+What:		/sys/bus/scst_target/devices/*/io_grouping_type
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		I/O context sharing setting. I/O context sharing may improve
+		I/O performance significantly when using the CFQ I/O scheduler
+		and rotating storage media. The allowed values for this
+		parameter are:
+		* "auto"		Use one I/O context per initiator.
+		* "this_group_only"	Use the same I/O context for all
+					sessions associated with this target.
+		* "never"		Never share I/O contexts.
+		* <I/O context number>	Share an I/O context over all targets
+					that have this I/O context number. Must
+					be a number above zero.
+		Read-write.
+
+What:		/sys/bus/scst_target/devices/*/luns/parameters
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Names of the parameters supported when adding a LUN to a
+		target, one per line. Read-only.
+
+What:		/sys/bus/scst_target/devices/*/luns/<number>/device
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Soft link to the exported SCST device. Read-only.
+
+What:		/sys/bus/scst_target/devices/*/luns/<number>/read_only
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Whether this LUN is read-only (1) or read-write (0).
+		Read-create.
+
+What:		/sys/bus/scst_target/devices/*/sessions/<session>/active_commands
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Number of SCSI commands being executed for this session.
+		Read-only.
+
+What:		/sys/bus/scst_target/devices/*/sessions/<session>/commands
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Number of SCSI commands being executed for this session.
+		Read-only.
+
+What:		/sys/bus/scst_target/devices/*/sessions/<session>/force_close
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Attribute that allows to forcibly close a session. Optional,
+		write-only.
+
+What:		/sys/bus/scst_target/devices/*/sessions/<session>/initiator_name
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Session name. For most target drivers this is a name that
+		identifies the initiator. Read-only.
+
+What:		/sys/bus/scst_target/devices/*/sessions/<session>/latency
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Latency statistics for this session. Only available if
+		CONFIG_SCST_MEASURE_LATENCY has been enabled in the
+		kernel configuration. Read-only.
+
+What:		/sys/bus/scst_target/devices/*/sessions/<session>/lun<number>/active_commands
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Number of active commands. Read-only.
+
+What:		/sys/bus/scst_target/devices/*/sessions/<session>/lun<number>/latency
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Latency statistics for this LUN. Only available if
+		CONFIG_SCST_MEASURE_LATENCY has been enabled in the kernel
+		configuration. Read-only.
+
+What:		/sys/bus/scst_target/devices/*/sessions/<session>/luns
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Soft link to the LUNs exported via this session. That soft
+		link either points to the LUNs associated with the
+		corresponding target or to the LUNs associated with an ACG.
+		Examples:
+
+		$ readlink /sys/devices/scst_local_tgt/sessions/scst_local_host/luns
+		../../luns
+		$ readlink /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/luns
+../../ini_groups/initiator1/luns
+
+What:		/sys/bus/scst_target/devices/*/rel_tgt_id
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		SCSI Relative Target Port Identifier, which is used by e.g.
+		persistent reservation commands. Read-write.
diff --git a/Documentation/ABI/stable/sysfs-devices-scst_target-scst_local b/Documentation/ABI/stable/sysfs-devices-scst_target-scst_local
new file mode 100644
index 0000000..4306ee0
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-devices-scst_target-scst_local
@@ -0,0 +1,23 @@
+What:		/sys/bus/scst_target/devices/scst_local/phys_transport_version
+Date:		December 2010
+Contact:	Richard Sharpe <realrichardsharpe@gmail.com>
+Description:
+		SCSI physical transport version. Defines which physical
+		interface scst_local will resemble. See also SPC-4 for more
+		information. Read-write.
+
+What:		/sys/bus/scst_target/devices/scst_local/scsi_transport_version
+Date:		December 2010
+Contact:	Richard Sharpe <realrichardsharpe@gmail.com>
+Description:
+		SCSI transport version. Defines which SCSI transport
+		scst_local will resemble. The default is SAS. See also SPC-4
+		for more information. Read-write.
+
+What:		/sys/bus/scst_target/devices/scst_local/sessions/*/transport_id
+Date:		December 2010
+Contact:	Richard Sharpe <realrichardsharpe@gmail.com>
+Description:
+		SCSI transport ID in binary format. Necessary e.g. for
+		implementing persistent reservation support. See also SPC-4
+		for more information. Read-write.
diff --git a/Documentation/ABI/stable/sysfs-devices-scst_tgt_dev b/Documentation/ABI/stable/sysfs-devices-scst_tgt_dev
new file mode 100644
index 0000000..698249a
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-devices-scst_tgt_dev
@@ -0,0 +1,217 @@
+What:		/sys/bus/scst_tgt_dev/device/*/blocksize
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Block size that has been configured for a virtual device. Must
+		be a power of two and equal to or above 512. Read-create.
+
+What:		/sys/bus/scst_tgt_dev/device/*/exported/export<nr>
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Zero or more soft links to the LUNs via which this device
+		has been exported. An example:
+
+		$ for f in /sys/bus/scst_tgt_dev/devices/disk01/exported/export*; do echo $f; readlink $f; done
+		/sys/bus/scst_tgt_dev/devices/disk01/exported/export0
+		../../ib_srpt_target_0/ini_groups/initiator1/luns/0
+		/sys/bus/scst_tgt_dev/devices/disk01/exported/export1
+		../../ib_srpt_target_0/luns/0
+		/sys/bus/scst_tgt_dev/devices/disk01/exported/export2
+		../../ib_srpt_target_1/luns/0
+
+What:		/sys/bus/scst_tgt_dev/device/*/filename
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		For virtual devices, the absolute path of the associated file
+		or device. Read-create for vdisk_blockio and vdisk_fileio
+		devices and read-only for vcdrom devices. For vcdrom devices
+		this parameter can be modified via the set_filename
+		command. Configuring a non-empty path is interpret as
+		inserting a medium and setting an empty path is interpret as
+		removing a medium. An example of how to add a vcdrom device,
+		how to trigger medium insertion and medium removal:
+
+		# echo "in device_driver/vcdrom add_device vcdrom1" >/sys/devices/scst/mgmt
+		# echo "in device/vcdrom1 set_filename /cdrom.iso" >/sys/devices/scst/mgmt
+		# cat /sys/bus/scst_tgt_dev/devices/vcdrom1/filename
+		/cdrom.iso
+		# echo "in device/vcdrom1 set_filename" >/sys/devices/scst/mgmt
+		# od -c /sys/bus/scst_tgt_dev/devices/vcdrom1/filename
+		0000000  \n
+		0000001
+
+What:		/sys/bus/scst_tgt_dev/device/*/nv_cache
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Whether or not acknowledging writes early has been enabled for
+		a vdisk_blockio or vdisk_fileio device. The value 1 means that
+		acknowledging writes early has been enabled and the value 0
+		means that acknowledging writes early has been disabled.
+		Warning: while enabling early write acknowledgements does
+		decrease I/O latency, for a storage medium that neither has a
+		non-volatile cache nor an UPS enabling early write
+		acknowledgements may result in data loss in case of a power
+		failure. Read-create.
+
+What:		/sys/bus/scst_tgt_dev/device/*/o_direct
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		The value 1 means that all caching has been disabled (direct
+		or non-buffered I/O) for a vdisk_fileio device and the value 0
+		means that caching is enabled (asynchronous or buffered
+		I/O). Read-create.
+
+What:		/sys/bus/scst_tgt_dev/device/*/read_only
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		For virtual devices, whether or not to deny write commands. 1
+		stands for read-only and 0 for read-write. The "read_only"
+		file itself is read-create.
+
+What:		/sys/bus/scst_tgt_dev/device/*/removable
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		For vdisk_blockio, vdisk_fileio and vdisk_nullio devices,
+		whether or not the underlying storage medium has been
+		configured as removable when the virtual device was
+		created. The value "1" means removable and the value "0" means
+		not removable. Read-create.
+
+What:		/sys/bus/scst_tgt_dev/device/*/resync_size
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		For vdisk_fileio and vdisk_blockio devices, writing any data
+		to this file will cause SCST to reexamine the size of the
+		underlying storage medium. Write-only. See also the "filename"
+		and "size_mb" files.
+
+What:		/sys/bus/scst_tgt_dev/device/*/scsi_device
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		For SCSI devices, the device identification in H:C:I:L format.
+		Read-only. An example:
+
+		$ cat /sys/bus/scst_tgt_dev/devices/1:0:0:0/scsi_device
+		1:0:0:0
+
+What:		/sys/bus/scst_tgt_dev/device/*/size_mb
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		For virtual devices, the internally cached size in MB of the
+		underlying storage device (1 MB = 1048576 bytes). Read-only.
+		See also the "filename" and "resync_size" files.
+
+What:		/sys/bus/scst_tgt_dev/device/*/t10_dev_id
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		SCSI device ID associated with the virtual device. This is the
+		ID reported e.g. via the Device Identification page (0x83) of
+		the INQUIRY command. Read-write.
+
+What:		/sys/bus/scst_tgt_dev/device/*/thin_provisioned
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Whether or not thin provisioning support has been enabled (1)
+		or not (0) for a virtual device. If thin provisioning support
+		has been enabled, SCST will report to the SCSI initiator that
+		thin provisioning is supported and SCSI UNMAP commands will be
+		translated to deallocation requests for the underlying
+		storage. See also SBC-3 for further information. Read-create.
+
+What:		/sys/bus/scst_tgt_dev/device/*/threads_num
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Zero if the global thread pool is used for processing SCSI
+		commands received for a device or the number of threads of a
+		dedicated thread pool that is used for processing SCSI
+		commands received for this device (any number above zero).
+		Read-create. Modifying this parameter is possible via the
+		set_threads_num command. An example:
+
+		# cat /sys/bus/scst_tgt_dev/devices/disk01/threads_num
+		2
+		# echo "in device/disk01 set_threads_num 4" >/sys/devices/scst/mgmt
+		# cat /sys/bus/scst_tgt_dev/devices/disk01/threads_num
+		4
+
+What:		/sys/bus/scst_tgt_dev/device/*/threads_pool_type
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Thread pool configuration setting. This file will contain the
+		text "Async" if the global thread pool is used for processing
+		SCSI commands for this device. If a dedicated thread pool has
+		been configured then there is either one thread pool per
+		initiator ("per_initiator") or one thread pool for all
+		initiators ("shared"). Read-create. Modifying this parameter
+		is possible via the set_thread_pool_type command. An example:
+
+		# cat /sys/bus/scst_tgt_dev/devices/disk01/threads_pool_type
+		shared
+		# echo "in device/disk01 set_thread_pool_type per_initiator" >/sys/devices/scst/mgmt
+		# cat /sys/bus/scst_tgt_dev/devices/disk01/threads_pool_type
+		per_initiator
+
+What:		/sys/bus/scst_tgt_dev/device/*/type
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		A number in the range 0..17 representing the SCSI peripheral
+		device type as defined in SPC-4. Read-only. The defined types
+		and their meaning are:
+
+		 0 Direct access block device (e.g., magnetic disk)
+		 1 Sequential-access device (e.g., magnetic tape)
+		 2 Printer device
+		 3 Processor device
+		 4 Write-once device (e.g., some optical disks)
+		 5 CD/DVD device
+		 6 Scanner device (obsolete)
+		 7 Optical memory device (e.g., some optical disks)
+		 8 Media changer device (e.g., jukeboxes)
+		 9 Communications device (obsolete)
+		10 Obsolete
+		11 Obsolete
+		12 Storage array controller device (e.g., RAID)
+		13 Enclosure services device
+		14 Simplified direct-access device (e.g., magnetic disk)
+		15 Optical card reader/writer device
+		16 Bridge Controller Commands
+		17 Object-based Storage Device
+
+What:		/sys/bus/scst_tgt_dev/device/*/type_description
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Textual description of the SCSI peripheral device type as
+		defined in SPC-4. See also the description of the
+		"type" file for a list of descriptions. Read-only.
+
+What:		/sys/bus/scst_tgt_dev/device/*/usn
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Unique serial number of a virtual device as reported e.g. by
+		the SCSI INQUIRY response. This number is generated by SCST
+		during creation of the virtual device by hashing the device
+		name and the setup ID. Read-only.
+
+What:		/sys/bus/scst_tgt_dev/device/*/write_through
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Whether or not write-back caching has been disabled for a
+		vdisk_fileio device. The value 0 stands for write-back mode
+		and the value 1 stands for write-through mode. Read-create.
diff --git a/Documentation/ABI/stable/sysfs-driver-scst_target b/Documentation/ABI/stable/sysfs-driver-scst_target
new file mode 100644
index 0000000..8592cec
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-driver-scst_target
@@ -0,0 +1,55 @@
+What:		/sys/bus/scst_target/drivers/*/add_target
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Whether or not dynamic creation and removal of SCSI targets is
+		supported by a particular SCST target driver. The value 1
+		means that dynamic target creation/removal is supported
+		and the value 0 means that dynamic target creation/removal is
+		not supported. Read-only.
+
+What:		/sys/bus/scst_target/drivers/*/add_target_parameters
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Names of the parameters that may be specified at target
+		creation time. Each parameter name appears on a separate
+		line. This file only exists if dynamic target creation and
+		removal is supported. Read-only.
+
+What:		/sys/bus/scst_target/drivers/*/driver_attributes
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Names of the SCSI target driver sysfs files that may be created
+		or removed dynamically. Each file name appears on a
+		separate line. This file only exists if dynamic target driver
+		file creation and removal is supported. Read-only.
+
+What:		/sys/bus/scst_target/drivers/*/enabled
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Allows to enable or disable the operation of a SCST target
+		driver. The value 1 means enabled and 0 means disabled.
+		Defaults to 0 (disabled). This allows to configure a target
+		driver before it becomes operational. Only exists if disabling
+		the particual target driver is supported. Read-write.
+
+What:		/sys/bus/scst_target/drivers/*/target_attributes
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Names of the sysfs files that may be created and/or removed
+		dynamically for a target. Each file name appears on a separate
+		line. This file only exists if dynamic target file creation
+		and removal is supported. Read-only.
+
+What:		/sys/bus/scst_target/drivers/*/version
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Target driver version. Read-only. An example:
+
+		$ cat /sys/bus/scst_target/drivers/scst_local/version
+		1.0.0
diff --git a/Documentation/ABI/stable/sysfs-driver-scst_target-scst_local b/Documentation/ABI/stable/sysfs-driver-scst_target-scst_local
new file mode 100644
index 0000000..3ea28dc
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-driver-scst_target-scst_local
@@ -0,0 +1,20 @@
+What:		/sys/bus/scst_target/drivers/scst_local/aborts
+Date:		December 2010
+Contact:	Richard Sharpe <realrichardsharpe@gmail.com>
+Description:
+		Number of SCSI commands that have been aborted by the SCSI
+		initiator. Read-only.
+
+What:		/sys/bus/scst_target/drivers/scst_local/device_resets
+Date:		December 2010
+Contact:	Richard Sharpe <realrichardsharpe@gmail.com>
+Description:
+		Number of SCSI device resets that have been performed by the
+		SCSI initiator. Read-only.
+
+What:		/sys/bus/scst_target/drivers/scst_local/target_resets
+Date:		December 2010
+Contact:	Richard Sharpe <realrichardsharpe@gmail.com>
+Description:
+		Number of SCSI target resets that have been performed by the
+		SCSI initiator. Read-only.
diff --git a/Documentation/ABI/stable/sysfs-driver-scst_tgt_dev b/Documentation/ABI/stable/sysfs-driver-scst_tgt_dev
new file mode 100644
index 0000000..87fc58f
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-driver-scst_tgt_dev
@@ -0,0 +1,51 @@
+What:		/sys/bus/scst_tgt_dev/drivers/*/add_device_parameters
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Names of the parameters supported when adding a device. Each
+		parameter name appears on a separate line. Read-only.
+		An example:
+
+		$ cat /sys/bus/scst_tgt_dev/drivers/vdisk_fileio/add_device_parameters
+		filename
+		blocksize
+		write_through
+		nv_cache
+		o_direct
+		read_only
+		removable
+		thin_provisioned
+
+What:		/sys/bus/scst_tgt_dev/drivers/*/type
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		A number in the range 0..17 representing the SCSI peripheral
+		device type of the devices managed by this driver as defined
+		in SPC-4. Read-only. The defined types and their meaning are:
+
+		 0 Direct access block device (e.g., magnetic disk)
+		 1 Sequential-access device (e.g., magnetic tape)
+		 2 Printer device
+		 3 Processor device
+		 4 Write-once device (e.g., some optical disks)
+		 5 CD/DVD device
+		 6 Scanner device (obsolete)
+		 7 Optical memory device (e.g., some optical disks)
+		 8 Media changer device (e.g., jukeboxes)
+		 9 Communications device (obsolete)
+		10 Obsolete
+		11 Obsolete
+		12 Storage array controller device (e.g., RAID)
+		13 Enclosure services device
+		14 Simplified direct-access device (e.g., magnetic disk)
+		15 Optical card reader/writer device
+		16 Bridge Controller Commands
+		17 Object-based Storage Device
+
+What:		/sys/bus/scst_tgt_dev/drivers/*/type_description
+Date:		December 2010
+Contact:	Bart Van Assche <bvanassche@acm.org>
+Description:
+		Textual description of the SCSI peripheral type of the devices
+		managed by this driver. Read-only.
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH 7/8] [SCSI] scst: Correct SCST core version number
  2010-12-27 13:35 [PATCH 0/8] Address recent SCST comments Bart Van Assche
                   ` (6 preceding siblings ...)
  2010-12-27 13:43 ` [PATCH 8/8] Make SCST sysfs documentation more complete Bart Van Assche
@ 2010-12-27 13:46 ` Bart Van Assche
  2010-12-28 17:23 ` [PATCH 0/8] Address recent SCST comments Bart Van Assche
  8 siblings, 0 replies; 10+ messages in thread
From: Bart Van Assche @ 2010-12-27 13:46 UTC (permalink / raw)
  To: linux-scsi
  Cc: scst-devel, Greg Kroah-Hartman, Konrad Rzeszutek Wilk,
	Vladislav Bolkhovitin, Richard Sharpe
Change the version number of the SCST core from 2.1.0-pre1 into 2.0.0.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 include/scst/scst.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/scst/scst.h b/include/scst/scst.h
index e44547a..9034624 100644
--- a/include/scst/scst.h
+++ b/include/scst/scst.h
@@ -48,7 +48,7 @@
 #define SCST_VERSION(a, b, c, d)    (((a) << 24) + ((b) << 16) + ((c) << 8) + d)
 #define SCST_VERSION_CODE	    SCST_VERSION(2, 0, 0, 0)
 #define SCST_VERSION_STRING_SUFFIX
-#define SCST_VERSION_STRING	    "2.1.0-pre1" SCST_VERSION_STRING_SUFFIX
+#define SCST_VERSION_STRING	    "2.0.0" SCST_VERSION_STRING_SUFFIX
 #define SCST_INTERFACE_VERSION	    \
 		SCST_VERSION_STRING "$Revision: 3139 $" SCST_CONST_VERSION
 
-- 
1.7.1
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* Re: [PATCH 0/8] Address recent SCST comments
  2010-12-27 13:35 [PATCH 0/8] Address recent SCST comments Bart Van Assche
                   ` (7 preceding siblings ...)
  2010-12-27 13:46 ` [PATCH 7/8] [SCSI] scst: Correct SCST core version number Bart Van Assche
@ 2010-12-28 17:23 ` Bart Van Assche
  8 siblings, 0 replies; 10+ messages in thread
From: Bart Van Assche @ 2010-12-28 17:23 UTC (permalink / raw)
  To: linux-scsi
  Cc: scst-devel, Greg Kroah-Hartman, Konrad Rzeszutek Wilk,
	Vladislav Bolkhovitin, Richard Sharpe
On Monday 27 December 2010 14:35:33 Bart Van Assche wrote:
> The paches in this patch series address the following issues:
> - Make sure that all SCST sysfs attributes have only one value per file.
> [ ... ]
Note: someone was so kind to inform me (via private e-mail) that two more
classes of sysfs files did not yet satisfy the one-value-per-file rule, namely
the SGV cache statistics and the I/O latency statistics. The two patches
below move these sysfs files to debugfs too:
[SCSI] scst: Move SGV cache statistics to debugfs
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 Documentation/ABI/stable/sysfs-devices-scst |   31 -----
 drivers/scst/Makefile                       |    4 +-
 drivers/scst/scst_mem.c                     |  168 +++-----------------------
 drivers/scst/scst_mem.h                     |   22 ++++-
 drivers/scst/scst_mem_stats.c               |  168 +++++++++++++++++++++++++++
 drivers/scst/scst_mem_stats.h               |   21 ++++
 drivers/scst/scst_priv.h                    |    2 -
 drivers/scst/scst_sysfs.c                   |    9 --
 drivers/scst/scst_tracing.c                 |   17 +++-
 9 files changed, 246 insertions(+), 196 deletions(-)
 create mode 100644 drivers/scst/scst_mem_stats.c
 create mode 100644 drivers/scst/scst_mem_stats.h
diff --git a/Documentation/ABI/stable/sysfs-devices-scst b/Documentation/ABI/stable/sysfs-devices-scst
index e25d1a4..8e02cff 100644
--- a/Documentation/ABI/stable/sysfs-devices-scst
+++ b/Documentation/ABI/stable/sysfs-devices-scst
@@ -18,37 +18,6 @@ Description:
 		specific identifier ID and USN of virtual devices. Must be
 		set before any virtual devices are created. Read-write.
 
-What:		/sys/devices/scst/sgv/global_stats
-Date:		December 2010
-Contact:	Bart Van Assche <bvanassche@acm.org>
-Description:
-		Global SGV (scatter/gather vector) cache statistics. Read-only.
-		An example:
-
-		$ cat sgv/global_stats
-		Inactive/active pages			0/0
-		Hi/lo watermarks [pages]		62208/0
-		Hi watermark releases/failures		0/0
-		Other allocs				0
-
-What:		/sys/devices/scst/sgv/sgv/stats
-Date:		December 2010
-Contact:	Bart Van Assche <bvanassche@acm.org>
-Description:
-		Statistics for the regular SGV cache. Read-only.
-
-What:		/sys/devices/scst/sgv/sgv-clust/stats
-Date:		December 2010
-Contact:	Bart Van Assche <bvanassche@acm.org>
-Description:
-		Statistics for the clustering SGV cache. Read-only.
-
-What:		/sys/devices/scst/sgv/sgv-dma/stats
-Date:		December 2010
-Contact:	Bart Van Assche <bvanassche@acm.org>
-Description:
-		Statistics for the DMA SGV cache. Read-only.
-
 What:		/sys/devices/scst/threads
 Date:		December 2010
 Contact:	Bart Van Assche <bvanassche@acm.org>
diff --git a/drivers/scst/Makefile b/drivers/scst/Makefile
index 38b3f4e..a27cf92 100644
--- a/drivers/scst/Makefile
+++ b/drivers/scst/Makefile
@@ -7,7 +7,7 @@ scst-y        += scst_lib.o
 scst-y        += scst_sysfs.o
 scst-y        += scst_mem.o
 scst-y        += scst_debug.o
-scst-$(CONFIG_SCST_DEBUG)	+= scst_tracing.o
-scst-$(CONFIG_SCST_TRACING)	+= scst_tracing.o
+scst-$(CONFIG_SCST_DEBUG)	+= scst_tracing.o scst_mem_stats.o
+scst-$(CONFIG_SCST_TRACING)	+= scst_tracing.o scst_mem_stats.o
 
 obj-$(CONFIG_SCST)   += scst.o dev_handlers/ scst_local/ srpt/
diff --git a/drivers/scst/scst_mem.c b/drivers/scst/scst_mem.c
index 048f848..b9d84f5 100644
--- a/drivers/scst/scst_mem.c
+++ b/drivers/scst/scst_mem.c
@@ -29,6 +29,7 @@
 #include <scst/scst.h>
 #include "scst_priv.h"
 #include "scst_mem.h"
+#include "scst_mem_stats.h"
 
 #define SGV_DEFAULT_PURGE_INTERVAL	(60 * HZ)
 #define SGV_MIN_SHRINK_INTERVAL		(1 * HZ)
@@ -66,12 +67,6 @@ static struct shrinker sgv_shrinker;
  */
 static LIST_HEAD(sgv_pools_list);
 
-static struct kobj_type pool_ktype;
-
-static struct kobject *scst_sgv_kobj;
-static int scst_sgv_sysfs_create(struct sgv_pool *pool, struct kobject *parent);
-static void scst_sgv_sysfs_del(struct sgv_pool *pool);
-
 static inline bool sgv_pool_clustered(const struct sgv_pool *pool)
 {
 	return pool->clustering_type != sgv_no_clustering;
@@ -1412,7 +1407,7 @@ static int sgv_pool_init(struct sgv_pool *pool, const char *name,
 	list_add_tail(&pool->sgv_pools_list_entry, &sgv_pools_list);
 	spin_unlock_bh(&sgv_pools_lock);
 
-	res = scst_sgv_sysfs_create(pool, scst_sgv_kobj);
+	res = scst_sgv_pool_debugfs_create(pool);
 	if (res != 0)
 		goto out_del;
 
@@ -1486,6 +1481,8 @@ EXPORT_SYMBOL_GPL(sgv_pool_flush);
 
 static void sgv_pool_destroy(struct sgv_pool *pool)
 {
+	int i;
+
 	cancel_delayed_work_sync(&pool->sgv_purge_work);
 
 	sgv_pool_flush(pool);
@@ -1496,10 +1493,15 @@ static void sgv_pool_destroy(struct sgv_pool *pool)
 	spin_unlock_bh(&sgv_pools_lock);
 	mutex_unlock(&sgv_pools_mutex);
 
-	scst_sgv_sysfs_del(pool);
+	scst_sgv_pool_debugfs_del(pool);
 
-	kobject_put(&pool->sgv_kobj);
-	return;
+	for (i = 0; i < pool->max_caches; i++) {
+		if (pool->caches[i])
+			kmem_cache_destroy(pool->caches[i]);
+		pool->caches[i] = NULL;
+	}
+
+	kfree(pool);
 }
 
 /**
@@ -1523,17 +1525,6 @@ void sgv_pool_set_allocator(struct sgv_pool *pool,
 EXPORT_SYMBOL_GPL(sgv_pool_set_allocator);
 
 /**
- * sgv_kobj_to_pool() - Convert a kobject pointer to a pool pointer.
- *
- * Must be called from inside an sgv pool sysfs .show() or .store() callback
- * function only.
- */
-static inline struct sgv_pool *sgv_kobj_to_pool(struct kobject *kobj)
-{
-	return container_of(kobj, struct sgv_pool, sgv_kobj);
-}
-
-/**
  * sgv_pool_create - creates and initializes an SGV pool
  * @name:	the name of the SGV pool
  * @clustered:	sets type of the pages clustering.
@@ -1591,8 +1582,6 @@ struct sgv_pool *sgv_pool_create(const char *name,
 		goto out_unlock;
 	}
 
-	kobject_init(&pool->sgv_kobj, &pool_ktype);
-
 	rc = sgv_pool_init(pool, name, clustering_type, single_alloc_pages,
 				purge_interval);
 	if (rc != 0)
@@ -1603,7 +1592,7 @@ out_unlock:
 	return pool;
 
 out_free:
-	kobject_put(&pool->sgv_kobj);
+	kfree(pool);
 	goto out_unlock;
 }
 EXPORT_SYMBOL_GPL(sgv_pool_create);
@@ -1707,15 +1696,13 @@ void scst_sgv_pools_deinit(void)
 	return;
 }
 
-static ssize_t sgv_sysfs_stat_show(struct kobject *kobj,
-	struct kobj_attribute *attr, char *buf)
+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
+
+ssize_t sgv_pool_stat_show(struct sgv_pool *pool, char *buf)
 {
-	struct sgv_pool *pool;
 	int i, total = 0, hit = 0, merged = 0, allocated = 0;
 	int oa, om, res;
 
-	pool = sgv_kobj_to_pool(kobj);
-
 	for (i = 0; i < SGV_POOL_ELEMENTS; i++) {
 		int t;
 
@@ -1763,14 +1750,10 @@ static ssize_t sgv_sysfs_stat_show(struct kobject *kobj,
 	return res;
 }
 
-static ssize_t sgv_sysfs_stat_reset(struct kobject *kobj,
-	struct kobj_attribute *attr, const char *buf, size_t count)
+void sgv_pool_stat_reset(struct sgv_pool *pool)
 {
-	struct sgv_pool *pool;
 	int i;
 
-	pool = sgv_kobj_to_pool(kobj);
-
 	for (i = 0; i < SGV_POOL_ELEMENTS; i++) {
 		atomic_set(&pool->cache_acc[i].hit_alloc, 0);
 		atomic_set(&pool->cache_acc[i].total_alloc, 0);
@@ -1785,11 +1768,9 @@ static ssize_t sgv_sysfs_stat_reset(struct kobject *kobj,
 	atomic_set(&pool->other_alloc, 0);
 
 	PRINT_INFO("Statistics for SGV pool %s reset", pool->name);
-	return count;
 }
 
-static ssize_t sgv_sysfs_global_stat_show(struct kobject *kobj,
-	struct kobj_attribute *attr, char *buf)
+ssize_t sgv_global_stat_show(char *buf)
 {
 	struct sgv_pool *pool;
 	int inactive_pages = 0, res;
@@ -1813,122 +1794,13 @@ static ssize_t sgv_sysfs_global_stat_show(struct kobject *kobj,
 	return res;
 }
 
-static ssize_t sgv_sysfs_global_stat_reset(struct kobject *kobj,
-	struct kobj_attribute *attr, const char *buf, size_t count)
+void sgv_global_stat_reset(void)
 {
 	atomic_set(&sgv_releases_on_hiwmk, 0);
 	atomic_set(&sgv_releases_on_hiwmk_failed, 0);
 	atomic_set(&sgv_other_total_alloc, 0);
 
 	PRINT_INFO("%s", "Global SGV pool statistics reset");
-	return count;
-}
-
-static struct kobj_attribute sgv_stat_attr =
-	__ATTR(stats, S_IRUGO | S_IWUSR, sgv_sysfs_stat_show,
-		sgv_sysfs_stat_reset);
-
-static struct attribute *sgv_attrs[] = {
-	&sgv_stat_attr.attr,
-	NULL,
-};
-
-static void scst_release_pool(struct kobject *kobj)
-{
-	struct sgv_pool *pool;
-	int i;
-
-	pool = sgv_kobj_to_pool(kobj);
-
-	for (i = 0; i < pool->max_caches; i++) {
-		if (pool->caches[i])
-			kmem_cache_destroy(pool->caches[i]);
-		pool->caches[i] = NULL;
-	}
-
-	kfree(pool);
-}
-
-static struct kobj_type pool_ktype = {
-	.release = scst_release_pool,
-	.sysfs_ops = &scst_sysfs_ops,
-	.default_attrs = sgv_attrs,
-};
-
-static int scst_sgv_sysfs_create(struct sgv_pool *pool, struct kobject *parent)
-{
-	int res;
-
-	res = kobject_add(&pool->sgv_kobj, parent, pool->name);
-	if (res != 0) {
-		PRINT_ERROR("Can't add sgv pool %s to sysfs", pool->name);
-		goto out;
-	}
-
-out:
-	return res;
-}
-
-static void scst_sgv_sysfs_del(struct sgv_pool *pool)
-{
-	kobject_del(&pool->sgv_kobj);
-}
-
-/**
- ** SGV directory implementation
- **/
-
-static struct kobj_attribute sgv_global_stat_attr =
-	__ATTR(global_stats, S_IRUGO | S_IWUSR, sgv_sysfs_global_stat_show,
-		sgv_sysfs_global_stat_reset);
-
-static struct attribute *sgv_default_attrs[] = {
-	&sgv_global_stat_attr.attr,
-	NULL,
-};
-
-static void scst_sysfs_release(struct kobject *kobj)
-{
-	kfree(kobj);
-}
-
-static struct kobj_type sgv_ktype = {
-	.sysfs_ops = &scst_sysfs_ops,
-	.release = scst_sysfs_release,
-	.default_attrs = sgv_default_attrs,
-};
-
-/**
- * scst_add_sgv_kobj() - Initialize and add the root SGV kernel object.
- */
-int scst_add_sgv_kobj(struct kobject *parent, const char *name)
-{
-	int res;
-
-	WARN_ON(scst_sgv_kobj);
-	res = -ENOMEM;
-	scst_sgv_kobj = kzalloc(sizeof(*scst_sgv_kobj), GFP_KERNEL);
-	if (!scst_sgv_kobj)
-		goto out;
-	res = kobject_init_and_add(scst_sgv_kobj, &sgv_ktype, parent, name);
-	if (res != 0)
-		goto out_free;
-out:
-	return res;
-out_free:
-	kobject_put(scst_sgv_kobj);
-	scst_sgv_kobj = NULL;
-	goto out;
-}
-
-/**
- * scst_del_put_sgv_kobj() - Remove the root SGV kernel object.
- */
-void scst_del_put_sgv_kobj(void)
-{
-	WARN_ON(!scst_sgv_kobj);
-	kobject_del(scst_sgv_kobj);
-	kobject_put(scst_sgv_kobj);
-	scst_sgv_kobj = NULL;
 }
 
+#endif /*defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)*/
diff --git a/drivers/scst/scst_mem.h b/drivers/scst/scst_mem.h
index ea3f549..18b7e8c 100644
--- a/drivers/scst/scst_mem.h
+++ b/drivers/scst/scst_mem.h
@@ -122,7 +122,9 @@ struct sgv_pool {
 
 	struct list_head sgv_pools_list_entry;
 
-	struct kobject sgv_kobj;
+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
+	struct dentry *debugfs_dir;
+#endif
 };
 
 static inline struct scatterlist *sgv_pool_sg(struct sgv_pool_obj *obj)
@@ -136,3 +138,21 @@ void scst_sgv_pools_deinit(void);
 void scst_sgv_pool_use_norm(struct scst_tgt_dev *tgt_dev);
 void scst_sgv_pool_use_norm_clust(struct scst_tgt_dev *tgt_dev);
 void scst_sgv_pool_use_dma(struct scst_tgt_dev *tgt_dev);
+
+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
+
+int scst_sgv_debugfs_create(struct dentry *parent);
+void scst_sgv_debugfs_del(void);
+
+#else /*defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)*/
+
+static inline int scst_sgv_debugfs_create(struct dentry *parent)
+{
+	return 0;
+}
+
+static inline void scst_sgv_debugfs_del(void)
+{
+}
+
+#endif /*defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)*/
diff --git a/drivers/scst/scst_mem_stats.c b/drivers/scst/scst_mem_stats.c
new file mode 100644
index 0000000..8095e61
--- /dev/null
+++ b/drivers/scst/scst_mem_stats.c
@@ -0,0 +1,168 @@
+/*
+ *  scst_mem.c
+ *
+ *  Copyright (C) 2006 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
+ *  Copyright (C) 2007 - 2010 ID7 Ltd.
+ *  Copyright (C) 2010 Bart Van Assche <bvanassche@acm.org>.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation, version 2
+ *  of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ */
+
+#include <linux/debugfs.h>
+#include <scst/scst.h>
+#include "scst_priv.h"
+#include "scst_mem.h"
+#include "scst_mem_stats.h"
+
+static struct dentry *scst_debug_sgv;
+
+static int sgv_debugfs_open(struct inode *inode, struct file *file)
+{
+	if (inode->i_private)
+		file->private_data = inode->i_private;
+
+	return 0;
+}
+
+static ssize_t sgv_pool_read_file(struct file *file, char __user *buf,
+				      size_t count, loff_t *ppos)
+{
+	struct sgv_pool *pool = file->private_data;
+	unsigned long pg;
+	void *contents;
+	int len;
+	ssize_t res;
+
+	if (*ppos > PAGE_SIZE)
+		return -EINVAL;
+	pg = __get_free_page(GFP_KERNEL);
+	if (!pg)
+		return -ENOMEM;
+	contents = (void *)pg;
+	len = sgv_pool_stat_show(pool, contents);
+	free_page(pg);
+	res = min_t(ssize_t, count, len - *ppos);
+	if (copy_to_user(buf, contents + *ppos, res))
+		return -EFAULT;
+	*ppos += res;
+	return res;
+}
+
+static ssize_t sgv_pool_write_file(struct file *file,
+				       const char __user *buf,
+				       size_t count, loff_t *ppos)
+{
+	struct sgv_pool *pool = file->private_data;
+
+	sgv_pool_stat_reset(pool);
+	return count;
+}
+
+static const struct file_operations sgv_pool_fops = {
+	.read	=	sgv_pool_read_file,
+	.write	=	sgv_pool_write_file,
+	.open	=	sgv_debugfs_open,
+	.llseek	=	noop_llseek,
+};
+
+int scst_sgv_pool_debugfs_create(struct sgv_pool *pool)
+{
+	struct dentry *file;
+	int res;
+
+	res = -ENOMEM;
+	pool->debugfs_dir = debugfs_create_dir(pool->name, scst_debug_sgv);
+	if (!pool->debugfs_dir)
+		goto out;
+	file = debugfs_create_file("stats", S_IRUGO | S_IWUSR,
+				   pool->debugfs_dir, pool, &sgv_pool_fops);
+	if (!file)
+		goto err;
+	res = 0;
+out:
+	return res;
+err:
+	debugfs_remove_recursive(pool->debugfs_dir);
+	pool->debugfs_dir = NULL;
+	goto out;
+}
+
+void scst_sgv_pool_debugfs_del(struct sgv_pool *pool)
+{
+	debugfs_remove_recursive(pool->debugfs_dir);
+	pool->debugfs_dir = NULL;
+}
+
+static ssize_t sgv_global_read_file(struct file *file, char __user *buf,
+				      size_t count, loff_t *ppos)
+{
+	unsigned long pg;
+	void *contents;
+	int len;
+	ssize_t res;
+
+	if (*ppos > PAGE_SIZE)
+		return -EINVAL;
+	pg = __get_free_page(GFP_KERNEL);
+	if (!pg)
+		return -ENOMEM;
+	contents = (void *)pg;
+	len = sgv_global_stat_show(contents);
+	free_page(pg);
+	res = min_t(ssize_t, count, len - *ppos);
+	if (copy_to_user(buf, contents + *ppos, res))
+		return -EFAULT;
+	*ppos += res;
+	return res;
+}
+
+static ssize_t sgv_global_write_file(struct file *file,
+				     const char __user *buf,
+				     size_t count, loff_t *ppos)
+{
+	sgv_global_stat_reset();
+	return count;
+}
+
+static const struct file_operations sgv_global_fops = {
+	.read	=	sgv_global_read_file,
+	.write	=	sgv_global_write_file,
+	.open	=	sgv_debugfs_open,
+	.llseek	=	noop_llseek,
+};
+
+int scst_sgv_debugfs_create(struct dentry *parent)
+{
+	struct dentry *file;
+	int res;
+
+	res = -ENOMEM;
+	scst_debug_sgv = debugfs_create_dir("sgv", parent);
+	if (!scst_debug_sgv)
+		goto out;
+	file = debugfs_create_file("global_stats", S_IRUGO | S_IWUSR,
+				   scst_debug_sgv, NULL, &sgv_global_fops);
+	if (!file)
+		goto err;
+	res = 0;
+out:
+	return res;
+err:
+	debugfs_remove_recursive(scst_debug_sgv);
+	scst_debug_sgv = NULL;
+	goto out;
+}
+
+void scst_sgv_debugfs_del(void)
+{
+	debugfs_remove_recursive(scst_debug_sgv);
+	scst_debug_sgv = NULL;
+}
diff --git a/drivers/scst/scst_mem_stats.h b/drivers/scst/scst_mem_stats.h
new file mode 100644
index 0000000..b51d294
--- /dev/null
+++ b/drivers/scst/scst_mem_stats.h
@@ -0,0 +1,21 @@
+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
+
+int scst_sgv_pool_debugfs_create(struct sgv_pool *pool);
+void scst_sgv_pool_debugfs_del(struct sgv_pool *pool);
+ssize_t sgv_pool_stat_show(struct sgv_pool *pool, char *buf);
+void sgv_pool_stat_reset(struct sgv_pool *pool);
+ssize_t sgv_global_stat_show(char *buf);
+void sgv_global_stat_reset(void);
+
+#else /*defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)*/
+
+static inline int scst_sgv_pool_debugfs_create(struct sgv_pool *pool)
+{
+	return 0;
+}
+
+static void scst_sgv_pool_debugfs_del(struct sgv_pool *pool)
+{
+}
+
+#endif /*defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)*/
diff --git a/drivers/scst/scst_priv.h b/drivers/scst/scst_priv.h
index 7a5a815..74e68a4 100644
--- a/drivers/scst/scst_priv.h
+++ b/drivers/scst/scst_priv.h
@@ -376,8 +376,6 @@ void scst_tgt_sysfs_put(struct scst_tgt *tgt);
 int scst_sess_sysfs_create(struct scst_session *sess);
 void scst_sess_sysfs_del(struct scst_session *sess);
 int scst_recreate_sess_luns_link(struct scst_session *sess);
-int scst_add_sgv_kobj(struct kobject *parent, const char *name);
-void scst_del_put_sgv_kobj(void);
 int scst_devt_sysfs_init(struct scst_dev_type *devt);
 int scst_devt_sysfs_create(struct scst_dev_type *devt);
 void scst_devt_sysfs_del(struct scst_dev_type *devt);
diff --git a/drivers/scst/scst_sysfs.c b/drivers/scst/scst_sysfs.c
index aadb066..84dc9ee 100644
--- a/drivers/scst/scst_sysfs.c
+++ b/drivers/scst/scst_sysfs.c
@@ -3860,16 +3860,9 @@ int __init scst_sysfs_init(void)
 		goto out_remove_files;
 	}
 
-	res = scst_add_sgv_kobj(&scst_device->kobj, "sgv");
-	if (res) {
-		PRINT_ERROR("%s", "Creation of SCST sgv kernel object failed.");
-		goto out_remove_trace_files;
-	}
-
 out:
 	return res;
 
-out_remove_trace_files:
 	scst_main_remove_trace_files();
 out_remove_files:
 	device_remove_files(scst_device, scst_root_default_attrs);
@@ -3891,8 +3884,6 @@ void scst_sysfs_cleanup(void)
 {
 	PRINT_INFO("%s", "Exiting SCST sysfs hierarchy...");
 
-	scst_del_put_sgv_kobj();
-
 	scst_main_remove_trace_files();
 
 	device_remove_files(scst_device, scst_root_default_attrs);
diff --git a/drivers/scst/scst_tracing.c b/drivers/scst/scst_tracing.c
index 7b97224..9b9aef4 100644
--- a/drivers/scst/scst_tracing.c
+++ b/drivers/scst/scst_tracing.c
@@ -18,6 +18,7 @@
 #include <linux/debugfs.h>
 #include <scst/scst.h>
 #include <scst/scst_debug.h>
+#include "scst_mem.h"
 #include "scst_priv.h"
 #include "scst_pres.h"
 #include "scst_tracing.h"
@@ -230,31 +231,41 @@ int scst_debugfs_init(void)
 		goto out;
 	}
 
+	res = scst_sgv_debugfs_create(scst_debug_root);
+	if (res) {
+		PRINT_ERROR("%s", "Creation of /sys/kernel/debug/scst/sgv"
+			    " failed");
+		goto err;
+	}
+
 	scst_debug_target = debugfs_create_dir("target", scst_debug_root);
 	if (!scst_debug_target) {
 		PRINT_ERROR("%s", "Creation of /sys/kernel/debug/scst/target"
 			    " failed");
-		goto out;
+		goto err;
 	}
 
 	scst_debug_devt = debugfs_create_dir("device_type", scst_debug_root);
 	if (!scst_debug_devt) {
 		PRINT_ERROR("%s", "Creation of /sys/kernel/debug/scst/"
 			    "device_type failed");
-		goto out;
+		goto err;
 	}
 
 	scst_debug_dev = debugfs_create_dir("device", scst_debug_root);
 	if (!scst_debug_dev) {
 		PRINT_ERROR("%s", "Creation of /sys/kernel/debug/scst/device"
 			    " failed");
-		goto out;
+		goto err;
 	}
 
 	res = 0;
 
 out:
 	return res;
+err:
+	scst_debugfs_cleanup();
+	goto out;
 }
 
 void scst_debugfs_cleanup(void)
-- 
1.7.1
[SCSI] scst: Move latency statistics to debugfs
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 Documentation/ABI/stable/sysfs-devices-scst_target |   16 -
 drivers/scst/Kconfig                               |    2 +-
 drivers/scst/Makefile                              |    1 +
 drivers/scst/scst_lat_stats.c                      |  435 ++++++++++++++++++++
 drivers/scst/scst_lat_stats.h                      |   28 ++
 drivers/scst/scst_sysfs.c                          |  371 ++---------------
 drivers/scst/scst_tracing.c                        |  204 +++++++---
 drivers/scst/scst_tracing.h                        |   57 ++-
 include/scst/scst.h                                |   21 +
 9 files changed, 719 insertions(+), 416 deletions(-)
 create mode 100644 drivers/scst/scst_lat_stats.c
 create mode 100644 drivers/scst/scst_lat_stats.h
diff --git a/Documentation/ABI/stable/sysfs-devices-scst_target b/Documentation/ABI/stable/sysfs-devices-scst_target
index 2d3a388..1792aa3 100644
--- a/Documentation/ABI/stable/sysfs-devices-scst_target
+++ b/Documentation/ABI/stable/sysfs-devices-scst_target
@@ -182,28 +182,12 @@ Description:
 		Session name. For most target drivers this is a name that
 		identifies the initiator. Read-only.
 
-What:		/sys/bus/scst_target/devices/*/sessions/<session>/latency
-Date:		December 2010
-Contact:	Bart Van Assche <bvanassche@acm.org>
-Description:
-		Latency statistics for this session. Only available if
-		CONFIG_SCST_MEASURE_LATENCY has been enabled in the
-		kernel configuration. Read-only.
-
 What:		/sys/bus/scst_target/devices/*/sessions/<session>/lun<number>/active_commands
 Date:		December 2010
 Contact:	Bart Van Assche <bvanassche@acm.org>
 Description:
 		Number of active commands. Read-only.
 
-What:		/sys/bus/scst_target/devices/*/sessions/<session>/lun<number>/latency
-Date:		December 2010
-Contact:	Bart Van Assche <bvanassche@acm.org>
-Description:
-		Latency statistics for this LUN. Only available if
-		CONFIG_SCST_MEASURE_LATENCY has been enabled in the kernel
-		configuration. Read-only.
-
 What:		/sys/bus/scst_target/devices/*/sessions/<session>/luns
 Date:		December 2010
 Contact:	Bart Van Assche <bvanassche@acm.org>
diff --git a/drivers/scst/Kconfig b/drivers/scst/Kconfig
index 75b0f97..62cb227 100644
--- a/drivers/scst/Kconfig
+++ b/drivers/scst/Kconfig
@@ -228,7 +228,7 @@ config SCST_TM_DBG_GO_OFFLINE
 
 config SCST_MEASURE_LATENCY
 	bool "Commands processing latency measurement facility"
-	depends on SCST
+	depends on SCST && (SCST_DEBUG || SCST_TRACING)
 	help
 	  This option enables commands processing latency measurement
 	  facility in SCST. It will provide in the sysfs interface
diff --git a/drivers/scst/Makefile b/drivers/scst/Makefile
index a27cf92..f2f9253 100644
--- a/drivers/scst/Makefile
+++ b/drivers/scst/Makefile
@@ -9,5 +9,6 @@ scst-y        += scst_mem.o
 scst-y        += scst_debug.o
 scst-$(CONFIG_SCST_DEBUG)	+= scst_tracing.o scst_mem_stats.o
 scst-$(CONFIG_SCST_TRACING)	+= scst_tracing.o scst_mem_stats.o
+scst-$(CONFIG_SCST_MEASURE_LATENCY)	+= scst_lat_stats.o
 
 obj-$(CONFIG_SCST)   += scst.o dev_handlers/ scst_local/ srpt/
diff --git a/drivers/scst/scst_lat_stats.c b/drivers/scst/scst_lat_stats.c
new file mode 100644
index 0000000..0bee2b9
--- /dev/null
+++ b/drivers/scst/scst_lat_stats.c
@@ -0,0 +1,435 @@
+/*
+ *  scst_lat_stats.c
+ *
+ *  Copyright (C) 2009 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
+ *  Copyright (C) 2010 Bart Van Assche <bvanassche@acm.org>
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation, version 2
+ *  of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <scst/scst.h>
+#include <scst/scst_debug.h>
+#include "scst_priv.h"
+#include "scst_lat_stats.h"
+
+/* Per LUN latency statistics. */
+
+static char *scst_io_size_names[] = {
+	"<=8K  ",
+	"<=32K ",
+	"<=128K",
+	"<=512K",
+	">512K "
+};
+
+static ssize_t scst_tgt_dev_latency_show(struct scst_tgt_dev *tgt_dev,
+					 char *buffer)
+{
+	int res, i;
+	char buf[50];
+
+	res = 0;
+	for (i = 0; i < SCST_LATENCY_STATS_NUM; i++) {
+		uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
+		unsigned int processed_cmds_wr;
+		uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
+		unsigned int processed_cmds_rd;
+		struct scst_ext_latency_stat *latency_stat;
+
+		latency_stat = &tgt_dev->dev_latency_stat[i];
+		scst_time_wr = latency_stat->scst_time_wr;
+		scst_time_rd = latency_stat->scst_time_rd;
+		tgt_time_wr = latency_stat->tgt_time_wr;
+		tgt_time_rd = latency_stat->tgt_time_rd;
+		dev_time_wr = latency_stat->dev_time_wr;
+		dev_time_rd = latency_stat->dev_time_rd;
+		processed_cmds_wr = latency_stat->processed_cmds_wr;
+		processed_cmds_rd = latency_stat->processed_cmds_rd;
+
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
+			 "%-5s %-9s %-15lu ", "Write", scst_io_size_names[i],
+			(unsigned long)processed_cmds_wr);
+		if (processed_cmds_wr == 0)
+			processed_cmds_wr = 1;
+
+		do_div(scst_time_wr, processed_cmds_wr);
+		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+			(unsigned long)latency_stat->min_scst_time_wr,
+			(unsigned long)scst_time_wr,
+			(unsigned long)latency_stat->max_scst_time_wr,
+			(unsigned long)latency_stat->scst_time_wr);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s", buf);
+
+		do_div(tgt_time_wr, processed_cmds_wr);
+		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+			(unsigned long)latency_stat->min_tgt_time_wr,
+			(unsigned long)tgt_time_wr,
+			(unsigned long)latency_stat->max_tgt_time_wr,
+			(unsigned long)latency_stat->tgt_time_wr);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s", buf);
+
+		do_div(dev_time_wr, processed_cmds_wr);
+		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+			(unsigned long)latency_stat->min_dev_time_wr,
+			(unsigned long)dev_time_wr,
+			(unsigned long)latency_stat->max_dev_time_wr,
+			(unsigned long)latency_stat->dev_time_wr);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s\n", buf);
+
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
+			"%-5s %-9s %-15lu ", "Read", scst_io_size_names[i],
+			(unsigned long)processed_cmds_rd);
+		if (processed_cmds_rd == 0)
+			processed_cmds_rd = 1;
+
+		do_div(scst_time_rd, processed_cmds_rd);
+		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+			(unsigned long)latency_stat->min_scst_time_rd,
+			(unsigned long)scst_time_rd,
+			(unsigned long)latency_stat->max_scst_time_rd,
+			(unsigned long)latency_stat->scst_time_rd);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s", buf);
+
+		do_div(tgt_time_rd, processed_cmds_rd);
+		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+			(unsigned long)latency_stat->min_tgt_time_rd,
+			(unsigned long)tgt_time_rd,
+			(unsigned long)latency_stat->max_tgt_time_rd,
+			(unsigned long)latency_stat->tgt_time_rd);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s", buf);
+
+		do_div(dev_time_rd, processed_cmds_rd);
+		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+			(unsigned long)latency_stat->min_dev_time_rd,
+			(unsigned long)dev_time_rd,
+			(unsigned long)latency_stat->max_dev_time_rd,
+			(unsigned long)latency_stat->dev_time_rd);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s\n", buf);
+	}
+	return res;
+}
+
+static int scst_debugfs_open(struct inode *inode, struct file *file)
+{
+	if (inode->i_private)
+		file->private_data = inode->i_private;
+
+	return 0;
+}
+
+static ssize_t tgt_dev_lat_read_file(struct file *file, char __user *buf,
+				      size_t count, loff_t *ppos)
+{
+	struct scst_tgt_dev *tgt_dev = file->private_data;
+	unsigned long pg;
+	void *contents;
+	int len;
+	ssize_t res;
+
+	if (*ppos > PAGE_SIZE)
+		return -EINVAL;
+	pg = __get_free_page(GFP_KERNEL);
+	if (!pg)
+		return -ENOMEM;
+	contents = (void *)pg;
+	len = scst_tgt_dev_latency_show(tgt_dev, contents);
+	free_page(pg);
+	res = min_t(ssize_t, count, len - *ppos);
+	if (copy_to_user(buf, contents + *ppos, res))
+		return -EFAULT;
+	*ppos += res;
+	return res;
+}
+
+static ssize_t tgt_dev_lat_write_file(struct file *file,
+				       const char __user *buf,
+				       size_t count, loff_t *ppos)
+{
+	return -EINVAL;
+}
+
+static const struct file_operations tgt_dev_lat_fops = {
+	.read	=	tgt_dev_lat_read_file,
+	.write	=	tgt_dev_lat_write_file,
+	.open	=	scst_debugfs_open,
+	.llseek	=	noop_llseek,
+};
+
+int scst_tgt_dev_lat_create(struct scst_tgt_dev *tgt_dev)
+{
+	tgt_dev->latency_file = debugfs_create_file("latency",
+				    S_IRUGO | S_IWUSR, tgt_dev->debugfs_dir,
+				    tgt_dev, &tgt_dev_lat_fops);
+	return tgt_dev->latency_file ? 0 : -ENOMEM;
+}
+
+void scst_tgt_dev_lat_remove(struct scst_tgt_dev *tgt_dev)
+{
+	debugfs_remove(tgt_dev->latency_file);
+	tgt_dev->latency_file = NULL;
+}
+
+/* Per session latency statistics. */
+
+static ssize_t scst_sess_latency_show(struct scst_session *sess, char *buffer)
+{
+	ssize_t res;
+	int i;
+	char buf[50];
+	uint64_t scst_time, tgt_time, dev_time;
+	unsigned int processed_cmds;
+
+	res = 0;
+	res += scnprintf(&buffer[res], PAGE_SIZE - res,
+		"%-15s %-15s %-46s %-46s %-46s\n",
+		"T-L names", "Total commands", "SCST latency",
+		"Target latency", "Dev latency (min/avg/max/all ns)");
+
+	spin_lock_bh(&sess->lat_lock);
+
+	for (i = 0; i < SCST_LATENCY_STATS_NUM ; i++) {
+		uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
+		unsigned int processed_cmds_wr;
+		uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
+		unsigned int processed_cmds_rd;
+		struct scst_ext_latency_stat *latency_stat;
+
+		latency_stat = &sess->sess_latency_stat[i];
+		scst_time_wr = latency_stat->scst_time_wr;
+		scst_time_rd = latency_stat->scst_time_rd;
+		tgt_time_wr = latency_stat->tgt_time_wr;
+		tgt_time_rd = latency_stat->tgt_time_rd;
+		dev_time_wr = latency_stat->dev_time_wr;
+		dev_time_rd = latency_stat->dev_time_rd;
+		processed_cmds_wr = latency_stat->processed_cmds_wr;
+		processed_cmds_rd = latency_stat->processed_cmds_rd;
+
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
+			"%-5s %-9s %-15lu ",
+			"Write", scst_io_size_names[i],
+			(unsigned long)processed_cmds_wr);
+		if (processed_cmds_wr == 0)
+			processed_cmds_wr = 1;
+
+		do_div(scst_time_wr, processed_cmds_wr);
+		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+			(unsigned long)latency_stat->min_scst_time_wr,
+			(unsigned long)scst_time_wr,
+			(unsigned long)latency_stat->max_scst_time_wr,
+			(unsigned long)latency_stat->scst_time_wr);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
+			"%-47s", buf);
+
+		do_div(tgt_time_wr, processed_cmds_wr);
+		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+			(unsigned long)latency_stat->min_tgt_time_wr,
+			(unsigned long)tgt_time_wr,
+			(unsigned long)latency_stat->max_tgt_time_wr,
+			(unsigned long)latency_stat->tgt_time_wr);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
+			"%-47s", buf);
+
+		do_div(dev_time_wr, processed_cmds_wr);
+		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+			(unsigned long)latency_stat->min_dev_time_wr,
+			(unsigned long)dev_time_wr,
+			(unsigned long)latency_stat->max_dev_time_wr,
+			(unsigned long)latency_stat->dev_time_wr);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
+			"%-47s\n", buf);
+
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
+			"%-5s %-9s %-15lu ",
+			"Read", scst_io_size_names[i],
+			(unsigned long)processed_cmds_rd);
+		if (processed_cmds_rd == 0)
+			processed_cmds_rd = 1;
+
+		do_div(scst_time_rd, processed_cmds_rd);
+		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+			(unsigned long)latency_stat->min_scst_time_rd,
+			(unsigned long)scst_time_rd,
+			(unsigned long)latency_stat->max_scst_time_rd,
+			(unsigned long)latency_stat->scst_time_rd);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
+			"%-47s", buf);
+
+		do_div(tgt_time_rd, processed_cmds_rd);
+		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+			(unsigned long)latency_stat->min_tgt_time_rd,
+			(unsigned long)tgt_time_rd,
+			(unsigned long)latency_stat->max_tgt_time_rd,
+			(unsigned long)latency_stat->tgt_time_rd);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
+			"%-47s", buf);
+
+		do_div(dev_time_rd, processed_cmds_rd);
+		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+			(unsigned long)latency_stat->min_dev_time_rd,
+			(unsigned long)dev_time_rd,
+			(unsigned long)latency_stat->max_dev_time_rd,
+			(unsigned long)latency_stat->dev_time_rd);
+		res += scnprintf(&buffer[res], PAGE_SIZE - res,
+			"%-47s\n", buf);
+	}
+
+	scst_time = sess->scst_time;
+	tgt_time = sess->tgt_time;
+	dev_time = sess->dev_time;
+	processed_cmds = sess->processed_cmds;
+
+	res += scnprintf(&buffer[res], PAGE_SIZE - res,
+		"\n%-15s %-16d", "Overall ", processed_cmds);
+
+	if (processed_cmds == 0)
+		processed_cmds = 1;
+
+	do_div(scst_time, processed_cmds);
+	snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+		(unsigned long)sess->min_scst_time,
+		(unsigned long)scst_time,
+		(unsigned long)sess->max_scst_time,
+		(unsigned long)sess->scst_time);
+	res += scnprintf(&buffer[res], PAGE_SIZE - res,
+		"%-47s", buf);
+
+	do_div(tgt_time, processed_cmds);
+	snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+		(unsigned long)sess->min_tgt_time,
+		(unsigned long)tgt_time,
+		(unsigned long)sess->max_tgt_time,
+		(unsigned long)sess->tgt_time);
+	res += scnprintf(&buffer[res], PAGE_SIZE - res,
+		"%-47s", buf);
+
+	do_div(dev_time, processed_cmds);
+	snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
+		(unsigned long)sess->min_dev_time,
+		(unsigned long)dev_time,
+		(unsigned long)sess->max_dev_time,
+		(unsigned long)sess->dev_time);
+	res += scnprintf(&buffer[res], PAGE_SIZE - res,
+		"%-47s\n\n", buf);
+
+	spin_unlock_bh(&sess->lat_lock);
+	return res;
+}
+
+static int scst_sess_zero_latency(struct scst_session *sess)
+{
+	int res, t;
+
+	res = mutex_lock_interruptible(&scst_mutex);
+	if (res)
+		goto out;
+
+	PRINT_INFO("Zeroing latency statistics for initiator "
+		"%s", sess->initiator_name);
+
+	spin_lock_bh(&sess->lat_lock);
+
+	sess->scst_time = 0;
+	sess->tgt_time = 0;
+	sess->dev_time = 0;
+	sess->min_scst_time = 0;
+	sess->min_tgt_time = 0;
+	sess->min_dev_time = 0;
+	sess->max_scst_time = 0;
+	sess->max_tgt_time = 0;
+	sess->max_dev_time = 0;
+	sess->processed_cmds = 0;
+	memset(sess->sess_latency_stat, 0,
+		sizeof(sess->sess_latency_stat));
+
+	for (t = SESS_TGT_DEV_LIST_HASH_SIZE-1; t >= 0; t--) {
+		struct list_head *head = &sess->sess_tgt_dev_list[t];
+		struct scst_tgt_dev *tgt_dev;
+		list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) {
+			tgt_dev->scst_time = 0;
+			tgt_dev->tgt_time = 0;
+			tgt_dev->dev_time = 0;
+			tgt_dev->processed_cmds = 0;
+			memset(tgt_dev->dev_latency_stat, 0,
+				sizeof(tgt_dev->dev_latency_stat));
+		}
+	}
+
+	spin_unlock_bh(&sess->lat_lock);
+
+	mutex_unlock(&scst_mutex);
+
+out:
+	return res;
+}
+
+static ssize_t sess_lat_read_file(struct file *file, char __user *buf,
+				      size_t count, loff_t *ppos)
+{
+	struct scst_session *sess = file->private_data;
+	unsigned long pg;
+	void *contents;
+	int len;
+	ssize_t res;
+
+	if (*ppos > PAGE_SIZE)
+		return -EINVAL;
+	pg = __get_free_page(GFP_KERNEL);
+	if (!pg)
+		return -ENOMEM;
+	contents = (void *)pg;
+	len = scst_sess_latency_show(sess, contents);
+	free_page(pg);
+	res = min_t(ssize_t, count, len - *ppos);
+	if (copy_to_user(buf, contents + *ppos, res))
+		return -EFAULT;
+	*ppos += res;
+	return res;
+}
+
+static ssize_t sess_lat_write_file(struct file *file,
+				       const char __user *buf,
+				       size_t count, loff_t *ppos)
+{
+	struct scst_session *sess = file->private_data;
+	int res;
+
+	res = scst_sess_zero_latency(sess);
+	if (res)
+		goto out;
+	*ppos += count;
+	res = count;
+out:
+	return res;
+}
+
+static const struct file_operations sess_lat_fops = {
+	.read	=	sess_lat_read_file,
+	.write	=	sess_lat_write_file,
+	.open	=	scst_debugfs_open,
+	.llseek	=	noop_llseek,
+};
+
+int scst_sess_lat_create(struct scst_session *sess)
+{
+	sess->latency_file = debugfs_create_file("latency",
+				    S_IRUGO | S_IWUSR, sess->debugfs_dir,
+				    sess, &sess_lat_fops);
+	return sess->latency_file ? 0 : -ENOMEM;
+}
+
+void scst_sess_lat_remove(struct scst_session *sess)
+{
+	debugfs_remove(sess->latency_file);
+	sess->latency_file = NULL;
+}
diff --git a/drivers/scst/scst_lat_stats.h b/drivers/scst/scst_lat_stats.h
new file mode 100644
index 0000000..50c89ee
--- /dev/null
+++ b/drivers/scst/scst_lat_stats.h
@@ -0,0 +1,28 @@
+#if defined(CONFIG_SCST_MEASURE_LATENCY)
+
+int scst_tgt_dev_lat_create(struct scst_tgt_dev *tgt_dev);
+void scst_tgt_dev_lat_remove(struct scst_tgt_dev *tgt_dev);
+int scst_sess_lat_create(struct scst_session *sess);
+void scst_sess_lat_remove(struct scst_session *sess);
+
+#else /*defined(CONFIG_SCST_MEASURE_LATENCY)*/
+
+static inline int scst_tgt_dev_lat_create(struct scst_tgt_dev *tgt_dev)
+{
+	return 0;
+}
+
+static inline void scst_tgt_dev_lat_remove(struct scst_tgt_dev *tgt_dev)
+{
+}
+
+static inline int scst_sess_lat_create(struct scst_session *sess)
+{
+	return 0;
+}
+
+static inline void scst_sess_lat_remove(struct scst_session *sess)
+{
+}
+
+#endif /*defined(CONFIG_SCST_MEASURE_LATENCY)*/
diff --git a/drivers/scst/scst_sysfs.c b/drivers/scst/scst_sysfs.c
index 84dc9ee..c9c4c28 100644
--- a/drivers/scst/scst_sysfs.c
+++ b/drivers/scst/scst_sysfs.c
@@ -46,6 +46,7 @@
 #include "scst_priv.h"
 #include "scst_mem.h"
 #include "scst_tracing.h"
+#include "scst_lat_stats.h"
 
 enum mgmt_path_type {
 	PATH_NOT_RECOGNIZED,
@@ -442,7 +443,7 @@ int scst_tgtt_sysfs_create(struct scst_tgt_template *tgtt)
 		}
 	}
 
-	res = scst_tgtt_create_trace_files(tgtt);
+	res = scst_tgtt_debugfs_create(tgtt);
 	if (res) {
 		PRINT_ERROR("Can't create tracing files for target driver %s",
 			    tgtt->name);
@@ -459,7 +460,7 @@ out_del:
 
 void scst_tgtt_sysfs_del(struct scst_tgt_template *tgtt)
 {
-	scst_tgtt_remove_trace_files(tgtt);
+	scst_tgtt_debugfs_remove(tgtt);
 	driver_unregister(&tgtt->tgtt_drv);
 }
 
@@ -1049,6 +1050,10 @@ int scst_tgt_sysfs_create(struct scst_tgt *tgt)
 		}
 	}
 
+	res = scst_tgt_debugfs_create(tgt);
+	if (res)
+		goto out_err;
+
 out:
 	return res;
 
@@ -1062,6 +1067,7 @@ out_err:
 
 void scst_tgt_sysfs_del(struct scst_tgt *tgt)
 {
+	scst_tgt_debugfs_remove(tgt);
 	kobject_del(tgt->tgt_sess_kobj);
 	kobject_del(tgt->tgt_luns_kobj);
 	kobject_del(tgt->tgt_ini_grp_kobj);
@@ -1502,112 +1508,6 @@ void scst_dev_sysfs_put(struct scst_device *dev)
  ** Tgt_dev implementation
  **/
 
-#ifdef CONFIG_SCST_MEASURE_LATENCY
-
-static char *scst_io_size_names[] = {
-	"<=8K  ",
-	"<=32K ",
-	"<=128K",
-	"<=512K",
-	">512K "
-};
-
-static ssize_t scst_tgt_dev_latency_show(struct kobject *kobj,
-	struct kobj_attribute *attr, char *buffer)
-{
-	int res, i;
-	char buf[50];
-	struct scst_tgt_dev *tgt_dev;
-
-	tgt_dev = scst_kobj_to_tgt_dev(kobj);
-
-	res = 0;
-	for (i = 0; i < SCST_LATENCY_STATS_NUM; i++) {
-		uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
-		unsigned int processed_cmds_wr;
-		uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
-		unsigned int processed_cmds_rd;
-		struct scst_ext_latency_stat *latency_stat;
-
-		latency_stat = &tgt_dev->dev_latency_stat[i];
-		scst_time_wr = latency_stat->scst_time_wr;
-		scst_time_rd = latency_stat->scst_time_rd;
-		tgt_time_wr = latency_stat->tgt_time_wr;
-		tgt_time_rd = latency_stat->tgt_time_rd;
-		dev_time_wr = latency_stat->dev_time_wr;
-		dev_time_rd = latency_stat->dev_time_rd;
-		processed_cmds_wr = latency_stat->processed_cmds_wr;
-		processed_cmds_rd = latency_stat->processed_cmds_rd;
-
-		res += scnprintf(&buffer[res], PAGE_SIZE - res,
-			 "%-5s %-9s %-15lu ", "Write", scst_io_size_names[i],
-			(unsigned long)processed_cmds_wr);
-		if (processed_cmds_wr == 0)
-			processed_cmds_wr = 1;
-
-		do_div(scst_time_wr, processed_cmds_wr);
-		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-			(unsigned long)latency_stat->min_scst_time_wr,
-			(unsigned long)scst_time_wr,
-			(unsigned long)latency_stat->max_scst_time_wr,
-			(unsigned long)latency_stat->scst_time_wr);
-		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s", buf);
-
-		do_div(tgt_time_wr, processed_cmds_wr);
-		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-			(unsigned long)latency_stat->min_tgt_time_wr,
-			(unsigned long)tgt_time_wr,
-			(unsigned long)latency_stat->max_tgt_time_wr,
-			(unsigned long)latency_stat->tgt_time_wr);
-		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s", buf);
-
-		do_div(dev_time_wr, processed_cmds_wr);
-		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-			(unsigned long)latency_stat->min_dev_time_wr,
-			(unsigned long)dev_time_wr,
-			(unsigned long)latency_stat->max_dev_time_wr,
-			(unsigned long)latency_stat->dev_time_wr);
-		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s\n", buf);
-
-		res += scnprintf(&buffer[res], PAGE_SIZE - res,
-			"%-5s %-9s %-15lu ", "Read", scst_io_size_names[i],
-			(unsigned long)processed_cmds_rd);
-		if (processed_cmds_rd == 0)
-			processed_cmds_rd = 1;
-
-		do_div(scst_time_rd, processed_cmds_rd);
-		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-			(unsigned long)latency_stat->min_scst_time_rd,
-			(unsigned long)scst_time_rd,
-			(unsigned long)latency_stat->max_scst_time_rd,
-			(unsigned long)latency_stat->scst_time_rd);
-		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s", buf);
-
-		do_div(tgt_time_rd, processed_cmds_rd);
-		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-			(unsigned long)latency_stat->min_tgt_time_rd,
-			(unsigned long)tgt_time_rd,
-			(unsigned long)latency_stat->max_tgt_time_rd,
-			(unsigned long)latency_stat->tgt_time_rd);
-		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s", buf);
-
-		do_div(dev_time_rd, processed_cmds_rd);
-		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-			(unsigned long)latency_stat->min_dev_time_rd,
-			(unsigned long)dev_time_rd,
-			(unsigned long)latency_stat->max_dev_time_rd,
-			(unsigned long)latency_stat->dev_time_rd);
-		res += scnprintf(&buffer[res], PAGE_SIZE - res, "%-47s\n", buf);
-	}
-	return res;
-}
-
-static struct kobj_attribute tgt_dev_latency_attr =
-	__ATTR(latency, S_IRUGO,
-		scst_tgt_dev_latency_show, NULL);
-
-#endif /* CONFIG_SCST_MEASURE_LATENCY */
-
 static ssize_t scst_tgt_dev_active_commands_show(struct kobject *kobj,
 			    struct kobj_attribute *attr, char *buf)
 {
@@ -1627,9 +1527,6 @@ static struct kobj_attribute tgt_dev_active_commands_attr =
 
 struct attribute *scst_tgt_dev_attrs[] = {
 	&tgt_dev_active_commands_attr.attr,
-#ifdef CONFIG_SCST_MEASURE_LATENCY
-	&tgt_dev_latency_attr.attr,
-#endif
 	NULL,
 };
 
@@ -1645,12 +1542,24 @@ int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev)
 		goto out;
 	}
 
+	res = scst_tgt_dev_debugfs_create(tgt_dev);
+	if (res)
+		goto err;
+
+	res = scst_tgt_dev_lat_create(tgt_dev);
+	if (res)
+		goto err;
 out:
 	return res;
+err:
+	scst_tgt_dev_sysfs_del(tgt_dev);
+	goto out;
 }
 
 void scst_tgt_dev_sysfs_del(struct scst_tgt_dev *tgt_dev)
 {
+	scst_tgt_dev_lat_remove(tgt_dev);
+	scst_tgt_dev_debugfs_remove(tgt_dev);
 	kobject_del(&tgt_dev->tgt_dev_kobj);
 }
 
@@ -1658,223 +1567,6 @@ void scst_tgt_dev_sysfs_del(struct scst_tgt_dev *tgt_dev)
  ** Sessions subdirectory implementation
  **/
 
-#ifdef CONFIG_SCST_MEASURE_LATENCY
-
-static ssize_t scst_sess_latency_show(struct kobject *kobj,
-	struct kobj_attribute *attr, char *buffer)
-{
-	ssize_t res;
-	struct scst_session *sess;
-	int i;
-	char buf[50];
-	uint64_t scst_time, tgt_time, dev_time;
-	unsigned int processed_cmds;
-
-	sess = scst_kobj_to_sess(kobj);
-
-	res = 0;
-	res += scnprintf(&buffer[res], PAGE_SIZE - res,
-		"%-15s %-15s %-46s %-46s %-46s\n",
-		"T-L names", "Total commands", "SCST latency",
-		"Target latency", "Dev latency (min/avg/max/all ns)");
-
-	spin_lock_bh(&sess->lat_lock);
-
-	for (i = 0; i < SCST_LATENCY_STATS_NUM ; i++) {
-		uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
-		unsigned int processed_cmds_wr;
-		uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
-		unsigned int processed_cmds_rd;
-		struct scst_ext_latency_stat *latency_stat;
-
-		latency_stat = &sess->sess_latency_stat[i];
-		scst_time_wr = latency_stat->scst_time_wr;
-		scst_time_rd = latency_stat->scst_time_rd;
-		tgt_time_wr = latency_stat->tgt_time_wr;
-		tgt_time_rd = latency_stat->tgt_time_rd;
-		dev_time_wr = latency_stat->dev_time_wr;
-		dev_time_rd = latency_stat->dev_time_rd;
-		processed_cmds_wr = latency_stat->processed_cmds_wr;
-		processed_cmds_rd = latency_stat->processed_cmds_rd;
-
-		res += scnprintf(&buffer[res], PAGE_SIZE - res,
-			"%-5s %-9s %-15lu ",
-			"Write", scst_io_size_names[i],
-			(unsigned long)processed_cmds_wr);
-		if (processed_cmds_wr == 0)
-			processed_cmds_wr = 1;
-
-		do_div(scst_time_wr, processed_cmds_wr);
-		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-			(unsigned long)latency_stat->min_scst_time_wr,
-			(unsigned long)scst_time_wr,
-			(unsigned long)latency_stat->max_scst_time_wr,
-			(unsigned long)latency_stat->scst_time_wr);
-		res += scnprintf(&buffer[res], PAGE_SIZE - res,
-			"%-47s", buf);
-
-		do_div(tgt_time_wr, processed_cmds_wr);
-		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-			(unsigned long)latency_stat->min_tgt_time_wr,
-			(unsigned long)tgt_time_wr,
-			(unsigned long)latency_stat->max_tgt_time_wr,
-			(unsigned long)latency_stat->tgt_time_wr);
-		res += scnprintf(&buffer[res], PAGE_SIZE - res,
-			"%-47s", buf);
-
-		do_div(dev_time_wr, processed_cmds_wr);
-		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-			(unsigned long)latency_stat->min_dev_time_wr,
-			(unsigned long)dev_time_wr,
-			(unsigned long)latency_stat->max_dev_time_wr,
-			(unsigned long)latency_stat->dev_time_wr);
-		res += scnprintf(&buffer[res], PAGE_SIZE - res,
-			"%-47s\n", buf);
-
-		res += scnprintf(&buffer[res], PAGE_SIZE - res,
-			"%-5s %-9s %-15lu ",
-			"Read", scst_io_size_names[i],
-			(unsigned long)processed_cmds_rd);
-		if (processed_cmds_rd == 0)
-			processed_cmds_rd = 1;
-
-		do_div(scst_time_rd, processed_cmds_rd);
-		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-			(unsigned long)latency_stat->min_scst_time_rd,
-			(unsigned long)scst_time_rd,
-			(unsigned long)latency_stat->max_scst_time_rd,
-			(unsigned long)latency_stat->scst_time_rd);
-		res += scnprintf(&buffer[res], PAGE_SIZE - res,
-			"%-47s", buf);
-
-		do_div(tgt_time_rd, processed_cmds_rd);
-		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-			(unsigned long)latency_stat->min_tgt_time_rd,
-			(unsigned long)tgt_time_rd,
-			(unsigned long)latency_stat->max_tgt_time_rd,
-			(unsigned long)latency_stat->tgt_time_rd);
-		res += scnprintf(&buffer[res], PAGE_SIZE - res,
-			"%-47s", buf);
-
-		do_div(dev_time_rd, processed_cmds_rd);
-		snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-			(unsigned long)latency_stat->min_dev_time_rd,
-			(unsigned long)dev_time_rd,
-			(unsigned long)latency_stat->max_dev_time_rd,
-			(unsigned long)latency_stat->dev_time_rd);
-		res += scnprintf(&buffer[res], PAGE_SIZE - res,
-			"%-47s\n", buf);
-	}
-
-	scst_time = sess->scst_time;
-	tgt_time = sess->tgt_time;
-	dev_time = sess->dev_time;
-	processed_cmds = sess->processed_cmds;
-
-	res += scnprintf(&buffer[res], PAGE_SIZE - res,
-		"\n%-15s %-16d", "Overall ", processed_cmds);
-
-	if (processed_cmds == 0)
-		processed_cmds = 1;
-
-	do_div(scst_time, processed_cmds);
-	snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-		(unsigned long)sess->min_scst_time,
-		(unsigned long)scst_time,
-		(unsigned long)sess->max_scst_time,
-		(unsigned long)sess->scst_time);
-	res += scnprintf(&buffer[res], PAGE_SIZE - res,
-		"%-47s", buf);
-
-	do_div(tgt_time, processed_cmds);
-	snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-		(unsigned long)sess->min_tgt_time,
-		(unsigned long)tgt_time,
-		(unsigned long)sess->max_tgt_time,
-		(unsigned long)sess->tgt_time);
-	res += scnprintf(&buffer[res], PAGE_SIZE - res,
-		"%-47s", buf);
-
-	do_div(dev_time, processed_cmds);
-	snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
-		(unsigned long)sess->min_dev_time,
-		(unsigned long)dev_time,
-		(unsigned long)sess->max_dev_time,
-		(unsigned long)sess->dev_time);
-	res += scnprintf(&buffer[res], PAGE_SIZE - res,
-		"%-47s\n\n", buf);
-
-	spin_unlock_bh(&sess->lat_lock);
-	return res;
-}
-
-static int scst_sess_zero_latency(struct scst_session *sess)
-{
-	int res, t;
-
-	res = mutex_lock_interruptible(&scst_mutex);
-	if (res != 0)
-		goto out;
-
-	PRINT_INFO("Zeroing latency statistics for initiator "
-		"%s", sess->initiator_name);
-
-	spin_lock_bh(&sess->lat_lock);
-
-	sess->scst_time = 0;
-	sess->tgt_time = 0;
-	sess->dev_time = 0;
-	sess->min_scst_time = 0;
-	sess->min_tgt_time = 0;
-	sess->min_dev_time = 0;
-	sess->max_scst_time = 0;
-	sess->max_tgt_time = 0;
-	sess->max_dev_time = 0;
-	sess->processed_cmds = 0;
-	memset(sess->sess_latency_stat, 0,
-		sizeof(sess->sess_latency_stat));
-
-	for (t = SESS_TGT_DEV_LIST_HASH_SIZE-1; t >= 0; t--) {
-		struct list_head *head = &sess->sess_tgt_dev_list[t];
-		struct scst_tgt_dev *tgt_dev;
-		list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) {
-			tgt_dev->scst_time = 0;
-			tgt_dev->tgt_time = 0;
-			tgt_dev->dev_time = 0;
-			tgt_dev->processed_cmds = 0;
-			memset(tgt_dev->dev_latency_stat, 0,
-				sizeof(tgt_dev->dev_latency_stat));
-		}
-	}
-
-	spin_unlock_bh(&sess->lat_lock);
-
-	mutex_unlock(&scst_mutex);
-
-out:
-	return res;
-}
-
-static ssize_t scst_sess_latency_store(struct kobject *kobj,
-	struct kobj_attribute *attr, const char *buf, size_t count)
-{
-	int res;
-	struct scst_session *sess;
-
-	sess = scst_kobj_to_sess(kobj);
-
-	res = scst_sess_zero_latency(sess);
-	if (res == 0)
-		res = count;
-	return res;
-}
-
-static struct kobj_attribute session_latency_attr =
-	__ATTR(latency, S_IRUGO | S_IWUSR, scst_sess_latency_show,
-	       scst_sess_latency_store);
-
-#endif /* CONFIG_SCST_MEASURE_LATENCY */
-
 static ssize_t scst_sess_sysfs_commands_show(struct kobject *kobj,
 			    struct kobj_attribute *attr, char *buf)
 {
@@ -1949,9 +1641,6 @@ struct attribute *scst_session_attrs[] = {
 	&session_commands_attr.attr,
 	&session_active_commands_attr.attr,
 	&session_initiator_name_attr.attr,
-#ifdef CONFIG_SCST_MEASURE_LATENCY
-	&session_latency_attr.attr,
-#endif /* CONFIG_SCST_MEASURE_LATENCY */
 	NULL,
 };
 
@@ -2010,6 +1699,14 @@ int scst_sess_sysfs_create(struct scst_session *sess)
 	if (res)
 		goto out_free;
 
+	res = scst_sess_debugfs_create(sess);
+	if (res)
+		goto out_free;
+
+	res = scst_sess_lat_create(sess);
+	if (res)
+		goto out_free;
+
 out:
 	return res;
 out_free:
@@ -2019,6 +1716,8 @@ out_free:
 
 void scst_sess_sysfs_del(struct scst_session *sess)
 {
+	scst_sess_lat_remove(sess);
+	scst_sess_debugfs_remove(sess);
 	kobject_del(&sess->sess_kobj);
 }
 
@@ -3183,7 +2882,7 @@ int scst_devt_sysfs_create(struct scst_dev_type *devt)
 		}
 	}
 
-	res = scst_devt_create_trace_files(devt);
+	res = scst_devt_debugfs_create(devt);
 	if (res) {
 		PRINT_ERROR("Can't create tracing files for device type %s",
 			    devt->name);
@@ -3200,7 +2899,7 @@ out_err:
 
 void scst_devt_sysfs_del(struct scst_dev_type *devt)
 {
-	scst_devt_remove_trace_files(devt);
+	scst_devt_debugfs_remove(devt);
 }
 
 void scst_devt_sysfs_put(struct scst_dev_type *devt)
@@ -3854,7 +3553,7 @@ int __init scst_sysfs_init(void)
 		goto out_unregister_device;
 	}
 
-	res = scst_main_create_trace_files();
+	res = scst_main_debugfs_create();
 	if (res) {
 		PRINT_ERROR("%s", "Creating SCST trace files failed.");
 		goto out_remove_files;
@@ -3863,7 +3562,7 @@ int __init scst_sysfs_init(void)
 out:
 	return res;
 
-	scst_main_remove_trace_files();
+	scst_main_debugfs_remove();
 out_remove_files:
 	device_remove_files(scst_device, scst_root_default_attrs);
 out_unregister_device:
@@ -3884,7 +3583,7 @@ void scst_sysfs_cleanup(void)
 {
 	PRINT_INFO("%s", "Exiting SCST sysfs hierarchy...");
 
-	scst_main_remove_trace_files();
+	scst_main_debugfs_remove();
 
 	device_remove_files(scst_device, scst_root_default_attrs);
 
diff --git a/drivers/scst/scst_tracing.c b/drivers/scst/scst_tracing.c
index 9b9aef4..c87597b 100644
--- a/drivers/scst/scst_tracing.c
+++ b/drivers/scst/scst_tracing.c
@@ -24,7 +24,8 @@
 #include "scst_tracing.h"
 
 static struct dentry *scst_debug_root;
-static struct dentry *scst_debug_target;
+static struct dentry *scst_debug_tgtt;
+static struct dentry *scst_debug_tgt;
 static struct dentry *scst_debug_devt;
 static struct dentry *scst_debug_dev;
 static struct dentry *scst_main_tracing_dir;
@@ -167,29 +168,21 @@ static const struct file_operations scst_tracing_fops = {
 	.llseek	=	noop_llseek,
 };
 
-static struct dentry *scst_create_trace_files(struct dentry *root,
-					      const char *dir_name,
+static struct dentry *scst_create_trace_files(struct dentry *dir,
 					      struct scst_trace_data *td)
 {
 	int i;
-	struct dentry *subdir, *tracing_dir, *file;
+	struct dentry *tracing_dir, *file;
 	const struct scst_trace_log *p;
 	const struct scst_trace_log *tracing_table[] = {
 		scst_trace_tbl,
 		td->trace_tbl,
 	};
 
-	BUG_ON(!root);
-	BUG_ON(!dir_name);
+	BUG_ON(!dir);
 	BUG_ON(!td);
 
-	subdir = debugfs_create_dir(dir_name, root);
-	if (!subdir) {
-		PRINT_ERROR("Creation of directory %s failed", dir_name);
-		goto out;
-	}
-
-	tracing_dir = debugfs_create_dir("tracing", subdir);
+	tracing_dir = debugfs_create_dir("tracing", dir);
 	if (!tracing_dir) {
 		PRINT_ERROR("%s", "Creation of tracing dir failed");
 		goto err;
@@ -208,18 +201,13 @@ static struct dentry *scst_create_trace_files(struct dentry *root,
 		}
 	}
 out:
-	return subdir;
+	return tracing_dir;
 err:
-	debugfs_remove_recursive(subdir);
-	subdir = NULL;
+	debugfs_remove_recursive(tracing_dir);
+	tracing_dir = NULL;
 	goto out;
 }
 
-static void scst_remove_trace_files(struct dentry *dir)
-{
-	debugfs_remove_recursive(dir);
-}
-
 int scst_debugfs_init(void)
 {
 	int res;
@@ -238,8 +226,15 @@ int scst_debugfs_init(void)
 		goto err;
 	}
 
-	scst_debug_target = debugfs_create_dir("target", scst_debug_root);
-	if (!scst_debug_target) {
+	scst_debug_tgtt = debugfs_create_dir("target_driver", scst_debug_root);
+	if (!scst_debug_tgtt) {
+		PRINT_ERROR("%s", "Creation of /sys/kernel/debug/scst/"
+			    "target_driver failed");
+		goto err;
+	}
+
+	scst_debug_tgt = debugfs_create_dir("target", scst_debug_root);
+	if (!scst_debug_tgt) {
 		PRINT_ERROR("%s", "Creation of /sys/kernel/debug/scst/target"
 			    " failed");
 		goto err;
@@ -273,57 +268,164 @@ void scst_debugfs_cleanup(void)
 	debugfs_remove_recursive(scst_debug_root);
 	scst_debug_dev = NULL;
 	scst_debug_devt = NULL;
-	scst_debug_target = NULL;
+	scst_debug_tgt = NULL;
+	scst_debug_tgtt = NULL;
 	scst_debug_root = NULL;
 }
 
-int scst_main_create_trace_files(void)
+int scst_main_debugfs_create(void)
 {
-	scst_main_tracing_dir = scst_create_trace_files(scst_debug_root,
-							"main",
-							&scst_main_trace_data);
-	return scst_main_tracing_dir ? 0 : -EINVAL;
+	int res;
+
+	res = -ENOMEM;
+	scst_main_tracing_dir = debugfs_create_dir("main", scst_debug_root);
+	if (!scst_main_tracing_dir)
+		goto out;
+
+	if (!scst_create_trace_files(scst_main_tracing_dir,
+				     &scst_main_trace_data)) {
+		goto out;
+	}
+	res = 0;
+out:
+	return res;
 }
 
-void scst_main_remove_trace_files(void)
+void scst_main_debugfs_remove(void)
 {
-	scst_remove_trace_files(scst_main_tracing_dir);
+	debugfs_remove_recursive(scst_main_tracing_dir);
 	scst_main_tracing_dir = NULL;
 }
 
-int scst_tgtt_create_trace_files(struct scst_tgt_template *tgtt)
+int scst_tgtt_debugfs_create(struct scst_tgt_template *tgtt)
 {
-	if (tgtt->trace_data.trace_flags) {
-		tgtt->tracing_dir = scst_create_trace_files(scst_debug_target,
-							    tgtt->name,
-							    &tgtt->trace_data);
-		if (!tgtt->tracing_dir)
-			return -EINVAL;
+	int res;
+
+	res = -ENOMEM;
+	tgtt->tracing_dir = debugfs_create_dir(tgtt->name, scst_debug_tgtt);
+	if (!tgtt->tracing_dir) {
+		PRINT_ERROR("Creation of directory %s failed", tgtt->name);
+		goto out;
 	}
-	return 0;
+
+	if (tgtt->trace_data.trace_flags &&
+	    !scst_create_trace_files(tgtt->tracing_dir, &tgtt->trace_data)) {
+			res = -ENOMEM;
+			goto out;
+	}
+	res = 0;
+out:
+	return res;
 }
 
-void scst_tgtt_remove_trace_files(struct scst_tgt_template *tgtt)
+void scst_tgtt_debugfs_remove(struct scst_tgt_template *tgtt)
 {
-	scst_remove_trace_files(tgtt->tracing_dir);
+	debugfs_remove_recursive(tgtt->tracing_dir);
 	tgtt->tracing_dir = NULL;
 }
 
-int scst_devt_create_trace_files(struct scst_dev_type *devt)
+int scst_tgt_debugfs_create(struct scst_tgt *tgt)
 {
-	if (devt->trace_data.trace_flags) {
-		devt->tracing_dir = scst_create_trace_files(scst_debug_devt,
-							    devt->name,
-							    &devt->trace_data);
-		if (!devt->tracing_dir)
-			return -EINVAL;
+	int res;
+
+	res = -ENOMEM;
+	tgt->debugfs_dir = debugfs_create_dir(tgt->tgt_name, scst_debug_tgt);
+	if (!tgt->debugfs_dir) {
+		PRINT_ERROR("Creation of directory %s failed", tgt->tgt_name);
+		goto out;
 	}
-	return 0;
+	tgt->sessions_dir = debugfs_create_dir("sessions", tgt->debugfs_dir);
+	if (!tgt->sessions_dir) {
+		PRINT_ERROR("Creation of directory %s/sessions failed",
+			    tgt->tgt_name);
+		goto out;
+	}
+	res = 0;
+out:
+	return res;
+}
+
+void scst_tgt_debugfs_remove(struct scst_tgt *tgt)
+{
+	debugfs_remove_recursive(tgt->debugfs_dir);
+	tgt->debugfs_dir = NULL;
+}
+
+int scst_sess_debugfs_create(struct scst_session *sess)
+{
+	int res;
+
+	res = -ENOMEM;
+	sess->debugfs_dir = debugfs_create_dir(sess->initiator_name,
+					       sess->tgt->sessions_dir);
+	if (!sess->debugfs_dir) {
+		PRINT_ERROR("Creation of directory %s failed",
+			    sess->initiator_name);
+		goto out;
+	}
+	sess->luns_dir = debugfs_create_dir("luns", sess->debugfs_dir);
+	if (!sess->luns_dir) {
+		PRINT_ERROR("Creation of directory %s/sessions failed",
+			    sess->initiator_name);
+		goto out;
+	}
+	res = 0;
+out:
+	return res;
+}
+
+void scst_sess_debugfs_remove(struct scst_session *sess)
+{
+	debugfs_remove_recursive(sess->debugfs_dir);
+	sess->debugfs_dir = NULL;
+}
+
+int scst_tgt_dev_debugfs_create(struct scst_tgt_dev *tgt_dev)
+{
+	int res;
+	char lun[16];
+
+	res = -ENOMEM;
+	snprintf(lun, sizeof(lun), "%llx", tgt_dev->lun);
+	tgt_dev->debugfs_dir = debugfs_create_dir(lun, tgt_dev->sess->luns_dir);
+	if (!tgt_dev->debugfs_dir) {
+		PRINT_ERROR("Creation of directory %s/luns/%s failed",
+			    tgt_dev->sess->initiator_name, lun);
+		goto out;
+	}
+	res = 0;
+out:
+	return res;
+}
+
+void scst_tgt_dev_debugfs_remove(struct scst_tgt_dev *tgt_dev)
+{
+	debugfs_remove_recursive(tgt_dev->debugfs_dir);
+	tgt_dev->debugfs_dir = NULL;
+}
+
+int scst_devt_debugfs_create(struct scst_dev_type *devt)
+{
+	int res;
+
+	res = -ENOMEM;
+	devt->tracing_dir = debugfs_create_dir(devt->name, scst_debug_devt);
+	if (!devt->tracing_dir)
+		goto out;
+	if (devt->trace_data.trace_flags &&
+	    !scst_create_trace_files(devt->tracing_dir, &devt->trace_data))
+		goto err;
+	res = 0;
+out:
+	return res;
+err:
+	scst_devt_debugfs_remove(devt);
+	goto out;
 }
 
-void scst_devt_remove_trace_files(struct scst_dev_type *devt)
+void scst_devt_debugfs_remove(struct scst_dev_type *devt)
 {
-	scst_remove_trace_files(devt->tracing_dir);
+	debugfs_remove_recursive(devt->tracing_dir);
 	devt->tracing_dir = NULL;
 }
 
diff --git a/drivers/scst/scst_tracing.h b/drivers/scst/scst_tracing.h
index 8fd40bd..23b820b 100644
--- a/drivers/scst/scst_tracing.h
+++ b/drivers/scst/scst_tracing.h
@@ -4,12 +4,18 @@
 
 int scst_debugfs_init(void);
 void scst_debugfs_cleanup(void);
-int scst_main_create_trace_files(void);
-void scst_main_remove_trace_files(void);
-int scst_tgtt_create_trace_files(struct scst_tgt_template *tgtt);
-void scst_tgtt_remove_trace_files(struct scst_tgt_template *tgtt);
-int scst_devt_create_trace_files(struct scst_dev_type *devt);
-void scst_devt_remove_trace_files(struct scst_dev_type *devt);
+int scst_main_debugfs_create(void);
+void scst_main_debugfs_remove(void);
+int scst_tgtt_debugfs_create(struct scst_tgt_template *tgtt);
+void scst_tgtt_debugfs_remove(struct scst_tgt_template *tgtt);
+int scst_tgt_debugfs_create(struct scst_tgt *tgtt);
+void scst_tgt_debugfs_remove(struct scst_tgt *tgtt);
+int scst_sess_debugfs_create(struct scst_session *tgtt);
+void scst_sess_debugfs_remove(struct scst_session *tgtt);
+int scst_tgt_dev_debugfs_create(struct scst_tgt_dev *tgtt);
+void scst_tgt_dev_debugfs_remove(struct scst_tgt_dev *tgtt);
+int scst_devt_debugfs_create(struct scst_dev_type *devt);
+void scst_devt_debugfs_remove(struct scst_dev_type *devt);
 int scst_dev_create_debug_files(struct scst_device *dev);
 void scst_dev_remove_debug_files(struct scst_device *dev);
 
@@ -24,30 +30,57 @@ static inline void scst_debugfs_cleanup(void)
 {
 }
 
-static inline int scst_main_create_trace_files(void)
+static inline int scst_main_debugfs_create(void)
 {
 	return 0;
 }
 
-static inline void scst_main_remove_trace_files(void)
+static inline void scst_main_debugfs_remove(void)
 {
 }
 
-static inline int scst_tgtt_create_trace_files(struct scst_tgt_template *tgtt)
+static inline int scst_tgtt_debugfs_create(struct scst_tgt_template *tgtt)
 {
 	return 0;
 }
 
-static inline void scst_tgtt_remove_trace_files(struct scst_tgt_template *tgtt)
+static inline void scst_tgtt_debugfs_remove(struct scst_tgt_template *tgtt)
 {
 }
 
-static inline int scst_devt_create_trace_files(struct scst_dev_type *devt)
+static inline int scst_tgt_debugfs_create(struct scst_tgt *tgtt)
 {
 	return 0;
 }
 
-static inline void scst_devt_remove_trace_files(struct scst_dev_type *devt)
+static inline void scst_tgt_debugfs_remove(struct scst_tgt *tgtt)
+{
+}
+
+static inline int scst_sess_debugfs_create(struct scst_session *tgtt)
+{
+	return 0;
+}
+
+static inline void scst_sess_debugfs_remove(struct scst_session *tgtt)
+{
+}
+
+static inline int scst_tgt_dev_debugfs_create(struct scst_tgt_dev *tgtt)
+{
+	return 0;
+}
+
+static inline void scst_tgt_dev_debugfs_remove(struct scst_tgt_dev *tgtt)
+{
+}
+
+static inline int scst_devt_debugfs_create(struct scst_dev_type *devt)
+{
+	return 0;
+}
+
+static inline void scst_devt_debugfs_remove(struct scst_dev_type *devt)
 {
 }
 
diff --git a/include/scst/scst.h b/include/scst/scst.h
index 9034624..1f59ec1 100644
--- a/include/scst/scst.h
+++ b/include/scst/scst.h
@@ -1316,6 +1316,11 @@ struct scst_tgt {
 	struct kobject *tgt_sess_kobj; /* target/sessions/ */
 	struct kobject *tgt_luns_kobj; /* target/luns/ */
 	struct kobject *tgt_ini_grp_kobj; /* target/ini_groups/ */
+
+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
+	struct dentry *debugfs_dir;
+	struct dentry *sessions_dir;
+#endif
 };
 
 #ifdef CONFIG_SCST_MEASURE_LATENCY
@@ -1449,6 +1454,10 @@ struct scst_session {
 				int result);
 	void (*unreg_done_fn) (struct scst_session *sess);
 
+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
+	struct dentry *debugfs_dir;
+	struct dentry *luns_dir;
+#endif
 #ifdef CONFIG_SCST_MEASURE_LATENCY
 	/*
 	 * Must be the last to allow to work with drivers who don't know
@@ -1460,6 +1469,8 @@ struct scst_session {
 	uint64_t min_scst_time, min_tgt_time, min_dev_time;
 	uint64_t max_scst_time, max_tgt_time, max_dev_time;
 	struct scst_ext_latency_stat sess_latency_stat[SCST_LATENCY_STATS_NUM];
+
+	struct dentry *latency_file;
 #endif
 };
 
@@ -1813,6 +1824,9 @@ struct scst_cmd {
 
 	struct scst_cmd *orig_cmd; /* Used to issue REQUEST SENSE */
 
+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
+	struct dentry *debugfs_dir;
+#endif
 #ifdef CONFIG_SCST_MEASURE_LATENCY
 	/*
 	 * Must be the last to allow to work with drivers who don't know
@@ -1822,6 +1836,8 @@ struct scst_cmd {
 	uint64_t restart_waiting_time, rdy_to_xfer_time;
 	uint64_t pre_exec_time, exec_time, dev_done_time;
 	uint64_t xmit_time, tgt_on_free_time, dev_on_free_time;
+
+	struct dentry *latency_file;
 #endif
 };
 
@@ -2228,6 +2244,9 @@ struct scst_tgt_dev {
 
 	struct kobject tgt_dev_kobj; /* kobject for this struct */
 
+#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
+	struct dentry *debugfs_dir;
+#endif
 #ifdef CONFIG_SCST_MEASURE_LATENCY
 	/*
 	 * Must be the last to allow to work with drivers who don't know
@@ -2238,6 +2257,8 @@ struct scst_tgt_dev {
 	uint64_t scst_time, tgt_time, dev_time;
 	unsigned int processed_cmds;
 	struct scst_ext_latency_stat dev_latency_stat[SCST_LATENCY_STATS_NUM];
+
+	struct dentry *latency_file;
 #endif
 };
 
-- 
1.7.1
^ permalink raw reply related	[flat|nested] 10+ messages in thread
end of thread, other threads:[~2010-12-28 17:23 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-27 13:35 [PATCH 0/8] Address recent SCST comments Bart Van Assche
2010-12-27 13:36 ` [PATCH 1/8] [SCSI] scst: Split sysfs type attribute Bart Van Assche
2010-12-27 13:37 ` [PATCH 2/8] [SCSI] scst: Split version and stats attributes Bart Van Assche
2010-12-27 13:38 ` [PATCH 3/8] [SCSI] scst: Remove [key] marker from sysfs files Bart Van Assche
2010-12-27 13:39 ` [PATCH 4/8] [SCSI] scst: Substitute SCST_SYSFS_BLOCK_SIZE Bart Van Assche
2010-12-27 13:39 ` [PATCH 5/8] [SCSI] scst: Improve sysfs parsing robustness Bart Van Assche
2010-12-27 13:40 ` [PATCH 6/8] [SCSI] scst: Fix online documentation Bart Van Assche
2010-12-27 13:43 ` [PATCH 8/8] Make SCST sysfs documentation more complete Bart Van Assche
2010-12-27 13:46 ` [PATCH 7/8] [SCSI] scst: Correct SCST core version number Bart Van Assche
2010-12-28 17:23 ` [PATCH 0/8] Address recent SCST comments Bart Van Assche
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).