RDMA/uverbs: Convert the write interface to use uverbs_api
authorJason Gunthorpe <jgg@mellanox.com>
Mon, 12 Nov 2018 20:59:56 +0000 (22:59 +0200)
committerJason Gunthorpe <jgg@mellanox.com>
Thu, 22 Nov 2018 18:57:33 +0000 (11:57 -0700)
This organizes the write commands into objects and links them to the
uverbs_api data structure. The command path is reworked to use uapi
instead of its internal structures.

The command mask is moved from a runtime check to a registration time
check in the uapi.

Since the write interface does not have the object ID as part of the
command, the radix bins are converted into linear lists to support the
lookup.

Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
drivers/infiniband/core/rdma_core.h
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/core/uverbs_uapi.c

index d36a0573c5e41145b38435bdfc4ec6bf3e697986..f9039cfb28b4d4c2917066396fae046f1eddffac 100644 (file)
@@ -182,5 +182,26 @@ extern const struct uapi_definition uverbs_def_obj_dm[];
 extern const struct uapi_definition uverbs_def_obj_flow_action[];
 extern const struct uapi_definition uverbs_def_obj_intf[];
 extern const struct uapi_definition uverbs_def_obj_mr[];
+extern const struct uapi_definition uverbs_def_write_intf[];
+
+static inline const struct uverbs_api_write_method *
+uapi_get_method(const struct uverbs_api *uapi, u32 command)
+{
+       u32 cmd_idx = command & IB_USER_VERBS_CMD_COMMAND_MASK;
+
+       if (command & ~(u32)(IB_USER_VERBS_CMD_FLAG_EXTENDED |
+                            IB_USER_VERBS_CMD_COMMAND_MASK))
+               return ERR_PTR(-EINVAL);
+
+       if (command & IB_USER_VERBS_CMD_FLAG_EXTENDED) {
+               if (cmd_idx >= uapi->num_write_ex)
+                       return ERR_PTR(-EOPNOTSUPP);
+               return uapi->write_ex_methods[cmd_idx];
+       }
+
+       if (cmd_idx >= uapi->num_write)
+               return ERR_PTR(-EOPNOTSUPP);
+       return uapi->write_methods[cmd_idx];
+}
 
 #endif /* RDMA_CORE_H */
