sysfs: add sysfs_dirent->s_name
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / sysfs / inode.c
index bdd30e74de6b00c16685e98745d2fe96325c483b..5c605b0003a8ddc5e10108cbbda039afdca32a08 100644 (file)
@@ -141,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) {
@@ -190,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;
@@ -245,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);
@@ -267,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);
        }
 }
 
@@ -288,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);