Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+127 -196
+1
drivers/target/target_core_device.c
··· 814 814 dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; 815 815 dev->dev_attrib.submit_type = TARGET_FABRIC_DEFAULT_SUBMIT; 816 816 817 + /* Skip allocating lun_stats since we can't export them. */ 817 818 xcopy_lun = &dev->xcopy_lun; 818 819 rcu_assign_pointer(xcopy_lun->lun_se_dev, dev); 819 820 init_completion(&xcopy_lun->lun_shutdown_comp);
+1 -1
drivers/target/target_core_fabric_configfs.c
··· 697 697 struct se_lun *lun = container_of(to_config_group(item), 698 698 struct se_lun, lun_group); 699 699 700 - kfree_rcu(lun, rcu_head); 700 + call_rcu(&lun->rcu_head, target_tpg_free_lun); 701 701 } 702 702 703 703 static struct configfs_item_operations target_fabric_port_item_ops = {
+1
drivers/target/target_core_internal.h
··· 125 125 struct se_lun *); 126 126 void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *); 127 127 struct se_lun *core_tpg_alloc_lun(struct se_portal_group *, u64); 128 + void target_tpg_free_lun(struct rcu_head *head); 128 129 int core_tpg_add_lun(struct se_portal_group *, struct se_lun *, 129 130 bool, struct se_device *); 130 131 void core_tpg_remove_lun(struct se_portal_group *, struct se_lun *);
+78 -176
drivers/target/target_core_stat.c
··· 276 276 return snprintf(page, PAGE_SIZE, "exposed\n"); 277 277 } 278 278 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); 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 294 } 295 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; 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 + } \ 303 305 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 - } 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); 329 312 330 313 static ssize_t target_stat_lu_resets_show(struct config_item *item, char *page) 331 314 { ··· 606 623 return ret; 607 624 } 608 625 609 - static ssize_t target_stat_tgt_port_in_cmds_show(struct config_item *item, 610 - char *page) 611 - { 612 - struct se_lun *lun = to_stat_tgt_port(item); 613 - struct se_device *dev; 614 - ssize_t ret = -ENODEV; 615 - 616 - rcu_read_lock(); 617 - dev = rcu_dereference(lun->lun_se_dev); 618 - if (dev) 619 - ret = snprintf(page, PAGE_SIZE, "%lu\n", 620 - atomic_long_read(&lun->lun_stats.cmd_pdus)); 621 - rcu_read_unlock(); 622 - return ret; 626 + #define tgt_port_show_per_cpu_stat(prefix, field, shift) \ 627 + per_cpu_stat_snprintf(scsi_port_stats, prefix, field, shift); \ 628 + static ssize_t \ 629 + target_stat_##prefix##_show(struct config_item *item, char *page) \ 630 + { \ 631 + struct se_lun *lun = to_stat_tgt_port(item); \ 632 + struct se_device *dev; \ 633 + int ret; \ 634 + \ 635 + rcu_read_lock(); \ 636 + dev = rcu_dereference(lun->lun_se_dev); \ 637 + if (!dev) { \ 638 + rcu_read_unlock(); \ 639 + return -ENODEV; \ 640 + } \ 641 + \ 642 + ret = per_cpu_stat_##prefix##_snprintf(lun->lun_stats, page); \ 643 + rcu_read_unlock(); \ 644 + return ret; \ 623 645 } 624 646 625 - static ssize_t target_stat_tgt_port_write_mbytes_show(struct config_item *item, 626 - char *page) 627 - { 628 - struct se_lun *lun = to_stat_tgt_port(item); 629 - struct se_device *dev; 630 - ssize_t ret = -ENODEV; 631 - 632 - rcu_read_lock(); 633 - dev = rcu_dereference(lun->lun_se_dev); 634 - if (dev) 635 - ret = snprintf(page, PAGE_SIZE, "%u\n", 636 - (u32)(atomic_long_read(&lun->lun_stats.rx_data_octets) >> 20)); 637 - rcu_read_unlock(); 638 - return ret; 639 - } 640 - 641 - static ssize_t target_stat_tgt_port_read_mbytes_show(struct config_item *item, 642 - char *page) 643 - { 644 - struct se_lun *lun = to_stat_tgt_port(item); 645 - struct se_device *dev; 646 - ssize_t ret = -ENODEV; 647 - 648 - rcu_read_lock(); 649 - dev = rcu_dereference(lun->lun_se_dev); 650 - if (dev) 651 - ret = snprintf(page, PAGE_SIZE, "%u\n", 652 - (u32)(atomic_long_read(&lun->lun_stats.tx_data_octets) >> 20)); 653 - rcu_read_unlock(); 654 - return ret; 655 - } 647 + tgt_port_show_per_cpu_stat(tgt_port_in_cmds, cmd_pdus, 0); 648 + tgt_port_show_per_cpu_stat(tgt_port_write_mbytes, rx_data_octets, 20); 649 + tgt_port_show_per_cpu_stat(tgt_port_read_mbytes, tx_data_octets, 20); 656 650 657 651 static ssize_t target_stat_tgt_port_hs_in_cmds_show(struct config_item *item, 658 652 char *page) ··· 995 1035 return ret; 996 1036 } 997 1037 998 - static ssize_t target_stat_auth_num_cmds_show(struct config_item *item, 999 - char *page) 1000 - { 1001 - struct se_lun_acl *lacl = auth_to_lacl(item); 1002 - struct se_node_acl *nacl = lacl->se_lun_nacl; 1003 - struct se_dev_entry_io_stats *stats; 1004 - struct se_dev_entry *deve; 1005 - unsigned int cpu; 1006 - ssize_t ret; 1007 - u32 cmds = 0; 1008 - 1009 - rcu_read_lock(); 1010 - deve = target_nacl_find_deve(nacl, lacl->mapped_lun); 1011 - if (!deve) { 1012 - rcu_read_unlock(); 1013 - return -ENODEV; 1014 - } 1015 - 1016 - for_each_possible_cpu(cpu) { 1017 - stats = per_cpu_ptr(deve->stats, cpu); 1018 - cmds += stats->total_cmds; 1019 - } 1020 - 1021 - /* scsiAuthIntrOutCommands */ 1022 - ret = snprintf(page, PAGE_SIZE, "%u\n", cmds); 1023 - rcu_read_unlock(); 1024 - return ret; 1038 + #define auth_show_per_cpu_stat(prefix, field, shift) \ 1039 + per_cpu_stat_snprintf(se_dev_entry_io_stats, prefix, field, shift); \ 1040 + static ssize_t \ 1041 + target_stat_##prefix##_show(struct config_item *item, char *page) \ 1042 + { \ 1043 + struct se_lun_acl *lacl = auth_to_lacl(item); \ 1044 + struct se_node_acl *nacl = lacl->se_lun_nacl; \ 1045 + struct se_dev_entry *deve; \ 1046 + int ret; \ 1047 + \ 1048 + rcu_read_lock(); \ 1049 + deve = target_nacl_find_deve(nacl, lacl->mapped_lun); \ 1050 + if (!deve) { \ 1051 + rcu_read_unlock(); \ 1052 + return -ENODEV; \ 1053 + } \ 1054 + \ 1055 + ret = per_cpu_stat_##prefix##_snprintf(deve->stats, page); \ 1056 + rcu_read_unlock(); \ 1057 + return ret; \ 1025 1058 } 1026 1059 1027 - static ssize_t target_stat_auth_read_mbytes_show(struct config_item *item, 1028 - char *page) 1029 - { 1030 - struct se_lun_acl *lacl = auth_to_lacl(item); 1031 - struct se_node_acl *nacl = lacl->se_lun_nacl; 1032 - struct se_dev_entry_io_stats *stats; 1033 - struct se_dev_entry *deve; 1034 - unsigned int cpu; 1035 - ssize_t ret; 1036 - u32 bytes = 0; 1037 - 1038 - rcu_read_lock(); 1039 - deve = target_nacl_find_deve(nacl, lacl->mapped_lun); 1040 - if (!deve) { 1041 - rcu_read_unlock(); 1042 - return -ENODEV; 1043 - } 1044 - 1045 - for_each_possible_cpu(cpu) { 1046 - stats = per_cpu_ptr(deve->stats, cpu); 1047 - bytes += stats->read_bytes; 1048 - } 1049 - 1050 - /* scsiAuthIntrReadMegaBytes */ 1051 - ret = snprintf(page, PAGE_SIZE, "%u\n", bytes >> 20); 1052 - rcu_read_unlock(); 1053 - return ret; 1054 - } 1055 - 1056 - static ssize_t target_stat_auth_write_mbytes_show(struct config_item *item, 1057 - char *page) 1058 - { 1059 - struct se_lun_acl *lacl = auth_to_lacl(item); 1060 - struct se_node_acl *nacl = lacl->se_lun_nacl; 1061 - struct se_dev_entry_io_stats *stats; 1062 - struct se_dev_entry *deve; 1063 - unsigned int cpu; 1064 - ssize_t ret; 1065 - u32 bytes = 0; 1066 - 1067 - rcu_read_lock(); 1068 - deve = target_nacl_find_deve(nacl, lacl->mapped_lun); 1069 - if (!deve) { 1070 - rcu_read_unlock(); 1071 - return -ENODEV; 1072 - } 1073 - 1074 - for_each_possible_cpu(cpu) { 1075 - stats = per_cpu_ptr(deve->stats, cpu); 1076 - bytes += stats->write_bytes; 1077 - } 1078 - 1079 - /* scsiAuthIntrWrittenMegaBytes */ 1080 - ret = snprintf(page, PAGE_SIZE, "%u\n", bytes >> 20); 1081 - rcu_read_unlock(); 1082 - return ret; 1083 - } 1060 + /* scsiAuthIntrOutCommands */ 1061 + auth_show_per_cpu_stat(auth_num_cmds, total_cmds, 0); 1062 + /* scsiAuthIntrReadMegaBytes */ 1063 + auth_show_per_cpu_stat(auth_read_mbytes, read_bytes, 20); 1064 + /* scsiAuthIntrWrittenMegaBytes */ 1065 + auth_show_per_cpu_stat(auth_write_mbytes, write_bytes, 20); 1084 1066 1085 1067 static ssize_t target_stat_auth_hs_num_cmds_show(struct config_item *item, 1086 1068 char *page)
+21 -2
drivers/target/target_core_tpg.c
··· 548 548 ret = core_tpg_add_lun(se_tpg, se_tpg->tpg_virt_lun0, 549 549 true, g_lun0_dev); 550 550 if (ret < 0) { 551 - kfree(se_tpg->tpg_virt_lun0); 551 + target_tpg_free_lun(&se_tpg->tpg_virt_lun0->rcu_head); 552 552 return ret; 553 553 } 554 554 } ··· 595 595 596 596 if (se_tpg->proto_id >= 0) { 597 597 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); 599 599 } 600 600 601 601 target_tpg_deregister_rtpi(se_tpg); ··· 615 615 pr_err("Unable to allocate se_lun memory\n"); 616 616 return ERR_PTR(-ENOMEM); 617 617 } 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 + 618 625 lun->unpacked_lun = unpacked_lun; 619 626 atomic_set(&lun->lun_acl_count, 0); 620 627 init_completion(&lun->lun_shutdown_comp); ··· 635 628 lun->lun_tpg = tpg; 636 629 637 630 return lun; 631 + 632 + free_lun: 633 + kfree(lun); 634 + return ERR_PTR(-ENOMEM); 635 + } 636 + 637 + void target_tpg_free_lun(struct rcu_head *head) 638 + { 639 + struct se_lun *lun = container_of(head, struct se_lun, rcu_head); 640 + 641 + free_percpu(lun->lun_stats); 642 + kfree(lun); 638 643 } 639 644 640 645 int core_tpg_add_lun(
+15 -7
drivers/target/target_core_transport.c
··· 1571 1571 return ret; 1572 1572 1573 1573 cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE; 1574 - atomic_long_inc(&cmd->se_lun->lun_stats.cmd_pdus); 1574 + /* 1575 + * If this is the xcopy_lun then we won't have lun_stats since we 1576 + * can't export them. 1577 + */ 1578 + if (cmd->se_lun->lun_stats) 1579 + this_cpu_inc(cmd->se_lun->lun_stats->cmd_pdus); 1575 1580 return 0; 1576 1581 } 1577 1582 EXPORT_SYMBOL(target_cmd_parse_cdb); ··· 2602 2597 !(cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL)) 2603 2598 goto queue_status; 2604 2599 2605 - atomic_long_add(cmd->data_length, 2606 - &cmd->se_lun->lun_stats.tx_data_octets); 2600 + if (cmd->se_lun->lun_stats) 2601 + this_cpu_add(cmd->se_lun->lun_stats->tx_data_octets, 2602 + cmd->data_length); 2607 2603 /* 2608 2604 * Perform READ_STRIP of PI using software emulation when 2609 2605 * backend had PI enabled, if the transport will not be ··· 2627 2621 goto queue_full; 2628 2622 break; 2629 2623 case DMA_TO_DEVICE: 2630 - atomic_long_add(cmd->data_length, 2631 - &cmd->se_lun->lun_stats.rx_data_octets); 2624 + if (cmd->se_lun->lun_stats) 2625 + this_cpu_add(cmd->se_lun->lun_stats->rx_data_octets, 2626 + cmd->data_length); 2632 2627 /* 2633 2628 * Check if we need to send READ payload for BIDI-COMMAND 2634 2629 */ 2635 2630 if (cmd->se_cmd_flags & SCF_BIDI) { 2636 - atomic_long_add(cmd->data_length, 2637 - &cmd->se_lun->lun_stats.tx_data_octets); 2631 + if (cmd->se_lun->lun_stats) 2632 + this_cpu_add(cmd->se_lun->lun_stats->tx_data_octets, 2633 + cmd->data_length); 2638 2634 ret = cmd->se_tfo->queue_data_in(cmd); 2639 2635 if (ret) 2640 2636 goto queue_full;
+10 -10
include/target/target_core_base.h
··· 672 672 }; 673 673 674 674 struct se_dev_entry_io_stats { 675 - u32 total_cmds; 676 - u32 read_bytes; 677 - u32 write_bytes; 675 + u64 total_cmds; 676 + u64 read_bytes; 677 + u64 write_bytes; 678 678 }; 679 679 680 680 struct se_dev_entry { ··· 750 750 }; 751 751 752 752 struct scsi_port_stats { 753 - atomic_long_t cmd_pdus; 754 - atomic_long_t tx_data_octets; 755 - atomic_long_t rx_data_octets; 753 + u64 cmd_pdus; 754 + u64 tx_data_octets; 755 + u64 rx_data_octets; 756 756 }; 757 757 758 758 struct se_lun { ··· 779 779 spinlock_t lun_tg_pt_gp_lock; 780 780 781 781 struct se_portal_group *lun_tpg; 782 - struct scsi_port_stats lun_stats; 782 + struct scsi_port_stats __percpu *lun_stats; 783 783 struct config_group lun_group; 784 784 struct se_port_stat_grps port_stat_grps; 785 785 struct completion lun_shutdown_comp; ··· 812 812 }; 813 813 814 814 struct se_dev_io_stats { 815 - u32 total_cmds; 816 - u32 read_bytes; 817 - u32 write_bytes; 815 + u64 total_cmds; 816 + u64 read_bytes; 817 + u64 write_bytes; 818 818 }; 819 819 820 820 struct se_device {