History

RDMA/core: Add netlink command to modify FRMR aging

Allow users to set FRMR pools aging timer through netlink. This functionality will allow user to control how long handles reside in the kernel before being destroyed, thus being able to tune the tradeoff between memory and HW object consumption and memory registration optimization. Since FRMR pools is highly beneficial for application restart scenarios, this command allows users to modify the aging timer to their application restart time, making sure the FRMR handles deregistered on application teardown are kept for long enough in the pools for reuse in the application startup.

Michael Guralnik committed 8 months ago

Commit d2ea6751 parent 50c03594 files · +71 −2Browse files

Unified · Split

4 files
  1. drivers/infiniband/core/frmr_pools.c +29 −2
  2. drivers/infiniband/core/frmr_pools.h +2 −0
  3. drivers/infiniband/core/nldev.c +37 −0
  4. include/uapi/rdma/rdma_netlink.h +3 −0
drivers/infiniband/core/frmr_pools.c+29−2
@@ -174,7 +174,7 @@ out: · 173 unmodified lines
174 if (has_work)174 if (has_work)
175 queue_delayed_work(175 queue_delayed_work(
176 pools->aging_wq, &pool->aging_work,176 pools->aging_wq, &pool->aging_work,
177 secs_to_jiffies(FRMR_POOLS_DEFAULT_AGING_PERIOD_SECS));177 secs_to_jiffies(READ_ONCE(pools->aging_period_sec)));
178}178}
179 179
180static void destroy_frmr_pool(struct ib_device *device,180static void destroy_frmr_pool(struct ib_device *device,
@@ -213,6 +213,8 @@ int ib_frmr_pools_init(struct ib_device *device, · 32 unmodified lines
213 return -ENOMEM;213 return -ENOMEM;
214 }214 }
215 215
216 pools->aging_period_sec = FRMR_POOLS_DEFAULT_AGING_PERIOD_SECS;
217
216 device->frmr_pools = pools;218 device->frmr_pools = pools;
217 return 0;219 return 0;
218}220}
@@ -245,6 +247,31 @@ void ib_frmr_pools_cleanup(struct ib_device *device) · 26 unmodified lines
245}247}
246EXPORT_SYMBOL(ib_frmr_pools_cleanup);248EXPORT_SYMBOL(ib_frmr_pools_cleanup);
247 249
250int ib_frmr_pools_set_aging_period(struct ib_device *device, u32 period_sec)
251{
252 struct ib_frmr_pools *pools = device->frmr_pools;
253 struct ib_frmr_pool *pool;
254 struct rb_node *node;
255
256 if (!pools)
257 return -EINVAL;
258
259 if (period_sec == 0)
260 return -EINVAL;
261
262 WRITE_ONCE(pools->aging_period_sec, period_sec);
263
264 read_lock(&pools->rb_lock);
265 for (node = rb_first(&pools->rb_root); node; node = rb_next(node)) {
266 pool = rb_entry(node, struct ib_frmr_pool, node);
267 mod_delayed_work(pools->aging_wq, &pool->aging_work,
268 secs_to_jiffies(period_sec));
269 }
270 read_unlock(&pools->rb_lock);
271
272 return 0;
273}
274
248static inline int compare_keys(struct ib_frmr_key *key1,275static inline int compare_keys(struct ib_frmr_key *key1,
249 struct ib_frmr_key *key2)276 struct ib_frmr_key *key2)
250{277{
@@ -513,7 +540,7 @@ int ib_frmr_pool_push(struct ib_device *device, struct ib_mr *mr) · 262 unmodified lines
513 540
514 if (ret == 0 && schedule_aging)541 if (ret == 0 && schedule_aging)
515 queue_delayed_work(pools->aging_wq, &pool->aging_work,542 queue_delayed_work(pools->aging_wq, &pool->aging_work,
516 secs_to_jiffies(FRMR_POOLS_DEFAULT_AGING_PERIOD_SECS));543 secs_to_jiffies(READ_ONCE(pools->aging_period_sec)));
517 544
518 return ret;545 return ret;
519}546}
drivers/infiniband/core/frmr_pools.h+2−0
@@ -54,8 +54,10 @@ struct ib_frmr_pools { · 53 unmodified lines
54 const struct ib_frmr_pool_ops *pool_ops;54 const struct ib_frmr_pool_ops *pool_ops;
55 55
56 struct workqueue_struct *aging_wq;56 struct workqueue_struct *aging_wq;
57 u32 aging_period_sec;
57};58};
58 59
59int ib_frmr_pools_set_pinned(struct ib_device *device, struct ib_frmr_key *key,60int ib_frmr_pools_set_pinned(struct ib_device *device, struct ib_frmr_key *key,
60 u32 pinned_handles);61 u32 pinned_handles);
62int ib_frmr_pools_set_aging_period(struct ib_device *device, u32 period_sec);
61#endif /* RDMA_CORE_FRMR_POOLS_H */63#endif /* RDMA_CORE_FRMR_POOLS_H */
drivers/infiniband/core/nldev.c+37−0
@@ -184,6 +184,7 @@ static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = { · 183 unmodified lines
184 [RDMA_NLDEV_ATTR_FRMR_POOL_QUEUE_HANDLES] = { .type = NLA_U32 },184 [RDMA_NLDEV_ATTR_FRMR_POOL_QUEUE_HANDLES] = { .type = NLA_U32 },
185 [RDMA_NLDEV_ATTR_FRMR_POOL_MAX_IN_USE] = { .type = NLA_U64 },185 [RDMA_NLDEV_ATTR_FRMR_POOL_MAX_IN_USE] = { .type = NLA_U64 },
186 [RDMA_NLDEV_ATTR_FRMR_POOL_IN_USE] = { .type = NLA_U64 },186 [RDMA_NLDEV_ATTR_FRMR_POOL_IN_USE] = { .type = NLA_U64 },
187 [RDMA_NLDEV_ATTR_FRMR_POOLS_AGING_PERIOD] = { .type = NLA_U32 },
187};188};
188 189
189static int put_driver_name_print_type(struct sk_buff *msg, const char *name,190static int put_driver_name_print_type(struct sk_buff *msg, const char *name,
@@ -2799,6 +2800,38 @@ err: · 2609 unmodified lines
2799 return ret;2800 return ret;
2800}2801}
2801 2802
2803static int nldev_frmr_pools_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
2804 struct netlink_ext_ack *extack)
2805{
2806 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
2807 struct ib_device *device;
2808 u32 aging_period;
2809 int err;
2810
2811 err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1, nldev_policy,
2812 extack);
2813 if (err)
2814 return err;
2815
2816 if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX])
2817 return -EINVAL;
2818
2819 if (!tb[RDMA_NLDEV_ATTR_FRMR_POOLS_AGING_PERIOD])
2820 return -EINVAL;
2821
2822 device = ib_device_get_by_index(
2823 sock_net(skb->sk), nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]));
2824 if (!device)
2825 return -EINVAL;
2826
2827 aging_period = nla_get_u32(tb[RDMA_NLDEV_ATTR_FRMR_POOLS_AGING_PERIOD]);
2828
2829 err = ib_frmr_pools_set_aging_period(device, aging_period);
2830
2831 ib_device_put(device);
2832 return err;
2833}
2834
2802static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {2835static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
2803 [RDMA_NLDEV_CMD_GET] = {2836 [RDMA_NLDEV_CMD_GET] = {
2804 .doit = nldev_get_doit,2837 .doit = nldev_get_doit,
@@ -2908,6 +2941,10 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = { · 103 unmodified lines
2908 [RDMA_NLDEV_CMD_FRMR_POOLS_GET] = {2941 [RDMA_NLDEV_CMD_FRMR_POOLS_GET] = {
2909 .dump = nldev_frmr_pools_get_dumpit,2942 .dump = nldev_frmr_pools_get_dumpit,
2910 },2943 },
2944 [RDMA_NLDEV_CMD_FRMR_POOLS_SET] = {
2945 .doit = nldev_frmr_pools_set_doit,
2946 .flags = RDMA_NL_ADMIN_PERM,
2947 },
2911};2948};
2912 2949
2913static int fill_mon_netdev_rename(struct sk_buff *msg,2950static int fill_mon_netdev_rename(struct sk_buff *msg,
include/uapi/rdma/rdma_netlink.h+3−0
@@ -310,6 +310,8 @@ enum rdma_nldev_command { · 309 unmodified lines
310 310
311 RDMA_NLDEV_CMD_FRMR_POOLS_GET, /* can dump */311 RDMA_NLDEV_CMD_FRMR_POOLS_GET, /* can dump */
312 312
313 RDMA_NLDEV_CMD_FRMR_POOLS_SET,
314
313 RDMA_NLDEV_NUM_OPS315 RDMA_NLDEV_NUM_OPS
314};316};
315 317
@@ -598,6 +600,7 @@ enum rdma_nldev_attr { · 282 unmodified lines
598 RDMA_NLDEV_ATTR_FRMR_POOL_QUEUE_HANDLES, /* u32 */600 RDMA_NLDEV_ATTR_FRMR_POOL_QUEUE_HANDLES, /* u32 */
599 RDMA_NLDEV_ATTR_FRMR_POOL_MAX_IN_USE, /* u64 */601 RDMA_NLDEV_ATTR_FRMR_POOL_MAX_IN_USE, /* u64 */
600 RDMA_NLDEV_ATTR_FRMR_POOL_IN_USE, /* u64 */602 RDMA_NLDEV_ATTR_FRMR_POOL_IN_USE, /* u64 */
603 RDMA_NLDEV_ATTR_FRMR_POOLS_AGING_PERIOD, /* u32 */
601 604
602 /*605 /*
603 * Always the end606 * Always the end