LCOV - code coverage report
Current view: top level - fs/sysfs - symlink.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 21 50 42.0 %
Date: 2022-04-01 13:59:58 Functions: 3 6 50.0 %
Branches: 5 24 20.8 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * fs/sysfs/symlink.c - sysfs symlink implementation
       4                 :            :  *
       5                 :            :  * Copyright (c) 2001-3 Patrick Mochel
       6                 :            :  * Copyright (c) 2007 SUSE Linux Products GmbH
       7                 :            :  * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
       8                 :            :  *
       9                 :            :  * Please see Documentation/filesystems/sysfs.txt for more information.
      10                 :            :  */
      11                 :            : 
      12                 :            : #include <linux/fs.h>
      13                 :            : #include <linux/module.h>
      14                 :            : #include <linux/kobject.h>
      15                 :            : #include <linux/mutex.h>
      16                 :            : #include <linux/security.h>
      17                 :            : 
      18                 :            : #include "sysfs.h"
      19                 :            : 
      20                 :            : static int sysfs_do_create_link_sd(struct kernfs_node *parent,
      21                 :            :                                    struct kobject *target_kobj,
      22                 :            :                                    const char *name, int warn)
      23                 :            : {
      24                 :            :         struct kernfs_node *kn, *target = NULL;
      25                 :            : 
      26                 :            :         if (WARN_ON(!name || !parent))
      27                 :            :                 return -EINVAL;
      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                 :            :         if (target_kobj->sd) {
      36                 :            :                 target = target_kobj->sd;
      37                 :            :                 kernfs_get(target);
      38                 :            :         }
      39                 :            :         spin_unlock(&sysfs_symlink_target_lock);
      40                 :            : 
      41                 :            :         if (!target)
      42                 :            :                 return -ENOENT;
      43                 :            : 
      44                 :            :         kn = kernfs_create_link(parent, name, target);
      45                 :            :         kernfs_put(target);
      46                 :            : 
      47                 :            :         if (!IS_ERR(kn))
      48                 :            :                 return 0;
      49                 :            : 
      50                 :            :         if (warn && PTR_ERR(kn) == -EEXIST)
      51                 :            :                 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                 :      73050 : static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
      68                 :            :                                 const char *name, int warn)
      69                 :            : {
      70                 :      73050 :         struct kernfs_node *parent = NULL;
      71                 :            : 
      72                 :      73050 :         if (!kobj)
      73                 :          0 :                 parent = sysfs_root_kn;
      74                 :            :         else
      75                 :      73050 :                 parent = kobj->sd;
      76                 :            : 
      77   [ -  -  +  - ]:      73050 :         if (!parent)
      78                 :            :                 return -EFAULT;
      79                 :            : 
      80                 :      73050 :         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                 :      73050 : int sysfs_create_link(struct kobject *kobj, struct kobject *target,
      90                 :            :                       const char *name)
      91                 :            : {
      92         [ -  + ]:      73050 :         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                 :            : EXPORT_SYMBOL_GPL(sysfs_create_link_nowarn);
     111                 :            : 
     112                 :            : /**
     113                 :            :  *      sysfs_delete_link - remove symlink in object's directory.
     114                 :            :  *      @kobj:  object we're acting for.
     115                 :            :  *      @targ:  object we're pointing to.
     116                 :            :  *      @name:  name of the symlink to remove.
     117                 :            :  *
     118                 :            :  *      Unlike sysfs_remove_link sysfs_delete_link has enough information
     119                 :            :  *      to successfully delete symlinks in tagged directories.
     120                 :            :  */
     121                 :         78 : void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
     122                 :            :                         const char *name)
     123                 :            : {
     124                 :         78 :         const void *ns = NULL;
     125                 :            : 
     126                 :            :         /*
     127                 :            :          * We don't own @target and it may be removed at any time.
     128                 :            :          * Synchronize using sysfs_symlink_target_lock.  See
     129                 :            :          * sysfs_remove_dir() for details.
     130                 :            :          */
     131                 :         78 :         spin_lock(&sysfs_symlink_target_lock);
     132   [ +  -  -  + ]:         78 :         if (targ->sd && kernfs_ns_enabled(kobj->sd))
     133                 :          0 :                 ns = targ->sd->ns;
     134                 :         78 :         spin_unlock(&sysfs_symlink_target_lock);
     135                 :         78 :         kernfs_remove_by_name_ns(kobj->sd, name, ns);
     136                 :         78 : }
     137                 :            : 
     138                 :            : /**
     139                 :            :  *      sysfs_remove_link - remove symlink in object's directory.
     140                 :            :  *      @kobj:  object we're acting for.
     141                 :            :  *      @name:  name of the symlink to remove.
     142                 :            :  */
     143                 :      18498 : void sysfs_remove_link(struct kobject *kobj, const char *name)
     144                 :            : {
     145                 :      18498 :         struct kernfs_node *parent = NULL;
     146                 :            : 
     147         [ -  + ]:      18498 :         if (!kobj)
     148                 :          0 :                 parent = sysfs_root_kn;
     149                 :            :         else
     150                 :      18498 :                 parent = kobj->sd;
     151                 :            : 
     152                 :      18498 :         kernfs_remove_by_name(parent, name);
     153                 :      18498 : }
     154                 :            : EXPORT_SYMBOL_GPL(sysfs_remove_link);
     155                 :            : 
     156                 :            : /**
     157                 :            :  *      sysfs_rename_link_ns - rename symlink in object's directory.
     158                 :            :  *      @kobj:  object we're acting for.
     159                 :            :  *      @targ:  object we're pointing to.
     160                 :            :  *      @old:   previous name of the symlink.
     161                 :            :  *      @new:   new name of the symlink.
     162                 :            :  *      @new_ns: new namespace of the symlink.
     163                 :            :  *
     164                 :            :  *      A helper function for the common rename symlink idiom.
     165                 :            :  */
     166                 :          0 : int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ,
     167                 :            :                          const char *old, const char *new, const void *new_ns)
     168                 :            : {
     169                 :          0 :         struct kernfs_node *parent, *kn = NULL;
     170                 :          0 :         const void *old_ns = NULL;
     171                 :          0 :         int result;
     172                 :            : 
     173         [ #  # ]:          0 :         if (!kobj)
     174                 :          0 :                 parent = sysfs_root_kn;
     175                 :            :         else
     176                 :          0 :                 parent = kobj->sd;
     177                 :            : 
     178         [ #  # ]:          0 :         if (targ->sd)
     179                 :          0 :                 old_ns = targ->sd->ns;
     180                 :            : 
     181                 :          0 :         result = -ENOENT;
     182                 :          0 :         kn = kernfs_find_and_get_ns(parent, old, old_ns);
     183         [ #  # ]:          0 :         if (!kn)
     184                 :          0 :                 goto out;
     185                 :            : 
     186                 :          0 :         result = -EINVAL;
     187         [ #  # ]:          0 :         if (kernfs_type(kn) != KERNFS_LINK)
     188                 :          0 :                 goto out;
     189         [ #  # ]:          0 :         if (kn->symlink.target_kn->priv != targ)
     190                 :          0 :                 goto out;
     191                 :            : 
     192                 :          0 :         result = kernfs_rename_ns(kn, parent, new, new_ns);
     193                 :            : 
     194                 :          0 : out:
     195                 :          0 :         kernfs_put(kn);
     196                 :          0 :         return result;
     197                 :            : }
     198                 :            : EXPORT_SYMBOL_GPL(sysfs_rename_link_ns);

Generated by: LCOV version 1.14