LCOV - code coverage report
Current view: top level - fs/sysfs - symlink.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 18 46 39.1 %
Date: 2014-04-16 Functions: 5 8 62.5 %
Branches: 9 32 28.1 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * fs/sysfs/symlink.c - sysfs symlink 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                 :            : #include <linux/fs.h>
      14                 :            : #include <linux/module.h>
      15                 :            : #include <linux/kobject.h>
      16                 :            : #include <linux/mutex.h>
      17                 :            : #include <linux/security.h>
      18                 :            : 
      19                 :            : #include "sysfs.h"
      20                 :            : 
      21                 :          0 : static int sysfs_do_create_link_sd(struct kernfs_node *parent,
      22                 :            :                                    struct kobject *target_kobj,
      23                 :            :                                    const char *name, int warn)
      24                 :            : {
      25                 :            :         struct kernfs_node *kn, *target = NULL;
      26                 :            : 
      27         [ -  + ]:        468 :         BUG_ON(!name || !parent);
      28                 :            : 
      29                 :            :         /*
      30                 :            :          * We don't own @target_kobj and it may be removed at any time.
      31                 :            :          * Synchronize using sysfs_symlink_target_lock.  See
      32                 :            :          * sysfs_remove_dir() for details.
      33                 :            :          */
      34                 :            :         spin_lock(&sysfs_symlink_target_lock);
      35         [ +  - ]:        468 :         if (target_kobj->sd) {
      36                 :            :                 target = target_kobj->sd;
      37                 :        468 :                 kernfs_get(target);
      38                 :            :         }
      39                 :            :         spin_unlock(&sysfs_symlink_target_lock);
      40                 :            : 
      41         [ +  - ]:        468 :         if (!target)
      42                 :            :                 return -ENOENT;
      43                 :            : 
      44                 :        468 :         kn = kernfs_create_link(parent, name, target);
      45                 :        468 :         kernfs_put(target);
      46                 :            : 
      47         [ -  + ]:        468 :         if (!IS_ERR(kn))
      48                 :            :                 return 0;
      49                 :            : 
      50 [ #  # ][ #  # ]:          0 :         if (warn && PTR_ERR(kn) == -EEXIST)
      51                 :          0 :                 sysfs_warn_dup(parent, name);
      52                 :            :         return PTR_ERR(kn);
      53                 :            : }
      54                 :            : 
      55                 :            : /**
      56                 :            :  *      sysfs_create_link_sd - create symlink to a given object.
      57                 :            :  *      @kn:            directory we're creating the link in.
      58                 :            :  *      @target:        object we're pointing to.
      59                 :            :  *      @name:          name of the symlink.
      60                 :            :  */
      61                 :          0 : int sysfs_create_link_sd(struct kernfs_node *kn, struct kobject *target,
      62                 :            :                          const char *name)
      63                 :            : {
      64                 :          0 :         return sysfs_do_create_link_sd(kn, target, name, 1);
      65                 :            : }
      66                 :            : 
      67                 :          0 : static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
      68                 :            :                                 const char *name, int warn)
      69                 :            : {
      70                 :            :         struct kernfs_node *parent = NULL;
      71                 :            : 
      72         [ -  + ]:        468 :         if (!kobj)
      73                 :          0 :                 parent = sysfs_root_kn;
      74                 :            :         else
      75                 :        468 :                 parent = kobj->sd;
      76                 :            : 
      77         [ +  - ]:        468 :         if (!parent)
      78                 :            :                 return -EFAULT;
      79                 :            : 
      80                 :        468 :         return sysfs_do_create_link_sd(parent, target, name, warn);
      81                 :            : }
      82                 :            : 
      83                 :            : /**
      84                 :            :  *      sysfs_create_link - create symlink between two objects.
      85                 :            :  *      @kobj:  object whose directory we're creating the link in.
      86                 :            :  *      @target:        object we're pointing to.
      87                 :            :  *      @name:          name of the symlink.
      88                 :            :  */
      89                 :          0 : int sysfs_create_link(struct kobject *kobj, struct kobject *target,
      90                 :            :                       const char *name)
      91                 :            : {
      92                 :        468 :         return sysfs_do_create_link(kobj, target, name, 1);
      93                 :            : }
      94                 :            : EXPORT_SYMBOL_GPL(sysfs_create_link);
      95                 :            : 
      96                 :            : /**
      97                 :            :  *      sysfs_create_link_nowarn - create symlink between two objects.
      98                 :            :  *      @kobj:  object whose directory we're creating the link in.
      99                 :            :  *      @target:        object we're pointing to.
     100                 :            :  *      @name:          name of the symlink.
     101                 :            :  *
     102                 :            :  *      This function does the same as sysfs_create_link(), but it
     103                 :            :  *      doesn't warn if the link already exists.
     104                 :            :  */
     105                 :          0 : int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target,
     106                 :            :                              const char *name)
     107                 :            : {
     108                 :          0 :         return sysfs_do_create_link(kobj, target, name, 0);
     109                 :            : }
     110                 :            : 
     111                 :            : /**
     112                 :            :  *      sysfs_delete_link - remove symlink in object's directory.
     113                 :            :  *      @kobj:  object we're acting for.
     114                 :            :  *      @targ:  object we're pointing to.
     115                 :            :  *      @name:  name of the symlink to remove.
     116                 :            :  *
     117                 :            :  *      Unlike sysfs_remove_link sysfs_delete_link has enough information
     118                 :            :  *      to successfully delete symlinks in tagged directories.
     119                 :            :  */
     120                 :          0 : void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
     121                 :            :                         const char *name)
     122                 :            : {
     123                 :            :         const void *ns = NULL;
     124                 :            : 
     125                 :            :         /*
     126                 :            :          * We don't own @target and it may be removed at any time.
     127                 :            :          * Synchronize using sysfs_symlink_target_lock.  See
     128                 :            :          * sysfs_remove_dir() for details.
     129                 :            :          */
     130                 :            :         spin_lock(&sysfs_symlink_target_lock);
     131 [ +  - ][ -  + ]:          6 :         if (targ->sd && kernfs_ns_enabled(kobj->sd))
     132                 :          0 :                 ns = targ->sd->ns;
     133                 :            :         spin_unlock(&sysfs_symlink_target_lock);
     134                 :          6 :         kernfs_remove_by_name_ns(kobj->sd, name, ns);
     135                 :          6 : }
     136                 :            : 
     137                 :            : /**
     138                 :            :  *      sysfs_remove_link - remove symlink in object's directory.
     139                 :            :  *      @kobj:  object we're acting for.
     140                 :            :  *      @name:  name of the symlink to remove.
     141                 :            :  */
     142                 :          0 : void sysfs_remove_link(struct kobject *kobj, const char *name)
     143                 :            : {
     144                 :            :         struct kernfs_node *parent = NULL;
     145                 :            : 
     146         [ -  + ]:        123 :         if (!kobj)
     147                 :          0 :                 parent = sysfs_root_kn;
     148                 :            :         else
     149                 :        123 :                 parent = kobj->sd;
     150                 :            : 
     151                 :            :         kernfs_remove_by_name(parent, name);
     152                 :        123 : }
     153                 :            : EXPORT_SYMBOL_GPL(sysfs_remove_link);
     154                 :            : 
     155                 :            : /**
     156                 :            :  *      sysfs_rename_link_ns - rename symlink in object's directory.
     157                 :            :  *      @kobj:  object we're acting for.
     158                 :            :  *      @targ:  object we're pointing to.
     159                 :            :  *      @old:   previous name of the symlink.
     160                 :            :  *      @new:   new name of the symlink.
     161                 :            :  *      @new_ns: new namespace of the symlink.
     162                 :            :  *
     163                 :            :  *      A helper function for the common rename symlink idiom.
     164                 :            :  */
     165                 :          0 : int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ,
     166                 :            :                          const char *old, const char *new, const void *new_ns)
     167                 :            : {
     168                 :          0 :         struct kernfs_node *parent, *kn = NULL;
     169                 :            :         const void *old_ns = NULL;
     170                 :            :         int result;
     171                 :            : 
     172         [ #  # ]:          0 :         if (!kobj)
     173                 :          0 :                 parent = sysfs_root_kn;
     174                 :            :         else
     175                 :          0 :                 parent = kobj->sd;
     176                 :            : 
     177         [ #  # ]:          0 :         if (targ->sd)
     178                 :          0 :                 old_ns = targ->sd->ns;
     179                 :            : 
     180                 :            :         result = -ENOENT;
     181                 :          0 :         kn = kernfs_find_and_get_ns(parent, old, old_ns);
     182         [ #  # ]:          0 :         if (!kn)
     183                 :            :                 goto out;
     184                 :            : 
     185                 :            :         result = -EINVAL;
     186         [ #  # ]:          0 :         if (kernfs_type(kn) != KERNFS_LINK)
     187                 :            :                 goto out;
     188         [ #  # ]:          0 :         if (kn->symlink.target_kn->priv != targ)
     189                 :            :                 goto out;
     190                 :            : 
     191                 :          0 :         result = kernfs_rename_ns(kn, parent, new, new_ns);
     192                 :            : 
     193                 :            : out:
     194                 :          0 :         kernfs_put(kn);
     195                 :          0 :         return result;
     196                 :            : }
     197                 :            : EXPORT_SYMBOL_GPL(sysfs_rename_link_ns);

Generated by: LCOV version 1.9