RDMA/core: Align abort/commit object scheme for write() and ioctl() paths
authorLeon Romanovsky <leonro@mellanox.com>
Sun, 19 Jul 2020 05:22:22 +0000 (08:22 +0300)
committerJason Gunthorpe <jgg@nvidia.com>
Fri, 24 Jul 2020 18:57:22 +0000 (15:57 -0300)
Create the same logic flow for the write() interface as we have for the
ioctl() path by making sure that the object is committed or aborted
automatically after HW object creation.

Link: https://lore.kernel.org/r/20200719052223.75245-2-leon@kernel.org
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/core/uverbs_std_types_device.c
include/rdma/uverbs_ioctl.h
include/rdma/uverbs_std_types.h

index 69e4755cc04ba2f28b2017ef3e872da4a953eb37..37794d88b1f3bbc6f7e2d623d2d663b7bef5abae 100644 (file)
@@ -601,6 +601,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
        memset(bundle.attr_present, 0, sizeof(bundle.attr_present));
        bundle.ufile = file;
        bundle.context = NULL; /* only valid if bundle has uobject */
+       bundle.uobject = NULL;
        if (!method_elm->is_ex) {
                size_t in_len = hdr.in_words * 4 - sizeof(hdr);
                size_t out_len = hdr.out_words * 4;
@@ -664,6 +665,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
        }
 
        ret = method_elm->handler(&bundle);
+       if (bundle.uobject)
+               uverbs_finalize_object(bundle.uobject, UVERBS_ACCESS_NEW, true,
+                                      !ret, &bundle);
 out_unlock:
        srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
        return (ret) ? : count;
index 8e58605a17be4e56d1e6f8b83486995dc197738f..75df2094a0104b40e3cdd173e56f749e469d0578 100644 (file)
@@ -38,7 +38,12 @@ static int UVERBS_HANDLER(UVERBS_METHOD_INVOKE_WRITE)(
            attrs->ucore.outlen < method_elm->resp_size)
                return -ENOSPC;
 
-       return method_elm->handler(attrs);
+       attrs->uobject = NULL;
+       rc = method_elm->handler(attrs);
+       if (attrs->uobject)
+               uverbs_finalize_object(attrs->uobject, UVERBS_ACCESS_NEW, true,
+                                      !rc, attrs);
+       return rc;
 }
 
 DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_INVOKE_WRITE,
index 86de10ea30afb150cd2a81f387442e568bf370e2..db419c8dbd10274c025c55c79aad93be4ca72dd2 100644 (file)
@@ -652,6 +652,7 @@ struct uverbs_attr_bundle {
        struct ib_udata ucore;
        struct ib_uverbs_file *ufile;
        struct ib_ucontext *context;
+       struct ib_uobject *uobject;
        DECLARE_BITMAP(attr_present, UVERBS_API_ATTR_BKEY_LEN);
        struct uverbs_attr attrs[];
 };
index bf0392ae15ebcfc19c4feab670d91cec24463c85..8451b19103eeee7b625c77c5853fd542135761a4 100644 (file)
@@ -110,6 +110,20 @@ static inline void uobj_alloc_abort(struct ib_uobject *uobj,
        rdma_alloc_abort_uobject(uobj, attrs, false);
 }
 
+static inline void uobj_finalize_uobj_create(struct ib_uobject *uobj,
+                                            struct uverbs_attr_bundle *attrs)
+{
+       /*
+        * Tell the core code that the write() handler has completed
+        * initializing the object and that the core should commit or
+        * abort this object based upon the return code from the write()
+        * method. Similar to what uverbs_finalize_uobj_create() does for
+        * ioctl()
+        */
+       WARN_ON(attrs->uobject);
+       attrs->uobject = uobj;
+}
+
 static inline struct ib_uobject *
 __uobj_alloc(const struct uverbs_api_object *obj,
             struct uverbs_attr_bundle *attrs, struct ib_device **ib_dev)