diff --git a/mm/shmem.c b/mm/shmem.c index 54c213b7b42a..78d07299ef04 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -81,6 +81,7 @@ static struct vfsmount *shm_mnt; #include #include #include +#include #include @@ -3882,6 +3883,85 @@ int shmem_register_guest(struct inode *inode, void *owner, return 0; } +static void test_guest_invalidate_page_range(struct inode *inode, void *owner, + pgoff_t start, pgoff_t end) +{ + /* + * XXX: We can get here after the owner no longer exists. Need to check + * somehow if the owner is still alive. + */ + + printk("invalidate: %#lx-%#lx\n", start, end); +} + +static const struct guest_ops guest_ops = { + .invalidate_page_range = test_guest_invalidate_page_range, +}; + +#define GUEST_MEM_REGISTER _IOW('m', 1, int) +#define GUEST_MEM_UNREGISTER _IOW('m', 2, int) +#define GUEST_MEM_GET_PFN _IOW('m', 3, unsigned long) + +static long guest_mem_test_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + static struct file *memfd_file = NULL; + static const struct guest_mem_ops *guest_mem_ops = NULL; + + switch (cmd) { + case GUEST_MEM_REGISTER: { + struct fd memfd = fdget(arg); + + if (memfd_file) + return -EBUSY; + + if (!memfd.file) + return -EINVAL; + + memfd_file = memfd.file; + return memfd_register_guest(memfd_file->f_inode, file, + &guest_ops, &guest_mem_ops); + } + case GUEST_MEM_UNREGISTER: { + if (!memfd_file) + return -EINVAL; + + fput(memfd_file); + memfd_file = NULL; + guest_mem_ops = NULL; + return 0; + } + case GUEST_MEM_GET_PFN: { + unsigned long pfn; + printk("guest_mem_ops: %px\n", guest_mem_ops); + pfn = guest_mem_ops->get_lock_pfn(memfd_file->f_inode, 0); + printk("pfn: %#lx\n"); + if (pfn < 0) + return pfn; + guest_mem_ops->put_unlock_pfn(pfn); + return 0; + } + default: + return -EINVAL; + } + + return -EINVAL; +} + +static const struct file_operations guest_mem_test_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = guest_mem_test_ioctl, + .llseek = no_llseek, +}; + +static int __init guest_mem_test(void) +{ + debugfs_create_file("guest_mem_test", 0200, NULL, NULL, + &guest_mem_test_fops); + return 0; +} +late_initcall(guest_mem_test); + static const struct file_operations shmem_file_operations = { .mmap = shmem_mmap, .get_unmapped_area = shmem_get_unmapped_area,