]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
IB/core: Add lock to multicast handlers
authorMatan Barak <matanb@mellanox.com>
Tue, 4 Apr 2017 10:31:45 +0000 (13:31 +0300)
committerDoug Ledford <dledford@redhat.com>
Wed, 5 Apr 2017 17:28:04 +0000 (13:28 -0400)
When two handlers used the same object in the old schema, we blocked
the process in the kernel. The new schema just returns -EBUSY. This
could lead to different behaviour in applications between the old
schema and the new schema. In most cases, using such handlers
concurrently could lead to crashing the process. For example, if
thread A destroys a QP and thread B modifies it, we could have the
destruction happens before the modification. In this case, we are
accessing freed memory which could lead to crashing the process.
This is true for most cases. However, attaching and detaching
a multicast address from QP concurrently is safe. Therefore, we
preserve the original behaviour by adding a lock there.

Signed-off-by: Matan Barak <matanb@mellanox.com>
Reviewed-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c

index 3660278b62b0f1dd2f791d380c7310fbc579c3e8..27c8b98b36f6ad27d0435b096b05d77f62592fb4 100644 (file)
@@ -163,6 +163,8 @@ struct ib_usrq_object {
 
 struct ib_uqp_object {
        struct ib_uevent_object uevent;
+       /* lock for mcast list */
+       struct mutex            mcast_lock;
        struct list_head        mcast_list;
        struct ib_uxrcd_object *uxrcd;
 };
index 2f258aaec7b94eb9b2e8ddb347860f84cd5d6820..119c10da7751472ea8849722c098b319cdb9001c 100644 (file)
@@ -1352,6 +1352,7 @@ static int create_qp(struct ib_uverbs_file *file,
                return PTR_ERR(obj);
        obj->uxrcd = NULL;
        obj->uevent.uobject.user_handle = cmd->user_handle;
+       mutex_init(&obj->mcast_lock);
 
        if (cmd_sz >= offsetof(typeof(*cmd), rwq_ind_tbl_handle) +
                      sizeof(cmd->rwq_ind_tbl_handle) &&
@@ -2589,6 +2590,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
 
        obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
 
+       mutex_lock(&obj->mcast_lock);
        list_for_each_entry(mcast, &obj->mcast_list, list)
                if (cmd.mlid == mcast->lid &&
                    !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
@@ -2612,6 +2614,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
                kfree(mcast);
 
 out_put:
+       mutex_unlock(&obj->mcast_lock);
        uobj_put_obj_read(qp);
 
        return ret ? ret : in_len;
@@ -2636,6 +2639,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
                return -EINVAL;
 
        obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
+       mutex_lock(&obj->mcast_lock);
 
        ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
        if (ret)
@@ -2650,6 +2654,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
                }
 
 out_put:
+       mutex_unlock(&obj->mcast_lock);
        uobj_put_obj_read(qp);
        return ret ? ret : in_len;
 }