From patchwork Sun Dec 11 12:57:57 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matan Barak X-Patchwork-Id: 9469729 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 48640607D3 for ; Sun, 11 Dec 2016 12:58:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 422BA2847B for ; Sun, 11 Dec 2016 12:58:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3765128499; Sun, 11 Dec 2016 12:58:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9301528492 for ; Sun, 11 Dec 2016 12:58:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753547AbcLKM6o (ORCPT ); Sun, 11 Dec 2016 07:58:44 -0500 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:57534 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753502AbcLKM6m (ORCPT ); Sun, 11 Dec 2016 07:58:42 -0500 Received: from Internal Mail-Server by MTLPINE1 (envelope-from matanb@mellanox.com) with ESMTPS (AES256-SHA encrypted); 11 Dec 2016 14:58:36 +0200 Received: from gen-l-vrt-078.mtl.labs.mlnx. (gen-l-vrt-078.mtl.labs.mlnx [10.137.78.1]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id uBBCwVNt018366; Sun, 11 Dec 2016 14:58:34 +0200 From: Matan Barak To: linux-rdma@vger.kernel.org Cc: Doug Ledford , Jason Gunthorpe , Sean Hefty , Christoph Lameter , Liran Liss , Haggai Eran , Majd Dibbiny , Matan Barak , Tal Alon , Leon Romanovsky Subject: [RFC ABI V6 03/14] IB/core: Add generic ucontext initialization and teardown Date: Sun, 11 Dec 2016 14:57:57 +0200 Message-Id: <1481461088-56355-4-git-send-email-matanb@mellanox.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1481461088-56355-1-git-send-email-matanb@mellanox.com> References: <1481461088-56355-1-git-send-email-matanb@mellanox.com> Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When a ucontext is created, we need to initialize the list of objects. This list consists of every user object that is associated with this ucontext. The possible elements in this list are either a file descriptor or an object which is represented by an IDR. Every such an object, has a release function (which is called upon object destruction) and a number associated to its release order. When a ucontext is destroyed, the list is traversed while holding a lock. This lock is necessary since a user might try to close a FD file [s]he created and exists in this list. Signed-off-by: Matan Barak --- drivers/infiniband/core/rdma_core.c | 87 +++++++++++++++++++++++++++++++++++++ drivers/infiniband/core/rdma_core.h | 4 ++ 2 files changed, 91 insertions(+) diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c index 398b61f..01221c0 100644 --- a/drivers/infiniband/core/rdma_core.c +++ b/drivers/infiniband/core/rdma_core.c @@ -73,6 +73,12 @@ struct ib_ucontext_lock { struct mutex lock; }; +static void init_uobjects_list_lock(struct ib_ucontext_lock *lock) +{ + mutex_init(&lock->lock); + kref_init(&lock->ref); +} + static void release_uobjects_list_lock(struct kref *ref) { struct ib_ucontext_lock *lock = container_of(ref, @@ -343,6 +349,20 @@ void uverbs_rollback_object(struct ib_uobject *uobj, return _uverbs_commit_object(uobj, access, false); } +static void ib_uverbs_remove_fd(struct ib_uobject *uobject) +{ + /* + * user should release the uobject in the release + * callback. + */ + if (uobject->context) { + list_del(&uobject->list); + uobject->type->free_fn(uobject->type, uobject); + kref_put(&uobject->context->ufile->ref, ib_uverbs_release_file); + uobject->context = NULL; + } +} + void ib_uverbs_close_fd(struct file *f) { struct ib_uobject *uobject = f->private_data - sizeof(struct ib_uobject); @@ -395,3 +415,70 @@ void uverbs_commit_objects(struct uverbs_attr_array *attr_array, } } } + +static unsigned int get_type_orders(const struct uverbs_root *root) +{ + unsigned int i; + unsigned int max = 0; + + for (i = 0; i < root->num_groups; i++) { + unsigned int j; + const struct uverbs_type_group *types = root->type_groups[i]; + + for (j = 0; j < types->num_types; j++) { + if (!types->types[j] || !types->types[j]->alloc) + continue; + if (types->types[j]->alloc->order > max) + max = types->types[j]->alloc->order; + } + } + + return max; +} + +void ib_uverbs_uobject_type_cleanup_ucontext(struct ib_ucontext *ucontext, + const struct uverbs_root *root) +{ + unsigned int num_orders = get_type_orders(root); + unsigned int i; + + for (i = 0; i <= num_orders; i++) { + struct ib_uobject *obj, *next_obj; + + /* + * No need to take lock here, as cleanup should be called + * after all commands finished executing. Newly executed + * commands should fail. + */ + mutex_lock(&ucontext->uobjects_lock->lock); + list_for_each_entry_safe(obj, next_obj, &ucontext->uobjects, + list) + if (obj->type->order == i) { + if (obj->type->type == UVERBS_ATTR_TYPE_IDR) + ib_uverbs_uobject_remove(obj, false); + else + ib_uverbs_remove_fd(obj); + } + mutex_unlock(&ucontext->uobjects_lock->lock); + } + kref_put(&ucontext->uobjects_lock->ref, release_uobjects_list_lock); +} + +int ib_uverbs_uobject_type_initialize_ucontext(struct ib_ucontext *ucontext) +{ + ucontext->uobjects_lock = kmalloc(sizeof(*ucontext->uobjects_lock), + GFP_KERNEL); + if (!ucontext->uobjects_lock) + return -ENOMEM; + + init_uobjects_list_lock(ucontext->uobjects_lock); + INIT_LIST_HEAD(&ucontext->uobjects); + + return 0; +} + +void ib_uverbs_uobject_type_release_ucontext(struct ib_ucontext *ucontext) +{ + kfree(ucontext->uobjects_lock); +} + diff --git a/drivers/infiniband/core/rdma_core.h b/drivers/infiniband/core/rdma_core.h index 0bb4be3..9b91c1c 100644 --- a/drivers/infiniband/core/rdma_core.h +++ b/drivers/infiniband/core/rdma_core.h @@ -60,6 +60,10 @@ void uverbs_commit_objects(struct uverbs_attr_array *attr_array, const struct uverbs_action *action, bool success); +void ib_uverbs_uobject_type_cleanup_ucontext(struct ib_ucontext *ucontext, + const struct uverbs_root *root); +int ib_uverbs_uobject_type_initialize_ucontext(struct ib_ucontext *ucontext); +void ib_uverbs_uobject_type_release_ucontext(struct ib_ucontext *ucontext); void ib_uverbs_close_fd(struct file *f); void ib_uverbs_cleanup_fd(void *private_data);