Patch from Smadar Gonen <smadar.gn@gmail.com> implementing extended latency statistics.
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Tue, 29 Sep 2009 20:30:17 +0000 (20:30 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Tue, 29 Sep 2009 20:30:17 +0000 (20:30 +0000)
Intermediate commit, don't use it!

git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1156 d57e44dd-8a1f-0410-8b47-8ef2f437770f

scst/include/scst.h
scst/src/Makefile
scst/src/scst_proc.c
scst/src/scst_targ.c

index c26c409..303285b 100644 (file)
@@ -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
 };
 
index 42b63e7..fe32dd0 100644 (file)
@@ -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, 
index b7d66ca..ca0598d 100644 (file)
@@ -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);
                }
        }
index 4f28898..6b955f0 100644 (file)
@@ -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, "