configfs: Allow ->make_item() and ->make_group() to return detailed errors.
authorJoel Becker <joel.becker@oracle.com>
Thu, 17 Jul 2008 22:21:29 +0000 (15:21 -0700)
committerJoel Becker <joel.becker@oracle.com>
Thu, 17 Jul 2008 22:21:29 +0000 (15:21 -0700)
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 11c3b79218390a139f2d474ee1e983a672d5839a.

Signed-off-by: Joel Becker <joel.becker@oracle.com>
Documentation/filesystems/configfs/configfs_example.c
drivers/net/netconsole.c
fs/configfs/dir.c
fs/dlm/config.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/nodemanager.c
include/linux/configfs.h

index 25151fd5c2c6f032a0cc95d57d213d7fa4fcdf18..039648791701f6e1b74a970d36f361cab695ab64 100644 (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,
index 665341e43055a3079465354f91c31b315d70e034..e13966bb5f7749d8462e76fb3d9aa802b80eab46 100644 (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";
index 614e382a60491b0b3446ef32342eac013e0abed3..179589be063abe97ba0d10a1982bdea244488d36 100644 (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;
        }
 
index eac23bd288b202cb6e8b099c6c3e8cdd7a93c687..c4e7d721bd8dcffaedcbdf3fcac2b2ea5ac26c31 100644 (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;
index f02ccb34604d5f855851eee98dc274f09787480e..7dce1612553e424e5d006ed20aa9d3429284f34c 100644 (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,
index cfdb08b484edb6ab33e5b4e4c89ccca612b18ab2..816a3f61330c6173ec04a360f4b7b40bb53ad0bf 100644 (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 @@ out:
                kfree(ns);
                o2hb_free_hb_set(o2hb_group);
                kfree(defs);
+               ret = ERR_PTR(-ENOMEM);
        }
 
        return ret;
index 3ae65b1bf90fd891b32538390c103f12632560fd..d62c19ff041ccb64905558f1d634b2d202c968ac 100644 (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