Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+59
+7
drivers/vfio/device_cdev.c
··· 39 39 40 40 filep->private_data = df; 41 41 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 + 42 49 return 0; 43 50 44 51 err_put_registration:
+7
drivers/vfio/group.c
··· 286 286 */ 287 287 filep->f_mode |= (FMODE_PREAD | FMODE_PWRITE); 288 288 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 + 289 296 if (device->group->type == VFIO_NO_IOMMU) 290 297 dev_warn(device->dev, "vfio-noiommu device opened by user " 291 298 "(%s:%d)\n", current->comm, task_pid_nr(current));
+44
drivers/vfio/vfio_main.c
··· 22 22 #include <linux/list.h> 23 23 #include <linux/miscdevice.h> 24 24 #include <linux/module.h> 25 + #include <linux/mount.h> 25 26 #include <linux/mutex.h> 26 27 #include <linux/pci.h> 28 + #include <linux/pseudo_fs.h> 27 29 #include <linux/rwsem.h> 28 30 #include <linux/sched.h> 29 31 #include <linux/slab.h> ··· 45 43 #define DRIVER_AUTHOR "Alex Williamson <alex.williamson@redhat.com>" 46 44 #define DRIVER_DESC "VFIO - User Level meta-driver" 47 45 46 + #define VFIO_MAGIC 0x5646494f /* "VFIO" */ 47 + 48 48 static struct vfio { 49 49 struct class *device_class; 50 50 struct ida device_ida; 51 + struct vfsmount *vfs_mount; 52 + int fs_count; 51 53 } vfio; 52 54 53 55 #ifdef CONFIG_VFIO_NOIOMMU ··· 192 186 if (device->ops->release) 193 187 device->ops->release(device); 194 188 189 + iput(device->inode); 190 + simple_release_fs(&vfio.vfs_mount, &vfio.fs_count); 195 191 kvfree(device); 196 192 } 197 193 ··· 236 228 } 237 229 EXPORT_SYMBOL_GPL(_vfio_alloc_device); 238 230 231 + static int vfio_fs_init_fs_context(struct fs_context *fc) 232 + { 233 + return init_pseudo(fc, VFIO_MAGIC) ? 0 : -ENOMEM; 234 + } 235 + 236 + static struct file_system_type vfio_fs_type = { 237 + .name = "vfio", 238 + .owner = THIS_MODULE, 239 + .init_fs_context = vfio_fs_init_fs_context, 240 + .kill_sb = kill_anon_super, 241 + }; 242 + 243 + static struct inode *vfio_fs_inode_new(void) 244 + { 245 + struct inode *inode; 246 + int ret; 247 + 248 + ret = simple_pin_fs(&vfio_fs_type, &vfio.vfs_mount, &vfio.fs_count); 249 + if (ret) 250 + return ERR_PTR(ret); 251 + 252 + inode = alloc_anon_inode(vfio.vfs_mount->mnt_sb); 253 + if (IS_ERR(inode)) 254 + simple_release_fs(&vfio.vfs_mount, &vfio.fs_count); 255 + 256 + return inode; 257 + } 258 + 239 259 /* 240 260 * Initialize a vfio_device so it can be registered to vfio core. 241 261 */ ··· 282 246 init_completion(&device->comp); 283 247 device->dev = dev; 284 248 device->ops = ops; 249 + device->inode = vfio_fs_inode_new(); 250 + if (IS_ERR(device->inode)) { 251 + ret = PTR_ERR(device->inode); 252 + goto out_inode; 253 + } 285 254 286 255 if (ops->init) { 287 256 ret = ops->init(device); ··· 301 260 return 0; 302 261 303 262 out_uninit: 263 + iput(device->inode); 264 + simple_release_fs(&vfio.vfs_mount, &vfio.fs_count); 265 + out_inode: 304 266 vfio_release_device_set(device); 305 267 ida_free(&vfio.device_ida, device->index); 306 268 return ret;
+1
include/linux/vfio.h
··· 64 64 struct completion comp; 65 65 struct iommufd_access *iommufd_access; 66 66 void (*put_kvm)(struct kvm *kvm); 67 + struct inode *inode; 67 68 #if IS_ENABLED(CONFIG_IOMMUFD) 68 69 struct iommufd_device *iommufd_device; 69 70 u8 iommufd_attached:1;