Skip to content

Commit bb8222b

Browse files
Merge patch series "target: RW/num_cmds stats improvements"
Mike Christie <michael.christie@oracle.com> says: The following patches were made over Linus tree. They fix/improve the stats used in the main IO path. The first patch fixes an issue where I made some stats u32 when they should have stayed u64. The rest of the patches improve the handling of RW/num_cmds stats to reduce code duplication and improve performance. Link: https://patch.msgid.link/20250917221338.14813-1-michael.christie@oracle.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2 parents 867e4b1 + bbb4900 commit bb8222b

7 files changed

Lines changed: 134 additions & 203 deletions

File tree

drivers/target/target_core_device.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
814814
dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN;
815815
dev->dev_attrib.submit_type = TARGET_FABRIC_DEFAULT_SUBMIT;
816816

817+
/* Skip allocating lun_stats since we can't export them. */
817818
xcopy_lun = &dev->xcopy_lun;
818819
rcu_assign_pointer(xcopy_lun->lun_se_dev, dev);
819820
init_completion(&xcopy_lun->lun_shutdown_comp);

drivers/target/target_core_fabric_configfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ static void target_fabric_port_release(struct config_item *item)
697697
struct se_lun *lun = container_of(to_config_group(item),
698698
struct se_lun, lun_group);
699699

700-
kfree_rcu(lun, rcu_head);
700+
call_rcu(&lun->rcu_head, target_tpg_free_lun);
701701
}
702702

703703
static struct configfs_item_operations target_fabric_port_item_ops = {

drivers/target/target_core_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ void core_tpg_add_node_to_devs(struct se_node_acl *, struct se_portal_group *,
125125
struct se_lun *);
126126
void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *);
127127
struct se_lun *core_tpg_alloc_lun(struct se_portal_group *, u64);
128+
void target_tpg_free_lun(struct rcu_head *head);
128129
int core_tpg_add_lun(struct se_portal_group *, struct se_lun *,
129130
bool, struct se_device *);
130131
void core_tpg_remove_lun(struct se_portal_group *, struct se_lun *);

drivers/target/target_core_stat.c

Lines changed: 85 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -276,56 +276,39 @@ static ssize_t target_stat_lu_state_bit_show(struct config_item *item,
276276
return snprintf(page, PAGE_SIZE, "exposed\n");
277277
}
278278

279-
static ssize_t target_stat_lu_num_cmds_show(struct config_item *item,
280-
char *page)
281-
{
282-
struct se_device *dev = to_stat_lu_dev(item);
283-
struct se_dev_io_stats *stats;
284-
unsigned int cpu;
285-
u32 cmds = 0;
286-
287-
for_each_possible_cpu(cpu) {
288-
stats = per_cpu_ptr(dev->stats, cpu);
289-
cmds += stats->total_cmds;
290-
}
291-
292-
/* scsiLuNumCommands */
293-
return snprintf(page, PAGE_SIZE, "%u\n", cmds);
294-
}
295-
296-
static ssize_t target_stat_lu_read_mbytes_show(struct config_item *item,
297-
char *page)
298-
{
299-
struct se_device *dev = to_stat_lu_dev(item);
300-
struct se_dev_io_stats *stats;
301-
unsigned int cpu;
302-
u32 bytes = 0;
303-
304-
for_each_possible_cpu(cpu) {
305-
stats = per_cpu_ptr(dev->stats, cpu);
306-
bytes += stats->read_bytes;
307-
}
308-
309-
/* scsiLuReadMegaBytes */
310-
return snprintf(page, PAGE_SIZE, "%u\n", bytes >> 20);
311-
}
312-
313-
static ssize_t target_stat_lu_write_mbytes_show(struct config_item *item,
314-
char *page)
315-
{
316-
struct se_device *dev = to_stat_lu_dev(item);
317-
struct se_dev_io_stats *stats;
318-
unsigned int cpu;
319-
u32 bytes = 0;
320-
321-
for_each_possible_cpu(cpu) {
322-
stats = per_cpu_ptr(dev->stats, cpu);
323-
bytes += stats->write_bytes;
324-
}
325-
326-
/* scsiLuWrittenMegaBytes */
327-
return snprintf(page, PAGE_SIZE, "%u\n", bytes >> 20);
328-
}
279+
#define per_cpu_stat_snprintf(stats_struct, prefix, field, shift) \
280+
static ssize_t \
281+
per_cpu_stat_##prefix##_snprintf(struct stats_struct __percpu *per_cpu_stats, \
282+
char *page) \
283+
{ \
284+
struct stats_struct *stats; \
285+
unsigned int cpu; \
286+
u64 sum = 0; \
287+
\
288+
for_each_possible_cpu(cpu) { \
289+
stats = per_cpu_ptr(per_cpu_stats, cpu); \
290+
sum += stats->field; \
291+
} \
292+
\
293+
return snprintf(page, PAGE_SIZE, "%llu\n", sum >> shift); \
294+
}
295+
296+
#define lu_show_per_cpu_stat(prefix, field, shift) \
297+
per_cpu_stat_snprintf(se_dev_io_stats, prefix, field, shift); \
298+
static ssize_t \
299+
target_stat_##prefix##_show(struct config_item *item, char *page) \
300+
{ \
301+
struct se_device *dev = to_stat_lu_dev(item); \
302+
\
303+
return per_cpu_stat_##prefix##_snprintf(dev->stats, page); \
304+
} \
305+
306+
/* scsiLuNumCommands */
307+
lu_show_per_cpu_stat(lu_num_cmds, total_cmds, 0);
308+
/* scsiLuReadMegaBytes */
309+
lu_show_per_cpu_stat(lu_read_mbytes, read_bytes, 20);
310+
/* scsiLuWrittenMegaBytes */
311+
lu_show_per_cpu_stat(lu_write_mbytes, write_bytes, 20);
329312

