LCOV - code coverage report
Current view: top level - fs/sysfs - dir.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 19 43 44.2 %
Date: 2014-04-16 Functions: 3 6 50.0 %
Branches: 9 30 30.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * fs/sysfs/dir.c - sysfs core and dir operation implementation
       3                 :            :  *
       4                 :            :  * Copyright (c) 2001-3 Patrick Mochel
       5                 :            :  * Copyright (c) 2007 SUSE Linux Products GmbH
       6                 :            :  * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
       7                 :            :  *
       8                 :            :  * This file is released under the GPLv2.
       9                 :            :  *
      10                 :            :  * Please see Documentation/filesystems/sysfs.txt for more information.
      11                 :            :  */
      12                 :            : 
      13                 :            : #undef DEBUG
      14                 :            : 
      15                 :            : #include <linux/fs.h>
      16                 :            : #include <linux/kobject.h>
      17                 :            : #include <linux/slab.h>
      18                 :            : #include "sysfs.h"
      19                 :            : 
      20                 :            : DEFINE_SPINLOCK(sysfs_symlink_target_lock);
      21                 :            : 
      22                 :            : /**
      23                 :            :  *      sysfs_pathname - return full path to sysfs dirent
      24                 :            :  *      @kn: kernfs_node whose path we want
      25                 :            :  *      @path: caller allocated buffer of size PATH_MAX
      26                 :            :  *
      27                 :            :  *      Gives the name "/" to the sysfs_root entry; any path returned
      28                 :            :  *      is relative to wherever sysfs is mounted.
      29                 :            :  */
      30                 :          0 : static char *sysfs_pathname(struct kernfs_node *kn, char *path)
      31                 :            : {
      32         [ #  # ]:          0 :         if (kn->parent) {
      33                 :          0 :                 sysfs_pathname(kn->parent, path);
      34                 :          0 :                 strlcat(path, "/", PATH_MAX);
      35                 :            :         }
      36                 :          0 :         strlcat(path, kn->name, PATH_MAX);
      37                 :          0 :         return path;
      38                 :            : }
      39                 :            : 
      40                 :          0 : void sysfs_warn_dup(struct kernfs_node *parent, const char *name)
      41                 :            : {
      42                 :            :         char *path;
      43                 :            : 
      44                 :            :         path = kzalloc(PATH_MAX, GFP_KERNEL);
      45         [ #  # ]:          0 :         if (path) {
      46                 :          0 :                 sysfs_pathname(parent, path);
      47                 :          0 :                 strlcat(path, "/", PATH_MAX);
      48                 :          0 :                 strlcat(path, name, PATH_MAX);
      49                 :            :         }
      50                 :            : 
      51         [ #  # ]:          0 :         WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s'\n",
      52                 :            :              path ? path : name);
      53                 :            : 
      54                 :          0 :         kfree(path);
      55                 :          0 : }
      56                 :            : 
      57                 :            : /**
      58                 :            :  * sysfs_create_dir_ns - create a directory for an object with a namespace tag
      59                 :            :  * @kobj: object we're creating directory for
      60                 :            :  * @ns: the namespace tag to use
      61                 :            :  */
      62                 :          0 : int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
      63                 :            : {
      64                 :            :         struct kernfs_node *parent, *kn;
      65                 :            : 
      66         [ -  + ]:        133 :         BUG_ON(!kobj);
      67                 :            : 
      68         [ +  - ]:        133 :         if (kobj->parent)
      69                 :        133 :                 parent = kobj->parent->sd;
      70                 :            :         else
      71                 :          0 :                 parent = sysfs_root_kn;
      72                 :            : 
      73         [ +  - ]:        133 :         if (!parent)
      74                 :            :                 return -ENOENT;
      75                 :            : 
      76                 :        133 :         kn = kernfs_create_dir_ns(parent, kobject_name(kobj),
      77                 :            :                                   S_IRWXU | S_IRUGO | S_IXUGO, kobj, ns);
      78         [ -  + ]:        266 :         if (IS_ERR(kn)) {
      79         [ #  # ]:          0 :                 if (PTR_ERR(kn) == -EEXIST)
      80                 :          0 :                         sysfs_warn_dup(parent, kobject_name(kobj));
      81                 :          0 :                 return PTR_ERR(kn);
      82                 :            :         }
      83                 :            : 
      84                 :        133 :         kobj->sd = kn;
      85                 :        133 :         return 0;
      86                 :            : }
      87                 :            : 
      88                 :            : /**
      89                 :            :  *      sysfs_remove_dir - remove an object's directory.
      90                 :            :  *      @kobj:  object.
      91                 :            :  *
      92                 :            :  *      The only thing special about this is that we remove any files in
      93                 :            :  *      the directory before we remove the directory, and we've inlined
      94                 :            :  *      what used to be sysfs_rmdir() below, instead of calling separately.
      95                 :            :  */
      96                 :          0 : void sysfs_remove_dir(struct kobject *kobj)
      97                 :            : {
      98                 :         42 :         struct kernfs_node *kn = kobj->sd;
      99                 :            : 
     100                 :            :         /*
     101                 :            :          * In general, kboject owner is responsible for ensuring removal
     102                 :            :          * doesn't race with other operations and sysfs doesn't provide any
     103                 :            :          * protection; however, when @kobj is used as a symlink target, the
     104                 :            :          * symlinking entity usually doesn't own @kobj and thus has no
     105                 :            :          * control over removal.  @kobj->sd may be removed anytime
     106                 :            :          * and symlink code may end up dereferencing an already freed node.
     107                 :            :          *
     108                 :            :          * sysfs_symlink_target_lock synchronizes @kobj->sd
     109                 :            :          * disassociation against symlink operations so that symlink code
     110                 :            :          * can safely dereference @kobj->sd.
     111                 :            :          */
     112                 :            :         spin_lock(&sysfs_symlink_target_lock);
     113                 :         21 :         kobj->sd = NULL;
     114                 :            :         spin_unlock(&sysfs_symlink_target_lock);
     115                 :            : 
     116         [ +  - ]:         21 :         if (kn) {
     117 [ -  + ][ #  # ]:         21 :                 WARN_ON_ONCE(kernfs_type(kn) != KERNFS_DIR);
                 [ #  # ]
     118                 :         21 :                 kernfs_remove(kn);
     119                 :            :         }
     120                 :         21 : }
     121                 :            : 
     122                 :          0 : int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
     123                 :            :                         const void *new_ns)
     124                 :            : {
     125                 :          0 :         struct kernfs_node *parent = kobj->sd->parent;
     126                 :            : 
     127                 :          0 :         return kernfs_rename_ns(kobj->sd, parent, new_name, new_ns);
     128                 :            : }
     129                 :            : 
     130                 :          0 : int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj,
     131                 :            :                       const void *new_ns)
     132                 :            : {
     133                 :         29 :         struct kernfs_node *kn = kobj->sd;
     134                 :            :         struct kernfs_node *new_parent;
     135                 :            : 
     136         [ -  + ]:         29 :         BUG_ON(!kn->parent);
     137         [ -  + ]:         29 :         new_parent = new_parent_kobj && new_parent_kobj->sd ?
     138         [ +  - ]:         29 :                 new_parent_kobj->sd : sysfs_root_kn;
     139                 :            : 
     140                 :         29 :         return kernfs_rename_ns(kn, new_parent, kn->name, new_ns);
     141                 :            : }

Generated by: LCOV version 1.9