Skip to content

Commit b7c5e64

Browse files
committed
vfio: Create vfio_fs_type with inode per device
By linking all the device fds we provide to userspace to an address space through a new pseudo fs, we can use tools like unmap_mapping_range() to zap all vmas associated with a device. Suggested-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Link: https://lore.kernel.org/r/20240530045236.1005864-2-alex.williamson@redhat.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
1 parent 1613e60 commit b7c5e64

File tree

4 files changed

+59
-0
lines changed

4 files changed

+59
-0
lines changed

drivers/vfio/device_cdev.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ int vfio_device_fops_cdev_open(struct inode *inode, struct file *filep)
3939

4040
filep->private_data = df;
4141

42+
/*
43+
* Use the pseudo fs inode on the device to link all mmaps
44+
* to the same address space, allowing us to unmap all vmas
45+
* associated to this device using unmap_mapping_range().
46+
*/
47+
filep->f_mapping = device->inode->i_mapping;
48+
4249
return 0;
4350

4451
err_put_registration:

drivers/vfio/group.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,13 @@ static struct file *vfio_device_open_file(struct vfio_device *device)
286286
*/
287287
filep->f_mode |= (FMODE_PREAD | FMODE_PWRITE);
288288

289+
/*
290+
* Use the pseudo fs inode on the device to link all mmaps
291+
* to the same address space, allowing us to unmap all vmas
292+
* associated to this device using unmap_mapping_range().
293+
*/
294+
filep->f_mapping = device->inode->i_mapping;
295+
289296
if (device->group->type == VFIO_NO_IOMMU)
290297
dev_warn(device->dev, "vfio-noiommu device opened by user "
291298
"(%s:%d)\n", current->comm, task_pid_nr(current));

drivers/vfio/vfio_main.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
#include <linux/list.h>
2323
#include <linux/miscdevice.h>
2424
#include <linux/module.h>
25+
#include <linux/mount.h>
2526
#include <linux/mutex.h>
2627
#include <linux/pci.h>
28+
#include <linux/pseudo_fs.h>
2729
#include <linux/rwsem.h>
2830
#include <linux/sched.h>
2931
#include <linux/slab.h>
@@ -43,9 +45,13 @@
4345
#define DRIVER_AUTHOR "Alex Williamson <alex.williamson@redhat.com>"
4446
#define DRIVER_DESC "VFIO - User Level meta-driver"
4547

48+
#define VFIO_MAGIC 0x5646494f /* "VFIO" */
49+
4650
static struct vfio {
4751
struct class *device_class;
4852
struct ida device_ida;
53+
struct vfsmount *vfs_mount;
54+
int fs_count;
4955
} vfio;
5056

5157
#ifdef CONFIG_VFIO_NOIOMMU
@@ -186,6 +192,8 @@ static void vfio_device_release(struct device *dev)
186192
if (device->ops->release)
187193
device->ops->release(device);
188194

195+
iput(device->inode);
196+
simple_release_fs(&vfio.vfs_mount, &vfio.fs_count);
189197
kvfree(device);
190198
}
191199

@@ -228,6 +236,34 @@ struct vfio_device *_vfio_alloc_device(size_t size, struct device *dev,
228236
}
229237
EXPORT_SYMBOL_GPL(_vfio_alloc_device);
230238

239+
static int vfio_fs_init_fs_context(struct fs_context *fc)
240+
{
241+
return init_pseudo(fc, VFIO_MAGIC) ? 0 : -ENOMEM;
242+
}
243+
244+
static struct file_system_type vfio_fs_type = {
245+
.name = "vfio",
246+
.owner = THIS_MODULE,
247+
.init_fs_context = vfio_fs_init_fs_context,
248+
.kill_sb = kill_anon_super,
249+
};
250+
251+
static struct inode *vfio_fs_inode_new(void)
252+
{
253+
struct inode *inode;
254+
int ret;
255+
256+
ret = simple_pin_fs(&vfio_fs_type, &vfio.vfs_mount, &vfio.fs_count);
257+
if (ret)
258+
return ERR_PTR(ret);
259+
260+
inode = alloc_anon_inode(vfio.vfs_mount->mnt_sb);
261+
if (IS_ERR(inode))
262+
simple_release_fs(&vfio.vfs_mount, &vfio.fs_count);
263+
264+
return inode;
265+
}
266+
231267
/*
232268
* Initialize a vfio_device so it can be registered to vfio core.
233269
*/
@@ -246,6 +282,11 @@ static int vfio_init_device(struct vfio_device *device, struct device *dev,
246282
init_completion(&device->comp);
247283
device->dev = dev;
248284
device->ops = ops;
285+
device->inode = vfio_fs_inode_new();
286+
if (IS_ERR(device->inode)) {
287+
ret = PTR_ERR(device->inode);
288+
goto out_inode;
289+
}
249290

250291
if (ops->init) {
251292
ret = ops->init(device);
@@ -260,6 +301,9 @@ static int vfio_init_device(struct vfio_device *device, struct device *dev,
260301
return 0;
261302

262303
out_uninit:
304+
iput(device->inode);
305+
simple_release_fs(&vfio.vfs_mount, &vfio.fs_count);
306+
out_inode:
263307
vfio_release_device_set(device);
264308
ida_free(&vfio.device_ida, device->index);
265309
return ret;

include/linux/vfio.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ struct vfio_device {
6464
struct completion comp;
6565
struct iommufd_access *iommufd_access;
6666
void (*put_kvm)(struct kvm *kvm);
67+
struct inode *inode;
6768
#if IS_ENABLED(CONFIG_IOMMUFD)
6869
struct iommufd_device *iommufd_device;
6970
u8 iommufd_attached:1;

0 commit comments

Comments
 (0)