Skip to content

Commit

Permalink
configfs: Allow ->make_item() and ->make_group() to return detailed e…
Browse files Browse the repository at this point in the history
…rrors.

The configfs operations ->make_item() and ->make_group() currently
return a new item/group.  A return of NULL signifies an error.  Because
of this, -ENOMEM is the only return code bubbled up the stack.

Multiple folks have requested the ability to return specific error codes
when these operations fail.  This patch adds that ability by changing the
->make_item/group() ops to return ERR_PTR() values.  These errors are
bubbled up appropriately.  NULL returns are changed to -ENOMEM for
compatibility.

Also updated are the in-kernel users of configfs.

This is a rework of reverted commit 11c3b79.

Signed-off-by: Joel Becker <[email protected]>
  • Loading branch information
Joel Becker committed Jul 17, 2008
1 parent f89ab86 commit a6795e9
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 37 deletions.
4 changes: 2 additions & 2 deletions Documentation/filesystems/configfs/configfs_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ static struct config_item *simple_children_make_item(struct config_group *group,

simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);
if (!simple_child)
return NULL;
return ERR_PTR(-ENOMEM);


config_item_init_type_name(&simple_child->item, name,
Expand Down Expand Up @@ -366,7 +366,7 @@ static struct config_group *group_children_make_group(struct config_group *group
simple_children = kzalloc(sizeof(struct simple_children),
GFP_KERNEL);
if (!simple_children)
return NULL;
return ERR_PTR(-ENOMEM);


config_group_init_type_name(&simple_children->group, name,
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/netconsole.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ static struct config_item *make_netconsole_target(struct config_group *group,
nt = kzalloc(sizeof(*nt), GFP_KERNEL);
if (!nt) {
printk(KERN_ERR "netconsole: failed to allocate memory\n");
return NULL;
return ERR_PTR(-ENOMEM);
}

nt->np.name = "netconsole";
Expand Down
25 changes: 15 additions & 10 deletions fs/configfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1027,9 +1027,10 @@ EXPORT_SYMBOL(configfs_undepend_item);

static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
int ret, module_got = 0;
struct config_group *group;
struct config_item *item;
int ret = 0;
int module_got = 0;
struct config_group *group = NULL;
struct config_item *item = NULL;
struct config_item *parent_item;
struct configfs_subsystem *subsys;
struct configfs_dirent *sd;
Expand Down Expand Up @@ -1070,28 +1071,32 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);

mutex_lock(&subsys->su_mutex);
group = NULL;
item = NULL;
if (type->ct_group_ops->make_group) {
group = type->ct_group_ops->make_group(to_config_group(parent_item), name);
if (group) {
if (!group)
group = ERR_PTR(-ENOMEM);
if (!IS_ERR(group)) {
link_group(to_config_group(parent_item), group);
item = &group->cg_item;
}
} else
ret = PTR_ERR(group);
} else {
item = type->ct_group_ops->make_item(to_config_group(parent_item), name);
if (item)
if (!item)
item = ERR_PTR(-ENOMEM);
if (!IS_ERR(item))
link_obj(parent_item, item);
else
ret = PTR_ERR(item);
}
mutex_unlock(&subsys->su_mutex);

kfree(name);
if (!item) {
if (ret) {
/*
* If item == NULL, then link_obj() was never called.
* There are no extra references to clean up.
*/
ret = -ENOMEM;
goto out_put;
}

Expand Down
8 changes: 4 additions & 4 deletions fs/dlm/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ static struct config_group *make_cluster(struct config_group *g,
kfree(gps);
kfree(sps);
kfree(cms);
return NULL;
return ERR_PTR(-ENOMEM);
}

static void drop_cluster(struct config_group *g, struct config_item *i)
Expand Down Expand Up @@ -495,7 +495,7 @@ static struct config_group *make_space(struct config_group *g, const char *name)
kfree(sp);
kfree(gps);
kfree(nds);
return NULL;
return ERR_PTR(-ENOMEM);
}

static void drop_space(struct config_group *g, struct config_item *i)
Expand Down Expand Up @@ -528,7 +528,7 @@ static struct config_item *make_comm(struct config_group *g, const char *name)

cm = kzalloc(sizeof(struct comm), GFP_KERNEL);
if (!cm)
return NULL;
return ERR_PTR(-ENOMEM);

config_item_init_type_name(&cm->item, name, &comm_type);
cm->nodeid = -1;
Expand Down Expand Up @@ -561,7 +561,7 @@ static struct config_item *make_node(struct config_group *g, const char *name)

nd = kzalloc(sizeof(struct node), GFP_KERNEL);
if (!nd)
return NULL;
return ERR_PTR(-ENOMEM);

config_item_init_type_name(&nd->item, name, &node_type);
nd->nodeid = -1;
Expand Down
10 changes: 2 additions & 8 deletions fs/ocfs2/cluster/heartbeat.c
Original file line number Diff line number Diff line change
Expand Up @@ -1493,24 +1493,18 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g
const char *name)
{
struct o2hb_region *reg = NULL;
struct config_item *ret = NULL;

reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL);
if (reg == NULL)
goto out; /* ENOMEM */
return ERR_PTR(-ENOMEM);

config_item_init_type_name(&reg->hr_item, name, &o2hb_region_type);

ret = &reg->hr_item;

spin_lock(&o2hb_live_lock);
list_add_tail(&reg->hr_all_item, &o2hb_all_regions);
spin_unlock(&o2hb_live_lock);
out:
if (ret == NULL)
kfree(reg);

return ret;
return &reg->hr_item;
}

static void o2hb_heartbeat_group_drop_item(struct config_group *group,
Expand Down
16 changes: 5 additions & 11 deletions fs/ocfs2/cluster/nodemanager.c
Original file line number Diff line number Diff line change
Expand Up @@ -648,26 +648,19 @@ static struct config_item *o2nm_node_group_make_item(struct config_group *group,
const char *name)
{
struct o2nm_node *node = NULL;
struct config_item *ret = NULL;

if (strlen(name) > O2NM_MAX_NAME_LEN)
goto out; /* ENAMETOOLONG */
return ERR_PTR(-ENAMETOOLONG);

node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL);
if (node == NULL)
goto out; /* ENOMEM */
return ERR_PTR(-ENOMEM);

strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */
config_item_init_type_name(&node->nd_item, name, &o2nm_node_type);
spin_lock_init(&node->nd_lock);

ret = &node->nd_item;

out:
if (ret == NULL)
kfree(node);

return ret;
return &node->nd_item;
}

static void o2nm_node_group_drop_item(struct config_group *group,
Expand Down Expand Up @@ -762,7 +755,7 @@ static struct config_group *o2nm_cluster_group_make_group(struct config_group *g
/* this runs under the parent dir's i_mutex; there can be only
* one caller in here at a time */
if (o2nm_single_cluster)
goto out; /* ENOSPC */
return ERR_PTR(-ENOSPC);

cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL);
ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL);
Expand Down Expand Up @@ -795,6 +788,7 @@ static struct config_group *o2nm_cluster_group_make_group(struct config_group *g
kfree(ns);
o2hb_free_hb_set(o2hb_group);
kfree(defs);
ret = ERR_PTR(-ENOMEM);
}

return ret;
Expand Down
3 changes: 2 additions & 1 deletion include/linux/configfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ struct configfs_attribute {
* items. If the item is a group, it may support mkdir(2).
* Groups supply one of make_group() and make_item(). If the
* group supports make_group(), one can create group children. If it
* supports make_item(), one can create config_item children. If it has
* supports make_item(), one can create config_item children. make_group()
* and make_item() return ERR_PTR() on errors. If it has
* default_groups on group->default_groups, it has automatically created
* group children. default_groups may coexist alongsize make_group() or
* make_item(), but if the group wishes to have only default_groups
Expand Down

0 comments on commit a6795e9

Please sign in to comment.