RDMA/nldev: Provide MR statistics
authorErez Alfasi <ereza@mellanox.com>
Wed, 16 Oct 2019 06:23:08 +0000 (09:23 +0300)
committerJason Gunthorpe <jgg@mellanox.com>
Tue, 22 Oct 2019 18:33:31 +0000 (15:33 -0300)
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>
drivers/infiniband/core/device.c
drivers/infiniband/core/nldev.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mlx5_ib.h
drivers/infiniband/hw/mlx5/restrack.c
include/rdma/ib_verbs.h
include/rdma/restrack.h

index 74941bc..eb35b66 100644 (file)
@@ -2605,6 +2605,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
        SET_DEVICE_OP(dev_ops, drain_sq);
        SET_DEVICE_OP(dev_ops, enable_driver);
        SET_DEVICE_OP(dev_ops, fill_res_entry);
+       SET_DEVICE_OP(dev_ops, fill_stat_entry);
        SET_DEVICE_OP(dev_ops, get_dev_fw_str);
        SET_DEVICE_OP(dev_ops, get_dma_mr);
        SET_DEVICE_OP(dev_ops, get_hw_stats);
index a7f5add..3bb2085 100644 (file)
@@ -439,6 +439,14 @@ static bool fill_res_entry(struct ib_device *dev, struct sk_buff *msg,
        return dev->ops.fill_res_entry(msg, res);
 }
 
+static bool fill_stat_entry(struct ib_device *dev, struct sk_buff *msg,
+                           struct rdma_restrack_entry *res)
+{
+       if (!dev->ops.fill_stat_entry)
+               return false;
+       return dev->ops.fill_stat_entry(msg, res);
+}
+
 static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin,
                             struct rdma_restrack_entry *res, uint32_t port)
 {
@@ -739,8 +747,8 @@ err:
        return ret;
 }
 
-static int fill_stat_hwcounter_entry(struct sk_buff *msg,
-                                    const char *name, u64 value)
+int rdma_nl_stat_hwcounter_entry(struct sk_buff *msg, const char *name,
+                                u64 value)
 {
        struct nlattr *entry_attr;
 
@@ -762,6 +770,25 @@ err:
        nla_nest_cancel(msg, entry_attr);
        return -EMSGSIZE;
 }
+EXPORT_SYMBOL(rdma_nl_stat_hwcounter_entry);
+
+static int fill_stat_mr_entry(struct sk_buff *msg, bool has_cap_net_admin,
+                             struct rdma_restrack_entry *res, uint32_t port)
+{
+       struct ib_mr *mr = container_of(res, struct ib_mr, res);
+       struct ib_device *dev = mr->pd->device;
+
+       if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_MRN, res->id))
+               goto err;
+
+       if (fill_stat_entry(dev, msg, res))
+               goto err;
+
+       return 0;
+
+err:
+       return -EMSGSIZE;
+}
 
 static int fill_stat_counter_hwcounters(struct sk_buff *msg,
                                        struct rdma_counter *counter)
