Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=996b73764e9bb9d5e751fd15b130ba38637d66a8
Commit:     996b73764e9bb9d5e751fd15b130ba38637d66a8
Parent:     dfeb9fb0343363aadc3ee00a9347d120bc2a26b1
Author:     Tejun Heo <[EMAIL PROTECTED]>
AuthorDate: Thu Jun 14 03:45:14 2007 +0900
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Wed Jul 11 16:09:03 2007 -0700

    sysfs: flatten and fix sysfs_rename_dir() error handling
    
    Error handling in sysfs_rename_dir() was broken.
    
    * When lookup_one_len() fails, 0 is returned.
    
    * If parent inode check fails, returns with inode mutex and rename
      rwsem held.
    
    This patch fixes the above bugs and flattens error handling such that
    it's more readable and easier to modify.
    
    Signed-off-by: Tejun Heo <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 fs/sysfs/dir.c |   73 +++++++++++++++++++++++++++++++------------------------
 1 files changed, 41 insertions(+), 32 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index b4c4824..90bed5d 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -452,8 +452,9 @@ void sysfs_remove_dir(struct kobject * kobj)
 int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
                     const char *new_name)
 {
-       int error = 0;
+       int error;
        struct dentry * new_dentry;
+       struct sysfs_dirent *sd, *parent_sd;
 
        if (!new_parent)
                return -EFAULT;
@@ -462,40 +463,48 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry 
*new_parent,
        mutex_lock(&new_parent->d_inode->i_mutex);
 
        new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name));
-       if (!IS_ERR(new_dentry)) {
-               /* By allowing two different directories with the
-                * same d_parent we allow this routine to move
-                * between different shadows of the same directory
-                */
-               if (kobj->dentry->d_parent->d_inode != new_parent->d_inode)
-                       return -EINVAL;
-               else if (new_dentry->d_parent->d_inode != new_parent->d_inode)
-                       error = -EINVAL;
-               else if (new_dentry == kobj->dentry)
-                       error = -EINVAL;
-               else if (!new_dentry->d_inode) {
-                       error = kobject_set_name(kobj, "%s", new_name);
-                       if (!error) {
-                               struct sysfs_dirent *sd, *parent_sd;
-
-                               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);
-                       }
-                       else
-                               d_drop(new_dentry);
-               } else
-                       error = -EEXIST;
-               dput(new_dentry);
+       if (IS_ERR(new_dentry)) {
+               error = PTR_ERR(new_dentry);
+               goto out_unlock;
        }
+
+       /* By allowing two different directories with the same
+        * d_parent we allow this routine to move between different
+        * shadows of the same directory
+        */
+       error = -EINVAL;
+       if (kobj->dentry->d_parent->d_inode != new_parent->d_inode ||
+           new_dentry->d_parent->d_inode != new_parent->d_inode ||
+           new_dentry == kobj->dentry)
+               goto out_dput;
+
+       error = -EEXIST;
+       if (new_dentry->d_inode)
+               goto out_dput;
+
+       error = kobject_set_name(kobj, "%s", new_name);
+       if (error)
+               goto out_drop;
+
+       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_drop:
+       d_drop(new_dentry);
+ out_dput:
+       dput(new_dentry);
+ out_unlock:
        mutex_unlock(&new_parent->d_inode->i_mutex);
        up_write(&sysfs_rename_sem);
-
        return error;
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to