From: Ackerley Tng The file represents a KVM instance's view into the underlying memory that is managed by the guest_memfd inode. Refactoring out the file creation enables this function to be reused when creating multiple views into the same guest_memfd inode. Signed-off-by: Ackerley Tng Co-developed-by: Ryan Afranji Signed-off-by: Ryan Afranji Co-developed-by: Tao Gong Signed-off-by: Tao Gong --- virt/kvm/guest_memfd.c | 67 +++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c index 93f3d29d5751a..3ca6f64d48040 100644 --- a/virt/kvm/guest_memfd.c +++ b/virt/kvm/guest_memfd.c @@ -937,10 +937,47 @@ static int kvm_gmem_init_inode(struct inode *inode, loff_t size, u64 flags) return r; } +/* + * Allocate a new guest_memfd file for @kvm that refers to @inode. On success, + * the returned file takes over the caller's reference to @inode. + */ +static struct file *kvm_gmem_alloc_file(struct kvm *kvm, struct inode *inode, + const char *name) +{ + struct gmem_file *f; + struct file *file; + + f = kzalloc_obj(*f); + if (!f) + return ERR_PTR(-ENOMEM); + + /* __fput() will take care of fops_put(). */ + if (!fops_get(&kvm_gmem_fops)) { + kfree(f); + return ERR_PTR(-ENOENT); + } + + file = alloc_file_pseudo(inode, kvm_gmem_mnt, name, O_RDWR, &kvm_gmem_fops); + if (IS_ERR(file)) { + fops_put(&kvm_gmem_fops); + kfree(f); + return file; + } + + file->f_flags |= O_LARGEFILE; + file->private_data = f; + + kvm_get_kvm(kvm); + f->kvm = kvm; + xa_init(&f->bindings); + list_add(&f->entry, &GMEM_I(inode)->gmem_file_list); + + return file; +} + static int __kvm_gmem_create(struct kvm *kvm, loff_t size, u64 flags) { static const char *name = "[kvm-gmem]"; - struct gmem_file *f; struct inode *inode; struct file *file; int fd, err; @@ -949,51 +986,27 @@ static int __kvm_gmem_create(struct kvm *kvm, loff_t size, u64 flags) if (fd < 0) return fd; - f = kzalloc_obj(*f); - if (!f) { - err = -ENOMEM; - goto err_fd; - } - - /* __fput() will take care of fops_put(). */ - if (!fops_get(&kvm_gmem_fops)) { - err = -ENOENT; - goto err_gmem; - } - inode = anon_inode_make_secure_inode(kvm_gmem_mnt->mnt_sb, name, NULL); if (IS_ERR(inode)) { err = PTR_ERR(inode); - goto err_fops; + goto err_fd; } err = kvm_gmem_init_inode(inode, size, flags); if (err) goto err_inode; - file = alloc_file_pseudo(inode, kvm_gmem_mnt, name, O_RDWR, &kvm_gmem_fops); + file = kvm_gmem_alloc_file(kvm, inode, name); if (IS_ERR(file)) { err = PTR_ERR(file); goto err_inode; } - file->f_flags |= O_LARGEFILE; - file->private_data = f; - - kvm_get_kvm(kvm); - f->kvm = kvm; - xa_init(&f->bindings); - list_add(&f->entry, &GMEM_I(inode)->gmem_file_list); - fd_install(fd, file); return fd; err_inode: iput(inode); -err_fops: - fops_put(&kvm_gmem_fops); -err_gmem: - kfree(f); err_fd: put_unused_fd(fd); return err; -- 2.56.0.257.gf7497c7d27-goog