index c97935a0c7c6ef2f9beb9c011bdd840dcbdcc27f..f5bc99eae222ee5cecb9168a546175122c545233 100644 (file)
@@ -161,9 +161,6 @@ struct ib_uverbs_file {
        struct mutex umap_lock;
        struct list_head umaps;
 
-       u64 uverbs_cmd_mask;
-       u64 uverbs_ex_cmd_mask;
-
        struct idr              idr;
        /* spinlock protects write access to idr */
        spinlock_t              idr_lock;
index a93853770e3ccf3c7f4bfc8e08df55d466c62e65..e82514284b19bc3752dc957ed330c983bbe84512 100644 (file)
@@ -4126,3 +4126,135 @@ int ib_uverbs_ex_modify_cq(struct ib_uverbs_file *file,
 
        return ret;
 }
+
+const struct uapi_definition uverbs_def_write_intf[] = {
+       DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_AH,
+                             DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_AH,
+                                                  ib_uverbs_create_ah),
+                             DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_AH,
+                                                  ib_uverbs_destroy_ah)),
+
+       DECLARE_UVERBS_OBJECT(
+               UVERBS_OBJECT_COMP_CHANNEL,
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL,
+                                    ib_uverbs_create_comp_channel)),
+
+       DECLARE_UVERBS_OBJECT(
+               UVERBS_OBJECT_CQ,
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_CQ,
+                                    ib_uverbs_create_cq),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_CQ,
+                                    ib_uverbs_destroy_cq),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POLL_CQ,
+                                    ib_uverbs_poll_cq),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REQ_NOTIFY_CQ,
+                                    ib_uverbs_req_notify_cq),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_RESIZE_CQ,
+                                    ib_uverbs_resize_cq),
+               DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_CQ,
+                                       ib_uverbs_ex_create_cq),
+               DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_MODIFY_CQ,
+                                       ib_uverbs_ex_modify_cq)),
+
+       DECLARE_UVERBS_OBJECT(
+               UVERBS_OBJECT_DEVICE,
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_GET_CONTEXT,
+                                    ib_uverbs_get_context),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_DEVICE,
+                                    ib_uverbs_query_device),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_PORT,
+                                    ib_uverbs_query_port),
+               DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_QUERY_DEVICE,
+                                       ib_uverbs_ex_query_device)),
+
+       DECLARE_UVERBS_OBJECT(
+               UVERBS_OBJECT_FLOW,
+               DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_FLOW,
+                                       ib_uverbs_ex_create_flow),
+               DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_DESTROY_FLOW,
+                                       ib_uverbs_ex_destroy_flow)),
+
+       DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_MR,
+                             DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEREG_MR,
+                                                  ib_uverbs_dereg_mr),
+                             DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REG_MR,
+                                                  ib_uverbs_reg_mr),
+                             DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REREG_MR,
+                                                  ib_uverbs_rereg_mr)),
+
+       DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_MW,
+                             DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ALLOC_MW,
+                                                  ib_uverbs_alloc_mw),
+                             DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEALLOC_MW,
+                                                  ib_uverbs_dealloc_mw)),
+
+       DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_PD,
+                             DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ALLOC_PD,
+                                                  ib_uverbs_alloc_pd),
+                             DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEALLOC_PD,
+                                                  ib_uverbs_dealloc_pd)),
+
+       DECLARE_UVERBS_OBJECT(
+               UVERBS_OBJECT_QP,
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ATTACH_MCAST,
+                                    ib_uverbs_attach_mcast),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_QP,
+                                    ib_uverbs_create_qp),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_QP,
+                                    ib_uverbs_destroy_qp),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DETACH_MCAST,
+                                    ib_uverbs_detach_mcast),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_MODIFY_QP,
+                                    ib_uverbs_modify_qp),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POST_RECV,
+                                    ib_uverbs_post_recv),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POST_SEND,
+                                    ib_uverbs_post_send),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_QP,
+                                    ib_uverbs_query_qp),
+               DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_QP,
+                                       ib_uverbs_ex_create_qp),
+               DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_MODIFY_QP,
+                                       ib_uverbs_ex_modify_qp)),
+
+       DECLARE_UVERBS_OBJECT(
+               UVERBS_OBJECT_RWQ_IND_TBL,
+               DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL,
+                                       ib_uverbs_ex_create_rwq_ind_table),
+               DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL,
+                                       ib_uverbs_ex_destroy_rwq_ind_table)),
+
+       DECLARE_UVERBS_OBJECT(
+               UVERBS_OBJECT_WQ,
+               DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_WQ,
+                                       ib_uverbs_ex_create_wq),
+               DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_DESTROY_WQ,
+                                       ib_uverbs_ex_destroy_wq),
+               DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_MODIFY_WQ,
+                                       ib_uverbs_ex_modify_wq)),
+
+       DECLARE_UVERBS_OBJECT(
+               UVERBS_OBJECT_SRQ,
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_SRQ,
+                                    ib_uverbs_create_srq),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_XSRQ,
+                                    ib_uverbs_create_xsrq),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_SRQ,
+                                    ib_uverbs_destroy_srq),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_MODIFY_SRQ,
+                                    ib_uverbs_modify_srq),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POST_SRQ_RECV,
+                                    ib_uverbs_post_srq_recv),
+               DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_SRQ,
+                                    ib_uverbs_query_srq)),
+
+       DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_XRCD,
+                             DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CLOSE_XRCD,
+                                                  ib_uverbs_close_xrcd),
+                             DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_QP,
+                                                  ib_uverbs_open_qp),
+                             DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_XRCD,
+                                                  ib_uverbs_open_xrcd)),
+
+       {},
+};
index 375121a4dd12a7a706546c21a717739c989a1965..6a1284c8a07d900eb7e9ddb09b51438d7a6b6839 100644 (file)
@@ -74,64 +74,6 @@ static dev_t dynamic_uverbs_dev;
 static struct class *uverbs_class;
 
 static DEFINE_IDA(uverbs_ida);
