scsi: target: Create and use macro helpers for per-CPU stats

Create some macros to reduce code duplication for when we handle per-CPU
stats. Convert the existing LUN and auth cases.

Note: This is similar to percpu_counters but they only support s64 since
they are also used for non-stat counters where you need to handle/prevent
rollover more gracefully. Our use is just for stats where the spec
defines u64 use plus we already have some files exporting u64 values so
it's not possible to directly use percpu_counters.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
Reviewed-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
Link: https://patch.msgid.link/20250917221338.14813-3-michael.christie@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Mike Christie
2025-09-17 17:12:54 -05:00
committed by Martin K. Petersen
parent 95aa2041c6
commit ed6b97a795

View File

@@ -276,56 +276,39 @@ static ssize_t target_stat_lu_state_bit_show(struct config_item *item,
return snprintf(page, PAGE_SIZE, "exposed\n");
}
static ssize_t target_stat_lu_num_cmds_show(struct config_item *item,
char *page)
{
struct se_device *dev = to_stat_lu_dev(item);
struct se_dev_io_stats *stats;
unsigned int cpu;
u64 cmds = 0;
for_each_possible_cpu(cpu) {
stats = per_cpu_ptr(dev->stats, cpu);
cmds += stats->total_cmds;
}
/* scsiLuNumCommands */
return snprintf(page, PAGE_SIZE, "%llu\n", cmds);
#define per_cpu_stat_snprintf(stats_struct, prefix, field, shift) \
static ssize_t \
per_cpu_stat_##prefix##_snprintf(struct stats_struct __percpu *per_cpu_stats, \
char *page) \
{ \
struct stats_struct *stats; \
unsigned int cpu; \
u64 sum = 0; \
\
for_each_possible_cpu(cpu) { \
stats = per_cpu_ptr(per_cpu_stats, cpu); \
sum += stats->field; \
} \
\
return snprintf(page, PAGE_SIZE, "%llu\n", sum >> shift); \
}
static ssize_t target_stat_lu_read_mbytes_show(struct config_item *item,
char *page)
{
struct se_device *dev = to_stat_lu_dev(item);
struct se_dev_io_stats *stats;
unsigned int cpu;
u64 bytes = 0;
#define lu_show_per_cpu_stat(prefix, field, shift) \
per_cpu_stat_snprintf(se_dev_io_stats, prefix, field, shift); \
static ssize_t \
target_stat_##prefix##_show(struct config_item *item, char *page) \
{ \
struct se_device *dev = to_stat_lu_dev(item); \
\
return per_cpu_stat_##prefix##_snprintf(dev->stats, page); \
} \
for_each_possible_cpu(cpu) {
stats = per_cpu_ptr(dev->stats, cpu);
bytes += stats->read_bytes;
}
/* scsiLuReadMegaBytes */
return snprintf(page, PAGE_SIZE, "%llu\n", bytes >> 20);
}
static ssize_t target_stat_lu_write_mbytes_show(struct config_item *item,
char *page)
{
struct se_device *dev = to_stat_lu_dev(item);
struct se_dev_io_stats *stats;
unsigned int cpu;
u64 bytes = 0;
for_each_possible_cpu(cpu) {
stats = per_cpu_ptr(dev->stats, cpu);
bytes += stats->write_bytes;
}
/* scsiLuWrittenMegaBytes */
return snprintf(page, PAGE_SIZE, "%llu\n", bytes >> 20);
}
/* scsiLuNumCommands */
lu_show_per_cpu_stat(lu_num_cmds, total_cmds, 0);
/* scsiLuReadMegaBytes */
lu_show_per_cpu_stat(lu_read_mbytes, read_bytes, 20);
/* scsiLuWrittenMegaBytes */
lu_show_per_cpu_stat(lu_write_mbytes, write_bytes, 20);
static ssize_t target_stat_lu_resets_show(struct config_item *item, char *page)
{
@@ -1035,92 +1018,34 @@ static ssize_t target_stat_auth_att_count_show(struct config_item *item,
return ret;
}
static ssize_t target_stat_auth_num_cmds_show(struct config_item *item,
char *page)
{
struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry_io_stats *stats;
struct se_dev_entry *deve;
unsigned int cpu;
ssize_t ret;
u64 cmds = 0;
rcu_read_lock();
deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve) {
rcu_read_unlock();
return -ENODEV;
}
for_each_possible_cpu(cpu) {
stats = per_cpu_ptr(deve->stats, cpu);
cmds += stats->total_cmds;
}
/* scsiAuthIntrOutCommands */
ret = snprintf(page, PAGE_SIZE, "%llu\n", cmds);
rcu_read_unlock();
return ret;
#define auth_show_per_cpu_stat(prefix, field, shift) \
per_cpu_stat_snprintf(se_dev_entry_io_stats, prefix, field, shift); \
static ssize_t \
target_stat_##prefix##_show(struct config_item *item, char *page) \
{ \
struct se_lun_acl *lacl = auth_to_lacl(item); \
struct se_node_acl *nacl = lacl->se_lun_nacl; \
struct se_dev_entry *deve; \
int ret; \
\
rcu_read_lock(); \
deve = target_nacl_find_deve(nacl, lacl->mapped_lun); \
if (!deve) { \
rcu_read_unlock(); \
return -ENODEV; \
} \
\
ret = per_cpu_stat_##prefix##_snprintf(deve->stats, page); \
rcu_read_unlock(); \
return ret; \
}
static ssize_t target_stat_auth_read_mbytes_show(struct config_item *item,
char *page)
{
struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry_io_stats *stats;
struct se_dev_entry *deve;
unsigned int cpu;
ssize_t ret;
u64 bytes = 0;
rcu_read_lock();
deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve) {
rcu_read_unlock();
return -ENODEV;
}
for_each_possible_cpu(cpu) {
stats = per_cpu_ptr(deve->stats, cpu);
bytes += stats->read_bytes;
}
/* scsiAuthIntrReadMegaBytes */
ret = snprintf(page, PAGE_SIZE, "%llu\n", bytes >> 20);
rcu_read_unlock();
return ret;
}
static ssize_t target_stat_auth_write_mbytes_show(struct config_item *item,
char *page)
{
struct se_lun_acl *lacl = auth_to_lacl(item);
struct se_node_acl *nacl = lacl->se_lun_nacl;
struct se_dev_entry_io_stats *stats;
struct se_dev_entry *deve;
unsigned int cpu;
ssize_t ret;
u64 bytes = 0;
rcu_read_lock();
deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve) {
rcu_read_unlock();
return -ENODEV;
}
for_each_possible_cpu(cpu) {
stats = per_cpu_ptr(deve->stats, cpu);
bytes += stats->write_bytes;
}
/* scsiAuthIntrWrittenMegaBytes */
ret = snprintf(page, PAGE_SIZE, "%llu\n", bytes >> 20);
rcu_read_unlock();
return ret;
}
/* scsiAuthIntrOutCommands */
auth_show_per_cpu_stat(auth_num_cmds, total_cmds, 0);
/* scsiAuthIntrReadMegaBytes */
auth_show_per_cpu_stat(auth_read_mbytes, read_bytes, 20);
/* scsiAuthIntrWrittenMegaBytes */
auth_show_per_cpu_stat(auth_write_mbytes, write_bytes, 20);
static ssize_t target_stat_auth_hs_num_cmds_show(struct config_item *item,
char *page)