target: Add counters for ABORT_TASK success + failure
authorNicholas Bellinger <nab@daterainc.com>
Thu, 19 Jan 2017 23:45:57 +0000 (15:45 -0800)
committerNicholas Bellinger <nab@linux-iscsi.org>
Mon, 27 Feb 2017 00:21:06 +0000 (16:21 -0800)
This patch introduces two counters for ABORT_TASK success +
failure under:

   /sys/kernel/config/target/core/$HBA/$DEV/statistics/scsi_tgt_dev/

that are useful for diagnosing various backend device latency
and front fabric issues.

Normally when folks see alot of aborts_complete happening,
it means the backend device I/O completion latency is high,
and not returning completions fast enough before host side
timeouts trigger.

And normally when folks see alot of aborts_no_task, it means
completions are being posted by target-core into fabric driver
code, but the responses aren't making it back to the host.

Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/target/target_core_stat.c
drivers/target/target_core_tmr.c
include/target/target_core_base.h

index be380e4acfcdbbdd49fcef05bf71b7f38d2693b4..8038255b21e874eddeb9d420f5c51a7b67c2821a 100644 (file)
@@ -158,12 +158,28 @@ static ssize_t target_stat_tgt_resets_show(struct config_item *item,
                        atomic_long_read(&to_stat_tgt_dev(item)->num_resets));
 }
 
+static ssize_t target_stat_tgt_aborts_complete_show(struct config_item *item,
+               char *page)
+{
+       return snprintf(page, PAGE_SIZE, "%lu\n",
+                       atomic_long_read(&to_stat_tgt_dev(item)->aborts_complete));
+}
+
+static ssize_t target_stat_tgt_aborts_no_task_show(struct config_item *item,
+               char *page)
+{
+       return snprintf(page, PAGE_SIZE, "%lu\n",
+                       atomic_long_read(&to_stat_tgt_dev(item)->aborts_no_task));
+}
+
 CONFIGFS_ATTR_RO(target_stat_tgt_, inst);
 CONFIGFS_ATTR_RO(target_stat_tgt_, indx);
 CONFIGFS_ATTR_RO(target_stat_tgt_, num_lus);
 CONFIGFS_ATTR_RO(target_stat_tgt_, status);
 CONFIGFS_ATTR_RO(target_stat_tgt_, non_access_lus);
 CONFIGFS_ATTR_RO(target_stat_tgt_, resets);
+CONFIGFS_ATTR_RO(target_stat_tgt_, aborts_complete);
+CONFIGFS_ATTR_RO(target_stat_tgt_, aborts_no_task);
 
 static struct configfs_attribute *target_stat_scsi_tgt_dev_attrs[] = {
        &target_stat_tgt_attr_inst,
@@ -172,6 +188,8 @@ static struct configfs_attribute *target_stat_scsi_tgt_dev_attrs[] = {
        &target_stat_tgt_attr_status,
        &target_stat_tgt_attr_non_access_lus,
        &target_stat_tgt_attr_resets,
+       &target_stat_tgt_attr_aborts_complete,
+       &target_stat_tgt_attr_aborts_no_task,
        NULL,
 };
 
index a806d9bca3d2aac185139ddf797a43fb623ddad5..dce1e1b47316173329292f90276843d26d32407b 100644 (file)
@@ -190,6 +190,7 @@ void core_tmr_abort_task(
                printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
                                " ref_tag: %llu\n", ref_tag);
                tmr->response = TMR_FUNCTION_COMPLETE;
+               atomic_long_inc(&dev->aborts_complete);
                return;
        }
        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
@@ -197,6 +198,7 @@ void core_tmr_abort_task(
        printk("ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: %lld\n",
                        tmr->ref_task_tag);
        tmr->response = TMR_TASK_DOES_NOT_EXIST;
+       atomic_long_inc(&dev->aborts_no_task);
 }
 
 static void core_tmr_drain_tmr_list(
index 16d3be8395bebb562e1b8601fca15868f79fd577..49ce5bc9912fb49f44720344d0f8b035aeededb8 100644 (file)
@@ -766,6 +766,8 @@ struct se_device {
        u32                     dev_index;
        u64                     creation_time;
        atomic_long_t           num_resets;
+       atomic_long_t           aborts_complete;
+       atomic_long_t           aborts_no_task;
        atomic_long_t           num_cmds;
        atomic_long_t           read_bytes;
        atomic_long_t           write_bytes;