All of lore.kernel.org
 help / color / mirror / Atom feed
* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.