linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / fs / configfs / dir.c
index 5f95218..ca60e3a 100644 (file)
@@ -504,16 +504,14 @@ static int populate_groups(struct config_group *group)
        int ret = 0;
        int i;
 
-       if (group->default_groups) {
-               /*
-                * FYI, we're faking mkdir here
+       if (group && group->default_groups) {
+               /* FYI, we're faking mkdir here
                 * I'm not sure we need this semaphore, as we're called
                 * from our parent's mkdir.  That holds our parent's
                 * i_mutex, so afaik lookup cannot continue through our
                 * parent to find us, let alone mess with our tree.
                 * That said, taking our i_mutex is closer to mkdir
-                * emulation, and shouldn't hurt.
-                */
+                * emulation, and shouldn't hurt. */
                mutex_lock(&dentry->d_inode->i_mutex);
 
                for (i = 0; group->default_groups[i]; i++) {
@@ -548,34 +546,20 @@ static void unlink_obj(struct config_item *item)
 
                item->ci_group = NULL;
                item->ci_parent = NULL;
-
-               /* Drop the reference for ci_entry */
                config_item_put(item);
 
-               /* Drop the reference for ci_parent */
                config_group_put(group);
        }
 }
 
 static void link_obj(struct config_item *parent_item, struct config_item *item)
 {
-       /*
-        * Parent seems redundant with group, but it makes certain
-        * traversals much nicer.
-        */
+       /* Parent seems redundant with group, but it makes certain
+        * traversals much nicer. */
        item->ci_parent = parent_item;
-
-       /*
-        * We hold a reference on the parent for the child's ci_parent
-        * link.
-        */
        item->ci_group = config_group_get(to_config_group(parent_item));
        list_add_tail(&item->ci_entry, &item->ci_group->cg_children);
 
-       /*
-        * We hold a reference on the child for ci_entry on the parent's
-        * cg_children
-        */
        config_item_get(item);
 }
 
@@ -700,10 +684,6 @@ static void client_drop_item(struct config_item *parent_item,
        type = parent_item->ci_type;
        BUG_ON(!type);
 
-       /*
-        * If ->drop_item() exists, it is responsible for the
-        * config_item_put().
-        */
        if (type->ct_group_ops && type->ct_group_ops->drop_item)
                type->ct_group_ops->drop_item(to_config_group(parent_item),
                                                item);
@@ -714,28 +694,23 @@ static void client_drop_item(struct config_item *parent_item,
 
 static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
-       int ret, module_got = 0;
+       int ret;
        struct config_group *group;
        struct config_item *item;
        struct config_item *parent_item;
        struct configfs_subsystem *subsys;
        struct configfs_dirent *sd;
        struct config_item_type *type;
-       struct module *owner = NULL;
+       struct module *owner;
        char *name;
 
-       if (dentry->d_parent == configfs_sb->s_root) {
-               ret = -EPERM;
-               goto out;
-       }
+       if (dentry->d_parent == configfs_sb->s_root)
+               return -EPERM;
 
        sd = dentry->d_parent->d_fsdata;
-       if (!(sd->s_type & CONFIGFS_USET_DIR)) {
-               ret = -EPERM;
-               goto out;
-       }
+       if (!(sd->s_type & CONFIGFS_USET_DIR))
+               return -EPERM;
 
-       /* Get a working ref for the duration of this function */
        parent_item = configfs_get_config_item(dentry->d_parent);
        type = parent_item->ci_type;
        subsys = to_config_group(parent_item)->cg_subsys;
@@ -744,16 +719,15 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        if (!type || !type->ct_group_ops ||
            (!type->ct_group_ops->make_group &&
             !type->ct_group_ops->make_item)) {
-               ret = -EPERM;  /* Lack-of-mkdir returns -EPERM */
-               goto out_put;
+               config_item_put(parent_item);
+               return -EPERM;  /* What lack-of-mkdir returns */
        }
 
        name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL);
        if (!name) {
-               ret = -ENOMEM;
-               goto out_put;
+               config_item_put(parent_item);
+               return -ENOMEM;
        }
-
        snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
 
        down(&subsys->su_sem);
@@ -774,67 +748,40 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        kfree(name);
        if (!item) {
-               /*
-                * If item == NULL, then link_obj() was never called.
-                * There are no extra references to clean up.
-                */
-               ret = -ENOMEM;
-               goto out_put;
+               config_item_put(parent_item);
+               return -ENOMEM;
        }
 
-       /*
-        * link_obj() has been called (via link_group() for groups).
-        * From here on out, errors must clean that up.
-        */
-
+       ret = -EINVAL;
        type = item->ci_type;
-       if (!type) {
-               ret = -EINVAL;
-               goto out_unlink;
-       }
-
-       owner = type->ct_owner;
-       if (!try_module_get(owner)) {
-               ret = -EINVAL;
-               goto out_unlink;
-       }
-
-       /*
-        * I hate doing it this way, but if there is
-        * an error,  module_put() probably should
-        * happen after any cleanup.
-        */
-       module_got = 1;
+       if (type) {
+               owner = type->ct_owner;
+               if (try_module_get(owner)) {
+                       if (group) {
+                               ret = configfs_attach_group(parent_item,
+                                                           item,
+                                                           dentry);
+                       } else {
+                               ret = configfs_attach_item(parent_item,
+                                                          item,
+                                                          dentry);
+                       }
 
-       if (group)
-               ret = configfs_attach_group(parent_item, item, dentry);
-       else
-               ret = configfs_attach_item(parent_item, item, dentry);
+                       if (ret) {
+                               down(&subsys->su_sem);
+                               if (group)
+                                       unlink_group(group);
+                               else
+                                       unlink_obj(item);
+                               client_drop_item(parent_item, item);
+                               up(&subsys->su_sem);
 
-out_unlink:
-       if (ret) {
-               /* Tear down everything we built up */
-               down(&subsys->su_sem);
-               if (group)
-                       unlink_group(group);
-               else
-                       unlink_obj(item);
-               client_drop_item(parent_item, item);
-               up(&subsys->su_sem);
-
-               if (module_got)
-                       module_put(owner);
+                               config_item_put(parent_item);
+                               module_put(owner);
+                       }
+               }
        }
 
-out_put:
-       /*
-        * link_obj()/link_group() took a reference from child->parent,
-        * so the parent is safely pinned.  We can drop our working
-        * reference.
-        */
-       config_item_put(parent_item);
-
-out:
        return ret;
 }
 
@@ -854,7 +801,6 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
        if (sd->s_type & CONFIGFS_USET_DEFAULT)
                return -EPERM;
 
-       /* Get a working ref until we have the child */
        parent_item = configfs_get_config_item(dentry->d_parent);
        subsys = to_config_group(parent_item)->cg_subsys;
        BUG_ON(!subsys);
@@ -871,7 +817,6 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
                return ret;
        }
 
-       /* Get a working ref for the duration of this function */
        item = configfs_get_config_item(dentry);
 
        /* Drop reference from above, item already holds one. */
@@ -1082,7 +1027,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin)
        return offset;
 }
 
-const struct file_operations configfs_dir_operations = {
+struct file_operations configfs_dir_operations = {
        .open           = configfs_dir_open,
        .release        = configfs_dir_close,
        .llseek         = configfs_dir_lseek,