Commit a6795e9e authored by Joel Becker's avatar Joel Becker

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 11c3b792.
Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
parent f89ab861
...@@ -279,7 +279,7 @@ static struct config_item *simple_children_make_item(struct config_group *group, ...@@ -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); simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);
if (!simple_child) if (!simple_child)
return NULL; return ERR_PTR(-ENOMEM);
config_item_init_type_name(&simple_child->item, name, 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 ...@@ -366,7 +366,7 @@ static struct config_group *group_children_make_group(struct config_group *group
simple_children = kzalloc(sizeof(struct simple_children), simple_children = kzalloc(sizeof(struct simple_children),
GFP_KERNEL); GFP_KERNEL);
if (!simple_children) if (!simple_children)
return NULL; return ERR_PTR(-ENOMEM);
config_group_init_type_name(&simple_children->group, name, config_group_init_type_name(&simple_children->group, name,
......
...@@ -598,7 +598,7 @@ static struct config_item *make_netconsole_target(struct config_group *group, ...@@ -598,7 +598,7 @@ static struct config_item *make_netconsole_target(struct config_group *group,
nt = kzalloc(sizeof(*nt), GFP_KERNEL); nt = kzalloc(sizeof(*nt), GFP_KERNEL);
if (!nt) { if (!nt) {
printk(KERN_ERR "netconsole: failed to allocate memory\n"); printk(KERN_ERR "netconsole: failed to allocate memory\n");
return NULL; return ERR_PTR(-ENOMEM);
} }
nt->np.name = "netconsole"; nt->np.name = "netconsole";
......
...@@ -1027,9 +1027,10 @@ EXPORT_SYMBOL(configfs_undepend_item); ...@@ -1027,9 +1027,10 @@ EXPORT_SYMBOL(configfs_undepend_item);
static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{ {
int ret, module_got = 0; int ret = 0;
struct config_group *group; int module_got = 0;
struct config_item *item; struct config_group *group = NULL;
struct config_item *item = NULL;
struct config_item *parent_item; struct config_item *parent_item;
struct configfs_subsystem *subsys; struct configfs_subsystem *subsys;
struct configfs_dirent *sd; struct configfs_dirent *sd;
...@@ -1070,28 +1071,32 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -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); snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
mutex_lock(&subsys->su_mutex); mutex_lock(&subsys->su_mutex);
group = NULL;
item = NULL;
if (type->ct_group_ops->make_group) { if (type->ct_group_ops->make_group) {
group = type->ct_group_ops->make_group(to_config_group(parent_item), name); 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); link_group(to_config_group(parent_item), group);
item = &group->cg_item; item = &group->cg_item;
} } else
ret = PTR_ERR(group);
} else { } else {
item = type->ct_group_ops->make_item(to_config_group(parent_item), name); 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); link_obj(parent_item, item);
else
ret = PTR_ERR(item);
} }
mutex_unlock(&subsys->su_mutex); mutex_unlock(&subsys->su_mutex);
kfree(name); kfree(name);
if (!item) { if (ret) {
/* /*
* If item == NULL, then link_obj() was never called. * If item == NULL, then link_obj() was never called.
* There are no extra references to clean up. * There are no extra references to clean up.
*/ */
ret = -ENOMEM;
goto out_put; goto out_put;
} }
......
...@@ -438,7 +438,7 @@ static struct config_group *make_cluster(struct config_group *g, ...@@ -438,7 +438,7 @@ static struct config_group *make_cluster(struct config_group *g,
kfree(gps); kfree(gps);
kfree(sps); kfree(sps);
kfree(cms); kfree(cms);
return NULL; return ERR_PTR(-ENOMEM);
} }
static void drop_cluster(struct config_group *g, struct config_item *i) 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) ...@@ -495,7 +495,7 @@ static struct config_group *make_space(struct config_group *g, const char *name)
kfree(sp); kfree(sp);
kfree(gps); kfree(gps);
kfree(nds); kfree(nds);
return NULL; return ERR_PTR(-ENOMEM);
} }
static void drop_space(struct config_group *g, struct config_item *i) 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) ...@@ -528,7 +528,7 @@ static struct config_item *make_comm(struct config_group *g, const char *name)
cm = kzalloc(sizeof(struct comm), GFP_KERNEL); cm = kzalloc(sizeof(struct comm), GFP_KERNEL);
if (!cm) if (!cm)
return NULL; return ERR_PTR(-ENOMEM);
config_item_init_type_name(&cm->item, name, &comm_type); config_item_init_type_name(&cm->item, name, &comm_type);
cm->nodeid = -1; cm->nodeid = -1;
...@@ -561,7 +561,7 @@ static struct config_item *make_node(struct config_group *g, const char *name) ...@@ -561,7 +561,7 @@ static struct config_item *make_node(struct config_group *g, const char *name)
nd = kzalloc(sizeof(struct node), GFP_KERNEL); nd = kzalloc(sizeof(struct node), GFP_KERNEL);
if (!nd) if (!nd)
return NULL; return ERR_PTR(-ENOMEM);
config_item_init_type_name(&nd->item, name, &node_type); config_item_init_type_name(&nd->item, name, &node_type);
nd->nodeid = -1; nd->nodeid = -1;
......
...@@ -1493,24 +1493,18 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g ...@@ -1493,24 +1493,18 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g
const char *name) const char *name)
{ {
struct o2hb_region *reg = NULL; struct o2hb_region *reg = NULL;
struct config_item *ret = NULL;
reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL); reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL);
if (reg == NULL) if (reg == NULL)
goto out; /* ENOMEM */ return ERR_PTR(-ENOMEM);
config_item_init_type_name(&reg->hr_item, name, &o2hb_region_type); config_item_init_type_name(&reg->hr_item, name, &o2hb_region_type);
ret = &reg->hr_item;
spin_lock(&o2hb_live_lock); spin_lock(&o2hb_live_lock);
list_add_tail(&reg->hr_all_item, &o2hb_all_regions); list_add_tail(&reg->hr_all_item, &o2hb_all_regions);
spin_unlock(&o2hb_live_lock); 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, static void o2hb_heartbeat_group_drop_item(struct config_group *group,
......
...@@ -648,26 +648,19 @@ static struct config_item *o2nm_node_group_make_item(struct config_group *group, ...@@ -648,26 +648,19 @@ static struct config_item *o2nm_node_group_make_item(struct config_group *group,
const char *name) const char *name)
{ {
struct o2nm_node *node = NULL; struct o2nm_node *node = NULL;
struct config_item *ret = NULL;
if (strlen(name) > O2NM_MAX_NAME_LEN) if (strlen(name) > O2NM_MAX_NAME_LEN)
goto out; /* ENAMETOOLONG */ return ERR_PTR(-ENAMETOOLONG);
node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL); node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL);
if (node == NULL) if (node == NULL)
goto out; /* ENOMEM */ return ERR_PTR(-ENOMEM);
strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */ strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */
config_item_init_type_name(&node->nd_item, name, &o2nm_node_type); config_item_init_type_name(&node->nd_item, name, &o2nm_node_type);
spin_lock_init(&node->nd_lock); spin_lock_init(&node->nd_lock);
ret = &node->nd_item; return &node->nd_item;
out:
if (ret == NULL)
kfree(node);
return ret;
} }
static void o2nm_node_group_drop_item(struct config_group *group, 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 ...@@ -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 /* this runs under the parent dir's i_mutex; there can be only
* one caller in here at a time */ * one caller in here at a time */
if (o2nm_single_cluster) if (o2nm_single_cluster)
goto out; /* ENOSPC */ return ERR_PTR(-ENOSPC);
cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL); cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL);
ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL); ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL);
...@@ -795,6 +788,7 @@ out: ...@@ -795,6 +788,7 @@ out:
kfree(ns); kfree(ns);
o2hb_free_hb_set(o2hb_group); o2hb_free_hb_set(o2hb_group);
kfree(defs); kfree(defs);
ret = ERR_PTR(-ENOMEM);
} }
return ret; return ret;
......
...@@ -148,7 +148,8 @@ struct configfs_attribute { ...@@ -148,7 +148,8 @@ struct configfs_attribute {
* items. If the item is a group, it may support mkdir(2). * items. If the item is a group, it may support mkdir(2).
* Groups supply one of make_group() and make_item(). If the * Groups supply one of make_group() and make_item(). If the
* group supports make_group(), one can create group children. If it * 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 * default_groups on group->default_groups, it has automatically created
* group children. default_groups may coexist alongsize make_group() or * group children. default_groups may coexist alongsize make_group() or
* make_item(), but if the group wishes to have only default_groups * make_item(), but if the group wishes to have only default_groups
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment