From 9a7ff263922e7163d0def5d35948e6b6545449f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20L=C3=B3pez?= Date: Fri, 13 Mar 2026 13:20:39 +0100 Subject: [PATCH 1/4] KVM: VFIO: clean up control flow in kvm_vfio_file_add() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct file that this function fgets() is always passed to fput() before returning, so use automatic cleanup via __free() to avoid several jumps to the end of the function. Similarly, use a mutex guard to completely remove the need to use gotos. Signed-off-by: Carlos López Reviewed-by: Alex Williamson Link: https://patch.msgid.link/20260313122040.1413091-4-clopez@suse.de Signed-off-by: Sean Christopherson --- virt/kvm/vfio.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c index 9f9acb66cc1e..2c91bad3333b 100644 --- a/virt/kvm/vfio.c +++ b/virt/kvm/vfio.c @@ -144,33 +144,26 @@ static int kvm_vfio_file_add(struct kvm_device *dev, unsigned int fd) { struct kvm_vfio *kv = dev->private; struct kvm_vfio_file *kvf; - struct file *filp; - int ret = 0; + struct file *filp __free(fput) = NULL; filp = fget(fd); if (!filp) return -EBADF; /* Ensure the FD is a vfio FD. */ - if (!kvm_vfio_file_is_valid(filp)) { - ret = -EINVAL; - goto out_fput; - } + if (!kvm_vfio_file_is_valid(filp)) + return -EINVAL; - mutex_lock(&kv->lock); + guard(mutex)(&kv->lock); list_for_each_entry(kvf, &kv->file_list, node) { - if (kvf->file == filp) { - ret = -EEXIST; - goto out_unlock; - } + if (kvf->file == filp) + return -EEXIST; } kvf = kzalloc_obj(*kvf, GFP_KERNEL_ACCOUNT); - if (!kvf) { - ret = -ENOMEM; - goto out_unlock; - } + if (!kvf) + return -ENOMEM; kvf->file = get_file(filp); list_add_tail(&kvf->node, &kv->file_list); @@ -178,11 +171,7 @@ static int kvm_vfio_file_add(struct kvm_device *dev, unsigned int fd) kvm_vfio_file_set_kvm(kvf->file, dev->kvm); kvm_vfio_update_coherency(dev); -out_unlock: - mutex_unlock(&kv->lock); -out_fput: - fput(filp); - return ret; + return 0; } static int kvm_vfio_file_del(struct kvm_device *dev, unsigned int fd) From 40f0f4bb6041b1f520445a4c5f0c8777f7c98f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20L=C3=B3pez?= Date: Fri, 13 Mar 2026 13:20:40 +0100 Subject: [PATCH 2/4] KVM: VFIO: use mutex guard in kvm_vfio_file_set_spapr_tce() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a mutex guard to hold a lock for the entirety of the function, which removes the need for a goto (whose label even has a misleading name since 8152f8201088 ("fdget(), more trivial conversions")) Signed-off-by: Carlos López Reviewed-by: Alex Williamson Link: https://patch.msgid.link/20260313122040.1413091-5-clopez@suse.de Signed-off-by: Sean Christopherson --- virt/kvm/vfio.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c index 2c91bad3333b..e0d621567dbf 100644 --- a/virt/kvm/vfio.c +++ b/virt/kvm/vfio.c @@ -216,7 +216,6 @@ static int kvm_vfio_file_set_spapr_tce(struct kvm_device *dev, struct kvm_vfio_spapr_tce param; struct kvm_vfio *kv = dev->private; struct kvm_vfio_file *kvf; - int ret; if (copy_from_user(¶m, arg, sizeof(struct kvm_vfio_spapr_tce))) return -EFAULT; @@ -225,9 +224,7 @@ static int kvm_vfio_file_set_spapr_tce(struct kvm_device *dev, if (fd_empty(f)) return -EBADF; - ret = -ENOENT; - - mutex_lock(&kv->lock); + guard(mutex)(&kv->lock); list_for_each_entry(kvf, &kv->file_list, node) { if (kvf->file != fd_file(f)) @@ -235,20 +232,15 @@ static int kvm_vfio_file_set_spapr_tce(struct kvm_device *dev, if (!kvf->iommu_group) { kvf->iommu_group = kvm_vfio_file_iommu_group(kvf->file); - if (WARN_ON_ONCE(!kvf->iommu_group)) { - ret = -EIO; - goto err_fdput; - } + if (WARN_ON_ONCE(!kvf->iommu_group)) + return -EIO; } - ret = kvm_spapr_tce_attach_iommu_group(dev->kvm, param.tablefd, - kvf->iommu_group); - break; + return kvm_spapr_tce_attach_iommu_group(dev->kvm, param.tablefd, + kvf->iommu_group); } -err_fdput: - mutex_unlock(&kv->lock); - return ret; + return -ENOENT; } #endif From 3b20a19c592d31d90594565de89f974135b22819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20L=C3=B3pez?= Date: Fri, 13 Mar 2026 13:20:41 +0100 Subject: [PATCH 3/4] KVM: VFIO: deduplicate file release logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are two callsites which destroy files in kv->file_list: the function servicing KVM_DEV_VFIO_FILE_DEL, and the relase of the whole KVM VFIO device. The process involves several steps, so move all those into a single function, removing duplicate code. Signed-off-by: Carlos López Reviewed-by: Alex Williamson Link: https://patch.msgid.link/20260313122040.1413091-6-clopez@suse.de Signed-off-by: Sean Christopherson --- virt/kvm/vfio.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c index e0d621567dbf..2fee1e82f8f6 100644 --- a/virt/kvm/vfio.c +++ b/virt/kvm/vfio.c @@ -174,6 +174,17 @@ static int kvm_vfio_file_add(struct kvm_device *dev, unsigned int fd) return 0; } +static void kvm_vfio_file_free(struct kvm_device *dev, struct kvm_vfio_file *kvf) +{ +#ifdef CONFIG_SPAPR_TCE_IOMMU + kvm_spapr_tce_release_vfio_group(dev->kvm, kvf); +#endif + kvm_vfio_file_set_kvm(kvf->file, NULL); + fput(kvf->file); + list_del(&kvf->node); + kfree(kvf); +} + static int kvm_vfio_file_del(struct kvm_device *dev, unsigned int fd) { struct kvm_vfio *kv = dev->private; @@ -189,18 +200,11 @@ static int kvm_vfio_file_del(struct kvm_device *dev, unsigned int fd) mutex_lock(&kv->lock); list_for_each_entry(kvf, &kv->file_list, node) { - if (kvf->file != fd_file(f)) - continue; - - list_del(&kvf->node); -#ifdef CONFIG_SPAPR_TCE_IOMMU - kvm_spapr_tce_release_vfio_group(dev->kvm, kvf); -#endif - kvm_vfio_file_set_kvm(kvf->file, NULL); - fput(kvf->file); - kfree(kvf); - ret = 0; - break; + if (kvf->file == fd_file(f)) { + kvm_vfio_file_free(dev, kvf); + ret = 0; + break; + } } kvm_vfio_update_coherency(dev); @@ -307,15 +311,8 @@ static void kvm_vfio_release(struct kvm_device *dev) struct kvm_vfio *kv = dev->private; struct kvm_vfio_file *kvf, *tmp; - list_for_each_entry_safe(kvf, tmp, &kv->file_list, node) { -#ifdef CONFIG_SPAPR_TCE_IOMMU - kvm_spapr_tce_release_vfio_group(dev->kvm, kvf); -#endif - kvm_vfio_file_set_kvm(kvf->file, NULL); - fput(kvf->file); - list_del(&kvf->node); - kfree(kvf); - } + list_for_each_entry_safe(kvf, tmp, &kv->file_list, node) + kvm_vfio_file_free(dev, kvf); kvm_vfio_update_coherency(dev); From 156615264fd3430e7f90b36f46076b2f6ec4a24a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20L=C3=B3pez?= Date: Fri, 13 Mar 2026 13:20:42 +0100 Subject: [PATCH 4/4] KVM: VFIO: update coherency only if file was deleted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When servicing a KVM_DEV_VFIO_FILE_DEL request, if a file is removed from kv->file_list, kv->noncoherent needs to be updated, in case we can revert to using coherent DMA. However, if we found no candidate to remove, there is no need to re-scan the list, so do it only if a matching file was found. To simplify the control flow, use a mutex guard so that we can return early from within the search loop if the maching file is found. Signed-off-by: Carlos López Reviewed-by: Alex Williamson Link: https://patch.msgid.link/20260313122040.1413091-7-clopez@suse.de Signed-off-by: Sean Christopherson --- virt/kvm/vfio.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c index 2fee1e82f8f6..6cdc4e9a333a 100644 --- a/virt/kvm/vfio.c +++ b/virt/kvm/vfio.c @@ -190,27 +190,21 @@ static int kvm_vfio_file_del(struct kvm_device *dev, unsigned int fd) struct kvm_vfio *kv = dev->private; struct kvm_vfio_file *kvf; CLASS(fd, f)(fd); - int ret; if (fd_empty(f)) return -EBADF; - ret = -ENOENT; - - mutex_lock(&kv->lock); + guard(mutex)(&kv->lock); list_for_each_entry(kvf, &kv->file_list, node) { if (kvf->file == fd_file(f)) { kvm_vfio_file_free(dev, kvf); - ret = 0; - break; + kvm_vfio_update_coherency(dev); + return 0; } } - kvm_vfio_update_coherency(dev); - - mutex_unlock(&kv->lock); - return ret; + return -ENOENT; } #ifdef CONFIG_SPAPR_TCE_IOMMU