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
174174 if (has_work)
175175 queue_delayed_work(
176176 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)));
178178 }
179179
180180 static void destroy_frmr_pool(struct ib_device *device,
@@ -213,6 +213,8 @@ int ib_frmr_pools_init(struct ib_device *device, · 32 unmodified lines
213213 return -ENOMEM;
214214 }
215215
216+ pools->aging_period_sec = FRMR_POOLS_DEFAULT_AGING_PERIOD_SECS;
217+
216218 device->frmr_pools = pools;
217219 return 0;
218220 }
@@ -245,6 +247,31 @@ void ib_frmr_pools_cleanup(struct ib_device *device) · 26 unmodified lines
245247 }
246248 EXPORT_SYMBOL(ib_frmr_pools_cleanup);
247249
250+int 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+
248275 static inline int compare_keys(struct ib_frmr_key *key1,
249276 struct ib_frmr_key *key2)
250277 {
@@ -513,7 +540,7 @@ int ib_frmr_pool_push(struct ib_device *device, struct ib_mr *mr) · 262 unmodified lines
513540
514541 if (ret == 0 && schedule_aging)
515542 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)));
517544
518545 return ret;
519546 }
drivers/infiniband/core/frmr_pools.h+2−0
@@ -54,8 +54,10 @@ struct ib_frmr_pools { · 53 unmodified lines
5454 const struct ib_frmr_pool_ops *pool_ops;
5555
5656 struct workqueue_struct *aging_wq;
57+ u32 aging_period_sec;
5758 };
5859
5960 int ib_frmr_pools_set_pinned(struct ib_device *device, struct ib_frmr_key *key,
6061 u32 pinned_handles);
62+int ib_frmr_pools_set_aging_period(struct ib_device *device, u32 period_sec);
6163 #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
184184 [RDMA_NLDEV_ATTR_FRMR_POOL_QUEUE_HANDLES] = { .type = NLA_U32 },
185185 [RDMA_NLDEV_ATTR_FRMR_POOL_MAX_IN_USE] = { .type = NLA_U64 },
186186 [RDMA_NLDEV_ATTR_FRMR_POOL_IN_USE] = { .type = NLA_U64 },
187+ [RDMA_NLDEV_ATTR_FRMR_POOLS_AGING_PERIOD] = { .type = NLA_U32 },
187188 };
188189
189190 static int put_driver_name_print_type(struct sk_buff *msg, const char *name,
@@ -2799,6 +2800,38 @@ err: · 2609 unmodified lines
27992800 return ret;
28002801 }
28012802
2803+static 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+
28022835 static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
28032836 [RDMA_NLDEV_CMD_GET] = {
28042837 .doit = nldev_get_doit,
@@ -2908,6 +2941,10 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = { · 103 unmodified lines
29082941 [RDMA_NLDEV_CMD_FRMR_POOLS_GET] = {
29092942 .dump = nldev_frmr_pools_get_dumpit,
29102943 },
2944+ [RDMA_NLDEV_CMD_FRMR_POOLS_SET] = {
2945+ .doit = nldev_frmr_pools_set_doit,
2946+ .flags = RDMA_NL_ADMIN_PERM,
2947+ },
29112948 };
29122949
29132950 static 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
310310
311311 RDMA_NLDEV_CMD_FRMR_POOLS_GET, /* can dump */
312312
313+ RDMA_NLDEV_CMD_FRMR_POOLS_SET,
314+
313315 RDMA_NLDEV_NUM_OPS
314316 };
315317
@@ -598,6 +600,7 @@ enum rdma_nldev_attr { · 282 unmodified lines
598600 RDMA_NLDEV_ATTR_FRMR_POOL_QUEUE_HANDLES, /* u32 */
599601 RDMA_NLDEV_ATTR_FRMR_POOL_MAX_IN_USE, /* u64 */
600602 RDMA_NLDEV_ATTR_FRMR_POOL_IN_USE, /* u64 */
603+ RDMA_NLDEV_ATTR_FRMR_POOLS_AGING_PERIOD, /* u32 */
601604
602605 /*
603606 * Always the end