public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Martin Peschke <mp3@de.ibm.com>
To: linux-kernel@vger.kernel.org
Cc: akpm@osdl.org, ak@suse.de, hch@infradead.org,
	arjan@infradead.org, James.Smart@Emulex.Com,
	James.Bottomley@SteelEye.com
Subject: [RFC] [Patch 8/8] statistics infrastructure - exploitation: scsi
Date: Tue, 16 May 2006 19:48:03 +0200	[thread overview]
Message-ID: <446A1053.9010902@de.ibm.com> (raw)

This patch is obviously broken.
It get's me latencies, request sizes and information about
TCQ utilisation, though.

Problem is that creating statistics requires process contexts,
mostly because we create debugfs directories and files.
SCSI device creation, and therewith SCSI device statistics
creation, doesn't provide process context. I think it's very
unfortunate that scsi_allocate_sdev isn't capable of being
interrupted by the scheduler.

Besides, I was surprised to see the scsi mid layer remove
a few sdev's (or their statistics, to be precise) twice.

I am quite sure my instrumentation of the SCSI mid layer is
far from perfect (additions of statistic_add & friends).
I would appriciate hints for refinements from the SCSI experts.

Signed-off-by: Martin Peschke <mp3@de.ibm.com>
---

  drivers/scsi/scsi_lib.c    |   33 ++++++++++++++++++++++++++++++++-
  drivers/scsi/scsi_scan.c   |   35 ++++++++++++++++++++++++++++++++++-
  drivers/scsi/scsi_sysfs.c  |    2 ++
  include/scsi/scsi_cmnd.h   |    2 ++
  include/scsi/scsi_device.h |   16 ++++++++++++++++
  5 files changed, 86 insertions(+), 2 deletions(-)

diff -Nurp a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	2006-05-15 12:42:10.000000000 +0200
+++ b/drivers/scsi/scsi_lib.c	2006-05-15 15:43:33.000000000 +0200
@@ -1522,6 +1522,35 @@ static void scsi_kill_request(struct req
  	__scsi_done(cmd);
  }

+static void scsi_stat_completion(struct scsi_cmnd *cmd, int disposition)
+{
+#ifdef CONFIG_STATISTICS
+	struct statistic *stat = cmd->device->stat;
+	unsigned size = cmd->request_bufflen;
+	long long unsigned latency = cmd->received - cmd->issued;
+	unsigned long flags;
+
+	do_div(latency, 1000000);
+	latency++;
+
+	get_cpu();
+	local_irq_save(flags);
+	statistic_inc_nolock(stat, SCSI_STAT_U_R, cmd->result);
+	if (cmd->sc_data_direction == DMA_TO_DEVICE) {
+		statistic_inc_nolock(stat, SCSI_STAT_U_SW, size);
+		statistic_inc_nolock(stat, SCSI_STAT_U_LW, latency);
+	} else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
+		statistic_inc_nolock(stat, SCSI_STAT_U_SR, size);
+		statistic_inc_nolock(stat, SCSI_STAT_U_LR, latency);
+	} else if (cmd->sc_data_direction == DMA_NONE) {
+		statistic_inc_nolock(stat, SCSI_STAT_U_SN, size);
+		statistic_inc_nolock(stat, SCSI_STAT_U_LN, latency);
+	}
+	local_irq_restore(flags);
+	put_cpu();
+#endif
+}
+
  static void scsi_softirq_done(struct request *rq)
  {
  	struct scsi_cmnd *cmd = rq->completion_data;
@@ -1538,7 +1567,8 @@ static void scsi_softirq_done(struct req
  			    wait_for/HZ);
  		disposition = SUCCESS;
  	}