-
-static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
-                                    const char __user *buf, int in_len,
-                                    int out_len) = {
-       [IB_USER_VERBS_CMD_GET_CONTEXT]         = ib_uverbs_get_context,
-       [IB_USER_VERBS_CMD_QUERY_DEVICE]        = ib_uverbs_query_device,
-       [IB_USER_VERBS_CMD_QUERY_PORT]          = ib_uverbs_query_port,
-       [IB_USER_VERBS_CMD_ALLOC_PD]            = ib_uverbs_alloc_pd,
-       [IB_USER_VERBS_CMD_DEALLOC_PD]          = ib_uverbs_dealloc_pd,
-       [IB_USER_VERBS_CMD_REG_MR]              = ib_uverbs_reg_mr,
-       [IB_USER_VERBS_CMD_REREG_MR]            = ib_uverbs_rereg_mr,
-       [IB_USER_VERBS_CMD_DEREG_MR]            = ib_uverbs_dereg_mr,
-       [IB_USER_VERBS_CMD_ALLOC_MW]            = ib_uverbs_alloc_mw,
-       [IB_USER_VERBS_CMD_DEALLOC_MW]          = ib_uverbs_dealloc_mw,
-       [IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel,
-       [IB_USER_VERBS_CMD_CREATE_CQ]           = ib_uverbs_create_cq,
-       [IB_USER_VERBS_CMD_RESIZE_CQ]           = ib_uverbs_resize_cq,
-       [IB_USER_VERBS_CMD_POLL_CQ]             = ib_uverbs_poll_cq,
-       [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ]       = ib_uverbs_req_notify_cq,
-       [IB_USER_VERBS_CMD_DESTROY_CQ]          = ib_uverbs_destroy_cq,
-       [IB_USER_VERBS_CMD_CREATE_QP]           = ib_uverbs_create_qp,
-       [IB_USER_VERBS_CMD_QUERY_QP]            = ib_uverbs_query_qp,
-       [IB_USER_VERBS_CMD_MODIFY_QP]           = ib_uverbs_modify_qp,
-       [IB_USER_VERBS_CMD_DESTROY_QP]          = ib_uverbs_destroy_qp,
-       [IB_USER_VERBS_CMD_POST_SEND]           = ib_uverbs_post_send,
-       [IB_USER_VERBS_CMD_POST_RECV]           = ib_uverbs_post_recv,
-       [IB_USER_VERBS_CMD_POST_SRQ_RECV]       = ib_uverbs_post_srq_recv,
-       [IB_USER_VERBS_CMD_CREATE_AH]           = ib_uverbs_create_ah,
-       [IB_USER_VERBS_CMD_DESTROY_AH]          = ib_uverbs_destroy_ah,
-       [IB_USER_VERBS_CMD_ATTACH_MCAST]        = ib_uverbs_attach_mcast,
-       [IB_USER_VERBS_CMD_DETACH_MCAST]        = ib_uverbs_detach_mcast,
-       [IB_USER_VERBS_CMD_CREATE_SRQ]          = ib_uverbs_create_srq,
-       [IB_USER_VERBS_CMD_MODIFY_SRQ]          = ib_uverbs_modify_srq,
-       [IB_USER_VERBS_CMD_QUERY_SRQ]           = ib_uverbs_query_srq,
-       [IB_USER_VERBS_CMD_DESTROY_SRQ]         = ib_uverbs_destroy_srq,
-       [IB_USER_VERBS_CMD_OPEN_XRCD]           = ib_uverbs_open_xrcd,
-       [IB_USER_VERBS_CMD_CLOSE_XRCD]          = ib_uverbs_close_xrcd,
-       [IB_USER_VERBS_CMD_CREATE_XSRQ]         = ib_uverbs_create_xsrq,
-       [IB_USER_VERBS_CMD_OPEN_QP]             = ib_uverbs_open_qp,
-};
-
-static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
-                                   struct ib_udata *ucore,
-                                   struct ib_udata *uhw) = {
-       [IB_USER_VERBS_EX_CMD_CREATE_FLOW]      = ib_uverbs_ex_create_flow,
-       [IB_USER_VERBS_EX_CMD_DESTROY_FLOW]     = ib_uverbs_ex_destroy_flow,
-       [IB_USER_VERBS_EX_CMD_QUERY_DEVICE]     = ib_uverbs_ex_query_device,
-       [IB_USER_VERBS_EX_CMD_CREATE_CQ]        = ib_uverbs_ex_create_cq,
-       [IB_USER_VERBS_EX_CMD_CREATE_QP]        = ib_uverbs_ex_create_qp,
-       [IB_USER_VERBS_EX_CMD_CREATE_WQ]        = ib_uverbs_ex_create_wq,
-       [IB_USER_VERBS_EX_CMD_MODIFY_WQ]        = ib_uverbs_ex_modify_wq,
-       [IB_USER_VERBS_EX_CMD_DESTROY_WQ]       = ib_uverbs_ex_destroy_wq,
-       [IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL] = ib_uverbs_ex_create_rwq_ind_table,
-       [IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL] = ib_uverbs_ex_destroy_rwq_ind_table,
-       [IB_USER_VERBS_EX_CMD_MODIFY_QP]        = ib_uverbs_ex_modify_qp,
-       [IB_USER_VERBS_EX_CMD_MODIFY_CQ]        = ib_uverbs_ex_modify_cq,
-};
-
 static void ib_uverbs_add_one(struct ib_device *device);
 static void ib_uverbs_remove_one(struct ib_device *device, void *client_data);
 
@@ -646,41 +588,6 @@ err_put_refs:
        return filp;
 }
 
