[RFC] [PATCH 01/12] Register/Unregister interface for Controllers

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

 



01/12 - ckrm_core

This patch defines data structures for defining a class and resource
controller.
Provides register/unregister functions for a controller.
Provides utility functions to get a controller's data structure.
--

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: Matt Helsley <[email protected]>

 include/linux/ckrm.h     |   76 +++++++++++++++++
 include/linux/ckrm_rc.h  |   67 ++++++++++++++
 init/Kconfig             |   14 +++
 kernel/Makefile          |    1 
 kernel/ckrm/Makefile     |    1 
 kernel/ckrm/ckrm.c       |  210 +++++++++++++++++++++++++++++++++++++++++++++++
 kernel/ckrm/ckrm_local.h |   13 ++
 7 files changed, 382 insertions(+)

Index: linux2617-rc2/include/linux/ckrm.h
===================================================================
--- /dev/null
+++ linux2617-rc2/include/linux/ckrm.h
@@ -0,0 +1,76 @@
+/*
+ *  ckrm.h - Header file to be used by Class-based Kernel Resource
+ *  Management (CKRM).
+ *
+ * Copyright (C) Hubertus Franke, IBM Corp. 2003, 2004
+ *		(C) Shailabh Nagar,  IBM Corp. 2003, 2004
+ *		(C) Chandra Seetharaman, IBM Corp. 2003, 2004, 2005
+ *
+ * Provides data structures, macros and kernel APIs
+ *
+ * More details at http://ckrm.sf.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#ifndef _LINUX_CKRM_H
+#define _LINUX_CKRM_H
+
+#ifdef CONFIG_CKRM
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+
+#define CKRM_SHARE_UNCHANGED	(-1)	/* implicitly specified by userspace,
+					 * never stored in a class' shares
+					 * struct, and never displayed */
+#define CKRM_SHARE_UNSUPPORTED	(-2)	/* If the resource controller doesn't
+					 * support user changing a shares value
+					 * it sets the corresponding share
+					 * value to UNSUPPORTED when it returns
+					 * the newly allocated shares data
+					 * structure */
+#define CKRM_SHARE_DONT_CARE	(-3)
+
+#define CKRM_SHARE_DEFAULT_DIVISOR 	(100)
+
+#define CKRM_MAX_RES_CTLRS	8	/* max # of resource controllers */
+
+#define CKRM_NO_CLASS		NULL
+#define CKRM_NO_SHARE		NULL
+#define CKRM_NO_RES_ID		CKRM_MAX_RES_CTLRS /* Invalid ID */
+
+/*
+ * Share quantities are a child's fraction of the parent's resource
+ * specified by a divisor in the parent and a dividend in the child.
+ *
+ * Shares are represented as a relative quantity between parent and child
+ * to simplify locking when propagating modifications to the shares of a
+ * class. Only the parent and the children of the modified class need to be
+ * locked.
+*/
+struct ckrm_shares {
+};
+
+/*
+ * Class is the grouping of tasks with shares of each resource that has
+ * registered a resource controller (see include/linux/ckrm_rc.h).
+ */
+struct ckrm_class {
+	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,
+				 * grab parent's class_lock first.
+				 * If resource controller uses a class
+				 * specific lock, grab class_lock before
+				 * 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 */
+};
+
+#endif /* CONFIG_CKRM */
+#endif /* _LINUX_CKRM_H */
Index: linux2617-rc2/include/linux/ckrm_rc.h
===================================================================
--- /dev/null
+++ linux2617-rc2/include/linux/ckrm_rc.h
@@ -0,0 +1,67 @@
+/*
+ *  ckrm_rc.h - Header file to be used by Resource controllers of CKRM
+ *
+ * Copyright (C) Hubertus Franke, IBM Corp. 2003
+ *		(C) Shailabh Nagar,  IBM Corp. 2003
+ *		(C) Chandra Seetharaman, IBM Corp. 2003, 2004, 2005
+ *		(C) Vivek Kashyap , IBM Corp. 2004
+ *
+ * Provides data structures, macros and kernel API of CKRM for
+ * resource controllers.
+ *
+ * More details at http://ckrm.sf.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#ifndef _LINUX_CKRM_RC_H
+#define _LINUX_CKRM_RC_H
+
+#include <linux/ckrm.h>
+
+struct ckrm_controller {
+	const char *name;
+	int depth_supported;/* maximum hierarchy supported by controller */
+	unsigned int ctlr_id;
+
+	/*
+	 * Keeps number of references to this controller structure. kref
+	 * does not work as we want to be able to allow removal of a
+	 * controller even when some classes are defined.
+	 */
+	atomic_t count;
+
+	/*
+	 * Allocate a new shares struct for this resource controller.
+	 * Called when registering a resource controller with pre-existing
+	 * classes and when new classes are created by the user.
+	 */
+	struct ckrm_shares *(*alloc_shares_struct)(struct ckrm_class *);
+	/* Corresponding free of shares struct for this resource controller */
+	void (*free_shares_struct)(struct ckrm_shares *);
+
+	/* Notifies the controller when the shares are changed */
+	void (*shares_changed)(struct ckrm_shares *);
+
+	/* resource statistics */
+	ssize_t (*show_stats)(struct ckrm_shares *, char *, size_t);
+	int (*reset_stats)(struct ckrm_shares *, const char *);
+
+	/*
+	 * move_task is called when a task moves from one class to another.
+	 * The first parameter is the task that is moving, the second
+	 * is the resource specific shares of the previous class the task
+	 * was in, and the third is the shares of the class the task has
+	 * moved to.
+	 */
+	void (*move_task)(struct task_struct *, struct ckrm_shares *,
+				struct ckrm_shares *);
+};
+
+extern int ckrm_register_controller(struct ckrm_controller *);
+extern int ckrm_unregister_controller(struct ckrm_controller *);
+#endif /* _LINUX_CKRM_RC_H */
Index: linux2617-rc2/kernel/ckrm/ckrm.c
===================================================================
--- /dev/null
+++ linux2617-rc2/kernel/ckrm/ckrm.c
@@ -0,0 +1,210 @@
+/* ckrm.c - Class-based Kernel Resource Management (CKRM)
+ *
+ * Copyright (C) Hubertus Franke, IBM Corp. 2003, 2004
+ *		(C) Shailabh Nagar, IBM Corp. 2003, 2004
+ *		(C) Chandra Seetharaman, IBM Corp. 2003, 2004, 2005
+ *		(C) Vivek Kashyap, IBM Corp. 2004
+ *		(C) Matt Helsley, IBM Corp. 2006
+ *
+ * Provides kernel API of CKRM for in-kernel,per-resource controllers
+ * (one each for cpu, memory and io).
+ *
+ * Latest version, more details at http://ckrm.sf.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/ckrm_rc.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 */
+
+/* Must be called with res_ctlr_lock held */
+static inline int is_ctlr_id_valid(unsigned int ctlr_id)
+{
+	return ((ctlr_id < CKRM_MAX_RES_CTLRS) &&
+			(ckrm_controllers[ctlr_id] != NULL));
+}
+
+struct ckrm_controller *ckrm_get_controller_by_id(unsigned int ctlr_id)
+{
+	/*
+	 * inc of controller[i].count has to be atomically done with
+	 * checking the array ckrm_controllers, as remove_controller()
+	 * checks controller[i].count and clears ckrm_controllers[i]
+	 * atomically, under res_ctlrs_lock.
+	 */
+	spin_lock(&res_ctlrs_lock);
+	if (!is_ctlr_id_valid(ctlr_id)) {
+		spin_unlock(&res_ctlrs_lock);
+		return NULL;
+	}
+	atomic_inc(&ckrm_controllers[ctlr_id]->count);
+	spin_unlock(&res_ctlrs_lock);
+	return ckrm_controllers[ctlr_id];
+}
+
+struct ckrm_controller *ckrm_get_controller_by_name(const char *name)
+{
+	struct ckrm_controller *ctlr;
+	unsigned int i;
+
+	spin_lock(&res_ctlrs_lock);
+	for (i = 0; i < CKRM_MAX_RES_CTLRS; i++, ctlr = NULL) {
+		ctlr = ckrm_controllers[i];
+		if (!ctlr)
+			continue;
+		if (!strcmp(name, ctlr->name)) {
+			atomic_inc(&ckrm_controllers[i]->count);
+			break;
+		}
+	}
+	spin_unlock(&res_ctlrs_lock);
+	return ctlr;
+}
+
+static void ckrm_get_controller(struct ckrm_controller *ctlr)
+{
+	atomic_inc(&ctlr->count);
+}
+
+void ckrm_put_controller(struct ckrm_controller *ctlr)
+{
+	atomic_dec(&ctlr->count);
+}
+
+/* Allocate resource specific information for a class */
+static void do_alloc_shares_struct(struct ckrm_class *class,
+					struct ckrm_controller *ctlr)
+{
+	if (class->shares[ctlr->ctlr_id]) /* already allocated */
+		return;
+
+	if (class->depth > ctlr->depth_supported)
+		return;
+
+	class->shares[ctlr->ctlr_id] = ctlr->alloc_shares_struct(class);
+	if (class->shares[ctlr->ctlr_id] != NULL)
+		ckrm_get_controller(ctlr);
+}
+
+/* Free up the given resource specific information in a class */
+static void do_free_shares_struct(struct ckrm_class *class,
+						struct ckrm_controller *ctlr)
+{
+	struct ckrm_shares *shares = class->shares[ctlr->ctlr_id];
+
+	/* No shares alloced previously */
+	if (shares == NULL)
+		return;
+
+	spin_lock(&class->class_lock);
+	class->shares[ctlr->ctlr_id] = NULL;
+	spin_unlock(&class->class_lock);
+	ctlr->free_shares_struct(shares);
+	ckrm_put_controller(ctlr); /* Drop reference acquired in do_alloc */
+}
+
+static int add_controller(struct ckrm_controller *ctlr)
+{
+	int ctlr_id, ret = -ENOSPC;
+
+	spin_lock(&res_ctlrs_lock);
+	for (ctlr_id = 0; ctlr_id < CKRM_MAX_RES_CTLRS; ctlr_id++)
+		if (ckrm_controllers[ctlr_id] == NULL) {
+			ckrm_controllers[ctlr_id] = ctlr;
+			ret = ctlr_id;
+			break;
+		}
+	spin_unlock(&res_ctlrs_lock);
+	return ret;
+}
+
+/*
+ * Interface for registering a resource controller.
+ *
+ * Returns the 0 on success, -errno for failure.
+ * Fills ctlr->ctlr_id with a valid controller id on success.
+ */
+int ckrm_register_controller(struct ckrm_controller *ctlr)
+{
+	int ret;
+	struct ckrm_class *class;
+
+	if (!ctlr)
+		return -EINVAL;
+
+	/* Make sure there is an alloc and a free */
+	if (!ctlr->alloc_shares_struct || !ctlr->free_shares_struct)
+		return -EINVAL;
+
+	ret = add_controller(ctlr);
+
+	if (ret < 0)
+		return ret;
+
+	ctlr->ctlr_id = ret;
+
+	atomic_set(&ctlr->count, 0);
+
+	/*
+	 * 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);
+	return 0;
+}
+
+static int remove_controller(struct ckrm_controller *ctlr)
+{
+	spin_lock(&res_ctlrs_lock);
+	if (atomic_read(&ctlr->count) > 0) {
+		spin_unlock(&res_ctlrs_lock);
+		return -EBUSY;
+	}
+
+	ckrm_controllers[ctlr->ctlr_id] = NULL;
+	ctlr->ctlr_id = CKRM_NO_RES_ID;
+	spin_unlock(&res_ctlrs_lock);
+	return 0;
+}
+
+/*
+ * Unregistering resource controller.
+ *
+ * Returns 0 on success -errno for failure.
+ */
+int ckrm_unregister_controller(struct ckrm_controller *ctlr)
+{
+	struct ckrm_class *class;
+
+	if (!ctlr)
+		return -EINVAL;
+
+	if (ckrm_get_controller_by_id(ctlr->ctlr_id) != ctlr)
+		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);
+
+	ckrm_put_controller(ctlr);
+	return remove_controller(ctlr);
+}
+
+EXPORT_SYMBOL_GPL(ckrm_register_controller);
+EXPORT_SYMBOL_GPL(ckrm_unregister_controller);
Index: linux2617-rc2/kernel/Makefile
===================================================================
--- linux2617-rc2.orig/kernel/Makefile
+++ linux2617-rc2/kernel/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
 obj-$(CONFIG_SECCOMP) += seccomp.o
 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_RELAY) += relay.o
