aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r--fs/sysfs/dir.c73
1 files changed, 41 insertions, 32 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index b4c482461403..90bed5df254f 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -452,8 +452,9 @@ void sysfs_remove_dir(struct kobject * kobj)
452int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, 452int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
453 const char *new_name) 453 const char *new_name)
454{ 454{
455 int error = 0; 455 int error;
456 struct dentry * new_dentry; 456 struct dentry * new_dentry;
457 struct sysfs_dirent *sd, *parent_sd;
457 458
458 if (!new_parent) 459 if (!new_parent)
459 return -EFAULT; 460 return -EFAULT;
@@ -462,40 +463,48 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
462 mutex_lock(&new_parent->d_inode->i_mutex); 463 mutex_lock(&new_parent->d_inode->i_mutex);
463 464
464 new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name)); 465 new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name));
465 if (!IS_ERR(new_dentry)) { 466 if (IS_ERR(new_dentry)) {
466 /* By allowing two different directories with the 467 error = PTR_ERR(new_dentry);
467 * same d_parent we allow this routine to move 468 goto out_unlock;
468 * between different shadows of the same directory
469 */
470 if (kobj->dentry->d_parent->d_inode != new_parent->d_inode)
471 return -EINVAL;
472 else if (new_dentry->d_parent->d_inode != new_parent->d_inode)
473 error = -EINVAL;
474 else if (new_dentry == kobj->dentry)
475 error = -EINVAL;
476 else if (!new_dentry->d_inode) {
477 error = kobject_set_name(kobj, "%s", new_name);
478 if (!error) {
479 struct sysfs_dirent *sd, *parent_sd;
480
481 d_add(new_dentry, NULL);
482 d_move(kobj->dentry, new_dentry);
483
484 sd = kobj->dentry->d_fsdata;
485 parent_sd = new_parent->d_fsdata;
486
487 list_del_init(&sd->s_sibling);
488 list_add(&sd->s_sibling, &parent_sd->s_children);
489 }
490 else
491 d_drop(new_dentry);
492 } else
493 error = -EEXIST;
494 dput(new_dentry);
495 } 469 }
470
471 /* By allowing two different directories with the same
472 * d_parent we allow this routine to move between different
473 * shadows of the same directory
474 */
475 error = -EINVAL;
476 if (kobj->dentry->d_parent->d_inode != new_parent->d_inode ||
477 new_dentry->d_parent->d_inode != new_parent->d_inode ||
478 new_dentry == kobj->dentry)
479 goto out_dput;
480
481 error = -EEXIST;
482 if (new_dentry->d_inode)
483 goto out_dput;
484
485 error = kobject_set_name(kobj, "%s", new_name);
486 if (error)
487 goto out_drop;
488
489 d_add(new_dentry, NULL);
490 d_move(kobj->dentry, new_dentry);
491
492 sd = kobj->dentry->d_fsdata;
493 parent_sd = new_parent->d_fsdata;
494
495 list_del_init(&sd->s_sibling);
496 list_add(&sd->s_sibling, &parent_sd->s_children);
497
498 error = 0;
499 goto out_unlock;
500
501 out_drop:
502 d_drop(new_dentry);
503 out_dput:
504 dput(new_dentry);
505 out_unlock:
496 mutex_unlock(&new_parent->d_inode->i_mutex); 506 mutex_unlock(&new_parent->d_inode->i_mutex);
497 up_write(&sysfs_rename_sem); 507 up_write(&sysfs_rename_sem);
498
499 return error; 508 return error;
500} 509}
501 510