-static bool verify_command_mask(struct ib_uverbs_file *ufile, u32 command,
-                               bool extended)
-{
-       if (!extended)
-               return ufile->uverbs_cmd_mask & BIT_ULL(command);
-
-       return ufile->uverbs_ex_cmd_mask & BIT_ULL(command);
-}
-
-static bool verify_command_idx(u32 command, bool extended)
-{
-       if (extended)
-               return command < ARRAY_SIZE(uverbs_ex_cmd_table) &&
-                      uverbs_ex_cmd_table[command];
-
-       return command < ARRAY_SIZE(uverbs_cmd_table) &&
-              uverbs_cmd_table[command];
-}
-
-static ssize_t process_hdr(struct ib_uverbs_cmd_hdr *hdr,
-                          u32 *command, bool *extended)
-{
-       if (hdr->command & ~(u32)(IB_USER_VERBS_CMD_FLAG_EXTENDED |
-                                  IB_USER_VERBS_CMD_COMMAND_MASK))
-               return -EINVAL;
-
-       *command = hdr->command & IB_USER_VERBS_CMD_COMMAND_MASK;
-       *extended = hdr->command & IB_USER_VERBS_CMD_FLAG_EXTENDED;
-
-       if (!verify_command_idx(*command, *extended))
-               return -EOPNOTSUPP;
-
-       return 0;
-}
-
 static ssize_t verify_hdr(struct ib_uverbs_cmd_hdr *hdr,
                          struct ib_uverbs_ex_cmd_hdr *ex_hdr,
                          size_t count, bool extended)
@@ -721,11 +628,11 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
                             size_t count, loff_t *pos)
 {
        struct ib_uverbs_file *file = filp->private_data;
+       const struct uverbs_api_write_method *method_elm;
+       struct uverbs_api *uapi = file->device->uapi;
        struct ib_uverbs_ex_cmd_hdr ex_hdr;
        struct ib_uverbs_cmd_hdr hdr;
-       bool extended;
        int srcu_key;
-       u32 command;
        ssize_t ret;
 
        if (!ib_safe_file_access(filp)) {
@@ -740,34 +647,28 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
        if (copy_from_user(&hdr, buf, sizeof(hdr)))
                return -EFAULT;
 
-       ret = process_hdr(&hdr, &command, &extended);
-       if (ret)
-               return ret;
+       method_elm = uapi_get_method(uapi, hdr.command);
+       if (IS_ERR(method_elm))
+               return PTR_ERR(method_elm);
 
-       if (extended) {
+       if (method_elm->is_ex) {
                if (count < (sizeof(hdr) + sizeof(ex_hdr)))
                        return -EINVAL;
                if (copy_from_user(&ex_hdr, buf + sizeof(hdr), sizeof(ex_hdr)))
                        return -EFAULT;
        }
 
-       ret = verify_hdr(&hdr, &ex_hdr, count, extended);
+       ret = verify_hdr(&hdr, &ex_hdr, count, method_elm->is_ex);
        if (ret)
                return ret;
 
        srcu_key = srcu_read_lock(&file->device->disassociate_srcu);
 
-       if (!verify_command_mask(file, command, extended)) {
-               ret = -EOPNOTSUPP;
-               goto out;
-       }
-
        buf += sizeof(hdr);
 
-       if (!extended) {
-               ret = uverbs_cmd_table[command](file, buf,
-                                               hdr.in_words * 4,
-                                               hdr.out_words * 4);
+       if (!method_elm->is_ex) {
+               ret = method_elm->handler(file, buf, hdr.in_words * 4,
+                                         hdr.out_words * 4);
        } else {
                struct ib_udata ucore;
                struct ib_udata uhw;
@@ -784,11 +685,10 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
                                        ex_hdr.provider_in_words * 8,
                                        ex_hdr.provider_out_words * 8);
 
-               ret = uverbs_ex_cmd_table[command](file, &ucore, &uhw);
+               ret = method_elm->handler_ex(file, &ucore, &uhw);
                ret = (ret) ? : count;
        }
 
-out:
        srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
        return ret;
 }
@@ -1102,9 +1002,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
        mutex_unlock(&dev->lists_mutex);
        srcu_read_unlock(&dev->disassociate_srcu, srcu_key);
 
-       file->uverbs_cmd_mask = ib_dev->uverbs_cmd_mask;
-       file->uverbs_ex_cmd_mask = ib_dev->uverbs_ex_cmd_mask;
-
        setup_ufile_idr_uobject(file);
 
        return nonseekable_open(inode, filp);
index 1cf79fc33c378563b91022602dff9cffab75f897..1e880f1d9d625c5eda83746d3b4b44909af23b6c 100644 (file)
@@ -587,6 +587,7 @@ static const struct uapi_definition uverbs_core_api[] = {
        UAPI_DEF_CHAIN(uverbs_def_obj_flow_action),
        UAPI_DEF_CHAIN(uverbs_def_obj_intf),
        UAPI_DEF_CHAIN(uverbs_def_obj_mr),
+       UAPI_DEF_CHAIN(uverbs_def_write_intf),
        {},
 };