LCOV - code coverage report
Current view: top level - fs/kernfs - inode.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 84 154 54.5 %
Date: 2014-04-16 Functions: 9 16 56.2 %
Branches: 22 59 37.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * fs/kernfs/inode.c - kernfs inode implementation
       3                 :            :  *
       4                 :            :  * Copyright (c) 2001-3 Patrick Mochel
       5                 :            :  * Copyright (c) 2007 SUSE Linux Products GmbH
       6                 :            :  * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org>
       7                 :            :  *
       8                 :            :  * This file is released under the GPLv2.
       9                 :            :  */
      10                 :            : 
      11                 :            : #include <linux/pagemap.h>
      12                 :            : #include <linux/backing-dev.h>
      13                 :            : #include <linux/capability.h>
      14                 :            : #include <linux/errno.h>
      15                 :            : #include <linux/slab.h>
      16                 :            : #include <linux/xattr.h>
      17                 :            : #include <linux/security.h>
      18                 :            : 
      19                 :            : #include "kernfs-internal.h"
      20                 :            : 
      21                 :            : static const struct address_space_operations kernfs_aops = {
      22                 :            :         .readpage       = simple_readpage,
      23                 :            :         .write_begin    = simple_write_begin,
      24                 :            :         .write_end      = simple_write_end,
      25                 :            : };
      26                 :            : 
      27                 :            : static struct backing_dev_info kernfs_bdi = {
      28                 :            :         .name           = "kernfs",
      29                 :            :         .ra_pages       = 0,    /* No readahead */
      30                 :            :         .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
      31                 :            : };
      32                 :            : 
      33                 :            : static const struct inode_operations kernfs_iops = {
      34                 :            :         .permission     = kernfs_iop_permission,
      35                 :            :         .setattr        = kernfs_iop_setattr,
      36                 :            :         .getattr        = kernfs_iop_getattr,
      37                 :            :         .setxattr       = kernfs_iop_setxattr,
      38                 :            :         .removexattr    = kernfs_iop_removexattr,
      39                 :            :         .getxattr       = kernfs_iop_getxattr,
      40                 :            :         .listxattr      = kernfs_iop_listxattr,
      41                 :            : };
      42                 :            : 
      43                 :          0 : void __init kernfs_inode_init(void)
      44                 :            : {
      45         [ #  # ]:          0 :         if (bdi_init(&kernfs_bdi))
      46                 :          0 :                 panic("failed to init kernfs_bdi");
      47                 :          0 : }
      48                 :            : 
      49                 :        157 : static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)
      50                 :            : {
      51                 :            :         struct iattr *iattrs;
      52                 :            : 
      53         [ +  + ]:        157 :         if (kn->iattr)
      54                 :            :                 return kn->iattr;
      55                 :            : 
      56                 :          5 :         kn->iattr = kzalloc(sizeof(struct kernfs_iattrs), GFP_KERNEL);
      57         [ +  - ]:          5 :         if (!kn->iattr)
      58                 :            :                 return NULL;
      59                 :          5 :         iattrs = &kn->iattr->ia_iattr;
      60                 :            : 
      61                 :            :         /* assign default attributes */
      62                 :          5 :         iattrs->ia_mode = kn->mode;
      63                 :          5 :         iattrs->ia_uid = GLOBAL_ROOT_UID;
      64                 :          5 :         iattrs->ia_gid = GLOBAL_ROOT_GID;
      65                 :          5 :         iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME;
      66                 :            : 
      67                 :          5 :         simple_xattrs_init(&kn->iattr->xattrs);
      68                 :            : 
      69                 :          5 :         return kn->iattr;
      70                 :            : }
      71                 :            : 
      72                 :          0 : static int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
      73                 :            : {
      74                 :            :         struct kernfs_iattrs *attrs;
      75                 :            :         struct iattr *iattrs;
      76                 :        157 :         unsigned int ia_valid = iattr->ia_valid;
      77                 :            : 
      78                 :        157 :         attrs = kernfs_iattrs(kn);
      79         [ +  - ]:        157 :         if (!attrs)
      80                 :            :                 return -ENOMEM;
      81                 :            : 
      82                 :            :         iattrs = &attrs->ia_iattr;
      83                 :            : 
      84         [ -  + ]:        157 :         if (ia_valid & ATTR_UID)
      85                 :          0 :                 iattrs->ia_uid = iattr->ia_uid;
      86         [ -  + ]:        157 :         if (ia_valid & ATTR_GID)
      87                 :          0 :                 iattrs->ia_gid = iattr->ia_gid;
      88         [ -  + ]:        157 :         if (ia_valid & ATTR_ATIME)
      89                 :          0 :                 iattrs->ia_atime = iattr->ia_atime;
      90            [ + ]:        157 :         if (ia_valid & ATTR_MTIME)
      91                 :        157 :                 iattrs->ia_mtime = iattr->ia_mtime;
      92         [ #  # ]:          0 :         if (ia_valid & ATTR_CTIME)
      93                 :        157 :                 iattrs->ia_ctime = iattr->ia_ctime;
      94         [ #  # ]:          0 :         if (ia_valid & ATTR_MODE) {
      95                 :          0 :                 umode_t mode = iattr->ia_mode;
      96                 :          0 :                 iattrs->ia_mode = kn->mode = mode;
      97                 :            :         }
      98                 :            :         return 0;
      99                 :            : }
     100                 :            : 
     101                 :            : /**
     102                 :            :  * kernfs_setattr - set iattr on a node
     103                 :            :  * @kn: target node
     104                 :            :  * @iattr: iattr to set
     105                 :            :  *
     106                 :            :  * Returns 0 on success, -errno on failure.
     107                 :            :  */
     108                 :          0 : int kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
     109                 :            : {
     110                 :            :         int ret;
     111                 :            : 
     112                 :          0 :         mutex_lock(&kernfs_mutex);
     113                 :          0 :         ret = __kernfs_setattr(kn, iattr);
     114                 :          0 :         mutex_unlock(&kernfs_mutex);
     115                 :          0 :         return ret;
     116                 :            : }
     117                 :            : 
     118                 :          0 : int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
     119                 :            : {
     120                 :        157 :         struct inode *inode = dentry->d_inode;
     121                 :        157 :         struct kernfs_node *kn = dentry->d_fsdata;
     122                 :            :         int error;
     123                 :            : 
     124         [ +  - ]:        157 :         if (!kn)
     125                 :            :                 return -EINVAL;
     126                 :            : 
     127                 :        157 :         mutex_lock(&kernfs_mutex);
     128                 :        157 :         error = inode_change_ok(inode, iattr);
     129         [ +  - ]:        157 :         if (error)
     130                 :            :                 goto out;
     131                 :            : 
     132                 :        157 :         error = __kernfs_setattr(kn, iattr);
     133         [ +  - ]:        157 :         if (error)
     134                 :            :                 goto out;
     135                 :            : 
     136                 :            :         /* this ignores size changes */
     137                 :        157 :         setattr_copy(inode, iattr);
     138                 :            : 
     139                 :            : out:
     140                 :        157 :         mutex_unlock(&kernfs_mutex);
     141                 :        157 :         return error;
     142                 :            : }
     143                 :            : 
     144                 :          0 : static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
     145                 :            :                                   u32 *secdata_len)
     146                 :            : {
     147                 :            :         struct kernfs_iattrs *attrs;
     148                 :            :         void *old_secdata;
     149                 :            :         size_t old_secdata_len;
     150                 :            : 
     151                 :          0 :         attrs = kernfs_iattrs(kn);
     152         [ #  # ]:          0 :         if (!attrs)
     153                 :            :                 return -ENOMEM;
     154                 :            : 
     155                 :          0 :         old_secdata = attrs->ia_secdata;
     156                 :          0 :         old_secdata_len = attrs->ia_secdata_len;
     157                 :            : 
     158                 :          0 :         attrs->ia_secdata = *secdata;
     159                 :          0 :         attrs->ia_secdata_len = *secdata_len;
     160                 :            : 
     161                 :          0 :         *secdata = old_secdata;
     162                 :          0 :         *secdata_len = old_secdata_len;
     163                 :          0 :         return 0;
     164                 :            : }
     165                 :            : 
     166                 :          0 : int kernfs_iop_setxattr(struct dentry *dentry, const char *name,
     167                 :            :                         const void *value, size_t size, int flags)
     168                 :            : {
     169                 :          0 :         struct kernfs_node *kn = dentry->d_fsdata;
     170                 :            :         struct kernfs_iattrs *attrs;
     171                 :            :         void *secdata;
     172                 :            :         int error;
     173                 :          0 :         u32 secdata_len = 0;
     174                 :            : 
     175                 :          0 :         attrs = kernfs_iattrs(kn);
     176         [ #  # ]:          0 :         if (!attrs)
     177                 :            :                 return -ENOMEM;
     178                 :            : 
     179         [ #  # ]:          0 :         if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
     180                 :          0 :                 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
     181                 :          0 :                 error = security_inode_setsecurity(dentry->d_inode, suffix,
     182                 :            :                                                 value, size, flags);
     183         [ #  # ]:          0 :                 if (error)
     184                 :            :                         return error;
     185                 :          0 :                 error = security_inode_getsecctx(dentry->d_inode,
     186                 :            :                                                 &secdata, &secdata_len);
     187         [ #  # ]:          0 :                 if (error)
     188                 :            :                         return error;
     189                 :            : 
     190                 :          0 :                 mutex_lock(&kernfs_mutex);
     191                 :          0 :                 error = kernfs_node_setsecdata(kn, &secdata, &secdata_len);
     192                 :          0 :                 mutex_unlock(&kernfs_mutex);
     193                 :            : 
     194         [ #  # ]:          0 :                 if (secdata)
     195                 :          0 :                         security_release_secctx(secdata, secdata_len);
     196                 :          0 :                 return error;
     197         [ #  # ]:          0 :         } else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
     198                 :          0 :                 return simple_xattr_set(&attrs->xattrs, name, value, size,
     199                 :            :                                         flags);
     200                 :            :         }
     201                 :            : 
     202                 :            :         return -EINVAL;
     203                 :            : }
     204                 :            : 
     205                 :          0 : int kernfs_iop_removexattr(struct dentry *dentry, const char *name)
     206                 :            : {
     207                 :          0 :         struct kernfs_node *kn = dentry->d_fsdata;
     208                 :            :         struct kernfs_iattrs *attrs;
     209                 :            : 
     210                 :          0 :         attrs = kernfs_iattrs(kn);
     211         [ #  # ]:          0 :         if (!attrs)
     212                 :            :                 return -ENOMEM;
     213                 :            : 
     214                 :          0 :         return simple_xattr_remove(&attrs->xattrs, name);
     215                 :            : }
     216                 :            : 
     217                 :          0 : ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf,
     218                 :            :                             size_t size)
     219                 :            : {
     220                 :          0 :         struct kernfs_node *kn = dentry->d_fsdata;
     221                 :            :         struct kernfs_iattrs *attrs;
     222                 :            : 
     223                 :          0 :         attrs = kernfs_iattrs(kn);
     224         [ #  # ]:          0 :         if (!attrs)
     225                 :            :                 return -ENOMEM;
     226                 :            : 
     227                 :          0 :         return simple_xattr_get(&attrs->xattrs, name, buf, size);
     228                 :            : }
     229                 :            : 
     230                 :          0 : ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
     231                 :            : {
     232                 :          0 :         struct kernfs_node *kn = dentry->d_fsdata;
     233                 :            :         struct kernfs_iattrs *attrs;
     234                 :            : 
     235                 :          0 :         attrs = kernfs_iattrs(kn);
     236         [ #  # ]:          0 :         if (!attrs)
     237                 :            :                 return -ENOMEM;
     238                 :            : 
     239                 :          0 :         return simple_xattr_list(&attrs->xattrs, buf, size);
     240                 :            : }
     241                 :            : 
     242                 :            : static inline void set_default_inode_attr(struct inode *inode, umode_t mode)
     243                 :            : {
     244                 :        555 :         inode->i_mode = mode;
     245                 :        555 :         inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
     246                 :            : }
     247                 :            : 
     248                 :            : static inline void set_inode_attr(struct inode *inode, struct iattr *iattr)
     249                 :            : {
     250                 :        208 :         inode->i_uid = iattr->ia_uid;
     251                 :        208 :         inode->i_gid = iattr->ia_gid;
     252                 :        208 :         inode->i_atime = iattr->ia_atime;
     253                 :        208 :         inode->i_mtime = iattr->ia_mtime;
     254                 :        208 :         inode->i_ctime = iattr->ia_ctime;
     255                 :            : }
     256                 :            : 
     257                 :          0 : static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode)
     258                 :            : {
     259                 :      66468 :         struct kernfs_iattrs *attrs = kn->iattr;
     260                 :            : 
     261                 :      66468 :         inode->i_mode = kn->mode;
     262         [ +  + ]:      66468 :         if (attrs) {
     263                 :            :                 /*
     264                 :            :                  * kernfs_node has non-default attributes get them from
     265                 :            :                  * persistent copy in kernfs_node.
     266                 :            :                  */
     267                 :            :                 set_inode_attr(inode, &attrs->ia_iattr);
     268                 :        208 :                 security_inode_notifysecctx(inode, attrs->ia_secdata,
     269                 :            :                                             attrs->ia_secdata_len);
     270                 :            :         }
     271                 :            : 
     272         [ +  + ]:      66468 :         if (kernfs_type(kn) == KERNFS_DIR)
     273                 :      62876 :                 set_nlink(inode, kn->dir.subdirs + 2);
     274                 :      66468 : }
     275                 :            : 
     276                 :          0 : int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry,
     277                 :            :                    struct kstat *stat)
     278                 :            : {
     279                 :       1619 :         struct kernfs_node *kn = dentry->d_fsdata;
     280                 :       1619 :         struct inode *inode = dentry->d_inode;
     281                 :            : 
     282                 :       1619 :         mutex_lock(&kernfs_mutex);
     283                 :       1619 :         kernfs_refresh_inode(kn, inode);
     284                 :       1619 :         mutex_unlock(&kernfs_mutex);
     285                 :            : 
     286                 :       1619 :         generic_fillattr(inode, stat);
     287                 :       1619 :         return 0;
     288                 :            : }
     289                 :            : 
     290                 :          0 : static void kernfs_init_inode(struct kernfs_node *kn, struct inode *inode)
     291                 :            : {
     292                 :        555 :         kernfs_get(kn);
     293                 :        555 :         inode->i_private = kn;
     294                 :        555 :         inode->i_mapping->a_ops = &kernfs_aops;
     295                 :        555 :         inode->i_mapping->backing_dev_info = &kernfs_bdi;
     296                 :        555 :         inode->i_op = &kernfs_iops;
     297                 :            : 
     298                 :        555 :         set_default_inode_attr(inode, kn->mode);
     299                 :        555 :         kernfs_refresh_inode(kn, inode);
     300                 :            : 
     301                 :            :         /* initialize inode according to type */
     302   [ +  +  +  - ]:       1110 :         switch (kernfs_type(kn)) {
     303                 :            :         case KERNFS_DIR:
     304                 :        164 :                 inode->i_op = &kernfs_dir_iops;
     305                 :        164 :                 inode->i_fop = &kernfs_dir_fops;
     306                 :        164 :                 break;
     307                 :            :         case KERNFS_FILE:
     308                 :        257 :                 inode->i_size = kn->attr.size;
     309                 :        257 :                 inode->i_fop = &kernfs_file_fops;
     310                 :        257 :                 break;
     311                 :            :         case KERNFS_LINK:
     312                 :        134 :                 inode->i_op = &kernfs_symlink_iops;
     313                 :        134 :                 break;
     314                 :            :         default:
     315                 :          0 :                 BUG();
     316                 :            :         }
     317                 :            : 
     318                 :        555 :         unlock_new_inode(inode);
     319                 :        555 : }
     320                 :            : 
     321                 :            : /**
     322                 :            :  *      kernfs_get_inode - get inode for kernfs_node
     323                 :            :  *      @sb: super block
     324                 :            :  *      @kn: kernfs_node to allocate inode for
     325                 :            :  *
     326                 :            :  *      Get inode for @kn.  If such inode doesn't exist, a new inode is
     327                 :            :  *      allocated and basics are initialized.  New inode is returned
     328                 :            :  *      locked.
     329                 :            :  *
     330                 :            :  *      LOCKING:
     331                 :            :  *      Kernel thread context (may sleep).
     332                 :            :  *
     333                 :            :  *      RETURNS:
     334                 :            :  *      Pointer to allocated inode on success, NULL on failure.
     335                 :            :  */
     336                 :          0 : struct inode *kernfs_get_inode(struct super_block *sb, struct kernfs_node *kn)
     337                 :            : {
     338                 :            :         struct inode *inode;
     339                 :            : 
     340                 :        555 :         inode = iget_locked(sb, kn->ino);
     341 [ +  - ][ +  - ]:        555 :         if (inode && (inode->i_state & I_NEW))
     342                 :        555 :                 kernfs_init_inode(kn, inode);
     343                 :            : 
     344                 :          0 :         return inode;
     345                 :            : }
     346                 :            : 
     347                 :            : /*
     348                 :            :  * The kernfs_node serves as both an inode and a directory entry for
     349                 :            :  * kernfs.  To prevent the kernfs inode numbers from being freed
     350                 :            :  * prematurely we take a reference to kernfs_node from the kernfs inode.  A
     351                 :            :  * super_operations.evict_inode() implementation is needed to drop that
     352                 :            :  * reference upon inode destruction.
     353                 :            :  */
     354                 :          0 : void kernfs_evict_inode(struct inode *inode)
     355                 :            : {
     356                 :       4113 :         struct kernfs_node *kn = inode->i_private;
     357                 :            : 
     358                 :       4113 :         truncate_inode_pages(&inode->i_data, 0);
     359                 :       4113 :         clear_inode(inode);
     360                 :       4113 :         kernfs_put(kn);
     361                 :       4113 : }
     362                 :            : 
     363                 :          0 : int kernfs_iop_permission(struct inode *inode, int mask)
     364                 :            : {
     365                 :            :         struct kernfs_node *kn;
     366                 :            : 
     367         [ +  + ]:      89555 :         if (mask & MAY_NOT_BLOCK)
     368                 :            :                 return -ECHILD;
     369                 :            : 
     370                 :      64288 :         kn = inode->i_private;
     371                 :            : 
     372                 :      64288 :         mutex_lock(&kernfs_mutex);
     373                 :      64294 :         kernfs_refresh_inode(kn, inode);
     374                 :      64294 :         mutex_unlock(&kernfs_mutex);
     375                 :            : 
     376                 :      64294 :         return generic_permission(inode, mask);
     377                 :            : }

Generated by: LCOV version 1.9