[PATCH 02/12] Resource group creation/deletion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



02/12 - resource_group_support

Provides functions to alloc and free a user defined resource group.
Provides utility macro to walk through the resource group hierarchy.
--

Signed-Off-By: Chandra Seetharaman <[email protected]>
Signed-Off-By: Hubertus Franke <[email protected]>
Signed-Off-By: Shailabh Nagar <[email protected]>
Signed-Off-By: Gerrit Huizenga <[email protected]>
Signed-Off-By: Vivek Kashyap <[email protected]>
Signed-Off-By: Matt Helsley <[email protected]>

 include/linux/res_group.h    |    9 ++
 include/linux/res_group_rc.h |    9 ++
 kernel/res_group/local.h     |    4 +
 kernel/res_group/res_group.c |  167 +++++++++++++++++++++++++++++++++++++++----
 4 files changed, 176 insertions(+), 13 deletions(-)

Index: linux-2617-rc3/include/linux/res_group.h
===================================================================
--- linux-2617-rc3.orig/include/linux/res_group.h	2006-04-27 09:21:46.000000000 -0700
+++ linux-2617-rc3/include/linux/res_group.h	2006-04-27 09:22:04.000000000 -0700
@@ -38,6 +38,7 @@
 #define SHARE_DEFAULT_DIVISOR 	(100)
 
 #define MAX_RES_CTLRS	8	/* max # of resource controllers */
+#define MAX_DEPTH	5	/* max depth of hierarchy supported */
 
 #define NO_RES_GROUP		NULL
 #define NO_SHARE		NULL
