0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/fs.h>
0013 #include <linux/module.h>
0014 #include <linux/kobject.h>
0015 #include <linux/mutex.h>
0016 #include <linux/security.h>
0017
0018 #include "sysfs.h"
0019
0020 static int sysfs_do_create_link_sd(struct kernfs_node *parent,
0021 struct kobject *target_kobj,
0022 const char *name, int warn)
0023 {
0024 struct kernfs_node *kn, *target = NULL;
0025
0026 if (WARN_ON(!name || !parent))
0027 return -EINVAL;
0028
0029
0030
0031
0032
0033
0034 spin_lock(&sysfs_symlink_target_lock);
0035 if (target_kobj->sd) {
0036 target = target_kobj->sd;
0037 kernfs_get(target);
0038 }
0039 spin_unlock(&sysfs_symlink_target_lock);
0040
0041 if (!target)
0042 return -ENOENT;
0043
0044 kn = kernfs_create_link(parent, name, target);
0045 kernfs_put(target);
0046
0047 if (!IS_ERR(kn))
0048 return 0;
0049
0050 if (warn && PTR_ERR(kn) == -EEXIST)
0051 sysfs_warn_dup(parent, name);
0052 return PTR_ERR(kn);
0053 }
0054
0055
0056
0057
0058
0059
0060
0061 int sysfs_create_link_sd(struct kernfs_node *kn, struct kobject *target,
0062 const char *name)
0063 {
0064 return sysfs_do_create_link_sd(kn, target, name, 1);
0065 }
0066
0067 static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
0068 const char *name, int warn)
0069 {
0070 struct kernfs_node *parent = NULL;
0071
0072 if (!kobj)
0073 parent = sysfs_root_kn;
0074 else
0075 parent = kobj->sd;
0076
0077 if (!parent)
0078 return -EFAULT;
0079
0080 return sysfs_do_create_link_sd(parent, target, name, warn);
0081 }
0082
0083
0084
0085
0086
0087
0088
0089 int sysfs_create_link(struct kobject *kobj, struct kobject *target,
0090 const char *name)
0091 {
0092 return sysfs_do_create_link(kobj, target, name, 1);
0093 }
0094 EXPORT_SYMBOL_GPL(sysfs_create_link);
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105 int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target,
0106 const char *name)
0107 {
0108 return sysfs_do_create_link(kobj, target, name, 0);
0109 }
0110 EXPORT_SYMBOL_GPL(sysfs_create_link_nowarn);
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121 void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
0122 const char *name)
0123 {
0124 const void *ns = NULL;
0125
0126
0127
0128
0129
0130
0131 spin_lock(&sysfs_symlink_target_lock);
0132 if (targ->sd && kernfs_ns_enabled(kobj->sd))
0133 ns = targ->sd->ns;
0134 spin_unlock(&sysfs_symlink_target_lock);
0135 kernfs_remove_by_name_ns(kobj->sd, name, ns);
0136 }
0137
0138
0139
0140
0141
0142
0143 void sysfs_remove_link(struct kobject *kobj, const char *name)
0144 {
0145 struct kernfs_node *parent = NULL;
0146
0147 if (!kobj)
0148 parent = sysfs_root_kn;
0149 else
0150 parent = kobj->sd;
0151
0152 kernfs_remove_by_name(parent, name);
0153 }
0154 EXPORT_SYMBOL_GPL(sysfs_remove_link);
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ,
0167 const char *old, const char *new, const void *new_ns)
0168 {
0169 struct kernfs_node *parent, *kn = NULL;
0170 const void *old_ns = NULL;
0171 int result;
0172
0173 if (!kobj)
0174 parent = sysfs_root_kn;
0175 else
0176 parent = kobj->sd;
0177
0178 if (targ->sd)
0179 old_ns = targ->sd->ns;
0180
0181 result = -ENOENT;
0182 kn = kernfs_find_and_get_ns(parent, old, old_ns);
0183 if (!kn)
0184 goto out;
0185
0186 result = -EINVAL;
0187 if (kernfs_type(kn) != KERNFS_LINK)
0188 goto out;
0189 if (kn->symlink.target_kn->priv != targ)
0190 goto out;
0191
0192 result = kernfs_rename_ns(kn, parent, new, new_ns);
0193
0194 out:
0195 kernfs_put(kn);
0196 return result;
0197 }
0198 EXPORT_SYMBOL_GPL(sysfs_rename_link_ns);