Commit 0c096b50 authored by Tejun Heo's avatar Tejun Heo Committed by Greg Kroah-Hartman

sysfs: add sysfs_dirent->s_name

Add s_name to sysfs_dirent.  This is to further reduce dependency to
the associated dentry.  Name is copied for directories and symlinks
but not for attributes.

Where possible, name dereferences are converted to use sd->s_name.
sysfs_symlink->link_name and sysfs_get_name() are unused now and
removed.

This change allows symlink to be implemented using sysfs_dirent tree
proper, which is the last remaining dentry-dependent sysfs walk.
Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 13b3086d
...@@ -54,10 +54,11 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) ...@@ -54,10 +54,11 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
if (sd->s_type & SYSFS_KOBJ_LINK) { if (sd->s_type & SYSFS_KOBJ_LINK) {
struct sysfs_symlink * sl = sd->s_element; struct sysfs_symlink * sl = sd->s_element;
kfree(sl->link_name);
kobject_put(sl->target_kobj); kobject_put(sl->target_kobj);
kfree(sl); kfree(sl);
} }
if (sd->s_type & SYSFS_COPY_NAME)
kfree(sd->s_name);
kfree(sd->s_iattr); kfree(sd->s_iattr);
sysfs_free_ino(sd->s_ino); sysfs_free_ino(sd->s_ino);
kmem_cache_free(sysfs_dir_cachep, sd); kmem_cache_free(sysfs_dir_cachep, sd);
...@@ -94,29 +95,41 @@ static struct dentry_operations sysfs_dentry_ops = { ...@@ -94,29 +95,41 @@ static struct dentry_operations sysfs_dentry_ops = {
.d_iput = sysfs_d_iput, .d_iput = sysfs_d_iput,
}; };
struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode, int type) struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element,
umode_t mode, int type)
{ {
struct sysfs_dirent * sd; char *dup_name = NULL;
struct sysfs_dirent *sd = NULL;
if (type & SYSFS_COPY_NAME) {
name = dup_name = kstrdup(name, GFP_KERNEL);
if (!name)
goto err_out;
}
sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
if (!sd) if (!sd)
return NULL; goto err_out;
if (sysfs_alloc_ino(&sd->s_ino)) { if (sysfs_alloc_ino(&sd->s_ino))
kmem_cache_free(sysfs_dir_cachep, sd); goto err_out;
return NULL;
}
atomic_set(&sd->s_count, 1); atomic_set(&sd->s_count, 1);
atomic_set(&sd->s_event, 1); atomic_set(&sd->s_event, 1);
INIT_LIST_HEAD(&sd->s_children); INIT_LIST_HEAD(&sd->s_children);
INIT_LIST_HEAD(&sd->s_sibling); INIT_LIST_HEAD(&sd->s_sibling);
sd->s_name = name;
sd->s_element = element; sd->s_element = element;
sd->s_mode = mode; sd->s_mode = mode;
sd->s_type = type; sd->s_type = type;
return sd; return sd;
err_out:
kfree(dup_name);
kmem_cache_free(sysfs_dir_cachep, sd);
return NULL;
} }
void sysfs_attach_dirent(struct sysfs_dirent *sd, void sysfs_attach_dirent(struct sysfs_dirent *sd,
...@@ -148,8 +161,7 @@ int sysfs_dirent_exist(struct sysfs_dirent *parent_sd, ...@@ -148,8 +161,7 @@ int sysfs_dirent_exist(struct sysfs_dirent *parent_sd,
list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
if (sd->s_element) { if (sd->s_element) {
const unsigned char *existing = sysfs_get_name(sd); if (strcmp(sd->s_name, new))
if (strcmp(existing, new))
continue; continue;
else else
return -EEXIST; return -EEXIST;
...@@ -203,7 +215,7 @@ static int create_dir(struct kobject *kobj, struct dentry *parent, ...@@ -203,7 +215,7 @@ static int create_dir(struct kobject *kobj, struct dentry *parent,
goto out_dput; goto out_dput;
error = -ENOMEM; error = -ENOMEM;
sd = sysfs_new_dirent(kobj, mode, SYSFS_DIR); sd = sysfs_new_dirent(name, kobj, mode, SYSFS_DIR);
if (!sd) if (!sd)
goto out_drop; goto out_drop;
sysfs_attach_dirent(sd, parent->d_fsdata, dentry); sysfs_attach_dirent(sd, parent->d_fsdata, dentry);
...@@ -334,9 +346,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -334,9 +346,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
if (sd->s_type & SYSFS_NOT_PINNED) { if (sd->s_type & SYSFS_NOT_PINNED) {
const unsigned char * name = sysfs_get_name(sd); if (strcmp(sd->s_name, dentry->d_name.name))
if (strcmp(name, dentry->d_name.name))
continue; continue;
if (sd->s_type & SYSFS_KOBJ_LINK) if (sd->s_type & SYSFS_KOBJ_LINK)
...@@ -427,9 +437,11 @@ void sysfs_remove_dir(struct kobject * kobj) ...@@ -427,9 +437,11 @@ void sysfs_remove_dir(struct kobject * kobj)
int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
const char *new_name) const char *new_name)
{ {
struct sysfs_dirent *sd = kobj->dentry->d_fsdata;
struct sysfs_dirent *parent_sd = new_parent->d_fsdata;
struct dentry *new_dentry;
char *dup_name;
int error; int error;
struct dentry * new_dentry;
struct sysfs_dirent *sd, *parent_sd;
if (!new_parent) if (!new_parent)
return -EFAULT; return -EFAULT;
...@@ -457,22 +469,31 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, ...@@ -457,22 +469,31 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
if (new_dentry->d_inode) if (new_dentry->d_inode)
goto out_dput; goto out_dput;
/* rename kobject and sysfs_dirent */
error = -ENOMEM;
new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
if (!new_name)
goto out_drop;
error = kobject_set_name(kobj, "%s", new_name); error = kobject_set_name(kobj, "%s", new_name);
if (error) if (error)
goto out_drop; goto out_free;
kfree(sd->s_name);
sd->s_name = new_name;
/* move under the new parent */
d_add(new_dentry, NULL); d_add(new_dentry, NULL);
d_move(kobj->dentry, new_dentry); d_move(kobj->dentry, new_dentry);
sd = kobj->dentry->d_fsdata;
parent_sd = new_parent->d_fsdata;
list_del_init(&sd->s_sibling); list_del_init(&sd->s_sibling);
list_add(&sd->s_sibling, &parent_sd->s_children); list_add(&sd->s_sibling, &parent_sd->s_children);
error = 0; error = 0;
goto out_unlock; goto out_unlock;
out_free:
kfree(dup_name);
out_drop: out_drop:
d_drop(new_dentry); d_drop(new_dentry);
out_dput: out_dput:
...@@ -535,7 +556,7 @@ static int sysfs_dir_open(struct inode *inode, struct file *file) ...@@ -535,7 +556,7 @@ static int sysfs_dir_open(struct inode *inode, struct file *file)
struct sysfs_dirent * sd; struct sysfs_dirent * sd;
mutex_lock(&dentry->d_inode->i_mutex); mutex_lock(&dentry->d_inode->i_mutex);
sd = sysfs_new_dirent(NULL, 0, 0); sd = sysfs_new_dirent("_DIR_", NULL, 0, 0);
if (sd) if (sd)
sysfs_attach_dirent(sd, parent_sd, NULL); sysfs_attach_dirent(sd, parent_sd, NULL);
mutex_unlock(&dentry->d_inode->i_mutex); mutex_unlock(&dentry->d_inode->i_mutex);
...@@ -605,7 +626,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) ...@@ -605,7 +626,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
if (!next->s_element) if (!next->s_element)
continue; continue;
name = sysfs_get_name(next); name = next->s_name;
len = strlen(name); len = strlen(name);
ino = next->s_ino; ino = next->s_ino;
...@@ -717,7 +738,7 @@ struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) ...@@ -717,7 +738,7 @@ struct dentry *sysfs_create_shadow_dir(struct kobject *kobj)
if (!shadow) if (!shadow)
goto nomem; goto nomem;
sd = sysfs_new_dirent(kobj, inode->i_mode, SYSFS_DIR); sd = sysfs_new_dirent("_SHADOW_", kobj, inode->i_mode, SYSFS_DIR);
if (!sd) if (!sd)
goto nomem; goto nomem;
/* point to parent_sd but don't attach to it */ /* point to parent_sd but don't attach to it */
......
...@@ -454,7 +454,7 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) ...@@ -454,7 +454,7 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
goto out_unlock; goto out_unlock;
} }
sd = sysfs_new_dirent((void *)attr, mode, type); sd = sysfs_new_dirent(attr->name, (void *)attr, mode, type);
if (!sd) { if (!sd) {
error = -ENOMEM; error = -ENOMEM;
goto out_unlock; goto out_unlock;
......
...@@ -191,37 +191,6 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) ...@@ -191,37 +191,6 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
return error; return error;
} }
/*
* Get the name for corresponding element represented by the given sysfs_dirent
*/
const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
{
struct attribute * attr;
struct bin_attribute * bin_attr;
struct sysfs_symlink * sl;
BUG_ON(!sd || !sd->s_element);
switch (sd->s_type) {
case SYSFS_DIR:
/* Always have a dentry so use that */
return sd->s_dentry->d_name.name;
case SYSFS_KOBJ_ATTR:
attr = sd->s_element;
return attr->name;
case SYSFS_KOBJ_BIN_ATTR:
bin_attr = sd->s_element;
return bin_attr->attr.name;
case SYSFS_KOBJ_LINK:
sl = sd->s_element;
return sl->link_name;
}
return NULL;
}
static inline void orphan_all_buffers(struct inode *node) static inline void orphan_all_buffers(struct inode *node)
{ {
struct sysfs_buffer_collection *set; struct sysfs_buffer_collection *set;
...@@ -305,7 +274,7 @@ int sysfs_hash_and_remove(struct dentry * dir, const char * name) ...@@ -305,7 +274,7 @@ int sysfs_hash_and_remove(struct dentry * dir, const char * name)
list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
if (!sd->s_element) if (!sd->s_element)
continue; continue;
if (!strcmp(sysfs_get_name(sd), name)) { if (!strcmp(sd->s_name, name)) {
list_del_init(&sd->s_sibling); list_del_init(&sd->s_sibling);
sysfs_drop_dentry(sd, dir); sysfs_drop_dentry(sd, dir);
sysfs_put(sd); sysfs_put(sd);
......
...@@ -57,14 +57,9 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj ...@@ -57,14 +57,9 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj
if (!sl) if (!sl)
goto err_out; goto err_out;
sl->link_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
if (!sl->link_name)
goto err_out;
strcpy(sl->link_name, name);
sl->target_kobj = kobject_get(target); sl->target_kobj = kobject_get(target);
sd = sysfs_new_dirent(sl, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); sd = sysfs_new_dirent(name, sl, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
if (!sd) if (!sd)
goto err_out; goto err_out;
sysfs_attach_dirent(sd, parent_sd, NULL); sysfs_attach_dirent(sd, parent_sd, NULL);
...@@ -74,7 +69,6 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj ...@@ -74,7 +69,6 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj
err_out: err_out:
if (sl) { if (sl) {
kobject_put(sl->target_kobj); kobject_put(sl->target_kobj);
kfree(sl->link_name);
kfree(sl); kfree(sl);
} }
return error; return error;
......
...@@ -3,6 +3,7 @@ struct sysfs_dirent { ...@@ -3,6 +3,7 @@ struct sysfs_dirent {
struct sysfs_dirent * s_parent; struct sysfs_dirent * s_parent;
struct list_head s_sibling; struct list_head s_sibling;
struct list_head s_children; struct list_head s_children;
const char * s_name;
void * s_element; void * s_element;
int s_type; int s_type;
umode_t s_mode; umode_t s_mode;
...@@ -21,8 +22,8 @@ extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); ...@@ -21,8 +22,8 @@ extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
extern void release_sysfs_dirent(struct sysfs_dirent * sd); extern void release_sysfs_dirent(struct sysfs_dirent * sd);
extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
extern struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode, extern struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element,
int type); umode_t mode, int type);
extern void sysfs_attach_dirent(struct sysfs_dirent *sd, extern void sysfs_attach_dirent(struct sysfs_dirent *sd,
struct sysfs_dirent *parent_sd, struct sysfs_dirent *parent_sd,
struct dentry *dentry); struct dentry *dentry);
...@@ -34,7 +35,6 @@ extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * na ...@@ -34,7 +35,6 @@ extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * na
extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
extern void sysfs_remove_subdir(struct dentry *); extern void sysfs_remove_subdir(struct dentry *);
extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
...@@ -48,7 +48,6 @@ extern const struct inode_operations sysfs_dir_inode_operations; ...@@ -48,7 +48,6 @@ extern const struct inode_operations sysfs_dir_inode_operations;
extern const struct inode_operations sysfs_symlink_inode_operations; extern const struct inode_operations sysfs_symlink_inode_operations;
struct sysfs_symlink { struct sysfs_symlink {
char * link_name;
struct kobject * target_kobj; struct kobject * target_kobj;
}; };
......
...@@ -76,6 +76,7 @@ struct sysfs_ops { ...@@ -76,6 +76,7 @@ struct sysfs_ops {
#define SYSFS_KOBJ_BIN_ATTR 0x0008 #define SYSFS_KOBJ_BIN_ATTR 0x0008
#define SYSFS_KOBJ_LINK 0x0020 #define SYSFS_KOBJ_LINK 0x0020
#define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK) #define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK)
#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)
#ifdef CONFIG_SYSFS #ifdef CONFIG_SYSFS
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment