sysfs: add sysfs_dirent->s_name
authorTejun Heo <htejun@gmail.com>
Wed, 13 Jun 2007 18:45:15 +0000 (03:45 +0900)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 11 Jul 2007 23:09:04 +0000 (16:09 -0700)
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: Tejun Heo <htejun@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
fs/sysfs/dir.c
fs/sysfs/file.c
fs/sysfs/inode.c
fs/sysfs/symlink.c
fs/sysfs/sysfs.h
include/linux/sysfs.h

index 5d50e1ddfbd16d188bec1dd0a351cc5a184d654d..6e8d6f54f08296146b81e7a0548b7bcccbd0b00a 100644 (file)
@@ -54,10 +54,11 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
 
        if (sd->s_type & SYSFS_KOBJ_LINK) {
                struct sysfs_symlink * sl = sd->s_element;
-               kfree(sl->link_name);
                kobject_put(sl->target_kobj);
                kfree(sl);
        }
+       if (sd->s_type & SYSFS_COPY_NAME)
+               kfree(sd->s_name);
        kfree(sd->s_iattr);
        sysfs_free_ino(sd->s_ino);
        kmem_cache_free(sysfs_dir_cachep, sd);
@@ -94,29 +95,41 @@ static struct dentry_operations sysfs_dentry_ops = {
        .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);
        if (!sd)
-               return NULL;
+               goto err_out;
 
-       if (sysfs_alloc_ino(&sd->s_ino)) {
-               kmem_cache_free(sysfs_dir_cachep, sd);
-               return NULL;
-       }
+       if (sysfs_alloc_ino(&sd->s_ino))
+               goto err_out;
 
        atomic_set(&sd->s_count, 1);
        atomic_set(&sd->s_event, 1);
        INIT_LIST_HEAD(&sd->s_children);
        INIT_LIST_HEAD(&sd->s_sibling);
 
+       sd->s_name = name;
        sd->s_element = element;
        sd->s_mode = mode;
        sd->s_type = type;
 
        return sd;