-			
+
+	scsi_stat_completion(cmd, disposition);
  	scsi_log_completion(cmd, disposition);

  	switch (disposition) {
@@ -1616,6 +1646,7 @@ static void scsi_request_fn(struct reque
  		if (!(blk_queue_tagged(q) && !blk_queue_start_tag(q, req)))
  			blkdev_dequeue_request(req);
  		sdev->device_busy++;
+		statistic_inc(sdev->stat, SCSI_STAT_U_QUD, sdev->device_busy);

  		spin_unlock(q->queue_lock);
  		cmd = req->special;
diff -Nurp a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	2006-05-15 19:29:27.000000000 +0200
+++ b/drivers/scsi/scsi_scan.c	2006-05-15 19:30:14.000000000 +0200
@@ -187,6 +187,28 @@ static void print_inquiry(unsigned char
  		printk("\n");
  }

+static struct statistic_info scsi_statinfo_u[] = {
+	{ /* SCSI_STAT_U_SW */
+	  "size_write", "bytes", "request", 0, "type=sparse entries=256"},
+	{ /* SCSI_STAT_U_SR */
+	  "size_read", "bytes", "request", 0, "type=sparse entries=256"},
+	{ /* SCSI_STAT_U_SN */
+	  "size_nodata", "bytes", "request", 0, "type=counter_inc"},
+	{ /* SCSI_STAT_U_LW */
+	  "latency_write", "msec", "request", 0,
+	  "type=histogram_log2 entries=13 base_interval=1 range_min=0"},
+	{ /* SCSI_STAT_U_LR */
+	  "latency_read", "msec", "request", 0,
+	  "type=histogram_log2 entries=13 base_interval=1 range_min=0"},
+	{ /* SCSI_STAT_U_LN */
+	  "latency_nodata", "msec", "request", 0,
+	  "type=histogram_log2 entries=13 base_interval=1 range_min=0"},
+	{ /* SCSI_STAT_U_R */
+	  "result", "", "", 0, "type=sparse entries=256" },
+	{ /* SCSI_STAT_U_QUD */
+	  "queue_used_depth", "requests", "", 0, "type=utilisation" },
+};
+
  /**
   * scsi_alloc_sdev - allocate and setup a scsi_Device
   *
@@ -204,6 +226,7 @@ static struct scsi_device *scsi_alloc_sd
  	struct scsi_device *sdev;
  	int display_failure_msg = 1, ret;
  	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	char name[64];

  	sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size,
  		       GFP_ATOMIC);
@@ -260,6 +283,14 @@ static struct scsi_device *scsi_alloc_sd

  	scsi_sysfs_device_initialize(sdev);

+	sprintf(name, "scsi-%d:%d:%d:%d", sdev->host->host_no, sdev->channel,
+		sdev->id, sdev->lun);
+	sdev->stat_if.stat = sdev->stat;
+	sdev->stat_if.info = scsi_statinfo_u;
+	sdev->stat_if.number = _SCSI_STAT_U_NUMBER;
+	if (statistic_create(&sdev->stat_if, name))
+		goto out_device_destroy;
+
  	if (shost->hostt->slave_alloc) {
  		ret = shost->hostt->slave_alloc(sdev);
  		if (ret) {
@@ -269,12 +300,14 @@ static struct scsi_device *scsi_alloc_sd
  			 */
  			if (ret == -ENXIO)
  				display_failure_msg = 0;
-			goto out_device_destroy;
+			goto out_stat_destroy;
  		}
  	}

  	return sdev;

+out_stat_destroy:
+	statistic_remove(&sdev->stat_if);
  out_device_destroy:
  	transport_destroy_device(&sdev->sdev_gendev);
  	put_device(&sdev->sdev_gendev);
diff -Nurp a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
--- a/drivers/scsi/scsi_sysfs.c	2006-05-15 12:42:10.000000000 +0200
+++ b/drivers/scsi/scsi_sysfs.c	2006-05-15 15:49:15.000000000 +0200
@@ -247,6 +247,8 @@ static void scsi_device_dev_release_user

  	scsi_target_reap(scsi_target(sdev));

+	statistic_remove(&sdev->stat_if);
+
  	kfree(sdev->inquiry);
  	kfree(sdev);

diff -Nurp a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
--- a/include/scsi/scsi_cmnd.h	2006-05-15 12:42:12.000000000 +0200
+++ b/include/scsi/scsi_cmnd.h	2006-05-15 16:04:10.000000000 +0200
@@ -58,6 +58,8 @@ struct scsi_cmnd {
  	 * been outstanding
  	 */
  	unsigned long jiffies_at_alloc;
+	unsigned long long issued;	/* sched_clock() */
+	unsigned long long received;	/* ditto */

  	int retries;
  	int allowed;
diff -Nurp a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
--- a/include/scsi/scsi_device.h	2006-05-15 12:42:12.000000000 +0200
+++ b/include/scsi/scsi_device.h	2006-05-15 16:06:13.000000000 +0200
@@ -5,6 +5,7 @@
  #include <linux/list.h>
  #include <linux/spinlock.h>
  #include <linux/workqueue.h>
+#include <linux/statistic.h>
  #include <asm/atomic.h>

  struct request_queue;
@@ -45,6 +46,18 @@ enum scsi_device_state {
  				 * to the scsi lld. */
  };

+enum scsi_unit_stats {
+	SCSI_STAT_U_SW,		/* size, write */
+	SCSI_STAT_U_SR,		/* size, read */
+	SCSI_STAT_U_SN,		/* size, no data */
+	SCSI_STAT_U_LW,		/* latency, write */
+	SCSI_STAT_U_LR,		/* latency, read */
+	SCSI_STAT_U_LN,		/* latency, no data */
+	SCSI_STAT_U_R,		/* result */
+	SCSI_STAT_U_QUD,	/* queue used depth */
+	_SCSI_STAT_U_NUMBER,
+};
+
  struct scsi_device {
  	struct Scsi_Host *host;
  	struct request_queue *request_queue;
@@ -133,6 +146,9 @@ struct scsi_device {
  	atomic_t iodone_cnt;
  	atomic_t ioerr_cnt;

+	struct statistic_interface stat_if;
+	struct statistic           stat[_SCSI_STAT_U_NUMBER];
+
  	int timeout;

  	struct device		sdev_gendev;


                 reply	other threads:[~2006-05-16 17:48 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=446A1053.9010902@de.ibm.com \
    --to=mp3@de.ibm.com \
    --cc=James.Bottomley@SteelEye.com \
    --cc=James.Smart@Emulex.Com \
    --cc=ak@suse.de \
    --cc=akpm@osdl.org \
    --cc=arjan@infradead.org \
    --cc=hch@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox