diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index 6d7ed2f1c..c7e08ab7d 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -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, };