+
+ err_out:
+       kfree(dup_name);
+       kmem_cache_free(sysfs_dir_cachep, sd);
+       return NULL;
 }
 
 void sysfs_attach_dirent(struct sysfs_dirent *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) {
                if (sd->s_element) {
-                       const unsigned char *existing = sysfs_get_name(sd);
-                       if (strcmp(existing, new))
+                       if (strcmp(sd->s_name, new))
                                continue;
                        else
                                return -EEXIST;
@@ -203,7 +215,7 @@ static int create_dir(struct kobject *kobj, struct dentry *parent,
                goto out_dput;
 
        error = -ENOMEM;
-       sd = sysfs_new_dirent(kobj, mode, SYSFS_DIR);
+       sd = sysfs_new_dirent(name, kobj, mode, SYSFS_DIR);
        if (!sd)
                goto out_drop;
        sysfs_attach_dirent(sd, parent->d_fsdata, 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) {
                if (sd->s_type & SYSFS_NOT_PINNED) {
-                       const unsigned char * name = sysfs_get_name(sd);
-
-                       if (strcmp(name, dentry->d_name.name))
+                       if (strcmp(sd->s_name, dentry->d_name.name))
                                continue;
 
                        if (sd->s_type & SYSFS_KOBJ_LINK)
@@ -427,9 +437,11 @@ void sysfs_remove_dir(struct kobject * kobj)
 int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
                     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;
-       struct dentry * new_dentry;
-       struct sysfs_dirent *sd, *parent_sd;
 
        if (!new_parent)
                return -EFAULT;
@@ -457,22 +469,31 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
        if (new_dentry->d_inode)
                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);
        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_move(kobj->dentry, new_dentry);
 
-       sd = kobj->dentry->d_fsdata;
-       parent_sd = new_parent->d_fsdata;
-
        list_del_init(&sd->s_sibling);
        list_add(&sd->s_sibling, &parent_sd->s_children);
 
        error = 0;
        goto out_unlock;
 
+ out_free:
+       kfree(dup_name);
  out_drop:
        d_drop(new_dentry);
  out_dput:
@@ -535,7 +556,7 @@ static int sysfs_dir_open(struct inode *inode, struct file *file)
        struct sysfs_dirent * sd;
 
        mutex_lock(&dentry->d_inode->i_mutex);
-       sd = sysfs_new_dirent(NULL, 0, 0);
+       sd = sysfs_new_dirent("_DIR_", NULL, 0, 0);
        if (sd)
                sysfs_attach_dirent(sd, parent_sd, NULL);
        mutex_unlock(&dentry->d_inode->i_mutex);
@@ -605,7 +626,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
                                if (!next->s_element)
                                        continue;
 
-                               name = sysfs_get_name(next);
+                               name = next->s_name;
                                len = strlen(name);
                                ino = next->s_ino;
 
@@ -717,7 +738,7 @@ struct dentry *sysfs_create_shadow_dir(struct kobject *kobj)
        if (!shadow)
                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)
                goto nomem;
        /* point to parent_sd but don't attach to it */
index fd4b6dc03d2d7d6630e451c3aaf69c005db9dd46..8240b1687dd08139b855c407a78cf19a78742214 100644 (file)
@@ -454,7 +454,7 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
                goto out_unlock;
        }
 
-       sd = sysfs_new_dirent((void *)attr, mode, type);
+       sd = sysfs_new_dirent(attr->name, (void *)attr, mode, type);
        if (!sd) {
                error = -ENOMEM;
                goto out_unlock;
index 5266eec15f6e35766c84939f1c7663690d6c3930..5c605b0003a8ddc5e10108cbbda039afdca32a08 100644 (file)
@@ -191,37 +191,6 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
        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)
 {
        struct sysfs_buffer_collection *set;
@@ -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) {
                if (!sd->s_element)
                        continue;
-               if (!strcmp(sysfs_get_name(sd), name)) {
+               if (!strcmp(sd->s_name, name)) {
                        list_del_init(&sd->s_sibling);
                        sysfs_drop_dentry(sd, dir);
                        sysfs_put(sd);
index d96bb9cbc9d41dbac53ffc7a0541cde4866ac2c0..c72820450e7ca8b3a0a9ce7b8686a3a0b62fa1a1 100644 (file)
@@ -57,14 +57,9 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj
        if (!sl)
                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);
 
-       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)
                goto err_out;
        sysfs_attach_dirent(sd, parent_sd, NULL);
@@ -74,7 +69,6 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj
  err_out:
        if (sl) {
                kobject_put(sl->target_kobj);
-               kfree(sl->link_name);
                kfree(sl);
        }
        return error;
index ce05d6fd752228ca15c88a3c0266708154ea36b9..d34b008537d50bbad874cf963a962c2b182c24fd 100644 (file)
@@ -3,6 +3,7 @@ struct sysfs_dirent {
        struct sysfs_dirent     * s_parent;
        struct list_head        s_sibling;
        struct list_head        s_children;
+       const char              * s_name;
        void                    * s_element;
        int                     s_type;
        umode_t                 s_mode;
@@ -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 int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
-extern struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode,
-                                            int type);
+extern struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element,
+                                            umode_t mode, int type);
 extern void sysfs_attach_dirent(struct sysfs_dirent *sd,
                                struct sysfs_dirent *parent_sd,
                                struct dentry *dentry);
@@ -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 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 int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
 
@@ -48,7 +48,6 @@ extern const struct inode_operations sysfs_dir_inode_operations;
 extern const struct inode_operations sysfs_symlink_inode_operations;
 
 struct sysfs_symlink {
-       char * link_name;
        struct kobject * target_kobj;
 };
 
index 7d5d1ec95c2e4b8dc719c042cc6a178550be3f09..2f86b080b39d0828c4a87f8e830ef42513d14064 100644 (file)
@@ -76,6 +76,7 @@ struct sysfs_ops {
 #define SYSFS_KOBJ_BIN_ATTR    0x0008
 #define SYSFS_KOBJ_LINK        0x0020
 #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