sysfs: Implement sysfs_rename_link

Because of rename ordering problems we occassionally give false
warnings about invalid sysfs operations. So using sysfs_rename
create a sysfs_rename_link function that doesn't need strange
workarounds.

Cc: Benjamin Thery <benjamin.thery@bull.net>
Cc: Daniel Lezcano <dlezcano@fr.ibm.com>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by Eric W. Biederman and committed by Greg Kroah-Hartman 7cb32942 19c38b63

+47
+38
fs/sysfs/symlink.c
··· 123 123 sysfs_hash_and_remove(parent_sd, name); 124 124 } 125 125 126 + /** 127 + * sysfs_rename_link - rename symlink in object's directory. 128 + * @kobj: object we're acting for. 129 + * @targ: object we're pointing to. 130 + * @old: previous name of the symlink. 131 + * @new: new name of the symlink. 132 + * 133 + * A helper function for the common rename symlink idiom. 134 + */ 135 + int sysfs_rename_link(struct kobject *kobj, struct kobject *targ, 136 + const char *old, const char *new) 137 + { 138 + struct sysfs_dirent *parent_sd, *sd = NULL; 139 + int result; 140 + 141 + if (!kobj) 142 + parent_sd = &sysfs_root; 143 + else 144 + parent_sd = kobj->sd; 145 + 146 + result = -ENOENT; 147 + sd = sysfs_get_dirent(parent_sd, old); 148 + if (!sd) 149 + goto out; 150 + 151 + result = -EINVAL; 152 + if (sysfs_type(sd) != SYSFS_KOBJ_LINK) 153 + goto out; 154 + if (sd->s_symlink.target_sd->s_dir.kobj != targ) 155 + goto out; 156 + 157 + result = sysfs_rename(sd, parent_sd, new); 158 + 159 + out: 160 + sysfs_put(sd); 161 + return result; 162 + } 163 + 126 164 static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, 127 165 struct sysfs_dirent *target_sd, char *path) 128 166 {
+9
include/linux/sysfs.h
··· 151 151 const char *name); 152 152 void sysfs_remove_link(struct kobject *kobj, const char *name); 153 153 154 + int sysfs_rename_link(struct kobject *kobj, struct kobject *target, 155 + const char *old_name, const char *new_name); 156 + 154 157 int __must_check sysfs_create_group(struct kobject *kobj, 155 158 const struct attribute_group *grp); 156 159 int sysfs_update_group(struct kobject *kobj, ··· 256 253 257 254 static inline void sysfs_remove_link(struct kobject *kobj, const char *name) 258 255 { 256 + } 257 + 258 + static inline int sysfs_rename_link(struct kobject *k, struct kobject *t, 259 + const char *old_name, const char *new_name) 260 + { 261 + return 0; 259 262 } 260 263 261 264 static inline int sysfs_create_group(struct kobject *kobj,