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.
Unified · Split
| @@ -174,7 +174,7 @@ out: · 173 unmodified lines | ||
| 174 | 174 | if (has_work) |
| 175 | 175 | queue_delayed_work( |
| 176 | 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 | |
| 180 | 180 | 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 | ||
| 213 | 213 | return -ENOMEM; |
| 214 | 214 | } |
| 215 | 215 | |
| 216 | + pools->aging_period_sec = FRMR_POOLS_DEFAULT_AGING_PERIOD_SECS; | |
| 217 | + | |
| 216 | 218 | device->frmr_pools = pools; |
| 217 | 219 | return 0; |
| 218 | 220 | } |
| @@ -245,6 +247,31 @@ void ib_frmr_pools_cleanup(struct ib_device *device) · 26 unmodified lines | ||
| 245 | 247 | } |
| 246 | 248 | EXPORT_SYMBOL(ib_frmr_pools_cleanup); |
| 247 | 249 | |
| 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 | + | |
| 248 | 275 | static inline int compare_keys(struct ib_frmr_key *key1, |
| 249 | 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 | 541 | if (ret == 0 && schedule_aging) |
| 515 | 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 | 545 | return ret; |
| 519 | 546 | } |
| @@ -54,8 +54,10 @@ struct ib_frmr_pools { · 53 unmodified lines | ||
| 54 | 54 | const struct ib_frmr_pool_ops *pool_ops; |
| 55 | 55 | |
| 56 | 56 | struct workqueue_struct *aging_wq; |
| 57 | + u32 aging_period_sec; | |
| 57 | 58 | }; |
| 58 | 59 | |
| 59 | 60 | int ib_frmr_pools_set_pinned(struct ib_device *device, struct ib_frmr_key *key, |
| 60 | 61 | u32 pinned_handles); |
| 62 | +int ib_frmr_pools_set_aging_period(struct ib_device *device, u32 period_sec); | |
| 61 | 63 | #endif /* RDMA_CORE_FRMR_POOLS_H */ |
| @@ -184,6 +184,7 @@ static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = { · 183 unmodified lines | ||
| 184 | 184 | [RDMA_NLDEV_ATTR_FRMR_POOL_QUEUE_HANDLES] = { .type = NLA_U32 }, |
| 185 | 185 | [RDMA_NLDEV_ATTR_FRMR_POOL_MAX_IN_USE] = { .type = NLA_U64 }, |
| 186 | 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 | |
| 189 | 190 | static int put_driver_name_print_type(struct sk_buff *msg, const char *name, |
| @@ -2799,6 +2800,38 @@ err: · 2609 unmodified lines | ||
| 2799 | 2800 | return ret; |
| 2800 | 2801 | } |
| 2801 | 2802 | |
| 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 | + | |
| 2802 | 2835 | static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = { |
| 2803 | 2836 | [RDMA_NLDEV_CMD_GET] = { |
| 2804 | 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 | 2941 | [RDMA_NLDEV_CMD_FRMR_POOLS_GET] = { |
| 2909 | 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 | |
| 2913 | 2950 | static int fill_mon_netdev_rename(struct sk_buff *msg, |
| @@ -310,6 +310,8 @@ enum rdma_nldev_command { · 309 unmodified lines | ||
| 310 | 310 | |
| 311 | 311 | RDMA_NLDEV_CMD_FRMR_POOLS_GET, /* can dump */ |
| 312 | 312 | |
| 313 | + RDMA_NLDEV_CMD_FRMR_POOLS_SET, | |
| 314 | + | |
| 313 | 315 | RDMA_NLDEV_NUM_OPS |
| 314 | 316 | }; |
| 315 | 317 | |
| @@ -598,6 +600,7 @@ enum rdma_nldev_attr { · 282 unmodified lines | ||
| 598 | 600 | RDMA_NLDEV_ATTR_FRMR_POOL_QUEUE_HANDLES, /* u32 */ |
| 599 | 601 | RDMA_NLDEV_ATTR_FRMR_POOL_MAX_IN_USE, /* u64 */ |
| 600 | 602 | RDMA_NLDEV_ATTR_FRMR_POOL_IN_USE, /* u64 */ |
| 603 | + RDMA_NLDEV_ATTR_FRMR_POOLS_AGING_PERIOD, /* u32 */ | |
| 601 | 604 | |
| 602 | 605 | /* |
| 603 | 606 | * Always the end |