330313
static ssize_t target_stat_lu_resets_show(struct config_item *item, char *page)
331314
{
@@ -623,53 +606,30 @@ static ssize_t target_stat_tgt_port_port_index_show(struct config_item *item,
623606
return ret;
624607
}
625608

626-
static ssize_t target_stat_tgt_port_in_cmds_show(struct config_item *item,
627-
char *page)
628-
{
629-
struct se_lun *lun = to_stat_tgt_port(item);
630-
struct se_device *dev;
631-
ssize_t ret = -ENODEV;
632-
633-
rcu_read_lock();
634-
dev = rcu_dereference(lun->lun_se_dev);
635-
if (dev)
636-
ret = snprintf(page, PAGE_SIZE, "%lu\n",
637-
atomic_long_read(&lun->lun_stats.cmd_pdus));
638-
rcu_read_unlock();
639-
return ret;
640-
}
641-
642-
static ssize_t target_stat_tgt_port_write_mbytes_show(struct config_item *item,
643-
char *page)
644-
{
645-
struct se_lun *lun = to_stat_tgt_port(item);
646-
struct se_device *dev;
647-
ssize_t ret = -ENODEV;
648-
649-
rcu_read_lock();
650-
dev = rcu_dereference(lun->lun_se_dev);
651-
if (dev)
652-
ret = snprintf(page, PAGE_SIZE, "%u\n",
653-
(u32)(atomic_long_read(&lun->lun_stats.rx_data_octets) >> 20));
654-
rcu_read_unlock();
655-
return ret;
656-
}
657-
658-
static ssize_t target_stat_tgt_port_read_mbytes_show(struct config_item *item,
659-
char *page)
660-
{
661-
struct se_lun *lun = to_stat_tgt_port(item);
662-
struct se_device *dev;
663-
ssize_t ret = -ENODEV;
664-
665-
rcu_read_lock();
666-
dev = rcu_dereference(lun->lun_se_dev);
667-
if (dev)
668-
ret = snprintf(page, PAGE_SIZE, "%u\n",
669-
(u32)(atomic_long_read(&lun->lun_stats.tx_data_octets) >> 20));
670-
rcu_read_unlock();
671-
return ret;
672-
}
609+
#define tgt_port_show_per_cpu_stat(prefix, field, shift) \
610+
per_cpu_stat_snprintf(scsi_port_stats, prefix, field, shift); \
611+
static ssize_t \
612+
target_stat_##prefix##_show(struct config_item *item, char *page) \
613+
{ \
614+
struct se_lun *lun = to_stat_tgt_port(item); \
615+
struct se_device *dev; \
616+
int ret; \
617+
\
618+
rcu_read_lock(); \
619+
dev = rcu_dereference(lun->lun_se_dev); \
620+
if (!dev) { \
621+
rcu_read_unlock(); \
622+
return -ENODEV; \
623+
} \
624+
\
625+
ret = per_cpu_stat_##prefix##_snprintf(lun->lun_stats, page); \
626+
rcu_read_unlock(); \
627+
return ret; \
628+
}
629+
630+
tgt_port_show_per_cpu_stat(tgt_port_in_cmds, cmd_pdus, 0);
631+
tgt_port_show_per_cpu_stat(tgt_port_write_mbytes, rx_data_octets, 20);
632+
tgt_port_show_per_cpu_stat(tgt_port_read_mbytes, tx_data_octets, 20);
673633

674634
static ssize_t target_stat_tgt_port_hs_in_cmds_show(struct config_item *item,
675635
char *page)
@@ -1035,92 +995,34 @@ static ssize_t target_stat_auth_att_count_show(struct config_item *item,
1035995
return ret;
1036996
}
1037997

1038-
static ssize_t target_stat_auth_num_cmds_show(struct config_item *item,
1039-
char *page)
1040-
{
1041-
struct se_lun_acl *lacl = auth_to_lacl(item);
1042-
struct se_node_acl *nacl = lacl->se_lun_nacl;
1043-
struct se_dev_entry_io_stats *stats;
1044-
struct se_dev_entry *deve;
1045-
unsigned int cpu;
1046-
ssize_t ret;
1047-
u32 cmds = 0;
1048-
1049-
rcu_read_lock();
1050-
deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
1051-
if (!deve) {
1052-
rcu_read_unlock();
1053-
return -ENODEV;
1054-
}
1055-
1056-
for_each_possible_cpu(cpu) {
1057-
stats = per_cpu_ptr(deve->stats, cpu);
1058-
cmds += stats->total_cmds;
1059-
}
1060-
1061-
/* scsiAuthIntrOutCommands */
1062-
ret = snprintf(page, PAGE_SIZE, "%u\n", cmds);
1063-
rcu_read_unlock();
1064-
return ret;
1065-
}
1066-
1067-
static ssize_t target_stat_auth_read_mbytes_show(struct config_item *item,
1068-
char *page)
1069-
{
1070-
struct se_lun_acl *lacl = auth_to_lacl(item);
1071-
struct se_node_acl *nacl = lacl->se_lun_nacl;
1072-
struct se_dev_entry_io_stats *stats;
1073-
struct se_dev_entry *deve;
1074-
unsigned int cpu;
1075-
ssize_t ret;
1076-
u32 bytes = 0;
1077-
1078-
rcu_read_lock();
1079-
deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
1080-
if (!deve) {
1081-
rcu_read_unlock();
1082-
return -ENODEV;
1083-
}
1084-
1085-
for_each_possible_cpu(cpu) {
1086-
stats = per_cpu_ptr(deve->stats, cpu);
1087-
bytes += stats->read_bytes;
1088-
}
1089-
1090-
/* scsiAuthIntrReadMegaBytes */
1091-
ret = snprintf(page, PAGE_SIZE, "%u\n", bytes >> 20);
1092-
rcu_read_unlock();
1093-
return ret;
1094-
}
1095-
1096-
static ssize_t target_stat_auth_write_mbytes_show(struct config_item *item,
1097-
char *page)
1098-
{
1099-
struct se_lun_acl *lacl = auth_to_lacl(item);
1100-
struct se_node_acl *nacl = lacl->se_lun_nacl;
1101-
struct se_dev_entry_io_stats *stats;
1102-
struct se_dev_entry *deve;
1103-
unsigned int cpu;
1104-
ssize_t ret;
1105-
u32 bytes = 0;
1106-
1107-
rcu_read_lock();
1108-
deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
1109-
if (!deve) {
1110-
rcu_read_unlock();
1111-
return -ENODEV;
1112-
}
1113-
1114-
for_each_possible_cpu(cpu) {
1115-
stats = per_cpu_ptr(deve->stats, cpu);
1116-
bytes += stats->write_bytes;
1117-
}
1118-
1119-
/* scsiAuthIntrWrittenMegaBytes */
1120-
ret = snprintf(page, PAGE_SIZE, "%u\n", bytes >> 20);
1121-
rcu_read_unlock();
1122-
return ret;
1123-
}
998+
#define auth_show_per_cpu_stat(prefix, field, shift) \
999+
per_cpu_stat_snprintf(se_dev_entry_io_stats, prefix, field, shift); \
1000+
static ssize_t \
1001+
target_stat_##prefix##_show(struct config_item *item, char *page) \
1002+
{ \
1003+
struct se_lun_acl *lacl = auth_to_lacl(item); \
1004+
struct se_node_acl *nacl = lacl->se_lun_nacl; \
1005+
struct se_dev_entry *deve; \
1006+
int ret; \
1007+
\
1008+
rcu_read_lock(); \
1009+
deve = target_nacl_find_deve(nacl, lacl->mapped_lun); \
1010+
if (!deve) { \
1011+
rcu_read_unlock(); \
1012+
return -ENODEV; \
1013+
} \
1014+
\
1015+
ret = per_cpu_stat_##prefix##_snprintf(deve->stats, page); \
1016+
rcu_read_unlock(); \
1017+
return ret; \
1018+
}
1019+
1020+
/* scsiAuthIntrOutCommands */
1021+
auth_show_per_cpu_stat(auth_num_cmds, total_cmds, 0);
1022+
/* scsiAuthIntrReadMegaBytes */
1023+
auth_show_per_cpu_stat(auth_read_mbytes, read_bytes, 20);
1024+
/* scsiAuthIntrWrittenMegaBytes */
1025+
auth_show_per_cpu_stat(auth_write_mbytes, write_bytes, 20);
11241026

11251027
static ssize_t target_stat_auth_hs_num_cmds_show(struct config_item *item,
11261028
char *page)

drivers/target/target_core_tpg.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ int core_tpg_register(
548548
ret = core_tpg_add_lun(se_tpg, se_tpg->tpg_virt_lun0,
549549
true, g_lun0_dev);
550550
if (ret < 0) {
551-
kfree(se_tpg->tpg_virt_lun0);
551+
target_tpg_free_lun(&se_tpg->tpg_virt_lun0->rcu_head);
552552
return ret;
553553
}
554554
}
@@ -595,7 +595,7 @@ int core_tpg_deregister(struct se_portal_group *se_tpg)
595595

596596
if (se_tpg->proto_id >= 0) {
597597
core_tpg_remove_lun(se_tpg, se_tpg->tpg_virt_lun0);
598-
kfree_rcu(se_tpg->tpg_virt_lun0, rcu_head);
598+
call_rcu(&se_tpg->tpg_virt_lun0->rcu_head, target_tpg_free_lun);
599599
}
600600

601601
target_tpg_deregister_rtpi(se_tpg);
@@ -615,6 +615,13 @@ struct se_lun *core_tpg_alloc_lun(
615615
pr_err("Unable to allocate se_lun memory\n");
616616
return ERR_PTR(-ENOMEM);
617617
}
618+
619+
lun->lun_stats = alloc_percpu(struct scsi_port_stats);
620+
if (!lun->lun_stats) {
621+
pr_err("Unable to allocate se_lun stats memory\n");
622+
goto free_lun;
623+
}
624+
618625
lun->unpacked_lun = unpacked_lun;
619626
atomic_set(&lun->lun_acl_count, 0);
620627
init_completion(&lun->lun_shutdown_comp);
@@ -628,6 +635,18 @@ struct se_lun *core_tpg_alloc_lun(
628635
lun->lun_tpg = tpg;
629636

630637
return lun;
638+
639+
free_lun:
640+
kfree(lun);
641+
return ERR_PTR(-ENOMEM);
642+
}
643+
644+
void target_tpg_free_lun(struct rcu_head *head)
645+
{
646+
struct se_lun *lun = container_of(head, struct se_lun, rcu_head);
647+
648+
free_percpu(lun->lun_stats);
649+
kfree(lun);
631650
}
632651

633652
int core_tpg_add_lun(

0 commit comments

Comments
 (0)