Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752585AbdGYU4Z (ORCPT ); Tue, 25 Jul 2017 16:56:25 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:33458 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752332AbdGYTUb (ORCPT ); Tue, 25 Jul 2017 15:20:31 -0400 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Alex Williamson , Eric Auger , Paolo Bonzini Subject: [PATCH 4.4 52/83] vfio: New external user group/file match Date: Tue, 25 Jul 2017 12:19:16 -0700 Message-Id: <20170725191716.591196385@linuxfoundation.org> X-Mailer: git-send-email 2.13.3 In-Reply-To: <20170725191708.449126292@linuxfoundation.org> References: <20170725191708.449126292@linuxfoundation.org> User-Agent: quilt/0.65 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3542 Lines: 114 4.4-stable review patch. If anyone has any objections, please let me know. ------------------ From: Alex Williamson commit 5d6dee80a1e94cc284d03e06d930e60e8d3ecf7d upstream. At the point where the kvm-vfio pseudo device wants to release its vfio group reference, we can't always acquire a new reference to make that happen. The group can be in a state where we wouldn't allow a new reference to be added. This new helper function allows a caller to match a file to a group to facilitate this. Given a file and group, report if they match. Thus the caller needs to already have a group reference to match to the file. This allows the deletion of a group without acquiring a new reference. Signed-off-by: Alex Williamson Reviewed-by: Eric Auger Reviewed-by: Paolo Bonzini Tested-by: Eric Auger Signed-off-by: Greg Kroah-Hartman --- drivers/vfio/vfio.c | 9 +++++++++ include/linux/vfio.h | 2 ++ virt/kvm/vfio.c | 27 +++++++++++++++++++-------- 3 files changed, 30 insertions(+), 8 deletions(-) --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -1587,6 +1587,15 @@ void vfio_group_put_external_user(struct } EXPORT_SYMBOL_GPL(vfio_group_put_external_user); +bool vfio_external_group_match_file(struct vfio_group *test_group, + struct file *filep) +{ + struct vfio_group *group = filep->private_data; + + return (filep->f_op == &vfio_group_fops) && (group == test_group); +} +EXPORT_SYMBOL_GPL(vfio_external_group_match_file); + int vfio_external_user_iommu_id(struct vfio_group *group) { return iommu_group_id(group->iommu_group); --- a/include/linux/vfio.h +++ b/include/linux/vfio.h @@ -85,6 +85,8 @@ extern void vfio_unregister_iommu_driver */ extern struct vfio_group *vfio_group_get_external_user(struct file *filep); extern void vfio_group_put_external_user(struct vfio_group *group); +extern bool vfio_external_group_match_file(struct vfio_group *group, + struct file *filep); extern int vfio_external_user_iommu_id(struct vfio_group *group); extern long vfio_external_check_extension(struct vfio_group *group, unsigned long arg); --- a/virt/kvm/vfio.c +++ b/virt/kvm/vfio.c @@ -47,6 +47,22 @@ static struct vfio_group *kvm_vfio_group return vfio_group; } +static bool kvm_vfio_external_group_match_file(struct vfio_group *group, + struct file *filep) +{ + bool ret, (*fn)(struct vfio_group *, struct file *); + + fn = symbol_get(vfio_external_group_match_file); + if (!fn) + return false; + + ret = fn(group, filep); + + symbol_put(vfio_external_group_match_file); + + return ret; +} + static void kvm_vfio_group_put_external_user(struct vfio_group *vfio_group) { void (*fn)(struct vfio_group *); @@ -171,18 +187,13 @@ static int kvm_vfio_set_group(struct kvm if (!f.file) return -EBADF; - vfio_group = kvm_vfio_group_get_external_user(f.file); - fdput(f); - - if (IS_ERR(vfio_group)) - return PTR_ERR(vfio_group); - ret = -ENOENT; mutex_lock(&kv->lock); list_for_each_entry(kvg, &kv->group_list, node) { - if (kvg->vfio_group != vfio_group) + if (!kvm_vfio_external_group_match_file(kvg->vfio_group, + f.file)) continue; list_del(&kvg->node); @@ -196,7 +207,7 @@ static int kvm_vfio_set_group(struct kvm mutex_unlock(&kv->lock); - kvm_vfio_group_put_external_user(vfio_group); + fdput(f); kvm_vfio_update_coherency(dev);