LCOV - code coverage report
Current view: top level - fs - anon_inodes.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 22 49 44.9 %
Date: 2014-02-18 Functions: 2 5 40.0 %
Branches: 6 22 27.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *  fs/anon_inodes.c
       3                 :            :  *
       4                 :            :  *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
       5                 :            :  *
       6                 :            :  *  Thanks to Arnd Bergmann for code review and suggestions.
       7                 :            :  *  More changes for Thomas Gleixner suggestions.
       8                 :            :  *
       9                 :            :  */
      10                 :            : 
      11                 :            : #include <linux/cred.h>
      12                 :            : #include <linux/file.h>
      13                 :            : #include <linux/poll.h>
      14                 :            : #include <linux/sched.h>
      15                 :            : #include <linux/init.h>
      16                 :            : #include <linux/fs.h>
      17                 :            : #include <linux/mount.h>
      18                 :            : #include <linux/module.h>
      19                 :            : #include <linux/kernel.h>
      20                 :            : #include <linux/magic.h>
      21                 :            : #include <linux/anon_inodes.h>
      22                 :            : 
      23                 :            : #include <asm/uaccess.h>
      24                 :            : 
      25                 :            : static struct vfsmount *anon_inode_mnt __read_mostly;
      26                 :            : static struct inode *anon_inode_inode;
      27                 :            : 
      28                 :            : /*
      29                 :            :  * anon_inodefs_dname() is called from d_path().
      30                 :            :  */
      31                 :          0 : static char *anon_inodefs_dname(struct dentry *dentry, char *buffer, int buflen)
      32                 :            : {
      33                 :          0 :         return dynamic_dname(dentry, buffer, buflen, "anon_inode:%s",
      34                 :            :                                 dentry->d_name.name);
      35                 :            : }
      36                 :            : 
      37                 :            : static const struct dentry_operations anon_inodefs_dentry_operations = {
      38                 :            :         .d_dname        = anon_inodefs_dname,
      39                 :            : };
      40                 :            : 
      41                 :          0 : static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type,
      42                 :            :                                 int flags, const char *dev_name, void *data)
      43                 :            : {
      44                 :            :         struct dentry *root;
      45                 :          0 :         root = mount_pseudo(fs_type, "anon_inode:", NULL,
      46                 :            :                         &anon_inodefs_dentry_operations, ANON_INODE_FS_MAGIC);
      47         [ #  # ]:          0 :         if (!IS_ERR(root)) {
      48                 :          0 :                 struct super_block *s = root->d_sb;
      49                 :          0 :                 anon_inode_inode = alloc_anon_inode(s);
      50         [ #  # ]:          0 :                 if (IS_ERR(anon_inode_inode)) {
      51                 :          0 :                         dput(root);
      52                 :          0 :                         deactivate_locked_super(s);
      53                 :          0 :                         root = ERR_CAST(anon_inode_inode);
      54                 :            :                 }
      55                 :            :         }
      56                 :          0 :         return root;
      57                 :            : }
      58                 :            : 
      59                 :            : static struct file_system_type anon_inode_fs_type = {
      60                 :            :         .name           = "anon_inodefs",
      61                 :            :         .mount          = anon_inodefs_mount,
      62                 :            :         .kill_sb        = kill_anon_super,
      63                 :            : };
      64                 :            : 
      65                 :            : /**
      66                 :            :  * anon_inode_getfile - creates a new file instance by hooking it up to an
      67                 :            :  *                      anonymous inode, and a dentry that describe the "class"
      68                 :            :  *                      of the file
      69                 :            :  *
      70                 :            :  * @name:    [in]    name of the "class" of the new file
      71                 :            :  * @fops:    [in]    file operations for the new file
      72                 :            :  * @priv:    [in]    private data for the new file (will be file's private_data)
      73                 :            :  * @flags:   [in]    flags
      74                 :            :  *
      75                 :            :  * Creates a new file by hooking it on a single inode. This is useful for files
      76                 :            :  * that do not need to have a full-fledged inode in order to operate correctly.
      77                 :            :  * All the files created with anon_inode_getfile() will share a single inode,
      78                 :            :  * hence saving memory and avoiding code duplication for the file/inode/dentry
      79                 :            :  * setup.  Returns the newly created file* or an error pointer.
      80                 :            :  */
      81                 :          0 : struct file *anon_inode_getfile(const char *name,
      82                 :            :                                 const struct file_operations *fops,
      83                 :            :                                 void *priv, int flags)
      84                 :            : {
      85                 :            :         struct qstr this;
      86                 :            :         struct path path;
      87                 :            :         struct file *file;
      88                 :            : 
      89         [ +  - ]:         60 :         if (IS_ERR(anon_inode_inode))
      90                 :            :                 return ERR_PTR(-ENODEV);
      91                 :            : 
      92 [ -  + ][ #  # ]:         60 :         if (fops->owner && !try_module_get(fops->owner))
      93                 :            :                 return ERR_PTR(-ENOENT);
      94                 :            : 
      95                 :            :         /*
      96                 :            :          * Link the inode to a directory entry by creating a unique name
      97                 :            :          * using the inode sequence number.
      98                 :            :          */
      99                 :            :         file = ERR_PTR(-ENOMEM);
     100                 :         60 :         this.name = name;
     101                 :         60 :         this.len = strlen(name);
     102                 :         60 :         this.hash = 0;
     103                 :         60 :         path.dentry = d_alloc_pseudo(anon_inode_mnt->mnt_sb, &this);
     104         [ +  - ]:         60 :         if (!path.dentry)
     105                 :            :                 goto err_module;
     106                 :            : 
     107                 :         60 :         path.mnt = mntget(anon_inode_mnt);
     108                 :            :         /*
     109                 :            :          * We know the anon_inode inode count is always greater than zero,
     110                 :            :          * so ihold() is safe.
     111                 :            :          */
     112                 :         60 :         ihold(anon_inode_inode);
     113                 :            : 
     114                 :         60 :         d_instantiate(path.dentry, anon_inode_inode);
     115                 :            : 
     116                 :         60 :         file = alloc_file(&path, OPEN_FMODE(flags), fops);
     117         [ +  - ]:        120 :         if (IS_ERR(file))
     118                 :            :                 goto err_dput;
     119                 :         60 :         file->f_mapping = anon_inode_inode->i_mapping;
     120                 :            : 
     121                 :         60 :         file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
     122                 :         60 :         file->private_data = priv;
     123                 :            : 
     124                 :         60 :         return file;
     125                 :            : 
     126                 :            : err_dput:
     127                 :          0 :         path_put(&path);
     128                 :            : err_module:
     129                 :          0 :         module_put(fops->owner);
     130                 :          0 :         return file;
     131                 :            : }
     132                 :            : EXPORT_SYMBOL_GPL(anon_inode_getfile);
     133                 :            : 
     134                 :            : /**
     135                 :            :  * anon_inode_getfd - creates a new file instance by hooking it up to an
     136                 :            :  *                    anonymous inode, and a dentry that describe the "class"
     137                 :            :  *                    of the file
     138                 :            :  *
     139                 :            :  * @name:    [in]    name of the "class" of the new file
     140                 :            :  * @fops:    [in]    file operations for the new file
     141                 :            :  * @priv:    [in]    private data for the new file (will be file's private_data)
     142                 :            :  * @flags:   [in]    flags
     143                 :            :  *
     144                 :            :  * Creates a new file by hooking it on a single inode. This is useful for files
     145                 :            :  * that do not need to have a full-fledged inode in order to operate correctly.
     146                 :            :  * All the files created with anon_inode_getfd() will share a single inode,
     147                 :            :  * hence saving memory and avoiding code duplication for the file/inode/dentry
     148                 :            :  * setup.  Returns new descriptor or an error code.
     149                 :            :  */
     150                 :          0 : int anon_inode_getfd(const char *name, const struct file_operations *fops,
     151                 :            :                      void *priv, int flags)
     152                 :            : {
     153                 :            :         int error, fd;
     154                 :            :         struct file *file;
     155                 :            : 
     156                 :         18 :         error = get_unused_fd_flags(flags);
     157         [ +  - ]:         18 :         if (error < 0)
     158                 :            :                 return error;
     159                 :            :         fd = error;
     160                 :            : 
     161                 :         18 :         file = anon_inode_getfile(name, fops, priv, flags);
     162         [ -  + ]:         18 :         if (IS_ERR(file)) {
     163                 :            :                 error = PTR_ERR(file);
     164                 :            :                 goto err_put_unused_fd;
     165                 :            :         }
     166                 :         18 :         fd_install(fd, file);
     167                 :            : 
     168                 :         18 :         return fd;
     169                 :            : 
     170                 :            : err_put_unused_fd:
     171                 :          0 :         put_unused_fd(fd);
     172                 :          0 :         return error;
     173                 :            : }
     174                 :            : EXPORT_SYMBOL_GPL(anon_inode_getfd);
     175                 :            : 
     176                 :          0 : static int __init anon_inode_init(void)
     177                 :            : {
     178                 :            :         int error;
     179                 :            : 
     180                 :          0 :         error = register_filesystem(&anon_inode_fs_type);
     181         [ #  # ]:          0 :         if (error)
     182                 :            :                 goto err_exit;
     183                 :          0 :         anon_inode_mnt = kern_mount(&anon_inode_fs_type);
     184         [ #  # ]:          0 :         if (IS_ERR(anon_inode_mnt)) {
     185                 :            :                 error = PTR_ERR(anon_inode_mnt);
     186                 :            :                 goto err_unregister_filesystem;
     187                 :            :         }
     188                 :          0 :         return 0;
     189                 :            : 
     190                 :            : err_unregister_filesystem:
     191                 :          0 :         unregister_filesystem(&anon_inode_fs_type);
     192                 :            : err_exit:
     193                 :          0 :         panic(KERN_ERR "anon_inode_init() failed (%d)\n", error);
     194                 :            : }
     195                 :            : 
     196                 :            : fs_initcall(anon_inode_init);
     197                 :            : 

Generated by: LCOV version 1.9