Upgrade to 4.4.50-rt62
[kvmfornfv.git] / kernel / drivers / infiniband / core / uverbs_main.c
index e3ef288..7becef2 100644 (file)
@@ -48,6 +48,8 @@
 
 #include <asm/uaccess.h>
 
+#include <rdma/ib.h>
+
 #include "uverbs.h"
 
 MODULE_AUTHOR("Roland Dreier");
@@ -242,12 +244,9 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
                        container_of(uobj, struct ib_uqp_object, uevent.uobject);
 
                idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
-               if (qp != qp->real_qp) {
-                       ib_close_qp(qp);
-               } else {
+               if (qp == qp->real_qp)
                        ib_uverbs_detach_umcast(qp, uqp);
-                       ib_destroy_qp(qp);
-               }
+               ib_destroy_qp(qp);
                ib_uverbs_release_uevent(file, &uqp->uevent);
                kfree(uqp);
        }
@@ -682,6 +681,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
        int srcu_key;
        ssize_t ret;
 
+       if (WARN_ON_ONCE(!ib_safe_file_access(filp)))
+               return -EACCES;
+
        if (count < sizeof hdr)
                return -EINVAL;
 
@@ -917,6 +919,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
        file->async_file = NULL;
        kref_init(&file->ref);
        mutex_init(&file->mutex);
+       mutex_init(&file->cleanup_mutex);
 
        filp->private_data = file;
        kobject_get(&dev->kobj);
@@ -942,18 +945,20 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
 {
        struct ib_uverbs_file *file = filp->private_data;
        struct ib_uverbs_device *dev = file->device;
-       struct ib_ucontext *ucontext = NULL;
+
+       mutex_lock(&file->cleanup_mutex);
+       if (file->ucontext) {
+               ib_uverbs_cleanup_ucontext(file, file->ucontext);
+               file->ucontext = NULL;
+       }
+       mutex_unlock(&file->cleanup_mutex);
 
        mutex_lock(&file->device->lists_mutex);
-       ucontext = file->ucontext;
-       file->ucontext = NULL;
        if (!file->is_closed) {
                list_del(&file->list);
                file->is_closed = 1;
        }
        mutex_unlock(&file->device->lists_mutex);
-       if (ucontext)
-               ib_uverbs_cleanup_ucontext(file, ucontext);
 
        if (file->async_file)
                kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
@@ -1167,22 +1172,30 @@ static void ib_uverbs_free_hw_resources(struct ib_uverbs_device *uverbs_dev,
        mutex_lock(&uverbs_dev->lists_mutex);
        while (!list_empty(&uverbs_dev->uverbs_file_list)) {
                struct ib_ucontext *ucontext;
-
                file = list_first_entry(&uverbs_dev->uverbs_file_list,
                                        struct ib_uverbs_file, list);
                file->is_closed = 1;
-               ucontext = file->ucontext;
                list_del(&file->list);
-               file->ucontext = NULL;
                kref_get(&file->ref);
                mutex_unlock(&uverbs_dev->lists_mutex);
-               /* We must release the mutex before going ahead and calling
-                * disassociate_ucontext. disassociate_ucontext might end up
-                * indirectly calling uverbs_close, for example due to freeing
-                * the resources (e.g mmput).
-                */
+
                ib_uverbs_event_handler(&file->event_handler, &event);
+
+               mutex_lock(&file->cleanup_mutex);
+               ucontext = file->ucontext;
+               file->ucontext = NULL;
+               mutex_unlock(&file->cleanup_mutex);
+
+               /* At this point ib_uverbs_close cannot be running
+                * ib_uverbs_cleanup_ucontext
+                */
                if (ucontext) {
+                       /* We must release the mutex before going ahead and
+                        * calling disassociate_ucontext. disassociate_ucontext
+                        * might end up indirectly calling uverbs_close,
+                        * for example due to freeing the resources
+                        * (e.g mmput).
+                        */
                        ib_dev->disassociate_ucontext(ucontext);
                        ib_uverbs_cleanup_ucontext(file, ucontext);
                }