@@ -60,6 +61,8 @@ struct res_shares {
  * registered a resource controller (see include/linux/res_group_rc.h).
  */
 struct resource_group {
+	const char *name;
+	struct kref ref;
 	int depth;		/* depth of this resource group. root == 0 */
 	spinlock_t group_lock;	/* protects task_list, shares and children
 				 * When grabbing group_lock in a hierarchy,
@@ -69,6 +72,12 @@ struct resource_group {
 				 * grabbing resource specific lock */
 	struct res_shares *shares[MAX_RES_CTLRS];/* resource shares */
 	struct list_head group_list;	/* entry in system-wide list */
+
+	struct list_head task_list;	/* this resource groups's tasks */
+
+	struct resource_group *parent;
+	struct list_head siblings;	/* entry in list of siblings */
+	struct list_head children;	/* head of children */
 };
 
 #endif /* CONFIG_RES_GROUPS */
Index: linux-2617-rc3/kernel/res_group/res_group.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/res_group.c	2006-04-27 09:21:46.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/res_group.c	2006-04-27 09:22:04.000000000 -0700
@@ -20,14 +20,26 @@
  */
 
 #include <linux/module.h>
-#include <linux/res_group_rc.h>
+#include "local.h"
 
 static struct res_controller *res_controllers[MAX_RES_CTLRS];
 /* res_ctlrs_lock protects res_controllers array and count in controllers*/
 static spinlock_t res_ctlrs_lock = SPIN_LOCK_UNLOCKED;
 
 static LIST_HEAD(res_groups);/* list of system-wide resource groups */
-static rwlock_t res_group_lock = RW_LOCK_UNLOCKED; /* protects res_groups */
+static int num_res_groups;	/* Number of user defined resource groups */
+static rwlock_t res_group_lock = RW_LOCK_UNLOCKED;
+			/* protects res_groups list and num_res_groups */
+
+struct resource_group default_res_group = {
+	.task_list = LIST_HEAD_INIT(default_res_group.task_list),
+	.group_lock = SPIN_LOCK_UNLOCKED,
+	.name = "task",
+	.group_list = LIST_HEAD_INIT(default_res_group.group_list),
+	.siblings = LIST_HEAD_INIT(default_res_group.siblings),
+	.children = LIST_HEAD_INIT(default_res_group.children),
+};
+
 
 /* Must be called with res_ctlr_lock held */
 static inline int is_ctlr_id_valid(unsigned int ctlr_id)
@@ -98,6 +110,59 @@ static void do_alloc_shares_struct(struc
 		get_controller(ctlr);
 }
 
+static void init_res_group(struct resource_group *rgroup)
+{
+	rgroup->group_lock = SPIN_LOCK_UNLOCKED;
+	kref_init(&rgroup->ref);
+	INIT_LIST_HEAD(&rgroup->task_list);
+	INIT_LIST_HEAD(&rgroup->children);
+	INIT_LIST_HEAD(&rgroup->siblings);
+}
+
+struct resource_group *alloc_res_group(struct resource_group *parent,
+						const char *name)
+{
+	int i;
+	struct resource_group *rgroup;
+
+	BUG_ON(parent == NULL);
+
+	/* Only upto MAX_DEPTH level of hierarchy is supported */
+	if (parent->depth == MAX_DEPTH)
+		return NULL;
+
+	kref_get(&parent->ref);
+	rgroup = kzalloc(sizeof(struct resource_group), GFP_KERNEL);
+	if (!rgroup) {
+		kref_put(&parent->ref, release_res_group);
+		return NULL;
+	}
+	init_res_group(rgroup);
+	rgroup->name = name;
+	rgroup->depth = parent->depth + 1;
+
+	/* Add to parent */
+	spin_lock(&parent->group_lock);
+	rgroup->parent = parent;
+	list_add(&rgroup->siblings, &parent->children);
+	spin_unlock(&parent->group_lock);
+
+	write_lock(&res_group_lock);
+	list_add_tail(&rgroup->group_list, &res_groups);
+	num_res_groups++;
+	write_unlock(&res_group_lock);
+
+	for (i = 0; i < MAX_RES_CTLRS; i++) {
+		struct res_controller *ctlr = get_controller_by_id(i);
+		if (!ctlr)
+			continue;
+		do_alloc_shares_struct(rgroup, ctlr);
+		put_controller(ctlr);
+	}
+
+	return rgroup;
+}
+
 /* Free up the given resource specific information in a resource group */
 static void do_free_shares_struct(struct resource_group *rgroup,
 						struct res_controller *ctlr)
@@ -115,6 +180,60 @@ static void do_free_shares_struct(struct
 	put_controller(ctlr); /* Drop reference acquired in do_alloc */
 }
 
+/*
+ * Release a resource group
+ *  requires that all tasks were previously reassigned to another resource
+ *  group.
+ *
+ * Returns 0 on success -errno on failure.
+ */
+void release_res_group(struct kref *kref)
+{
+	int i;
+	struct resource_group *rgroup = container_of(kref,
+				struct resource_group, ref);
+	struct resource_group *parent = rgroup->parent;
+
+	BUG_ON(is_res_group_root(rgroup));
+
+	for (i = 0; i < MAX_RES_CTLRS; i++) {
+		struct res_controller *ctlr = get_controller_by_id(i);
+		if (!ctlr)
+			continue;
+		do_free_shares_struct(rgroup, ctlr);
+		put_controller(ctlr);
+	}
+
+	/* Remove this resource group from the list system-wide groups */
+	write_lock(&res_group_lock);
+	list_del(&rgroup->group_list);
+	num_res_groups--;
+	write_unlock(&res_group_lock);
+
+	/* remove from parent */
+	spin_lock(&parent->group_lock);
+	list_del(&rgroup->siblings);
+	rgroup->parent = NO_RES_GROUP;
+	spin_unlock(&parent->group_lock);
+
+	kref_put(&parent->ref, release_res_group);
+	kfree(rgroup);
+}
+
+int free_res_group(struct resource_group *rgroup)
+{
+	BUG_ON(is_res_group_root(rgroup));
+	spin_lock(&rgroup->group_lock);
+	if (!list_empty(&rgroup->children)) {
+		spin_unlock(&rgroup->group_lock);
+		return -EBUSY;
+	}
+	spin_unlock(&rgroup->group_lock);
+	kref_put(&rgroup->ref, release_res_group);
+	return 0;
+}
+
+
 static int add_controller(struct res_controller *ctlr)
 {
 	int ctlr_id, ret = -ENOSPC;
@@ -129,7 +248,6 @@ static int add_controller(struct res_con
 	spin_unlock(&res_ctlrs_lock);
 	return ret;
 }
-
 /*
  * Interface for registering a resource controller.
  *
@@ -139,7 +257,7 @@ static int add_controller(struct res_con
 int register_controller(struct res_controller *ctlr)
 {
 	int ret;
-	struct resource_group *rgroup;
+	struct resource_group *rgroup, *prev_rgroup;
 
 	if (!ctlr)
 		return -EINVAL;
@@ -161,10 +279,20 @@ int register_controller(struct res_contr
 	 * Run through all resource groups and create the controller specific
 	 * data structures.
 	 */
-	read_lock(&res_group_lock);
-	list_for_each_entry(rgroup, &res_groups, group_list)
-		do_alloc_shares_struct(rgroup, ctlr);
-	read_unlock(&res_group_lock);
+	prev_rgroup = NULL;
+  	read_lock(&res_group_lock);
+	list_for_each_entry(rgroup, &res_groups, group_list) {
+		kref_get(&rgroup->ref);
+		read_unlock(&res_group_lock);
+  		do_alloc_shares_struct(rgroup, ctlr);
+		if (prev_rgroup)
+			kref_put(&prev_rgroup->ref, release_res_group);
+		prev_rgroup = rgroup;
+		read_lock(&res_group_lock);
+	}
+  	read_unlock(&res_group_lock);
+	if (prev_rgroup)
+		kref_put(&prev_rgroup->ref, release_res_group);
 	return 0;
 }
 
@@ -189,7 +317,7 @@ static int remove_controller(struct res_
  */
 int unregister_controller(struct res_controller *ctlr)
 {
-	struct resource_group *rgroup;
+	struct resource_group *rgroup, *prev_rgroup;
 
 	if (!ctlr)
 		return -EINVAL;
@@ -198,10 +326,20 @@ int unregister_controller(struct res_con
 		return -EINVAL;
 
 	/* free shares structs for this resource from all resource groups */
-	read_lock(&res_group_lock);
-	list_for_each_entry_reverse(rgroup, &res_groups, group_list)
-		do_free_shares_struct(rgroup, ctlr);
-	read_unlock(&res_group_lock);
+	prev_rgroup = NULL;
+  	read_lock(&res_group_lock);
+	list_for_each_entry_reverse(rgroup, &res_groups, group_list) {
+		kref_get(&rgroup->ref);
+		read_unlock(&res_group_lock);
+  		do_free_shares_struct(rgroup, ctlr);
+		if (prev_rgroup)
+			kref_put(&prev_rgroup->ref, release_res_group);
+		prev_rgroup = rgroup;
+		read_lock(&res_group_lock);
+	}
+  	read_unlock(&res_group_lock);
+	if (prev_rgroup)
+		kref_put(&prev_rgroup->ref, release_res_group);
 
 	put_controller(ctlr);
 	return remove_controller(ctlr);
@@ -212,3 +350,6 @@ EXPORT_SYMBOL_GPL(unregister_controller)
 EXPORT_SYMBOL_GPL(get_controller_by_name);
 EXPORT_SYMBOL_GPL(get_controller_by_id);
 EXPORT_SYMBOL_GPL(put_controller);
+EXPORT_SYMBOL_GPL(alloc_res_group);
+EXPORT_SYMBOL_GPL(free_res_group);
+EXPORT_SYMBOL_GPL(default_res_group);
Index: linux-2617-rc3/include/linux/res_group_rc.h
===================================================================
--- linux-2617-rc3.orig/include/linux/res_group_rc.h	2006-04-27 09:21:46.000000000 -0700
+++ linux-2617-rc3/include/linux/res_group_rc.h	2006-04-27 09:22:04.000000000 -0700
@@ -65,4 +65,13 @@ struct res_controller {
 
 extern int register_controller(struct res_controller *);
 extern int unregister_controller(struct res_controller *);
+extern struct resource_group default_res_group;
+static inline int is_res_group_root(const struct resource_group *rgroup)
+{
+	return (rgroup == &default_res_group);
+}
+
+#define for_each_child(child, parent)	\
+	list_for_each_entry(child, &parent->children, siblings)
+
 #endif /* _LINUX_RES_GROUP_RC_H */
Index: linux-2617-rc3/kernel/res_group/local.h
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/local.h	2006-04-27 09:21:46.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/local.h	2006-04-27 09:22:04.000000000 -0700
@@ -8,3 +8,7 @@
 extern struct res_controller *get_controller_by_name(const char *);
 extern struct res_controller *get_controller_by_id(unsigned int);
 extern void put_controller(struct res_controller *);
+extern struct resource_group *alloc_res_group(struct resource_group *,
+							const char *);
+extern int free_res_group(struct resource_group *);
+extern void release_res_group(struct kref *);

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - [email protected]   |      .......you may get it.
----------------------------------------------------------------------
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux