From 21aeb806ff0d86fa6c087f2114852d20e9964dc8 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Tue, 29 Sep 2009 20:30:17 +0000 Subject: [PATCH] Patch from Smadar Gonen implementing extended latency statistics. Intermediate commit, don't use it! git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1156 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scst.h | 28 ++++++++++++++++ scst/src/Makefile | 1 + scst/src/scst_proc.c | 76 ++++++++++++++++++++++++++++++++++++++------ scst/src/scst_targ.c | 47 ++++++++++++++++++++++++++- 4 files changed, 142 insertions(+), 10 deletions(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index c26c4091a..303285b33 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -1029,6 +1029,31 @@ struct scst_tgt { #define TGT_DEV_HASH_SIZE (1 << TGT_DEV_HASH_SHIFT) #define HASH_VAL(_val) (_val & (TGT_DEV_HASH_SIZE - 1)) +#ifdef CONFIG_SCST_MEASURE_LATENCY_EXT +/*define the structure for extended latency statistics*/ +struct scst_latency_stat { + uint64_t scst_time_wr; + uint64_t scst_time_rd; + uint64_t processing_time_wr; + uint64_t processing_time_rd; + unsigned int processed_cmds_wr; + unsigned int processed_cmds_rd; +}; + +#define SCST_IO_SIZE_THRESHOLD_SMALL (8*1024) +#define SCST_IO_SIZE_THRESHOLD_MEDIUM (32*1024) +#define SCST_IO_SIZE_THRESHOLD_LARGE (128*1024) +#define SCST_IO_SIZE_THRESHOLD_VERY_LARGE (512*1024) + +#define SCST_LATENCY_STAT_INDEX_SMALL 0 +#define SCST_LATENCY_STAT_INDEX_MEDIUM 1 +#define SCST_LATENCY_STAT_INDEX_LARGE 2 +#define SCST_LATENCY_STAT_INDEX_VERY_LARGE 3 +#define SCST_LATENCY_STAT_INDEX_OTHER 4 +#define SCST_LATENCY_NUM_OF_THRESHOLDS 5 + +#endif + struct scst_session { /* * Initialization phase, one of SCST_SESS_IPH_* constants, protected by @@ -1128,6 +1153,9 @@ struct scst_session { spinlock_t meas_lock; uint64_t scst_time, processing_time; unsigned int processed_cmds; +#ifdef CONFIG_SCST_MEASURE_LATENCY_EXT + struct scst_latency_stat latency_stat[SCST_LATENCY_NUM_OF_THRESHOLDS]; +#endif #endif }; diff --git a/scst/src/Makefile b/scst/src/Makefile index 42b63e769..fe32dd015 100644 --- a/scst/src/Makefile +++ b/scst/src/Makefile @@ -134,6 +134,7 @@ EXTRA_CFLAGS += -DCONFIG_SCST_DEBUG -g #EXTRA_CFLAGS += -DCONFIG_SCST_DEBUG_SN #EXTRA_CFLAGS += -DCONFIG_SCST_MEASURE_LATENCY +#EXTRA_CFLAGS += -DCONFIG_SCST_MEASURE_LATENCY_EXT # If defined, makes SCST zero allocated data buffers. # Undefining it considerably improves performance and eases CPU load, diff --git a/scst/src/scst_proc.c b/scst/src/scst_proc.c index b7d66ca17..ca0598d2d 100644 --- a/scst/src/scst_proc.c +++ b/scst/src/scst_proc.c @@ -412,6 +412,14 @@ out: #ifdef CONFIG_SCST_MEASURE_LATENCY +#ifdef CONFIG_SCST_MEASURE_LATENCY_EXT +static char *scst_io_size_names[] = { "<=8K ", + "<=32K ", + "<=128K", + "<=512K", + ">512K " }; +#endif + static int lat_info_show(struct seq_file *seq, void *v) { int res = 0; @@ -425,10 +433,10 @@ static int lat_info_show(struct seq_file *seq, void *v) goto out; } - seq_printf(seq, "%-20s %-45s %-15s %15s\n", - "Target name", - "Initiator name", - "SCST latency", + seq_printf(seq, "%-30s %-15s %-15s %-15s\n", + "T-L names", + "Total commands", + "SCST latenct", "Processing latency (ns)"); list_for_each_entry(acg, &scst_acg_list, scst_acg_list_entry) { @@ -437,8 +445,51 @@ static int lat_info_show(struct seq_file *seq, void *v) unsigned long proc_lat = 0, scst_lat = 0; uint64_t proc_time, scst_time; unsigned int processed_cmds; +#ifdef CONFIG_SCST_MEASURE_LATENCY_EXT + uint64_t proc_time_rd, scst_time_rd; + unsigned int processed_cmds_rd; + unsigned int i; + struct scst_latency_stat *latency_stat; +#endif + + seq_printf(seq, + "Target name: %s \nInitiator name: %s\n", + sess->tgt->tgtt->name, + sess->initiator_name); spin_lock_bh(&sess->meas_lock); +#ifdef CONFIG_SCST_MEASURE_LATENCY_EXT + for (i = 0; i <= SCST_LATENCY_STAT_INDEX_OTHER ; i++) { + latency_stat = &sess->latency_stat[i]; + proc_time = + latency_stat->processing_time_wr; + proc_time_rd = + latency_stat->processing_time_rd; + scst_time = + latency_stat->scst_time_wr; + scst_time_rd = + latency_stat->scst_time_rd; + processed_cmds = + latency_stat->processed_cmds_wr; + processed_cmds_rd = + latency_stat->processed_cmds_rd; + + seq_printf(seq, + "%-5s %-24s %-15ld %-15ld %-15ld\n", + "Write", + scst_io_size_names[i], + (unsigned long)processed_cmds, + (unsigned long)scst_time, + (unsigned long)proc_time); + seq_printf(seq, + "%-5s %-24s %-15ld %-15ld %-15ld\n", + "Read", + scst_io_size_names[i], + (unsigned long)processed_cmds_rd, + (unsigned long)scst_time_rd, + (unsigned long)proc_time_rd); + } +#endif proc_time = sess->processing_time; scst_time = sess->scst_time; processed_cmds = sess->processed_cmds; @@ -459,17 +510,19 @@ static int lat_info_show(struct seq_file *seq, void *v) } #endif - if (sess->processed_cmds != 0) { + if (processed_cmds != 0) { proc_lat = (unsigned long)proc_time / processed_cmds; scst_lat = (unsigned long)scst_time / processed_cmds; } - seq_printf(seq, "%-20s %-45s %-15ld %-15ld\n", - sess->tgt->tgtt->name, - sess->initiator_name, - scst_lat, proc_lat); + seq_printf(seq, + "%-30s %-15d %-15ld %-15ld\n\n", + "Average", + processed_cmds, + scst_lat, + proc_lat); } } @@ -505,6 +558,11 @@ static ssize_t scst_proc_scsi_tgt_gen_write_lat(struct file *file, sess->processing_time = 0; sess->scst_time = 0; sess->processed_cmds = 0; +#ifdef CONFIG_SCST_MEASURE_LATENCY_EXT + memset(sess->latency_stat, + 0, + sizeof(sess->latency_stat)); +#endif spin_unlock_bh(&sess->meas_lock); } } diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 4f28898e7..6b955f09b 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -2938,20 +2938,65 @@ out: { struct timespec ts; uint64_t finish, scst_time, proc_time; + struct scst_session *sess = cmd->sess; +#ifdef CONFIG_SCST_MEASURE_LATENCY_EXT + int data_len; + int i; + struct scst_latency_stat *latency_stat; +#endif ktime_get_ts(&ts); finish = scst_sec_to_nsec(ts.tv_sec) + ts.tv_nsec; - spin_lock_bh(&sess->meas_lock); +#ifdef CONFIG_SCST_MEASURE_LATENCY_EXT + /* Determine the IO size for extended latency statistics*/ + data_len = cmd->data_len; + i = SCST_LATENCY_STAT_INDEX_OTHER; + if (data_len <= SCST_IO_SIZE_THRESHOLD_SMALL) + i = SCST_LATENCY_STAT_INDEX_SMALL; + else if (data_len <= SCST_IO_SIZE_THRESHOLD_MEDIUM) + i = SCST_LATENCY_STAT_INDEX_MEDIUM; + else if (data_len <= SCST_IO_SIZE_THRESHOLD_LARGE) + i = SCST_LATENCY_STAT_INDEX_LARGE; + else if (data_len <= SCST_IO_SIZE_THRESHOLD_VERY_LARGE) + i = SCST_LATENCY_STAT_INDEX_VERY_LARGE; + latency_stat = &sess->latency_stat[i]; +#endif + spin_lock_bh(&sess->meas_lock); + /* Calculate the latencies */ scst_time = cmd->pre_exec_finish - cmd->start; scst_time += finish - cmd->post_exec_start; proc_time = finish - cmd->start; + /* Save the basic latency information */ sess->scst_time += scst_time; sess->processing_time += proc_time; sess->processed_cmds++; +#ifdef CONFIG_SCST_MEASURE_LATENCY_EXT + /* Save the extended latency information */ + switch (cmd->cdb[0]) { + case READ_6: + case READ_10: + case READ_12: + latency_stat->scst_time_rd += scst_time; + latency_stat->processing_time_rd += proc_time; + latency_stat->processed_cmds_rd++; + break; + case WRITE_6: + case WRITE_10: + case WRITE_12: + case WRITE_VERIFY: + case WRITE_VERIFY_12: + latency_stat->scst_time_wr += scst_time; + latency_stat->processing_time_wr += proc_time; + latency_stat->processed_cmds_wr++; + break; + default: + break; + } +#endif spin_unlock_bh(&sess->meas_lock); TRACE_DBG("cmd %p (sess %p): finish %lld (tv_sec %ld, "