]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - fs/sysfs/inode.c
sysfs: add sysfs_dirent->s_name
[mv-sheeva.git] / fs / sysfs / inode.c
index 4de5c6b899181b47c07bf7140cda467c1f68d8cc..5c605b0003a8ddc5e10108cbbda039afdca32a08 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/backing-dev.h>
 #include <linux/capability.h>
 #include <linux/errno.h>
+#include <linux/sched.h>
 #include <asm/semaphore.h>
 #include "sysfs.h"
 
@@ -140,6 +141,7 @@ struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
                inode->i_mapping->a_ops = &sysfs_aops;
                inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
                inode->i_op = &sysfs_inode_operations;
+               inode->i_ino = sd->s_ino;
                lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
 
                if (sd->s_iattr) {
@@ -189,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;
@@ -244,13 +215,27 @@ static inline void orphan_all_buffers(struct inode *node)
  */
 void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
 {
-       struct dentry * dentry = sd->s_dentry;
+       struct dentry *dentry = NULL;
        struct inode *inode;
 
+       /* We're not holding a reference to ->s_dentry dentry but the
+        * field will stay valid as long as sysfs_lock is held.
+        */
+       spin_lock(&sysfs_lock);
+       spin_lock(&dcache_lock);
+
+       /* dget dentry if it's still alive */
+       if (sd->s_dentry && sd->s_dentry->d_inode)
+               dentry = dget_locked(sd->s_dentry);
+
+       spin_unlock(&dcache_lock);
+       spin_unlock(&sysfs_lock);
+
+       /* drop dentry */
        if (dentry) {
                spin_lock(&dcache_lock);
                spin_lock(&dentry->d_lock);
-               if (!(d_unhashed(dentry) && dentry->d_inode)) {
+               if (!d_unhashed(dentry) && dentry->d_inode) {
                        inode = dentry->d_inode;
                        spin_lock(&inode->i_lock);
                        __iget(inode);
@@ -266,6 +251,8 @@ void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
                        spin_unlock(&dentry->d_lock);
                        spin_unlock(&dcache_lock);
                }
+
+               dput(dentry);
        }
 }
 
@@ -287,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);