From c87ba9c49c1fa86261448b09c5f1b2223bf7efd9 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 19 Jan 2017 15:45:57 -0800 Subject: [PATCH] target: Add counters for ABORT_TASK success + failure 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 --- drivers/target/target_core_stat.c | 18 ++++++++++++++++++ drivers/target/target_core_tmr.c | 2 ++ include/target/target_core_base.h | 2 ++ 3 files changed, 22 insertions(+) diff --git a/drivers/target/target_core_stat.c b/drivers/target/target_core_stat.c index be380e4acfcd..8038255b21e8 100644 --- a/drivers/target/target_core_stat.c +++ b/drivers/target/target_core_stat.c @@ -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, }; diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index a806d9bca3d2..dce1e1b47316 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -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( diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 16d3be8395be..49ce5bc9912f 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -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;