@@ -775,7 +802,7 @@ static int fill_stat_counter_hwcounters(struct sk_buff *msg,
                return -EMSGSIZE;
 
        for (i = 0; i < st->num_counters; i++)
-               if (fill_stat_hwcounter_entry(msg, st->names[i], st->value[i]))
+               if (rdma_nl_stat_hwcounter_entry(msg, st->names[i], st->value[i]))
                        goto err;
 
        nla_nest_end(msg, table_attr);
@@ -1897,7 +1924,7 @@ static int stat_get_doit_default_counter(struct sk_buff *skb,
        for (i = 0; i < num_cnts; i++) {
                v = stats->value[i] +
                        rdma_counter_get_hwstat_value(device, port, i);
-               if (fill_stat_hwcounter_entry(msg, stats->names[i], v)) {
+               if (rdma_nl_stat_hwcounter_entry(msg, stats->names[i], v)) {
                        ret = -EMSGSIZE;
                        goto err_table;
                }
@@ -2006,7 +2033,10 @@ static int nldev_stat_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
        case RDMA_NLDEV_ATTR_RES_QP:
                ret = stat_get_doit_qp(skb, nlh, extack, tb);
                break;
-
+       case RDMA_NLDEV_ATTR_RES_MR:
+               ret = res_get_common_doit(skb, nlh, extack, RDMA_RESTRACK_MR,
+                                         fill_stat_mr_entry);
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -2030,7 +2060,10 @@ static int nldev_stat_get_dumpit(struct sk_buff *skb,
        case RDMA_NLDEV_ATTR_RES_QP:
                ret = nldev_res_get_counter_dumpit(skb, cb);
                break;
-
+       case RDMA_NLDEV_ATTR_RES_MR:
+               ret = res_get_common_dumpit(skb, cb, RDMA_RESTRACK_MR,
+                                           fill_stat_mr_entry);
+               break;
        default:
                ret = -EINVAL;
                break;
index 4a731ca..39d54e2 100644 (file)
@@ -67,6 +67,7 @@
 #include <rdma/uverbs_std_types.h>
 #include <rdma/mlx5_user_ioctl_verbs.h>
 #include <rdma/mlx5_user_ioctl_cmds.h>
+#include <rdma/ib_umem_odp.h>
 
 #define UVERBS_MODULE_NAME mlx5_ib
 #include <rdma/uverbs_named_ioctl.h>
@@ -6272,6 +6273,7 @@ static const struct ib_device_ops mlx5_ib_dev_ops = {
        .drain_rq = mlx5_ib_drain_rq,
        .drain_sq = mlx5_ib_drain_sq,
        .fill_res_entry = mlx5_ib_fill_res_entry,
+       .fill_stat_entry = mlx5_ib_fill_stat_entry,
        .get_dev_fw_str = get_dev_fw_str,
        .get_dma_mr = mlx5_ib_get_dma_mr,
        .get_link_layer = mlx5_ib_port_link_layer,
index a0ca1ef..e9bdb48 100644 (file)
@@ -1342,6 +1342,8 @@ void mlx5_ib_put_native_port_mdev(struct mlx5_ib_dev *dev,
                                  u8 port_num);
 int mlx5_ib_fill_res_entry(struct sk_buff *msg,
                           struct rdma_restrack_entry *res);
+int mlx5_ib_fill_stat_entry(struct sk_buff *msg,
+                           struct rdma_restrack_entry *res);
 
 #if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
 int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, bool is_user);
index 065049f..8f6c04f 100644 (file)
@@ -8,6 +8,39 @@
 #include <rdma/restrack.h>
 #include "mlx5_ib.h"
 
+static int fill_stat_mr_entry(struct sk_buff *msg,
+                             struct rdma_restrack_entry *res)
+{
+       struct ib_mr *ibmr = container_of(res, struct ib_mr, res);
+       struct mlx5_ib_mr *mr = to_mmr(ibmr);
+       struct nlattr *table_attr;
+
+       if (!(mr->access_flags & IB_ACCESS_ON_DEMAND))
+               return 0;
+
+       table_attr = nla_nest_start(msg,
+                                   RDMA_NLDEV_ATTR_STAT_HWCOUNTERS);
+
+       if (!table_attr)
+               goto err;
+
+       if (rdma_nl_stat_hwcounter_entry(msg, "page_faults",
+                                        atomic64_read(&mr->odp_stats.faults)))
+               goto err_table;
+       if (rdma_nl_stat_hwcounter_entry(
+                   msg, "page_invalidations",
+                   atomic64_read(&mr->odp_stats.invalidations)))
+               goto err_table;
+
+       nla_nest_end(msg, table_attr);
+       return 0;
+
+err_table:
+       nla_nest_cancel(msg, table_attr);
+err:
+       return -EMSGSIZE;
+}
+
 static int fill_res_mr_entry(struct sk_buff *msg,
                             struct rdma_restrack_entry *res)
 {
@@ -46,3 +79,12 @@ int mlx5_ib_fill_res_entry(struct sk_buff *msg,
 
        return 0;
 }
+
+int mlx5_ib_fill_stat_entry(struct sk_buff *msg,
+                           struct rdma_restrack_entry *res)
+{
+       if (res->type == RDMA_RESTRACK_MR)
+               return fill_stat_mr_entry(msg, res);
+
+       return 0;
+}
index 1ef31b2..cca9985 100644 (file)
@@ -2570,6 +2570,13 @@ struct ib_device_ops {
         */
        int (*counter_update_stats)(struct rdma_counter *counter);
 
+       /**
+        * Allows rdma drivers to add their own restrack attributes
+        * dumped via 'rdma stat' iproute2 command.
+        */
+       int (*fill_stat_entry)(struct sk_buff *msg,
+                              struct rdma_restrack_entry *entry);
+
        DECLARE_RDMA_OBJ_SIZE(ib_ah);
        DECLARE_RDMA_OBJ_SIZE(ib_cq);
        DECLARE_RDMA_OBJ_SIZE(ib_pd);
index fe9b3c5..7682d1b 100644 (file)
@@ -158,6 +158,8 @@ int rdma_nl_put_driver_u64_hex(struct sk_buff *msg, const char *name,
                               u64 value);
 int rdma_nl_put_driver_string(struct sk_buff *msg, const char *name,
                              const char *str);
+int rdma_nl_stat_hwcounter_entry(struct sk_buff *msg, const char *name,
+                                u64 value);
 
 struct rdma_restrack_entry *rdma_restrack_get_byid(struct ib_device *dev,
                                                   enum rdma_restrack_type type,