LCOV - code coverage report
Current view: top level - fs - anon_inodes.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 31 43 72.1 %
Date: 2022-03-28 15:32:58 Functions: 4 5 80.0 %
Branches: 8 18 44.4 %

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

Generated by: LCOV version 1.14