+obj-$(CONFIG_CKRM) += ckrm/
 
 ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
 # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
Index: linux2617-rc2/kernel/ckrm/Makefile
===================================================================
--- /dev/null
+++ linux2617-rc2/kernel/ckrm/Makefile
@@ -0,0 +1 @@
+obj-y = ckrm.o
Index: linux2617-rc2/init/Kconfig
===================================================================
--- linux2617-rc2.orig/init/Kconfig
+++ linux2617-rc2/init/Kconfig
@@ -150,6 +150,20 @@ config BSD_PROCESS_ACCT_V3
 	  for processing it. A preliminary version of these tools is available
 	  at <http://www.physik3.uni-rostock.de/tim/kernel/utils/acct/>.
 
+menu "Class Based Kernel Resource Management"
+
+config CKRM
+	bool "Class Based Kernel Resource Management Core"
+	depends on EXPERIMENTAL
+	help
+	  Class-based Kernel Resource Management is a framework for controlling
+	  and monitoring resource allocation of user-defined groups of tasks.
+	  For more information, please visit http://ckrm.sf.net.
+
+	  If you say Y here, enable the Resource Class File System and at least
+	  one of the resource controllers below. Say N if you are unsure.
+
+endmenu
 config SYSCTL
 	bool "Sysctl support"
 	---help---
Index: linux2617-rc2/kernel/ckrm/ckrm_local.h
===================================================================
--- /dev/null
+++ linux2617-rc2/kernel/ckrm/ckrm_local.h
@@ -0,0 +1,13 @@
+/*
+ * Contains function definitions that are local to ckrm core.
+ * NOT to be included by controllers.
+ */
+
+#include <linux/ckrm_rc.h>
+
+extern struct ckrm_controller *ckrm_get_controller_by_name(const char *);
+extern struct ckrm_controller *ckrm_get_controller_by_id(unsigned int);
+extern void ckrm_put_controller(struct ckrm_controller *);
+extern struct ckrm_class *ckrm_alloc_class(struct ckrm_class *, const char *);
+extern int ckrm_free_class(struct ckrm_class *);
+extern void ckrm_release_class(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