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

RDMA/nldev: Provide MR statistics

Add RDMA nldev netlink interface for dumping MR statistics information.

Output example:

$ ./ibv_rc_pingpong -o -P -s 500000000
local address: LID 0x0001, QPN 0x00008a, PSN 0xf81096, GID ::

$ rdma stat show mr
dev mlx5_0 mrn 2 page_faults 122071 page_invalidations 0

Link: https://lore.kernel.org/r/20191016062308.11886-5-leon@kernel.org
Signed-off-by: Erez Alfasi <ereza@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Reviewed-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>

authored by

Erez Alfasi and committed by
Jason Gunthorpe
4061ff7a e1b95ae0

+95 -6
+1
drivers/infiniband/core/device.c
··· 2605 2605 SET_DEVICE_OP(dev_ops, drain_sq); 2606 2606 SET_DEVICE_OP(dev_ops, enable_driver); 2607 2607 SET_DEVICE_OP(dev_ops, fill_res_entry); 2608 + SET_DEVICE_OP(dev_ops, fill_stat_entry); 2608 2609 SET_DEVICE_OP(dev_ops, get_dev_fw_str); 2609 2610 SET_DEVICE_OP(dev_ops, get_dma_mr); 2610 2611 SET_DEVICE_OP(dev_ops, get_hw_stats);
+39 -6
drivers/infiniband/core/nldev.c
··· 439 439 return dev->ops.fill_res_entry(msg, res); 440 440 } 441 441 442 + static bool fill_stat_entry(struct ib_device *dev, struct sk_buff *msg, 443 + struct rdma_restrack_entry *res) 444 + { 445 + if (!dev->ops.fill_stat_entry) 446 + return false; 447 + return dev->ops.fill_stat_entry(msg, res); 448 + } 449 + 442 450 static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin, 443 451 struct rdma_restrack_entry *res, uint32_t port) 444 452 { ··· 747 739 return ret; 748 740 } 749 741 750 - static int fill_stat_hwcounter_entry(struct sk_buff *msg, 751 - const char *name, u64 value) 742 + int rdma_nl_stat_hwcounter_entry(struct sk_buff *msg, const char *name, 743 + u64 value) 752 744 { 753 745 struct nlattr *entry_attr; 754 746 ··· 770 762 nla_nest_cancel(msg, entry_attr); 771 763 return -EMSGSIZE; 772 764 } 765 + EXPORT_SYMBOL(rdma_nl_stat_hwcounter_entry); 766 + 767 + static int fill_stat_mr_entry(struct sk_buff *msg, bool has_cap_net_admin, 768 + struct rdma_restrack_entry *res, uint32_t port) 769 + { 770 + struct ib_mr *mr = container_of(res, struct ib_mr, res); 771 + struct ib_device *dev = mr->pd->device; 772 + 773 + if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_MRN, res->id)) 774 + goto err; 775 + 776 + if (fill_stat_entry(dev, msg, res)) 777 + goto err; 778 + 779 + return 0; 780 + 781 + err: 782 + return -EMSGSIZE; 783 + } 773 784 774 785 static int fill_stat_counter_hwcounters(struct sk_buff *msg, 775 786 struct rdma_counter *counter) ··· 802 775 return -EMSGSIZE; 803 776 804 777 for (i = 0; i < st->num_counters; i++) 805 - if (fill_stat_hwcounter_entry(msg, st->names[i], st->value[i])) 778 + if (rdma_nl_stat_hwcounter_entry(msg, st->names[i], st->value[i])) 806 779 goto err; 807 780 808 781 nla_nest_end(msg, table_attr); ··· 1924 1897 for (i = 0; i < num_cnts; i++) { 1925 1898 v = stats->value[i] + 1926 1899 rdma_counter_get_hwstat_value(device, port, i); 1927 - if (fill_stat_hwcounter_entry(msg, stats->names[i], v)) { 1900 + if (rdma_nl_stat_hwcounter_entry(msg, stats->names[i], v)) { 1928 1901 ret = -EMSGSIZE; 1929 1902 goto err_table; 1930 1903 } ··· 2033 2006 case RDMA_NLDEV_ATTR_RES_QP: 2034 2007 ret = stat_get_doit_qp(skb, nlh, extack, tb); 2035 2008 break; 2036 - 2009 + case RDMA_NLDEV_ATTR_RES_MR: 2010 + ret = res_get_common_doit(skb, nlh, extack, RDMA_RESTRACK_MR, 2011 + fill_stat_mr_entry); 2012 + break; 2037 2013 default: 2038 2014 ret = -EINVAL; 2039 2015 break; ··· 2060 2030 case RDMA_NLDEV_ATTR_RES_QP: 2061 2031 ret = nldev_res_get_counter_dumpit(skb, cb); 2062 2032 break; 2063 - 2033 + case RDMA_NLDEV_ATTR_RES_MR: 2034 + ret = res_get_common_dumpit(skb, cb, RDMA_RESTRACK_MR, 2035 + fill_stat_mr_entry); 2036 + break; 2064 2037 default: 2065 2038 ret = -EINVAL; 2066 2039 break;
+2
drivers/infiniband/hw/mlx5/main.c
··· 67 67 #include <rdma/uverbs_std_types.h> 68 68 #include <rdma/mlx5_user_ioctl_verbs.h> 69 69 #include <rdma/mlx5_user_ioctl_cmds.h> 70 + #include <rdma/ib_umem_odp.h> 70 71 71 72 #define UVERBS_MODULE_NAME mlx5_ib 72 73 #include <rdma/uverbs_named_ioctl.h> ··· 6273 6272 .drain_rq = mlx5_ib_drain_rq, 6274 6273 .drain_sq = mlx5_ib_drain_sq, 6275 6274 .fill_res_entry = mlx5_ib_fill_res_entry, 6275 + .fill_stat_entry = mlx5_ib_fill_stat_entry, 6276 6276 .get_dev_fw_str = get_dev_fw_str, 6277 6277 .get_dma_mr = mlx5_ib_get_dma_mr, 6278 6278 .get_link_layer = mlx5_ib_port_link_layer,
+2
drivers/infiniband/hw/mlx5/mlx5_ib.h
··· 1342 1342 u8 port_num); 1343 1343 int mlx5_ib_fill_res_entry(struct sk_buff *msg, 1344 1344 struct rdma_restrack_entry *res); 1345 + int mlx5_ib_fill_stat_entry(struct sk_buff *msg, 1346 + struct rdma_restrack_entry *res); 1345 1347 1346 1348 #if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS) 1347 1349 int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user);
+42
drivers/infiniband/hw/mlx5/restrack.c
··· 8 8 #include <rdma/restrack.h> 9 9 #include "mlx5_ib.h" 10 10 11 + static int fill_stat_mr_entry(struct sk_buff *msg, 12 + struct rdma_restrack_entry *res) 13 + { 14 + struct ib_mr *ibmr = container_of(res, struct ib_mr, res); 15 + struct mlx5_ib_mr *mr = to_mmr(ibmr); 16 + struct nlattr *table_attr; 17 + 18 + if (!(mr->access_flags & IB_ACCESS_ON_DEMAND)) 19 + return 0; 20 + 21 + table_attr = nla_nest_start(msg, 22 + RDMA_NLDEV_ATTR_STAT_HWCOUNTERS); 23 + 24 + if (!table_attr) 25 + goto err; 26 + 27 + if (rdma_nl_stat_hwcounter_entry(msg, "page_faults", 28 + atomic64_read(&mr->odp_stats.faults))) 29 + goto err_table; 30 + if (rdma_nl_stat_hwcounter_entry( 31 + msg, "page_invalidations", 32 + atomic64_read(&mr->odp_stats.invalidations))) 33 + goto err_table; 34 + 35 + nla_nest_end(msg, table_attr); 36 + return 0; 37 + 38 + err_table: 39 + nla_nest_cancel(msg, table_attr); 40 + err: 41 + return -EMSGSIZE; 42 + } 43 + 11 44 static int fill_res_mr_entry(struct sk_buff *msg, 12 45 struct rdma_restrack_entry *res) 13 46 { ··· 76 43 { 77 44 if (res->type == RDMA_RESTRACK_MR) 78 45 return fill_res_mr_entry(msg, res); 46 + 47 + return 0; 48 + } 49 + 50 + int mlx5_ib_fill_stat_entry(struct sk_buff *msg, 51 + struct rdma_restrack_entry *res) 52 + { 53 + if (res->type == RDMA_RESTRACK_MR) 54 + return fill_stat_mr_entry(msg, res); 79 55 80 56 return 0; 81 57 }
+7
include/rdma/ib_verbs.h
··· 2570 2570 */ 2571 2571 int (*counter_update_stats)(struct rdma_counter *counter); 2572 2572 2573 + /** 2574 + * Allows rdma drivers to add their own restrack attributes 2575 + * dumped via 'rdma stat' iproute2 command. 2576 + */ 2577 + int (*fill_stat_entry)(struct sk_buff *msg, 2578 + struct rdma_restrack_entry *entry); 2579 + 2573 2580 DECLARE_RDMA_OBJ_SIZE(ib_ah); 2574 2581 DECLARE_RDMA_OBJ_SIZE(ib_cq); 2575 2582 DECLARE_RDMA_OBJ_SIZE(ib_pd);
+2
include/rdma/restrack.h
··· 158 158 u64 value); 159 159 int rdma_nl_put_driver_string(struct sk_buff *msg, const char *name, 160 160 const char *str); 161 + int rdma_nl_stat_hwcounter_entry(struct sk_buff *msg, const char *name, 162 + u64 value); 161 163 162 164 struct rdma_restrack_entry *rdma_restrack_get_byid(struct ib_device *dev, 163 165 enum rdma_restrack_type type,