In order to accelerate the validation and parsing process, we calculate the number of attributes of all groups in an action and the mandatory attributes bitmask in advance. Signed-off-by: Matan Barak <matanb@xxxxxxxxxxxx> --- drivers/infiniband/core/uverbs.h | 3 ++ drivers/infiniband/core/uverbs_ioctl.c | 58 ++++++++++++++++++++++++++++++++++ drivers/infiniband/core/uverbs_main.c | 3 ++ 3 files changed, 64 insertions(+) diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index a3230b6..6e59a00 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -191,7 +191,10 @@ struct ib_ucq_object { u32 async_events_reported; }; +struct uverbs_type_group; + extern const struct file_operations uverbs_event_fops; +void uverbs_initialize_type_group(const struct uverbs_type_group *type_group); void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue); struct file *ib_uverbs_alloc_async_event_file(struct ib_uverbs_file *uverbs_file, struct ib_device *ib_dev); diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c index 3465a18..18c0799 100644 --- a/drivers/infiniband/core/uverbs_ioctl.c +++ b/drivers/infiniband/core/uverbs_ioctl.c @@ -349,3 +349,61 @@ long ib_uverbs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return err; } + +static void uverbs_initialize_action(struct uverbs_action *action) +{ + size_t attr_group_idx; + + for (attr_group_idx = 0; attr_group_idx < action->num_groups; + attr_group_idx++) { + struct uverbs_attr_spec_group *attr_group = + action->attr_groups[attr_group_idx]; + size_t attr_idx; + + if (!attr_group) + continue; + action->num_child_attrs += attr_group->num_attrs; + for (attr_idx = 0; attr_idx < attr_group->num_attrs; + attr_idx++) { + struct uverbs_attr_spec *attr = + &attr_group->attrs[attr_idx]; + + if (attr->flags & UVERBS_ATTR_SPEC_F_MANDATORY) + set_bit(attr_idx, + attr_group->mandatory_attrs_bitmask); + } + } +} + +void uverbs_initialize_type_group(const struct uverbs_type_group *type_group) +{ + size_t type_idx; + + for (type_idx = 0; type_idx < type_group->num_types; type_idx++) { + const struct uverbs_type *type = type_group->types[type_idx]; + size_t action_group_idx; + + if (!type) + continue; + for (action_group_idx = 0; + action_group_idx < type->num_groups; + action_group_idx++) { + const struct uverbs_action_group *action_group = + type->action_groups[action_group_idx]; + size_t action_idx; + + if (!action_group) + continue; + for (action_idx = 0; + action_idx < action_group->num_actions; + action_idx++) { + struct uverbs_action *action = + action_group->actions[action_idx]; + + if (!action) + continue; + uverbs_initialize_action(action); + } + } + } +} diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index b282daf..44c4d92 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -45,6 +45,7 @@ #include <linux/cdev.h> #include <linux/anon_inodes.h> #include <linux/slab.h> +#include <rdma/uverbs_std_types.h> #include <linux/uaccess.h> @@ -1253,6 +1254,8 @@ static int __init ib_uverbs_init(void) { int ret; + uverbs_initialize_type_group(&uverbs_common_types); + ret = register_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES, "infiniband_verbs"); if (ret) { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html