[RFC] [PATCH 02/12] Class creation/deletion

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

 



02/12 - ckrm_core_class_support

Provides functions to alloc and free a user defined class.
Provides utility macro to walk through the class 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/ckrm.h    |    8 ++
 include/linux/ckrm_rc.h |    9 ++
 kernel/ckrm/ckrm.c      |  171 ++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 175 insertions(+), 13 deletions(-)

Index: linux2617-rc2/include/linux/ckrm.h
===================================================================
--- linux2617-rc2.orig/include/linux/ckrm.h
+++ linux2617-rc2/include/linux/ckrm.h
@@ -61,6 +61,8 @@ struct ckrm_shares {
  * registered a resource controller (see include/linux/ckrm_rc.h).
  */
 struct ckrm_class {
+	const char *name;
+	struct kref ref;
 	int depth;		/* depth of this class. root == 0 */
 	spinlock_t class_lock;	/* protects task_list, shares and children
 				 * When grabbing class_lock in a hierarchy,
@@ -70,6 +72,12 @@ struct ckrm_class {
 				 * grabbing resource specific lock */
 	struct ckrm_shares *shares[CKRM_MAX_RES_CTLRS];/* resource shares */
 	struct list_head class_list;	/* entry in list of all classes */
+
+	struct list_head task_list;	/* this class's tasks */
+
+	struct ckrm_class *parent;
+	struct list_head siblings;	/* entry in list of siblings */
+	struct list_head children;	/* head of children */
 };
 
 #endif /* CONFIG_CKRM */
Index: linux2617-rc2/kernel/ckrm/ckrm.c
===================================================================
--- linux2617-rc2.orig/kernel/ckrm/ckrm.c
+++ linux2617-rc2/kernel/ckrm/ckrm.c
@@ -19,14 +19,32 @@
  */
 
 #include <linux/module.h>
-#include <linux/ckrm_rc.h>
+#include "ckrm_local.h"
 
 static struct ckrm_controller *ckrm_controllers[CKRM_MAX_RES_CTLRS];
 /* res_ctlrs_lock protects ckrm_controllers array and count in controllers*/
 static spinlock_t res_ctlrs_lock = SPIN_LOCK_UNLOCKED;
 
 static LIST_HEAD(ckrm_classes);/* link all classes */
-static rwlock_t ckrm_class_lock = RW_LOCK_UNLOCKED; /* protects ckrm_classes */
+static int ckrm_num_classes;	/* Number of user defined classes */
+static rwlock_t ckrm_class_lock = RW_LOCK_UNLOCKED;
+			/* protects ckrm_classes list and ckrm_num_classes */
+
+struct ckrm_class ckrm_default_class = {
+	.task_list = LIST_HEAD_INIT(ckrm_default_class.task_list),
+	.class_lock = SPIN_LOCK_UNLOCKED,
+	.name = "task",
+	.class_list = LIST_HEAD_INIT(ckrm_default_class.class_list),
+	.siblings = LIST_HEAD_INIT(ckrm_default_class.siblings),
+	.children = LIST_HEAD_INIT(ckrm_default_class.children),
+};
+
+/* Must be called with parent's class_lock held */
+static inline void ckrm_remove_child(struct ckrm_class *child)
+{
+	list_del(&child->siblings);
+	child->parent = CKRM_NO_CLASS;
+}
 
 /* Must be called with res_ctlr_lock held */
 static inline int is_ctlr_id_valid(unsigned int ctlr_id)
@@ -97,6 +115,55 @@ static void do_alloc_shares_struct(struc
 		ckrm_get_controller(ctlr);
 }
 
+static void ckrm_class_init(struct ckrm_class *class)
+{
+	class->class_lock = SPIN_LOCK_UNLOCKED;
+	kref_init(&class->ref);
+	INIT_LIST_HEAD(&class->task_list);
+	INIT_LIST_HEAD(&class->children);
+	INIT_LIST_HEAD(&class->siblings);
+}
+
+struct ckrm_class *ckrm_alloc_class(struct ckrm_class *parent,
+						const char *name)
+{
+	int i;
+	struct ckrm_class *class;
+
+	BUG_ON(parent == NULL);
+
+	kref_get(&parent->ref);
+	class = kzalloc(sizeof(struct ckrm_class), GFP_KERNEL);
+	if (!class) {
+		kref_put(&parent->ref, ckrm_release_class);
+		return NULL;
+	}
+	ckrm_class_init(class);
+	class->name = name;
+	class->depth = parent->depth + 1;
+
+	/* Add to parent */
+	spin_lock(&parent->class_lock);
+	class->parent = parent;
+	list_add(&class->siblings, &parent->children);
+	spin_unlock(&parent->class_lock);
+
+	write_lock(&ckrm_class_lock);
+	list_add_tail(&class->class_list, &ckrm_classes);
+	ckrm_num_classes++;
+	write_unlock(&ckrm_class_lock);
+
+	for (i = 0; i < CKRM_MAX_RES_CTLRS; i++) {
+		struct ckrm_controller *ctlr = ckrm_get_controller_by_id(i);
+		if (!ctlr)
+			continue;
+		do_alloc_shares_struct(class, ctlr);
+		ckrm_put_controller(ctlr);
+	}
+
+	return class;
+}
+
 /* Free up the given resource specific information in a class */
 static void do_free_shares_struct(struct ckrm_class *class,
 						struct ckrm_controller *ctlr)
@@ -114,6 +181,59 @@ static void do_free_shares_struct(struct
 	ckrm_put_controller(ctlr); /* Drop reference acquired in do_alloc */
 }
 
+/*
+ * Release a class
+ *  requires that all tasks were previously reassigned to another class
+ *
+ * Returns 0 on success -errno on failure.
+ */
+void ckrm_release_class(struct kref *kref)
+{
+	int i;
+	struct ckrm_class *class = container_of(kref,
+				struct ckrm_class, ref);
+	struct ckrm_class *parent = class->parent;
+
+	BUG_ON(ckrm_is_class_root(class));
+
+	for (i = 0; i < CKRM_MAX_RES_CTLRS; i++) {
+		struct ckrm_controller *ctlr = ckrm_get_controller_by_id(i);
+		if (!ctlr)
+			continue;
+		do_free_shares_struct(class, ctlr);
+		ckrm_put_controller(ctlr);
+	}
+
+	/* Remove this class from the list of all classes */
+	write_lock(&ckrm_class_lock);
+	list_del(&class->class_list);
+	ckrm_num_classes--;
+	write_unlock(&ckrm_class_lock);
+
+	/* remove from parent */
+	spin_lock(&parent->class_lock);
+	list_del(&class->siblings);
+	class->parent = CKRM_NO_CLASS;
+	spin_unlock(&parent->class_lock);
+
+	kref_put(&parent->ref, ckrm_release_class);
+	kfree(class);
+}
+
+int ckrm_free_class(struct ckrm_class *class)
+{
+	BUG_ON(ckrm_is_class_root(class));
+	spin_lock(&class->class_lock);
+	if (!list_empty(&class->children)) {
+		spin_unlock(&class->class_lock);
+		return -EBUSY;
+	}
+	spin_unlock(&class->class_lock);
+	kref_put(&class->ref, ckrm_release_class);
+	return 0;
+}
+
+
 static int add_controller(struct ckrm_controller *ctlr)
 {
 	int ctlr_id, ret = -ENOSPC;
@@ -128,7 +248,6 @@ static int add_controller(struct ckrm_co
 	spin_unlock(&res_ctlrs_lock);
 	return ret;
 }
-
 /*
  * Interface for registering a resource controller.
  *
@@ -138,7 +257,7 @@ static int add_controller(struct ckrm_co
 int ckrm_register_controller(struct ckrm_controller *ctlr)
 {
 	int ret;
-	struct ckrm_class *class;
+	struct ckrm_class *class, *prev_class;
 
 	if (!ctlr)
 		return -EINVAL;
@@ -160,10 +279,20 @@ int ckrm_register_controller(struct ckrm
 	 * Run through all classes and create the controller specific data
 	 * structures.
 	 */
-	read_lock(&ckrm_class_lock);
-	list_for_each_entry(class, &ckrm_classes, class_list)
-		do_alloc_shares_struct(class, ctlr);
-	read_unlock(&ckrm_class_lock);
+	prev_class = NULL;
+  	read_lock(&ckrm_class_lock);
+	list_for_each_entry(class, &ckrm_classes, class_list) {
+		kref_get(&class->ref);
+		read_unlock(&ckrm_class_lock);
+  		do_alloc_shares_struct(class, ctlr);
+		if (prev_class)
+			kref_put(&prev_class->ref, ckrm_release_class);
+		prev_class = class;
+		read_lock(&ckrm_class_lock);
+	}
+  	read_unlock(&ckrm_class_lock);
+	if (prev_class)
+		kref_put(&prev_class->ref, ckrm_release_class);
 	return 0;
 }
 
@@ -188,7 +317,7 @@ static int remove_controller(struct ckrm
  */
 int ckrm_unregister_controller(struct ckrm_controller *ctlr)
 {
-	struct ckrm_class *class;
+	struct ckrm_class *class, *prev_class;
 
 	if (!ctlr)
 		return -EINVAL;
@@ -197,10 +326,20 @@ int ckrm_unregister_controller(struct ck
 		return -EINVAL;
 
 	/* free shares structs for this resource from all the classes */
-	read_lock(&ckrm_class_lock);
-	list_for_each_entry_reverse(class, &ckrm_classes, class_list)
-		do_free_shares_struct(class, ctlr);
-	read_unlock(&ckrm_class_lock);
+	prev_class = NULL;
+  	read_lock(&ckrm_class_lock);
+	list_for_each_entry_reverse(class, &ckrm_classes, class_list) {
+		kref_get(&class->ref);
+		read_unlock(&ckrm_class_lock);
+  		do_free_shares_struct(class, ctlr);
+		if (prev_class)
+			kref_put(&prev_class->ref, ckrm_release_class);
+		prev_class = class;
+		read_lock(&ckrm_class_lock);
+	}
+  	read_unlock(&ckrm_class_lock);
+	if (prev_class)
+		kref_put(&prev_class->ref, ckrm_release_class);
 
 	ckrm_put_controller(ctlr);
 	return remove_controller(ctlr);
@@ -208,3 +347,9 @@ int ckrm_unregister_controller(struct ck
 
 EXPORT_SYMBOL_GPL(ckrm_register_controller);
 EXPORT_SYMBOL_GPL(ckrm_unregister_controller);
+EXPORT_SYMBOL_GPL(ckrm_alloc_class);
+EXPORT_SYMBOL_GPL(ckrm_free_class);
+EXPORT_SYMBOL_GPL(ckrm_default_class);
+EXPORT_SYMBOL_GPL(ckrm_get_controller_by_name);
+EXPORT_SYMBOL_GPL(ckrm_get_controller_by_id);
+EXPORT_SYMBOL_GPL(ckrm_put_controller);
Index: linux2617-rc2/include/linux/ckrm_rc.h
===================================================================
--- linux2617-rc2.orig/include/linux/ckrm_rc.h
+++ linux2617-rc2/include/linux/ckrm_rc.h
@@ -64,4 +64,13 @@ struct ckrm_controller {
 
 extern int ckrm_register_controller(struct ckrm_controller *);
 extern int ckrm_unregister_controller(struct ckrm_controller *);
+extern struct ckrm_class ckrm_default_class;
+static inline int ckrm_is_class_root(const struct ckrm_class* class)
+{
+	return (class == &ckrm_default_class);
+}
+
+#define for_each_child(child, parent)	\
+	list_for_each_entry(child, &parent->children, siblings)
+
 #endif /* _LINUX_CKRM_RC_H */

-- 

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