aboutsummaryrefslogtreecommitdiffstats
path: root/fs/configfs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/configfs/dir.c')
-rw-r--r--fs/configfs/dir.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 5638c8f9362f..810c1395d6b2 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -704,13 +704,18 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
704 struct module *owner; 704 struct module *owner;
705 char *name; 705 char *name;
706 706
707 if (dentry->d_parent == configfs_sb->s_root) 707 if (dentry->d_parent == configfs_sb->s_root) {
708 return -EPERM; 708 ret = -EPERM;
709 goto out;
710 }
709 711
710 sd = dentry->d_parent->d_fsdata; 712 sd = dentry->d_parent->d_fsdata;
711 if (!(sd->s_type & CONFIGFS_USET_DIR)) 713 if (!(sd->s_type & CONFIGFS_USET_DIR)) {
712 return -EPERM; 714 ret = -EPERM;
715 goto out;
716 }
713 717
718 /* Get a working ref for the duration of this function */
714 parent_item = configfs_get_config_item(dentry->d_parent); 719 parent_item = configfs_get_config_item(dentry->d_parent);
715 type = parent_item->ci_type; 720 type = parent_item->ci_type;
716 subsys = to_config_group(parent_item)->cg_subsys; 721 subsys = to_config_group(parent_item)->cg_subsys;
@@ -719,15 +724,16 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
719 if (!type || !type->ct_group_ops || 724 if (!type || !type->ct_group_ops ||
720 (!type->ct_group_ops->make_group && 725 (!type->ct_group_ops->make_group &&
721 !type->ct_group_ops->make_item)) { 726 !type->ct_group_ops->make_item)) {
722 config_item_put(parent_item); 727 ret = -EPERM; /* Lack-of-mkdir returns -EPERM */
723 return -EPERM; /* What lack-of-mkdir returns */ 728 goto out_put;
724 } 729 }
725 730
726 name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL); 731 name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL);
727 if (!name) { 732 if (!name) {
728 config_item_put(parent_item); 733 ret = -ENOMEM;
729 return -ENOMEM; 734 goto out_put;
730 } 735 }
736
731 snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name); 737 snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
732 738
733 down(&subsys->su_sem); 739 down(&subsys->su_sem);
@@ -748,8 +754,8 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
748 754
749 kfree(name); 755 kfree(name);
750 if (!item) { 756 if (!item) {
751 config_item_put(parent_item); 757 ret = -ENOMEM;
752 return -ENOMEM; 758 goto out_put;
753 } 759 }
754 760
755 ret = -EINVAL; 761 ret = -EINVAL;
@@ -776,12 +782,19 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
776 client_drop_item(parent_item, item); 782 client_drop_item(parent_item, item);
777 up(&subsys->su_sem); 783 up(&subsys->su_sem);
778 784
779 config_item_put(parent_item);
780 module_put(owner); 785 module_put(owner);
781 } 786 }
782 } 787 }
783 } 788 }
784 789
790out_put:
791 /*
792 * link_obj()/link_group() took a reference from child->parent.
793 * Drop our working ref
794 */
795 config_item_put(parent_item);
796
797out:
785 return ret; 798 return ret;
786} 799}
787 800
@@ -801,6 +814,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
801 if (sd->s_type & CONFIGFS_USET_DEFAULT) 814 if (sd->s_type & CONFIGFS_USET_DEFAULT)
802 return -EPERM; 815 return -EPERM;
803 816
817 /* Get a working ref until we have the child */
804 parent_item = configfs_get_config_item(dentry->d_parent); 818 parent_item = configfs_get_config_item(dentry->d_parent);
805 subsys = to_config_group(parent_item)->cg_subsys; 819 subsys = to_config_group(parent_item)->cg_subsys;
806 BUG_ON(!subsys); 820 BUG_ON(!subsys);
@@ -817,6 +831,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
817 return ret; 831 return ret;
818 } 832 }
819 833
834 /* Get a working ref for the duration of this function */
820 item = configfs_get_config_item(dentry); 835 item = configfs_get_config_item(dentry);
821 836
822 /* Drop reference from above, item already holds one. */ 837 /* Drop reference from above, item already holds one. */