root/fs/anon_inodes.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. anon_inodefs_dname
  2. anon_inodefs_init_fs_context
  3. anon_inode_getfile
  4. anon_inode_getfd
  5. anon_inode_init

   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 static char *anon_inodefs_dname(struct dentry *dentry, char *buffer, int buflen)
  34 {
  35         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 static int anon_inodefs_init_fs_context(struct fs_context *fc)
  44 {
  45         struct pseudo_fs_context *ctx = init_pseudo(fc, ANON_INODE_FS_MAGIC);
  46         if (!ctx)
  47                 return -ENOMEM;
  48         ctx->dops = &anon_inodefs_dentry_operations;
  49         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 struct file *anon_inode_getfile(const char *name,
  75                                 const struct file_operations *fops,
  76                                 void *priv, int flags)
  77 {
  78         struct file *file;
  79 
  80         if (IS_ERR(anon_inode_inode))
  81                 return ERR_PTR(-ENODEV);
  82 
  83         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         ihold(anon_inode_inode);
  91         file = alloc_file_pseudo(anon_inode_inode, anon_inode_mnt, name,
  92                                  flags & (O_ACCMODE | O_NONBLOCK), fops);
  93         if (IS_ERR(file))
  94                 goto err;
  95 
  96         file->f_mapping = anon_inode_inode->i_mapping;
  97 
  98         file->private_data = priv;
  99 
 100         return file;
 101 
 102 err:
 103         iput(anon_inode_inode);
 104         module_put(fops->owner);
 105         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 int anon_inode_getfd(const char *name, const struct file_operations *fops,
 126                      void *priv, int flags)
 127 {
 128         int error, fd;
 129         struct file *file;
 130 
 131         error = get_unused_fd_flags(flags);
 132         if (error < 0)
 133                 return error;
 134         fd = error;
 135 
 136         file = anon_inode_getfile(name, fops, priv, flags);
 137         if (IS_ERR(file)) {
 138                 error = PTR_ERR(file);
 139                 goto err_put_unused_fd;
 140         }
 141         fd_install(fd, file);
 142 
 143         return fd;
 144 
 145 err_put_unused_fd:
 146         put_unused_fd(fd);
 147         return error;
 148 }
 149 EXPORT_SYMBOL_GPL(anon_inode_getfd);
 150 
 151 static int __init anon_inode_init(void)
 152 {
 153         anon_inode_mnt = kern_mount(&anon_inode_fs_type);
 154         if (IS_ERR(anon_inode_mnt))
 155                 panic("anon_inode_init() kernel mount failed (%ld)\n", PTR_ERR(anon_inode_mnt));
 156 
 157         anon_inode_inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
 158         if (IS_ERR(anon_inode_inode))
 159                 panic("anon_inode_init() inode allocation failed (%ld)\n", PTR_ERR(anon_inode_inode));
 160 
 161         return 0;
 162 }
 163 
 164 fs_initcall(anon_inode_init);
 165 

/* [<][>][^][v][top][bottom][index][help] */