Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only 2 : : /* 3 : : * fs/anon_inodes.c 4 : : * 5 : : * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org> 6 : : * 7 : : * Thanks to Arnd Bergmann for code review and suggestions. 8 : : * More changes for Thomas Gleixner suggestions. 9 : : * 10 : : */ 11 : : 12 : : #include <linux/cred.h> 13 : : #include <linux/file.h> 14 : : #include <linux/poll.h> 15 : : #include <linux/sched.h> 16 : : #include <linux/init.h> 17 : : #include <linux/fs.h> 18 : : #include <linux/mount.h> 19 : : #include <linux/module.h> 20 : : #include <linux/kernel.h> 21 : : #include <linux/magic.h> 22 : : #include <linux/anon_inodes.h> 23 : : #include <linux/pseudo_fs.h> 24 : : 25 : : #include <linux/uaccess.h> 26 : : 27 : : static struct vfsmount *anon_inode_mnt __read_mostly; 28 : : static struct inode *anon_inode_inode; 29 : : 30 : : /* 31 : : * anon_inodefs_dname() is called from d_path(). 32 : : */ 33 : 0 : static char *anon_inodefs_dname(struct dentry *dentry, char *buffer, int buflen) 34 : : { 35 : 0 : return dynamic_dname(dentry, buffer, buflen, "anon_inode:%s", 36 : : dentry->d_name.name); 37 : : } 38 : : 39 : : static const struct dentry_operations anon_inodefs_dentry_operations = { 40 : : .d_dname = anon_inodefs_dname, 41 : : }; 42 : : 43 : 3 : static int anon_inodefs_init_fs_context(struct fs_context *fc) 44 : : { 45 : 3 : struct pseudo_fs_context *ctx = init_pseudo(fc, ANON_INODE_FS_MAGIC); 46 [ + - ]: 3 : if (!ctx) 47 : : return -ENOMEM; 48 : 3 : ctx->dops = &anon_inodefs_dentry_operations; 49 : 3 : return 0; 50 : : } 51 : : 52 : : static struct file_system_type anon_inode_fs_type = { 53 : : .name = "anon_inodefs", 54 : : .init_fs_context = anon_inodefs_init_fs_context, 55 : : .kill_sb = kill_anon_super, 56 : : }; 57 : : 58 : : /** 59 : : * anon_inode_getfile - creates a new file instance by hooking it up to an 60 : : * anonymous inode, and a dentry that describe the "class" 61 : : * of the file 62 : : * 63 : : * @name: [in] name of the "class" of the new file 64 : : * @fops: [in] file operations for the new file 65 : : * @priv: [in] private data for the new file (will be file's private_data) 66 : : * @flags: [in] flags 67 : : * 68 : : * Creates a new file by hooking it on a single inode. This is useful for files 69 : : * that do not need to have a full-fledged inode in order to operate correctly. 70 : : * All the files created with anon_inode_getfile() will share a single inode, 71 : : * hence saving memory and avoiding code duplication for the file/inode/dentry 72 : : * setup. Returns the newly created file* or an error pointer. 73 : : */ 74 : 264 : struct file *anon_inode_getfile(const char *name, 75 : : const struct file_operations *fops, 76 : : void *priv, int flags) 77 : : { 78 : 264 : struct file *file; 79 : : 80 [ + - ]: 264 : if (IS_ERR(anon_inode_inode)) 81 : : return ERR_PTR(-ENODEV); 82 : : 83 [ - + - - ]: 264 : if (fops->owner && !try_module_get(fops->owner)) 84 : : return ERR_PTR(-ENOENT); 85 : : 86 : : /* 87 : : * We know the anon_inode inode count is always greater than zero, 88 : : * so ihold() is safe. 89 : : */ 90 : 264 : ihold(anon_inode_inode); 91 : 264 : file = alloc_file_pseudo(anon_inode_inode, anon_inode_mnt, name, 92 : : flags & (O_ACCMODE | O_NONBLOCK), fops); 93 [ - + ]: 264 : if (IS_ERR(file)) 94 : 0 : goto err; 95 : : 96 : 264 : file->f_mapping = anon_inode_inode->i_mapping; 97 : : 98 : 264 : file->private_data = priv; 99 : : 100 : 264 : return file; 101 : : 102 : : err: 103 : 0 : iput(anon_inode_inode); 104 : 0 : module_put(fops->owner); 105 : 0 : return file; 106 : : } 107 : : EXPORT_SYMBOL_GPL(anon_inode_getfile); 108 : : 109 : : /** 110 : : * anon_inode_getfd - creates a new file instance by hooking it up to an 111 : : * anonymous inode, and a dentry that describe the "class" 112 : : * of the file 113 : : * 114 : : * @name: [in] name of the "class" of the new file 115 : : * @fops: [in] file operations for the new file 116 : : * @priv: [in] private data for the new file (will be file's private_data) 117 : : * @flags: [in] flags 118 : : * 119 : : * Creates a new file by hooking it on a single inode. This is useful for files 120 : : * that do not need to have a full-fledged inode in order to operate correctly. 121 : : * All the files created with anon_inode_getfd() will share a single inode, 122 : : * hence saving memory and avoiding code duplication for the file/inode/dentry 123 : : * setup. Returns new descriptor or an error code. 124 : : */ 125 : 186 : int anon_inode_getfd(const char *name, const struct file_operations *fops, 126 : : void *priv, int flags) 127 : : { 128 : 186 : int error, fd; 129 : 186 : struct file *file; 130 : : 131 : 186 : error = get_unused_fd_flags(flags); 132 [ + - ]: 186 : if (error < 0) 133 : : return error; 134 : 186 : fd = error; 135 : : 136 : 186 : file = anon_inode_getfile(name, fops, priv, flags); 137 [ - + ]: 186 : if (IS_ERR(file)) { 138 : 0 : error = PTR_ERR(file); 139 : 0 : goto err_put_unused_fd; 140 : : } 141 : 186 : fd_install(fd, file); 142 : : 143 : 186 : return fd; 144 : : 145 : : err_put_unused_fd: 146 : 0 : put_unused_fd(fd); 147 : 0 : return error; 148 : : } 149 : : EXPORT_SYMBOL_GPL(anon_inode_getfd); 150 : : 151 : 3 : static int __init anon_inode_init(void) 152 : : { 153 : 3 : anon_inode_mnt = kern_mount(&anon_inode_fs_type); 154 [ - + ]: 3 : if (IS_ERR(anon_inode_mnt)) 155 : 0 : panic("anon_inode_init() kernel mount failed (%ld)\n", PTR_ERR(anon_inode_mnt)); 156 : : 157 : 3 : anon_inode_inode = alloc_anon_inode(anon_inode_mnt->mnt_sb); 158 [ - + ]: 3 : if (IS_ERR(anon_inode_inode)) 159 : 0 : panic("anon_inode_init() inode allocation failed (%ld)\n", PTR_ERR(anon_inode_inode)); 160 : : 161 : 3 : return 0; 162 : : } 163 : : 164 : : fs_initcall(anon_inode_init); 165 : :