RDMA/uverbs: Add a method to introspect handles in a context
authorJason Gunthorpe <jgg@mellanox.com>
Fri, 30 Nov 2018 11:16:47 +0000 (13:16 +0200)
committerJason Gunthorpe <jgg@mellanox.com>
Tue, 18 Dec 2018 21:54:54 +0000 (14:54 -0700)
Introduce a helper function gather_objects_handle() to copy object handles
under a spin lock.

Expose these objects handles via the uverbs ioctl interface.

Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Parav Pandit <parav@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
drivers/infiniband/core/uverbs_std_types_device.c
include/uapi/rdma/ib_user_ioctl_cmds.h

index aafb251b7d372da3c183dd82037bf74cd1399323..165ece1eb6552c618a1b294143074acdcb3bb963 100644 (file)
@@ -51,8 +51,95 @@ DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_INVOKE_WRITE,
                                                UA_OPTIONAL),
                            UVERBS_ATTR_UHW());
 
+static uint32_t *
+gather_objects_handle(struct ib_uverbs_file *ufile,
+                     const struct uverbs_api_object *uapi_object,
+                     struct uverbs_attr_bundle *attrs,
+                     ssize_t out_len,
+                     u64 *total)
+{
+       u64 max_count = out_len / sizeof(u32);
+       struct ib_uobject *obj;
+       u64 count = 0;
+       u32 *handles;
+
+       /* Allocated memory that cannot page out where we gather
+        * all object ids under a spin_lock.
+        */
+       handles = uverbs_zalloc(attrs, out_len);
+       if (IS_ERR(handles))
+               return handles;
+
+       spin_lock_irq(&ufile->uobjects_lock);
+       list_for_each_entry(obj, &ufile->uobjects, list) {
+               u32 obj_id = obj->id;
+
+               if (obj->uapi_object != uapi_object)
+                       continue;
+
+               if (count >= max_count)
+                       break;
+
+               handles[count] = obj_id;
+               count++;
+       }
+       spin_unlock_irq(&ufile->uobjects_lock);
+
+       *total = count;
+       return handles;
+}
+
+static int UVERBS_HANDLER(UVERBS_METHOD_INFO_HANDLES)(
+       struct uverbs_attr_bundle *attrs)
+{
+       const struct uverbs_api_object *uapi_object;
+       ssize_t out_len;
+       u64 total = 0;
+       u16 object_id;
+       u32 *handles;
+       int ret;
+
+       out_len = uverbs_attr_get_len(attrs, UVERBS_ATTR_INFO_HANDLES_LIST);
+       if (out_len <= 0 || (out_len % sizeof(u32) != 0))
+               return -EINVAL;
+
+       ret = uverbs_get_const(&object_id, attrs, UVERBS_ATTR_INFO_OBJECT_ID);
+       if (ret)
+               return ret;
+
+       uapi_object = uapi_get_object(attrs->ufile->device->uapi, object_id);
+       if (!uapi_object)
+               return -EINVAL;
+
+       handles = gather_objects_handle(attrs->ufile, uapi_object, attrs,
+                                       out_len, &total);
+       if (IS_ERR(handles))
+               return PTR_ERR(handles);
+
+       ret = uverbs_copy_to(attrs, UVERBS_ATTR_INFO_HANDLES_LIST, handles,
+                            sizeof(u32) * total);
+       if (ret)
+               goto err;
+
+       ret = uverbs_copy_to(attrs, UVERBS_ATTR_INFO_TOTAL_HANDLES, &total,
+                            sizeof(total));
+err:
+       return ret;
+}
+
+DECLARE_UVERBS_NAMED_METHOD(
+       UVERBS_METHOD_INFO_HANDLES,
+       /* Also includes any device specific object ids */
+       UVERBS_ATTR_CONST_IN(UVERBS_ATTR_INFO_OBJECT_ID,
+                            enum uverbs_default_objects, UA_MANDATORY),
+       UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_INFO_TOTAL_HANDLES,
+                           UVERBS_ATTR_TYPE(u32), UA_OPTIONAL),
+       UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_INFO_HANDLES_LIST,
+                           UVERBS_ATTR_MIN_SIZE(sizeof(u32)), UA_OPTIONAL));
+
 DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE,
-                             &UVERBS_METHOD(UVERBS_METHOD_INVOKE_WRITE));
+                             &UVERBS_METHOD(UVERBS_METHOD_INVOKE_WRITE),
+                             &UVERBS_METHOD(UVERBS_METHOD_INFO_HANDLES));
 
 const struct uapi_definition uverbs_def_obj_device[] = {
        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE),
index 34e71994f4a559fd790805e5f0f683c01768a9a6..cf6e5f5756969c8dd0284bb5fb3aec65e445f6e2 100644 (file)
@@ -65,6 +65,7 @@ enum {
 
 enum uverbs_methods_device {
        UVERBS_METHOD_INVOKE_WRITE,
+       UVERBS_METHOD_INFO_HANDLES,
 };
 
 enum uverbs_attrs_invoke_write_cmd_attr_ids {
@@ -167,4 +168,10 @@ enum uverbs_methods_actions_counters_ops {
        UVERBS_METHOD_COUNTERS_READ,
 };
 
+enum uverbs_attrs_info_handles_id {
+       UVERBS_ATTR_INFO_OBJECT_ID,
+       UVERBS_ATTR_INFO_TOTAL_HANDLES,
+       UVERBS_ATTR_INFO_HANDLES_LIST,
+};
+
 #endif