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++) {
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);
}
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);
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;
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);
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;
}
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);
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. */
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,