[PATCH 2/2] scst_sysfs: Add I/O statistics per target

Although it is possible to obtain these statistics by iterating over
all sessions and by computing the sum of the per-target statistics,
make per-target statistics directly available such that these can be
retrieved easily.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5249 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2014-01-30 01:41:54 +00:00
parent c905b530b7
commit 927748befa

View File

@@ -2400,12 +2400,88 @@ out:
}
EXPORT_SYMBOL(scst_create_tgt_attr);
#define SCST_TGT_SYSFS_STAT_ATTR(member_name, attr, dir, result_op) \
static int scst_tgt_sysfs_##attr##_show_work_fn( \
struct scst_sysfs_work_item *work) \
{ \
struct scst_tgt *tgt = work->tgt; \
struct scst_session *sess; \
int res; \
uint64_t c = 0; \
\
BUILD_BUG_ON((unsigned)(dir) >= ARRAY_SIZE(sess->io_stats)); \
\
res = mutex_lock_interruptible(&scst_mutex); \
if (res) \
goto out; \
list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) \
c += sess->io_stats[(dir)].member_name; \
mutex_unlock(&scst_mutex); \
\
work->res_buf = kasprintf(GFP_KERNEL, "%llu\n", c result_op); \
res = work->res_buf ? 0 : -ENOMEM; \
\
out: \
kobject_put(&tgt->tgt_kobj); \
return res; \
} \
\
static ssize_t scst_tgt_sysfs_##attr##_show(struct kobject *kobj, \
struct kobj_attribute *attr, \
char *buf) \
{ \
struct scst_tgt *tgt = \
container_of(kobj, struct scst_tgt, tgt_kobj); \
struct scst_sysfs_work_item *work; \
int res; \
\
res = scst_alloc_sysfs_work(scst_tgt_sysfs_##attr##_show_work_fn, \
true, &work); \
if (res) \
goto out; \
\
work->tgt = tgt; \
SCST_SET_DEP_MAP(work, &scst_tgt_dep_map); \
kobject_get(&tgt->tgt_kobj); \
scst_sysfs_work_get(work); \
res = scst_sysfs_queue_wait_work(work); \
if (res == 0) \
res = scnprintf(buf, PAGE_SIZE, "%s", work->res_buf); \
scst_sysfs_work_put(work); \
\
out: \
return res; \
} \
\
static struct kobj_attribute scst_tgt_##attr##_attr = \
__ATTR(attr, S_IRUGO, scst_tgt_sysfs_##attr##_show, NULL);
SCST_TGT_SYSFS_STAT_ATTR(cmd_count, unknown_cmd_count, SCST_DATA_UNKNOWN, >> 0);
SCST_TGT_SYSFS_STAT_ATTR(cmd_count, write_cmd_count, SCST_DATA_WRITE, >> 0);
SCST_TGT_SYSFS_STAT_ATTR(io_byte_count, write_io_count_kb, SCST_DATA_WRITE,
>> 10);
SCST_TGT_SYSFS_STAT_ATTR(cmd_count, read_cmd_count, SCST_DATA_READ, >> 0);
SCST_TGT_SYSFS_STAT_ATTR(io_byte_count, read_io_count_kb, SCST_DATA_READ,
>> 10);
SCST_TGT_SYSFS_STAT_ATTR(cmd_count, bidi_cmd_count, SCST_DATA_BIDI, >> 0);
SCST_TGT_SYSFS_STAT_ATTR(io_byte_count, bidi_io_count_kb, SCST_DATA_BIDI,
>> 10);
SCST_TGT_SYSFS_STAT_ATTR(cmd_count, none_cmd_count, SCST_DATA_NONE, >> 0);
static struct attribute *scst_tgt_attrs[] = {
&scst_rel_tgt_id.attr,
&scst_tgt_comment.attr,
&scst_tgt_addr_method.attr,
&scst_tgt_io_grouping_type.attr,
&scst_tgt_cpu_mask.attr,
&scst_tgt_unknown_cmd_count_attr.attr,
&scst_tgt_write_cmd_count_attr.attr,
&scst_tgt_write_io_count_kb_attr.attr,
&scst_tgt_read_cmd_count_attr.attr,
&scst_tgt_read_io_count_kb_attr.attr,
&scst_tgt_bidi_cmd_count_attr.attr,
&scst_tgt_bidi_io_count_kb_attr.attr,
&scst_tgt_none_cmd_count_attr.attr,
NULL,
};