configfs: Allow ->make_item() and ->make_group() to return detailed errors.

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 11c3b79218.

Signed-off-by: Joel Becker <joel.becker@oracle.com>
This commit is contained in:
Joel Becker 2008-07-17 15:21:29 -07:00
parent f89ab8619e
commit a6795e9ebb
7 changed files with 31 additions and 37 deletions

View File

@ -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,
@ -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,

View File

@ -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";

View File

@ -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;
@ -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;
}

View File

@ -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)
@ -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)
@ -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;
@ -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;

View File

@ -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,

View File

@ -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,
@ -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);
@ -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;

View File

@ -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