0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #define pr_fmt(fmt) "sysfs: " fmt
0013
0014 #include <linux/fs.h>
0015 #include <linux/kobject.h>
0016 #include <linux/slab.h>
0017 #include "sysfs.h"
0018
0019 DEFINE_SPINLOCK(sysfs_symlink_target_lock);
0020
0021 void sysfs_warn_dup(struct kernfs_node *parent, const char *name)
0022 {
0023 char *buf;
0024
0025 buf = kzalloc(PATH_MAX, GFP_KERNEL);
0026 if (buf)
0027 kernfs_path(parent, buf, PATH_MAX);
0028
0029 pr_warn("cannot create duplicate filename '%s/%s'\n", buf, name);
0030 dump_stack();
0031
0032 kfree(buf);
0033 }
0034
0035
0036
0037
0038
0039
0040 int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
0041 {
0042 struct kernfs_node *parent, *kn;
0043 kuid_t uid;
0044 kgid_t gid;
0045
0046 if (WARN_ON(!kobj))
0047 return -EINVAL;
0048
0049 if (kobj->parent)
0050 parent = kobj->parent->sd;
0051 else
0052 parent = sysfs_root_kn;
0053
0054 if (!parent)
0055 return -ENOENT;
0056
0057 kobject_get_ownership(kobj, &uid, &gid);
0058
0059 kn = kernfs_create_dir_ns(parent, kobject_name(kobj), 0755, uid, gid,
0060 kobj, ns);
0061 if (IS_ERR(kn)) {
0062 if (PTR_ERR(kn) == -EEXIST)
0063 sysfs_warn_dup(parent, kobject_name(kobj));
0064 return PTR_ERR(kn);
0065 }
0066
0067 kobj->sd = kn;
0068 return 0;
0069 }
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 void sysfs_remove_dir(struct kobject *kobj)
0080 {
0081 struct kernfs_node *kn = kobj->sd;
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 spin_lock(&sysfs_symlink_target_lock);
0096 kobj->sd = NULL;
0097 spin_unlock(&sysfs_symlink_target_lock);
0098
0099 if (kn) {
0100 WARN_ON_ONCE(kernfs_type(kn) != KERNFS_DIR);
0101 kernfs_remove(kn);
0102 }
0103 }
0104
0105 int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
0106 const void *new_ns)
0107 {
0108 struct kernfs_node *parent;
0109 int ret;
0110
0111 parent = kernfs_get_parent(kobj->sd);
0112 ret = kernfs_rename_ns(kobj->sd, parent, new_name, new_ns);
0113 kernfs_put(parent);
0114 return ret;
0115 }
0116
0117 int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj,
0118 const void *new_ns)
0119 {
0120 struct kernfs_node *kn = kobj->sd;
0121 struct kernfs_node *new_parent;
0122
0123 new_parent = new_parent_kobj && new_parent_kobj->sd ?
0124 new_parent_kobj->sd : sysfs_root_kn;
0125
0126 return kernfs_rename_ns(kn, new_parent, kn->name, new_ns);
0127 }
0128
0129
0130
0131
0132
0133
0134 int sysfs_create_mount_point(struct kobject *parent_kobj, const char *name)
0135 {
0136 struct kernfs_node *kn, *parent = parent_kobj->sd;
0137
0138 kn = kernfs_create_empty_dir(parent, name);
0139 if (IS_ERR(kn)) {
0140 if (PTR_ERR(kn) == -EEXIST)
0141 sysfs_warn_dup(parent, name);
0142 return PTR_ERR(kn);
0143 }
0144
0145 return 0;
0146 }
0147 EXPORT_SYMBOL_GPL(sysfs_create_mount_point);
0148
0149
0150
0151
0152
0153
0154
0155 void sysfs_remove_mount_point(struct kobject *parent_kobj, const char *name)
0156 {
0157 struct kernfs_node *parent = parent_kobj->sd;
0158
0159 kernfs_remove_by_name_ns(parent, name, NULL);
0160 }
0161 EXPORT_SYMBOL_GPL(sysfs_remove_mount_point);