public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] Resource Groups... formerly CKRM
@ 2006-04-28  1:34 Chandra Seetharaman
  2006-04-28  1:34 ` [PATCH 01/12] Register/Unregister interface for Controllers Chandra Seetharaman
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:34 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

Andrew,

CKRM has gone through a major overhaul by removing some of the complexity,
cutting down on features and moving portions to userspace.

We have posted ckrm last week as an RFC:
infrastructure:
	http://www.ussg.iu.edu/hypermail/linux/kernel/0604.2/1297.html
numtasks controller:
	http://www.ussg.iu.edu/hypermail/linux/kernel/0604.2/1311.html
CPU controller:
	http://www.ussg.iu.edu/hypermail/linux/kernel/0604.2/1310.html

Diffstat of this patchset (including the numtasks controller that follows)
is:

	23 files changed, 2466 insertions(+), 5 deletions(-)

including Documentaion and comments.

This patchset will be followed with two controllers:
	- a simple controller, numtasks to control number of tasks
	- CPU controller, to control CPU resource.

Please consider these for inclusion in -mm tree.
--

Changes since last post:
 - CKRM has been replaced with Resource Groups
 - 'class' has been replaced with resource group
 - Limit the depth of the hierarchy.

---------
Patch Descriptions:

01/12 - controller_support

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

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.

03/12 - shares_support

Provides functions to set/get shares of a specific resource of a resource
group.
Defines a teardown function that is intended to be called when user
disables resource group (by umount of the configfs component).

04/12 - tasksupport

Adds logic to support adding/removing task to/from a resource group
Provides interface to set a task's resource group.

05/12 - tasksupport_fork_exit_init

Initializes and clears Resource Group specific information in a task
at fork() and exit().  Inititalizes Resource Groups (called from start_kernel)

06/12: task_procsupport

Adds an interface in /proc to get the name of a resource group to which a task
is attached.

07/12 - user_interface

Create the configfs component for managing Resource groups. Hooks up with
configfs. Provides functions for creating and deleting resource groups.

08/12 - user_interface_attr_support

Adds the basic attribute store and show functions. 

09/12 - user_interface_stats

Adds attr_store and attr_show support for stats file. 

10/12 - user_interface_shares

Adds attr_store and attr_show support for shares file. 

11/12 - user_interface_members

Adds attr_store and attr_show support for members file. 

12/12 - res_groups_docs

Documentation describing important Resource Groups components such as resource
group, shares, controllers, and the configfs based user interface.
--
Thanks & Regards,

chandra

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 01/12] Register/Unregister interface for Controllers
  2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
@ 2006-04-28  1:34 ` Chandra Seetharaman
  2006-04-28  1:34 ` [PATCH 02/12] Resource group creation/deletion Chandra Seetharaman
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:34 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

01/12 - controller_support

This patch defines data structures for defining a resource group 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 <sekharan@us.ibm.com>
Signed-Off-By: Hubertus Franke <frankeh@us.ibm.com>
Signed-Off-By: Shailabh Nagar <nagar@watson.ibm.com>
Signed-Off-By: Gerrit Huizenga <gh@us.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>

 include/linux/res_group.h    |   75 +++++++++++++++
 include/linux/res_group_rc.h |   68 +++++++++++++
 init/Kconfig                 |   14 ++
 kernel/Makefile              |    1 
 kernel/res_group/Makefile    |    1 
 kernel/res_group/local.h     |   10 ++
 kernel/res_group/res_group.c |  214 +++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 383 insertions(+)

Index: linux-2617-rc3/include/linux/res_group.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/include/linux/res_group.h	2006-04-27 09:21:46.000000000 -0700
@@ -0,0 +1,75 @@
+/*
+ *  res_group.h - Header file to be used by Resource Groups
+ *
+ * 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_RES_GROUP_H
+#define _LINUX_RES_GROUP_H
+
+#ifdef CONFIG_RES_GROUPS
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+
+#define SHARE_UNCHANGED	(-1)	/* implicitly specified by userspace,
+					 * never stored in a resource group'
+					 * shares struct; never displayed */
+#define 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 SHARE_DONT_CARE	(-3)
+
+#define SHARE_DEFAULT_DIVISOR 	(100)
+
+#define MAX_RES_CTLRS	8	/* max # of resource controllers */
+
+#define NO_RES_GROUP		NULL
+#define NO_SHARE		NULL
+#define NO_RES_ID		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
+ * resource group. Only the parent and the children of the modified
+ * resource group need to be locked.
+*/
+struct res_shares {
+};
+
+/*
+ * Class is the grouping of tasks with shares of each resource that has
+ * registered a resource controller (see include/linux/res_group_rc.h).
+ */
+struct resource_group {
+	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,
+				 * grab parent's group_lock first.
+				 * If resource controller uses a resource_group
+				 * specific lock, grab group_lock before
+				 * grabbing resource specific lock */
+	struct res_shares *shares[MAX_RES_CTLRS];/* resource shares */
+	struct list_head group_list;	/* entry in system-wide list */
+};
+
+#endif /* CONFIG_RES_GROUPS */
+#endif /* _LINUX_RES_GROUP_H */
Index: linux-2617-rc3/include/linux/res_group_rc.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/include/linux/res_group_rc.h	2006-04-27 09:21:46.000000000 -0700
@@ -0,0 +1,68 @@
+/*
+ *  res_group_rc.h - Header file to be used by Resource controllers of
+ *		      Resource Groups
+ *
+ * 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 Resource Groups 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_RES_GROUP_RC_H
+#define _LINUX_RES_GROUP_RC_H
+
+#include <linux/res_group.h>
+
+struct res_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 resource group are still defined.
+	 */
+	atomic_t count;
+
+	/*
+	 * Allocate a new shares struct for this resource controller.
+	 * Called when registering a resource controller with pre-existing
+	 * resource groups and when new resource group is created by the user.
+	 */
+	struct res_shares *(*alloc_shares_struct)(struct resource_group *);
+	/* Corresponding free of shares struct for this resource controller */
+	void (*free_shares_struct)(struct res_shares *);
+
+	/* Notifies the controller when the shares are changed */
+	void (*shares_changed)(struct res_shares *);
+
+	/* resource statistics */
+	ssize_t (*show_stats)(struct res_shares *, char *, size_t);
+	int (*reset_stats)(struct res_shares *, const char *);
+
+	/*
+	 * move_task is called when a task moves from one resource group to
+	 * another. First parameter is the task that is moving, the second
+	 * is the resource specific shares of the resource group the task
+	 * was in, and the third is the shares of the resource group the
+	 * task has moved to.
+	 */
+	void (*move_task)(struct task_struct *, struct res_shares *,
+				struct res_shares *);
+};
+
+extern int register_controller(struct res_controller *);
+extern int unregister_controller(struct res_controller *);
+#endif /* _LINUX_RES_GROUP_RC_H */
Index: linux-2617-rc3/kernel/res_group/res_group.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/kernel/res_group/res_group.c	2006-04-27 09:21:46.000000000 -0700
@@ -0,0 +1,214 @@
+/* res_group.c - Resource Groups: Resource management through grouping of
+ *		  unrelated tasks.
+ *
+ * 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 Resource Groups 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/res_group_rc.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 */
+
+/* Must be called with res_ctlr_lock held */
+static inline int is_ctlr_id_valid(unsigned int ctlr_id)
+{
+	return ((ctlr_id < MAX_RES_CTLRS) &&
+			(res_controllers[ctlr_id] != NULL));
+}
+
+struct res_controller *get_controller_by_id(unsigned int ctlr_id)
+{
+	/*
+	 * inc of controller[i].count has to be atomically done with
+	 * checking the array res_controllers, as remove_controller()
+	 * checks controller[i].count and clears res_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(&res_controllers[ctlr_id]->count);
+	spin_unlock(&res_ctlrs_lock);
+	return res_controllers[ctlr_id];
+}
+
+struct res_controller *get_controller_by_name(const char *name)
+{
+	struct res_controller *ctlr;
+	unsigned int i;
+
+	spin_lock(&res_ctlrs_lock);
+	for (i = 0; i < MAX_RES_CTLRS; i++, ctlr = NULL) {
+		ctlr = res_controllers[i];
+		if (!ctlr)
+			continue;
+		if (!strcmp(name, ctlr->name)) {
+			atomic_inc(&res_controllers[i]->count);
+			break;
+		}
+	}
+	spin_unlock(&res_ctlrs_lock);
+	return ctlr;
+}
+
+static void get_controller(struct res_controller *ctlr)
+{
+	atomic_inc(&ctlr->count);
+}
+
+void put_controller(struct res_controller *ctlr)
+{
+	atomic_dec(&ctlr->count);
+}
+
+/* Allocate resource specific information for a resource group */
+static void do_alloc_shares_struct(struct resource_group *rgroup,
+					struct res_controller *ctlr)
+{
+	if (rgroup->shares[ctlr->ctlr_id]) /* already allocated */
+		return;
+
+	if (rgroup->depth > ctlr->depth_supported)
+		return;
+
+	rgroup->shares[ctlr->ctlr_id] = ctlr->alloc_shares_struct(rgroup);
+	if (rgroup->shares[ctlr->ctlr_id] != NULL)
+		get_controller(ctlr);
+}
+
+/* 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)
+{
+	struct res_shares *shares = rgroup->shares[ctlr->ctlr_id];
+
+	/* No shares alloced previously */
+	if (shares == NULL)
+		return;
+
+	spin_lock(&rgroup->group_lock);
+	rgroup->shares[ctlr->ctlr_id] = NULL;
+	spin_unlock(&rgroup->group_lock);
+	ctlr->free_shares_struct(shares);
+	put_controller(ctlr); /* Drop reference acquired in do_alloc */
+}
+
+static int add_controller(struct res_controller *ctlr)
+{
+	int ctlr_id, ret = -ENOSPC;
+
+	spin_lock(&res_ctlrs_lock);
+	for (ctlr_id = 0; ctlr_id < MAX_RES_CTLRS; ctlr_id++)
+		if (res_controllers[ctlr_id] == NULL) {
+			res_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 register_controller(struct res_controller *ctlr)
+{
+	int ret;
+	struct resource_group *rgroup;
+
+	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 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);
+	return 0;
+}
+
+static int remove_controller(struct res_controller *ctlr)
+{
+	spin_lock(&res_ctlrs_lock);
+	if (atomic_read(&ctlr->count) > 0) {
+		spin_unlock(&res_ctlrs_lock);
+		return -EBUSY;
+	}
+
+	res_controllers[ctlr->ctlr_id] = NULL;
+	ctlr->ctlr_id = NO_RES_ID;
+	spin_unlock(&res_ctlrs_lock);
+	return 0;
+}
+
+/*
+ * Unregistering resource controller.
+ *
+ * Returns 0 on success -errno for failure.
+ */
+int unregister_controller(struct res_controller *ctlr)
+{
+	struct resource_group *rgroup;
+
+	if (!ctlr)
+		return -EINVAL;
+
+	if (get_controller_by_id(ctlr->ctlr_id) != ctlr)
+		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);
+
+	put_controller(ctlr);
+	return remove_controller(ctlr);
+}
+
+EXPORT_SYMBOL_GPL(register_controller);
+EXPORT_SYMBOL_GPL(unregister_controller);
+EXPORT_SYMBOL_GPL(get_controller_by_name);
+EXPORT_SYMBOL_GPL(get_controller_by_id);
+EXPORT_SYMBOL_GPL(put_controller);
Index: linux-2617-rc3/kernel/Makefile
===================================================================
--- linux-2617-rc3.orig/kernel/Makefile	2006-04-27 09:18:25.000000000 -0700
+++ linux-2617-rc3/kernel/Makefile	2006-04-27 09:20:59.000000000 -0700
@@ -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_RES_GROUPS) += res_group/
 
 ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
Index: linux-2617-rc3/kernel/res_group/Makefile
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/kernel/res_group/Makefile	2006-04-27 09:21:42.000000000 -0700
@@ -0,0 +1 @@
+obj-y = res_group.o
Index: linux-2617-rc3/init/Kconfig
===================================================================
--- linux-2617-rc3.orig/init/Kconfig	2006-04-27 09:18:25.000000000 -0700
+++ linux-2617-rc3/init/Kconfig	2006-04-27 09:20:59.000000000 -0700
@@ -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 "Resource Groups"
+
+config RES_GROUPS
+	bool "Resource Groups"
+	depends on EXPERIMENTAL
+	help
+	  Resource Groups 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 Group 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: linux-2617-rc3/kernel/res_group/local.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/kernel/res_group/local.h	2006-04-27 09:21:46.000000000 -0700
@@ -0,0 +1,10 @@
+/*
+ * Contains function definitions that are local to the Resource Groups.
+ * NOT to be included by controllers.
+ */
+
+#include <linux/res_group_rc.h>
+
+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 *);

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 02/12] Resource group creation/deletion
  2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
  2006-04-28  1:34 ` [PATCH 01/12] Register/Unregister interface for Controllers Chandra Seetharaman
@ 2006-04-28  1:34 ` Chandra Seetharaman
  2006-04-28  1:34 ` [PATCH 03/12] Share Handling Chandra Seetharaman
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:34 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

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 <sekharan@us.ibm.com>
Signed-Off-By: Hubertus Franke <frankeh@us.ibm.com>
Signed-Off-By: Shailabh Nagar <nagar@watson.ibm.com>
Signed-Off-By: Gerrit Huizenga <gh@us.ibm.com>
Signed-Off-By: Vivek Kashyap <kashyapv@us.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>

 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....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 03/12] Share Handling
  2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
  2006-04-28  1:34 ` [PATCH 01/12] Register/Unregister interface for Controllers Chandra Seetharaman
  2006-04-28  1:34 ` [PATCH 02/12] Resource group creation/deletion Chandra Seetharaman
@ 2006-04-28  1:34 ` Chandra Seetharaman
  2006-04-28  1:34 ` [PATCH 04/12] Add task logic to resource groups Chandra Seetharaman
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:34 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

03/12 - shares_support

Provides functions to set/get shares of a specific resource of a resource
group.
Defines a teardown function that is intended to be called when user
disables resource group (by umount of the configfs component).
--

Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Hubertus Franke <frankeh@us.ibm.com>
Signed-Off-By: Shailabh Nagar <nagar@watson.ibm.com>
Signed-Off-By: Gerrit Huizenga <gh@us.ibm.com>
Signed-off-by: MAEDA Naoaki <maeda.naoaki@jp.fujitsu.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>

 include/linux/res_group.h    |   14 ++
 include/linux/res_group_rc.h |   10 +
 kernel/res_group/Makefile    |    2 
 kernel/res_group/local.h     |    6 +
 kernel/res_group/res_group.c |   24 ++++
 kernel/res_group/shares.c    |  242 +++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 297 insertions(+), 1 deletion(-)

Index: linux-2617-rc3/include/linux/res_group.h
===================================================================
--- linux-2617-rc3.orig/include/linux/res_group.h	2006-04-27 09:22:04.000000000 -0700
+++ linux-2617-rc3/include/linux/res_group.h	2006-04-27 09:22:07.000000000 -0700
@@ -54,6 +54,20 @@
  * resource group need to be locked.
 */
 struct res_shares {
+	/* shares only set by userspace */
+	int min_shares; /* minimun fraction of parent's resources allowed */
+	int max_shares; /* maximum fraction of parent's resources allowed */
+	int child_shares_divisor; /* >= 1, may not be DONT_CARE */
+
+	/*
+	 * share values invisible to userspace.  adjusted when userspace
+	 * sets shares
+	 */
+	int unused_min_shares;
+		/* 0 <= unused_min_shares <= (child_shares_divisor -
+		 * 			Sum of min_shares of children)
+		 */
+	int cur_max_shares; /* max(children's max_shares). need better name */
 };
 
 /*
Index: linux-2617-rc3/kernel/res_group/shares.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/kernel/res_group/shares.c	2006-04-27 09:22:07.000000000 -0700
@@ -0,0 +1,242 @@
+/*
+ * shares.c - Share management functions for Resource Groups
+ *
+ * Copyright (C) Chandra Seetharaman,  IBM Corp. 2003, 2004, 2005, 2006
+ *		(C) Hubertus Franke,  IBM Corp. 2004
+ *		(C) Matt Helsley,  IBM Corp. 2006
+ *
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/errno.h>
+#include <linux/res_group_rc.h>
+
+/*
+ * Share values can be quantitative (quantity of memory for instance) or
+ * symbolic. The symbolic value DONT_CARE allows for any quantity of a resource
+ * to be substituted in its place. The symbolic value UNCHANGED is only used
+ * when setting share values and means that the old value should be used.
+ */
+
+/* Is the share a quantity (as opposed to "symbols" DONT_CARE or UNCHANGED) */
+static inline int is_share_quantitative(int share)
+{
+	return (share >= 0);
+}
+
+static inline int is_share_symbolic(int share)
+{
+	return !is_share_quantitative(share);
+}
+
+static inline int is_share_valid(int share)
+{
+	return ((share == SHARE_DONT_CARE) ||
+			(share == SHARE_UNSUPPORTED) ||
+			is_share_quantitative(share));
+}
+
+static inline int did_share_change(int share)
+{
+	return (share != SHARE_UNCHANGED);
+}
+
+static inline int change_supported(int share)
+{
+	return (share != SHARE_UNSUPPORTED);
+}
+
+/*
+ * Caller is responsible for protecting 'parent'
+ * Caller is responsible for making sure that the sum of sibling min_shares
+ * doesn't exceed parent's total min_shares.
+ */
+static inline void child_min_shares_changed(struct res_shares *parent,
+				   int child_cur_min_shares,
+				   int child_new_min_shares)
+{
+	if (is_share_quantitative(child_new_min_shares))
+		parent->unused_min_shares -= child_new_min_shares;
+	if (is_share_quantitative(child_cur_min_shares))
+		parent->unused_min_shares += child_cur_min_shares;
+}
+
+/*
+ * Set parent's cur_max_shares to the largest 'max_shares' of all
+ * of its children.
+ */
+static inline void set_cur_max_shares(struct resource_group *parent,
+					struct res_controller *ctlr)
+{
+	int max_shares = 0;
+	struct resource_group *child = NULL;
+	struct res_shares *child_shares, *parent_shares;
+
+	for_each_child(child, parent) {
+		child_shares = get_controller_shares(child, ctlr);
+		max_shares = max(max_shares, child_shares->max_shares);
+	}
+
+	parent_shares = get_controller_shares(parent, ctlr);
+	parent_shares->cur_max_shares = max_shares;
+}
+
+/*
+ * Return -EINVAL if the child's shares violate self-consistency or
+ * parent-imposed restrictions. Otherwise return 0.
+ *
+ * This involves checking shares between the child and its parent;
+ * the child and itself (userspace can't be trusted).
+ */
+static inline int are_shares_valid(struct res_shares *child,
+				   struct res_shares *parent,
+				   int current_usage,
+				   int min_shares_increase)
+{
+	/*
+	 * CHILD <-> PARENT validation
+	 * Increases in child's min_shares or max_shares can't exceed
+	 * limitations imposed by the parent resource group.
+	 * Only validate this if we have a parent.
+	 */
+	if (parent &&
+	    ((is_share_quantitative(child->min_shares) &&
+	      (min_shares_increase > parent->unused_min_shares)) ||
+	     (is_share_quantitative(child->max_shares) &&
+	      (child->max_shares > parent->child_shares_divisor))))
+		return -EINVAL;
+
+	/* CHILD validation: is min valid */
+	if (!is_share_valid(child->min_shares))
+		return -EINVAL;
+
+	/* CHILD validation: is max valid */
+	if (!is_share_valid(child->max_shares))
+		return -EINVAL;
+
+	/*
+	 * CHILD validation: is divisor quantitative & current_usage
+	 * is not more than the new divisor
+	 */
+	if (!is_share_quantitative(child->child_shares_divisor) ||
+			(current_usage > child->child_shares_divisor))
+		return -EINVAL;
+
+	/*
+	 * CHILD validation: is the new child_shares_divisor large
+	 * enough to accomodate largest max_shares of any of my child
+	 */
+	if (child->child_shares_divisor < child->cur_max_shares)
+		return -EINVAL;
+
+	/* CHILD validation: min <= max */
+	if (is_share_quantitative(child->min_shares) &&
+			is_share_quantitative(child->max_shares) &&
+			(child->min_shares > child->max_shares))
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Set the resource shares of a child resource group given the new shares
+ * specified by userspace, the child's current shares, and the parent
+ * resource group's shares.
+ *
+ * Caller is responsible for holding group_lock of child and parent
+ * resource groups to protect the shares structures passed to this function.
+ */
+static int set_shares(const struct res_shares *new,
+		    struct res_shares *child_shares,
+    		    struct res_shares *parent_shares)
+{
+	int rc, current_usage, min_shares_increase;
+	struct res_shares final_shares;
+
+	BUG_ON(!new || !child_shares);
+
+	final_shares = *child_shares;
+	if (did_share_change(new->child_shares_divisor) &&
+			change_supported(child_shares->child_shares_divisor))
+		final_shares.child_shares_divisor = new->child_shares_divisor;
+	if (did_share_change(new->min_shares) &&
+			change_supported(child_shares->min_shares))
+		final_shares.min_shares = new->min_shares;
+	if (did_share_change(new->max_shares) &&
+			change_supported(child_shares->max_shares))
+		final_shares.max_shares = new->max_shares;
+
+	current_usage = child_shares->child_shares_divisor -
+	    		 child_shares->unused_min_shares;
+	min_shares_increase = final_shares.min_shares;
+	if (is_share_quantitative(child_shares->min_shares))
+		min_shares_increase -= child_shares->min_shares;
+
+	rc = are_shares_valid(&final_shares, parent_shares, current_usage,
+   			      min_shares_increase);
+	if (rc)
+		return rc; /* new shares would violate restrictions */
+
+	if (did_share_change(new->child_shares_divisor))
+		final_shares.unused_min_shares =
+			(final_shares.child_shares_divisor - current_usage);
+	*child_shares = final_shares;
+	return 0;
+}
+
+int set_controller_shares(struct resource_group *rgroup,
+					struct res_controller *ctlr,
+					const struct res_shares *new_shares)
+{
+	struct res_shares *shares, *parent_shares;
+	int prev_min, prev_max, rc;
+
+	if (!ctlr->shares_changed)
+		return -EINVAL;
+
+	shares = get_controller_shares(rgroup, ctlr);
+	if (!shares)
+		return -EINVAL;
+
+	prev_min = shares->min_shares;
+	prev_max = shares->max_shares;
+
+	if (!is_res_group_root(rgroup))
+		spin_lock(&rgroup->parent->group_lock);
+	spin_lock(&rgroup->group_lock);
+	parent_shares = get_controller_shares(rgroup->parent, ctlr);
+	rc = set_shares(new_shares, shares, parent_shares);
+	spin_unlock(&rgroup->group_lock);
+
+	if (rc || is_res_group_root(rgroup))
+		goto done;
+
+	/* Notify parent about changes in my shares */
+	child_min_shares_changed(parent_shares, prev_min,
+				      shares->min_shares);
+	if (prev_max != shares->max_shares)
+		set_cur_max_shares(rgroup->parent, ctlr);
+
+done:
+	if (!is_res_group_root(rgroup))
+		spin_unlock(&rgroup->parent->group_lock);
+	if (!rc)
+		ctlr->shares_changed(shares);
+	return rc;
+}
+
+void set_shares_to_default(struct resource_group *rgroup,
+						struct res_controller *ctlr)
+{
+	struct res_shares shares = {
+		.min_shares = SHARE_DONT_CARE,
+		.max_shares = SHARE_DONT_CARE,
+		.child_shares_divisor = SHARE_DEFAULT_DIVISOR,
+	};
+	set_controller_shares(rgroup, ctlr, &shares);
+}
+
Index: linux-2617-rc3/kernel/res_group/Makefile
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/Makefile	2006-04-27 09:21:42.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/Makefile	2006-04-27 09:22:07.000000000 -0700
@@ -1 +1 @@
-obj-y = res_group.o
+obj-y = res_group.o shares.o
Index: linux-2617-rc3/kernel/res_group/res_group.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/res_group.c	2006-04-27 09:22:04.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/res_group.c	2006-04-27 09:22:07.000000000 -0700
@@ -173,6 +173,8 @@ static void do_free_shares_struct(struct
 	if (shares == NULL)
 		return;
 
+	set_shares_to_default(rgroup, ctlr);
+
 	spin_lock(&rgroup->group_lock);
 	rgroup->shares[ctlr->ctlr_id] = NULL;
 	spin_unlock(&rgroup->group_lock);
@@ -345,6 +347,26 @@ int unregister_controller(struct res_con
 	return remove_controller(ctlr);
 }
 
+/*
+ * Bring the state of Resource Groups to the initial state. Only shares
+ * of the default resource group need to be changed to default values.
+ * At this point no user-defined resource groups should exist.
+ */
+void res_group_teardown(void)
+{
+	int i;
+	struct res_controller *ctlr;
+
+	BUG_ON(num_res_groups != 0);
+	for (i = 0; i < MAX_RES_CTLRS; i++) {
+		ctlr = get_controller_by_id(i);
+		if (ctlr) {
+			set_shares_to_default(&default_res_group, ctlr);
+			put_controller(ctlr);
+		}
+	}
+}
+
 EXPORT_SYMBOL_GPL(register_controller);
 EXPORT_SYMBOL_GPL(unregister_controller);
 EXPORT_SYMBOL_GPL(get_controller_by_name);
@@ -353,3 +375,5 @@ EXPORT_SYMBOL_GPL(put_controller);
 EXPORT_SYMBOL_GPL(alloc_res_group);
 EXPORT_SYMBOL_GPL(free_res_group);
 EXPORT_SYMBOL_GPL(default_res_group);
+EXPORT_SYMBOL_GPL(set_controller_shares);
+EXPORT_SYMBOL_GPL(res_group_teardown);
Index: linux-2617-rc3/include/linux/res_group_rc.h
===================================================================
--- linux-2617-rc3.orig/include/linux/res_group_rc.h	2006-04-27 09:22:04.000000000 -0700
+++ linux-2617-rc3/include/linux/res_group_rc.h	2006-04-27 09:22:07.000000000 -0700
@@ -74,4 +74,14 @@ static inline int is_res_group_root(cons
 #define for_each_child(child, parent)	\
 	list_for_each_entry(child, &parent->children, siblings)
 
+/* Get controller specific shares structure for the given resource group */
+static inline struct res_shares *get_controller_shares(
+		struct resource_group *rgroup, struct res_controller *ctlr)
+{
+	if (rgroup && ctlr)
+		return rgroup->shares[ctlr->ctlr_id];
+	else
+		return NO_SHARE;
+}
+
 #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:22:04.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/local.h	2006-04-27 09:22:07.000000000 -0700
@@ -12,3 +12,9 @@ extern struct resource_group *alloc_res_
 							const char *);
 extern int free_res_group(struct resource_group *);
 extern void release_res_group(struct kref *);
+extern int set_controller_shares(struct resource_group *,
+			struct res_controller *, const struct res_shares *);
+/* Set shares for the given resource group and resource to default values */
+extern void set_shares_to_default(struct resource_group *,
+						struct res_controller *);
+extern void res_group_teardown(void);

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 04/12] Add task logic to resource groups
  2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
                   ` (2 preceding siblings ...)
  2006-04-28  1:34 ` [PATCH 03/12] Share Handling Chandra Seetharaman
@ 2006-04-28  1:34 ` Chandra Seetharaman
  2006-04-28  1:34 ` [PATCH 05/12] Init and clear resource group info in task Chandra Seetharaman
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:34 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

04/12 - tasksupport

Adds logic to support adding/removing task to/from a resource group
Provides interface to set a task's resource group.
--

Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>

 include/linux/sched.h        |    4 +
 kernel/res_group/Makefile    |    2 
 kernel/res_group/local.h     |    1 
 kernel/res_group/res_group.c |   25 +++++++
 kernel/res_group/task.c      |  145 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 176 insertions(+), 1 deletion(-)

Index: linux-2617-rc3/include/linux/sched.h
===================================================================
--- linux-2617-rc3.orig/include/linux/sched.h	2006-04-27 09:22:14.000000000 -0700
+++ linux-2617-rc3/include/linux/sched.h	2006-04-27 09:22:16.000000000 -0700
@@ -888,6 +888,10 @@ struct task_struct {
 	 * cache last used pipe for splice
 	 */
 	struct pipe_inode_info *splice_pipe;
+#ifdef CONFIG_RES_GROUPS
+	struct resource_group *res_group;
+	struct list_head member_list; /* list of tasks in the resource group */
+#endif /* CONFIG_RES_GROUPS */
 };
 
 static inline pid_t process_group(struct task_struct *tsk)
Index: linux-2617-rc3/kernel/res_group/task.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/kernel/res_group/task.c	2006-04-27 09:22:16.000000000 -0700
@@ -0,0 +1,145 @@
+/* task.c - Resource Groups
+ *
+ * Copyright (C) Hubertus Franke, IBM Corp. 2003,2004
+ *		(C) Shailabh Nagar,  IBM Corp. 2003
+ *		(C) Chandra Seetharaman,  IBM Corp. 2003, 2004, 2005
+ *		(C) Vivek Kashyap,	IBM Corp. 2004
+ *
+ * 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/sched.h>
+#include <linux/module.h>
+#include "local.h"
+
+static inline struct resource_group
+			*remove_from_old_rgroup(struct task_struct *tsk)
+{
+	struct resource_group *rgroup;
+
+retry:
+	rgroup = tsk->res_group;
+	if (rgroup == NO_RES_GROUP)
+		goto done;
+
+	spin_lock(&rgroup->group_lock);
+	if (rgroup != tsk->res_group) { /* lost the race, retry */
+		spin_unlock(&rgroup->group_lock);
+		goto retry;
+	}
+	/* take out of old resource group */
+	list_del_init(&tsk->member_list);
+	tsk->res_group = NO_RES_GROUP;
+	spin_unlock(&rgroup->group_lock);
+done:
+	return rgroup;
+}
+
+static void move_to_new_rgroup(struct task_struct *tsk,
+				struct resource_group *new_rgroup)
+{
+	BUG_ON(!list_empty(&tsk->member_list));
+	BUG_ON(tsk->res_group != NO_RES_GROUP);
+
+	spin_lock(&new_rgroup->group_lock);
+	tsk->res_group = new_rgroup;
+	list_add(&tsk->member_list, &new_rgroup->task_list);
+	spin_unlock(&new_rgroup->group_lock);
+}
+
+static void notify_res_ctlrs(struct task_struct *tsk,
+	struct resource_group *old_rgroup, struct resource_group *new_rgroup)
+{
+	int i;
+	struct res_controller *ctlr;
+	struct res_shares *old_shares, *new_shares;
+
+	for (i = 0; i < MAX_RES_CTLRS; i++) {
+		ctlr = get_controller_by_id(i);
+		if (ctlr == NULL)
+			continue;
+		if (ctlr->move_task) {
+			old_shares = get_controller_shares(old_rgroup, ctlr);
+			new_shares = get_controller_shares(new_rgroup, ctlr);
+			ctlr->move_task(tsk, old_shares, new_shares);
+		}
+		put_controller(ctlr);
+	}
+}
+
+/*
+ * Change the resource group of the given task to "new_rgroup"
+ *
+ * Caller is responsible to make sure the task structure stays put
+ * through this function.
+ *
+ * This function should be called without holding group_lock of
+ * new_rgroup and tsk->res_group.
+ *
+ * Called with a reference to the new resource group held. The reference is
+ * dropped only when the task is assigned to a different resource group
+ * or when the task exits.
+ */
+static void __set_res_group(struct task_struct *tsk,
+				struct resource_group *new_rgroup)
+{
+	struct resource_group *old_rgroup;
+
+retry:
+	old_rgroup = remove_from_old_rgroup(tsk);
+
+	/* task is exiting or is moving to a different resource group. */
+	if (old_rgroup == NO_RES_GROUP) {
+		/* In the exit path, must succeed */
+		if (new_rgroup == NO_RES_GROUP)
+			goto retry;
+		kref_put(&new_rgroup->ref, release_res_group);
+		return;
+	}
+
+	/*
+	 * notify resource controllers before we actually set the resource
+	 * group in the task to avoid a race with notify_res_ctlrs being
+	 * called from another __set_res_group.
+	 */
+	notify_res_ctlrs(tsk, old_rgroup, new_rgroup);
+	if (new_rgroup != NO_RES_GROUP)
+		move_to_new_rgroup(tsk, new_rgroup);
+	kref_put(&old_rgroup->ref, release_res_group);
+}
+
+/*
+ * Set resource group of the task associated with pid to rgroup.
+ * returns 0 on success, -errno on error.
+ */
+int set_res_group(pid_t pid, struct resource_group *rgroup)
+{
+	int rc = 0;
+	struct task_struct *tsk;
+
+	read_lock(&tasklist_lock);
+	tsk = find_task_by_pid(pid);
+	if (tsk == NULL) {
+		read_unlock(&tasklist_lock);
+		return -ESRCH; /* pid not found */
+	}
+	get_task_struct(tsk);
+	read_unlock(&tasklist_lock);
+
+	/* Check permissions */
+	if ((!capable(CAP_SYS_NICE)) &&
+		(!capable(CAP_SYS_RESOURCE)) && (current->user != tsk->user))
+		rc = -EPERM;
+	else {
+		kref_get(&rgroup->ref);
+		__set_res_group(tsk, rgroup);
+	}
+	put_task_struct(tsk);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(set_res_group);
Index: linux-2617-rc3/kernel/res_group/Makefile
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/Makefile	2006-04-27 09:22:14.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/Makefile	2006-04-27 09:22:16.000000000 -0700
@@ -1 +1 @@
-obj-y = res_group.o shares.o
+obj-y = res_group.o shares.o task.o
Index: linux-2617-rc3/kernel/res_group/res_group.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/res_group.c	2006-04-27 09:22:14.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/res_group.c	2006-04-27 09:22:16.000000000 -0700
@@ -251,6 +251,27 @@ static int add_controller(struct res_con
 	return ret;
 }
 /*
+ * Helper function to move all tasks in a resource group to/from the
+ * registering/unregistering resource controller.
+ *
+ * Assumes ctlr is valid and rgroup is initialized with resource
+ * controller's shares.
+ */
+static void move_tasks(struct resource_group *rgroup,
+		struct res_controller *ctlr,
+		struct res_shares *from, struct res_shares *to)
+{
+	struct task_struct *tsk;
+
+	if (!ctlr->move_task)
+		return;
+	spin_lock(&rgroup->group_lock);
+	list_for_each_entry(tsk, &rgroup->task_list, member_list)
+		ctlr->move_task(tsk, from, to);
+	spin_unlock(&rgroup->group_lock);
+}
+
+/*
  * Interface for registering a resource controller.
  *
  * Returns the 0 on success, -errno for failure.
@@ -287,6 +308,8 @@ int register_controller(struct res_contr
 		kref_get(&rgroup->ref);
 		read_unlock(&res_group_lock);
   		do_alloc_shares_struct(rgroup, ctlr);
+		move_tasks(rgroup, ctlr, NO_SHARE,
+					rgroup->shares[ctlr->ctlr_id]);
 		if (prev_rgroup)
 			kref_put(&prev_rgroup->ref, release_res_group);
 		prev_rgroup = rgroup;
@@ -333,6 +356,8 @@ int unregister_controller(struct res_con
 	list_for_each_entry_reverse(rgroup, &res_groups, group_list) {
 		kref_get(&rgroup->ref);
 		read_unlock(&res_group_lock);
+		move_tasks(rgroup, ctlr, rgroup->shares[ctlr->ctlr_id],
+								NO_SHARE);
   		do_free_shares_struct(rgroup, ctlr);
 		if (prev_rgroup)
 			kref_put(&prev_rgroup->ref, release_res_group);
Index: linux-2617-rc3/kernel/res_group/local.h
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/local.h	2006-04-27 09:22:14.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/local.h	2006-04-27 09:22:16.000000000 -0700
@@ -18,3 +18,4 @@ extern int set_controller_shares(struct 
 extern void set_shares_to_default(struct resource_group *,
 						struct res_controller *);
 extern void res_group_teardown(void);
+extern int set_res_group(pid_t, struct resource_group *);

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 05/12] Init and clear resource group info in task
  2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
                   ` (3 preceding siblings ...)
  2006-04-28  1:34 ` [PATCH 04/12] Add task logic to resource groups Chandra Seetharaman
@ 2006-04-28  1:34 ` Chandra Seetharaman
  2006-04-28  1:34 ` [PATCH 06/12] Add proc interface to get resource group info of task Chandra Seetharaman
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:34 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

05/12 - tasksupport_fork_exit_init

Initializes and clears Resource Group specific information in a task at 
fork() and exit().
Inititalizes Resource Groups (called from start_kernel)
--

Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>

 include/linux/res_group.h    |    7 +++++
 init/main.c                  |    2 +
 kernel/exit.c                |    2 +
 kernel/fork.c                |    2 +
 kernel/res_group/local.h     |    1 
 kernel/res_group/res_group.c |   11 +++++++++
 kernel/res_group/task.c      |   52 +++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 77 insertions(+)

Index: linux-2617-rc3/kernel/exit.c
===================================================================
--- linux-2617-rc3.orig/kernel/exit.c	2006-04-27 09:18:03.000000000 -0700
+++ linux-2617-rc3/kernel/exit.c	2006-04-27 09:22:20.000000000 -0700
@@ -35,6 +35,7 @@
 #include <linux/futex.h>
 #include <linux/compat.h>
 #include <linux/pipe_fs_i.h>
+#include <linux/res_group.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -731,6 +732,7 @@ static void exit_notify(struct task_stru
 	struct task_struct *t;
 	struct list_head ptrace_dead, *_p, *_n;
 
+	clear_task_res_group(tsk);
 	if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT)
 	    && !thread_group_empty(tsk)) {
 		/*
Index: linux-2617-rc3/kernel/fork.c
===================================================================
--- linux-2617-rc3.orig/kernel/fork.c	2006-04-27 09:18:03.000000000 -0700
+++ linux-2617-rc3/kernel/fork.c	2006-04-27 09:22:20.000000000 -0700
@@ -44,6 +44,7 @@
 #include <linux/rmap.h>
 #include <linux/acct.h>
 #include <linux/cn_proc.h>
+#include <linux/res_group.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -1215,6 +1216,7 @@ static task_t *copy_process(unsigned lon
 	total_forks++;
 	spin_unlock(&current->sighand->siglock);
 	write_unlock_irq(&tasklist_lock);
+	init_task_res_group(p);
 	proc_fork_connector(p);
 	return p;
 
Index: linux-2617-rc3/init/main.c
===================================================================
--- linux-2617-rc3.orig/init/main.c	2006-04-27 09:18:03.000000000 -0700
+++ linux-2617-rc3/init/main.c	2006-04-27 09:22:20.000000000 -0700
@@ -47,6 +47,7 @@
 #include <linux/rmap.h>
 #include <linux/mempolicy.h>
 #include <linux/key.h>
+#include <linux/res_group.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -541,6 +542,7 @@ asmlinkage void __init start_kernel(void
 	proc_root_init();
 #endif
 	cpuset_init();
+	res_group_init();
 
 	check_bugs();
 
Index: linux-2617-rc3/kernel/res_group/res_group.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/res_group.c	2006-04-27 09:22:16.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/res_group.c	2006-04-27 09:22:20.000000000 -0700
@@ -231,6 +231,7 @@ int free_res_group(struct resource_group
 		return -EBUSY;
 	}
 	spin_unlock(&rgroup->group_lock);
+	move_tasks_to_parent(rgroup);
 	kref_put(&rgroup->ref, release_res_group);
 	return 0;
 }
@@ -392,6 +393,16 @@ void res_group_teardown(void)
 	}
 }
 
+void res_group_init(void)
+{
+	write_lock(&res_group_lock);
+	list_add_tail(&default_res_group.group_list, &res_groups);
+	write_unlock(&res_group_lock);
+	kref_init(&default_res_group.ref);
+	init_task.res_group = &default_res_group;
+	init_task_res_group(&init_task);
+}
+
 EXPORT_SYMBOL_GPL(register_controller);
 EXPORT_SYMBOL_GPL(unregister_controller);
 EXPORT_SYMBOL_GPL(get_controller_by_name);
Index: linux-2617-rc3/kernel/res_group/task.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/task.c	2006-04-27 09:22:16.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/task.c	2006-04-27 09:22:20.000000000 -0700
@@ -142,4 +142,56 @@ int set_res_group(pid_t pid, struct reso
 	put_task_struct(tsk);
 	return rc;
 }
+
+void init_task_res_group(struct task_struct *tsk)
+{
+	struct resource_group *rgroup;
+
+	/*
+	 * processes inherit their resource group from their real parent and
+	 * threads inherit resource group from their process.
+	 */
+	if (thread_group_leader(tsk))
+		rgroup = tsk->real_parent->res_group;
+	else
+		rgroup = tsk->group_leader->res_group;
+
+	tsk->res_group = NO_RES_GROUP;
+	INIT_LIST_HEAD(&tsk->member_list);
+
+	BUG_ON(rgroup == NULL);
+	kref_get(&rgroup->ref);
+	move_to_new_rgroup(tsk, rgroup);
+	notify_res_ctlrs(tsk, NO_RES_GROUP, rgroup);
+}
+
+void clear_task_res_group(struct task_struct *tsk)
+{
+	__set_res_group(tsk, NO_RES_GROUP);
+}
+
+/*
+ * Move all tasks in the given resource group to its parent.
+ */
+void move_tasks_to_parent(struct resource_group *rgroup)
+{
+	kref_get(&rgroup->ref);
+
+next_task:
+	spin_lock(&rgroup->group_lock);
+	if (!list_empty(&rgroup->task_list)) {
+		struct task_struct *tsk =
+			list_entry(rgroup->task_list.next,
+				struct task_struct, member_list);
+		get_task_struct(tsk);
+		spin_unlock(&rgroup->group_lock);
+		kref_get(&rgroup->parent->ref);
+		__set_res_group(tsk, rgroup->parent);
+		put_task_struct(tsk);
+		goto next_task;
+	}
+	spin_unlock(&rgroup->group_lock);
+	kref_put(&rgroup->ref, release_res_group);
+}
+
 EXPORT_SYMBOL_GPL(set_res_group);
Index: linux-2617-rc3/include/linux/res_group.h
===================================================================
--- linux-2617-rc3.orig/include/linux/res_group.h	2006-04-27 09:22:07.000000000 -0700
+++ linux-2617-rc3/include/linux/res_group.h	2006-04-27 09:22:20.000000000 -0700
@@ -94,5 +94,12 @@ struct resource_group {
 	struct list_head children;	/* head of children */
 };
 
+extern void init_task_res_group(struct task_struct *);
+extern void clear_task_res_group(struct task_struct *);
+extern void res_group_init(void);
+#else /* CONFIG_RES_GROUPS */
+static inline void init_task_res_group(struct task_struct *tsk) { }
+static inline void clear_task_res_group(struct task_struct *tsk) { }
+static inline void res_group_init(void) { }
 #endif /* CONFIG_RES_GROUPS */
 #endif /* _LINUX_RES_GROUP_H */
Index: linux-2617-rc3/kernel/res_group/local.h
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/local.h	2006-04-27 09:22:16.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/local.h	2006-04-27 09:22:20.000000000 -0700
@@ -19,3 +19,4 @@ extern void set_shares_to_default(struct
 						struct res_controller *);
 extern void res_group_teardown(void);
 extern int set_res_group(pid_t, struct resource_group *);
+extern void move_tasks_to_parent(struct resource_group *);

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 06/12] Add proc interface to get resource group info of task
  2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
                   ` (4 preceding siblings ...)
  2006-04-28  1:34 ` [PATCH 05/12] Init and clear resource group info in task Chandra Seetharaman
@ 2006-04-28  1:34 ` Chandra Seetharaman
  2006-04-28  1:34 ` [PATCH 07/12] Resource Groups Configfs Subsystem (RGCS) Chandra Seetharaman
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:34 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

06/12: task_procsupport

Adds an interface in /proc to get the name of a resource group to which
a task is attached.
--

Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-off-by: MAEDA Naoaki <maeda.naoaki@jp.fujitsu.com>

 fs/proc/base.c            |   19 +++++++++++++++++++
 include/linux/res_group.h |    2 ++
 kernel/res_group/task.c   |   32 +++++++++++++++++++++++++++++++-
 3 files changed, 52 insertions(+), 1 deletion(-)

Index: linux-2617-rc3/fs/proc/base.c
===================================================================
--- linux-2617-rc3.orig/fs/proc/base.c	2006-04-27 09:18:03.000000000 -0700
+++ linux-2617-rc3/fs/proc/base.c	2006-04-27 09:22:27.000000000 -0700
@@ -70,6 +70,7 @@
 #include <linux/ptrace.h>
 #include <linux/seccomp.h>
 #include <linux/cpuset.h>
+#include <linux/res_group.h>
 #include <linux/audit.h>
 #include <linux/poll.h>
 #include "internal.h"
@@ -115,6 +116,9 @@ enum pid_directory_inos {
 #ifdef CONFIG_CPUSETS
 	PROC_TGID_CPUSET,
 #endif
+#ifdef CONFIG_RES_GROUPS
+	PROC_TGID_RES_GROUP,
+#endif
 #ifdef CONFIG_SECURITY
 	PROC_TGID_ATTR,
 	PROC_TGID_ATTR_CURRENT,
@@ -156,6 +160,9 @@ enum pid_directory_inos {
 #ifdef CONFIG_CPUSETS
 	PROC_TID_CPUSET,
 #endif
+#ifdef CONFIG_RES_GROUPS
+	PROC_TID_RES_GROUP,
+#endif
 #ifdef CONFIG_SECURITY
 	PROC_TID_ATTR,
 	PROC_TID_ATTR_CURRENT,
@@ -219,6 +226,9 @@ static struct pid_entry tgid_base_stuff[
 #ifdef CONFIG_CPUSETS
 	E(PROC_TGID_CPUSET,    "cpuset",  S_IFREG|S_IRUGO),
 #endif
+#ifdef CONFIG_RES_GROUPS
+	E(PROC_TGID_RES_GROUP,"res_group",S_IFREG|S_IRUGO),
+#endif
 	E(PROC_TGID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
 	E(PROC_TGID_OOM_ADJUST,"oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
 #ifdef CONFIG_AUDITSYSCALL
@@ -261,6 +271,9 @@ static struct pid_entry tid_base_stuff[]
 #ifdef CONFIG_CPUSETS
 	E(PROC_TID_CPUSET,     "cpuset",  S_IFREG|S_IRUGO),
 #endif
+#ifdef CONFIG_RES_GROUPS
+	E(PROC_TID_RES_GROUP, "res_group",S_IFREG|S_IRUGO),
+#endif
 	E(PROC_TID_OOM_SCORE,  "oom_score",S_IFREG|S_IRUGO),
 	E(PROC_TID_OOM_ADJUST, "oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
 #ifdef CONFIG_AUDITSYSCALL
@@ -1823,6 +1836,12 @@ static struct dentry *proc_pident_lookup
 			inode->i_fop = &proc_cpuset_operations;
 			break;
 #endif
+#ifdef CONFIG_RES_GROUPS
+		case PROC_TID_RES_GROUP:
+		case PROC_TGID_RES_GROUP:
+			inode->i_fop = &proc_res_group_operations;
+			break;
+#endif
 		case PROC_TID_OOM_SCORE:
 		case PROC_TGID_OOM_SCORE:
 			inode->i_fop = &proc_info_file_operations;
Index: linux-2617-rc3/kernel/res_group/task.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/task.c	2006-04-27 09:22:20.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/task.c	2006-04-27 09:22:27.000000000 -0700
@@ -13,7 +13,8 @@
  * (at your option) any later version.
  *
  */
-#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
 #include <linux/module.h>
 #include "local.h"
 
@@ -194,4 +195,33 @@ next_task:
 	kref_put(&rgroup->ref, release_res_group);
 }
 
+static int proc_res_group_show(struct seq_file *m, void *v)
+{
+	struct task_struct *tsk = m->private;
+	struct resource_group *rgroup = tsk->res_group;
+
+	if (!rgroup)
+		return -EINVAL;
+
+	kref_get(&rgroup->ref);
+	seq_puts(m, "/");
+	if (!is_res_group_root(rgroup))
+		seq_puts(m, rgroup->name);
+	seq_putc(m, '\n');
+	kref_put(&rgroup->ref, release_res_group);
+	return 0;
+}
+
+static int res_group_open(struct inode *inode, struct file *file)
+{
+	struct task_struct *tsk = PROC_I(inode)->task;
+	return single_open(file, proc_res_group_show, tsk);
+}
+
+struct file_operations proc_res_group_operations = {
+	.open		= res_group_open,
+	.read		= seq_read,
+	.llseek 	= seq_lseek,
+	.release	= single_release,
+};
 EXPORT_SYMBOL_GPL(set_res_group);
Index: linux-2617-rc3/include/linux/res_group.h
===================================================================
--- linux-2617-rc3.orig/include/linux/res_group.h	2006-04-27 09:22:20.000000000 -0700
+++ linux-2617-rc3/include/linux/res_group.h	2006-04-27 09:22:27.000000000 -0700
@@ -94,6 +94,8 @@ struct resource_group {
 	struct list_head children;	/* head of children */
 };
 
+extern struct file_operations proc_res_group_operations;
+
 extern void init_task_res_group(struct task_struct *);
 extern void clear_task_res_group(struct task_struct *);
 extern void res_group_init(void);

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 07/12] Resource Groups Configfs Subsystem (RGCS)
  2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
                   ` (5 preceding siblings ...)
  2006-04-28  1:34 ` [PATCH 06/12] Add proc interface to get resource group info of task Chandra Seetharaman
@ 2006-04-28  1:34 ` Chandra Seetharaman
  2006-04-28  1:34 ` [PATCH 08/12] Add attribute support to RGCS Chandra Seetharaman
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:34 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

07/12 - user_interface

Create the configfs component for managing Resource groups. Hooks up with
configfs. Provides functions for creating and deleting resource groups.
--

Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Shailabh Nagar <nagar@watson.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>

 init/Kconfig              |   12 +++
 kernel/res_group/Makefile |    1 
 kernel/res_group/rgcs.c   |  162 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+)

Index: linux-2617-rc3/init/Kconfig
===================================================================
--- linux-2617-rc3.orig/init/Kconfig	2006-04-27 09:20:59.000000000 -0700
+++ linux-2617-rc3/init/Kconfig	2006-04-27 10:17:11.000000000 -0700
@@ -163,6 +163,18 @@ config RES_GROUPS
 	  If you say Y here, enable the Resource Group File System and at least
 	  one of the resource controllers below. Say N if you are unsure.
 
+config RGCS
+	tristate "Resource Groups Configfs Subsystem"
+	depends on RES_GROUPS
+	select CONFIGFS_FS
+	default m
+	help
+	  RGCS is the User Interface for Resource Groups. Compiling it as
+	  a module permits users to only load RGCS if they intend to use it.
+
+	  Say M if unsure, Y to save on module loading. N doesn't make sense
+	  when Resource Groups has been configured.
+
 endmenu
 config SYSCTL
 	bool "Sysctl support"
Index: linux-2617-rc3/kernel/res_group/rgcs.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/kernel/res_group/rgcs.c	2006-04-27 10:18:39.000000000 -0700
@@ -0,0 +1,162 @@
+/*
+ * kernel/res_group/rgcs.c
+ *
+ * Copyright (C) Shailabh Nagar,  IBM Corp. 2005
+ *               Chandra Seetharaman,   IBM Corp. 2005, 2006
+ *
+ * Resource Group Configfs Subsystem (rgcs) provides the user interface
+ * for Resource groups.
+ *
+ * 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 version 2 of the  GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/configfs.h>
+#include "local.h"
+
+static struct configfs_subsystem rgcs_subsys;
+static struct config_item_type rgcs_item_type;
+
+struct rgcs_rgroup {
+	char *name;
+	struct resource_group *core;
+	struct config_group group;
+};
+
+static inline struct rgcs_rgroup *group_to_rgcs_rgroup(struct config_group *grp)
+{
+	return container_of(grp, struct rgcs_rgroup, group);
+}
+
+static inline struct rgcs_rgroup *item_to_rgcs_rgroup(struct config_item *item)
+{
+	return group_to_rgcs_rgroup(to_config_group(item));
+}
+
+static inline struct resource_group *group_to_res_group(
+					struct config_group *grp)
+{
+	struct rgcs_rgroup *rgroup;
+	/*
+	 * A configfs wrinkle forces us to treat the root group as a special
+	 * case instead of wrapping the group in a struct rgcs_rgroup like all
+	 * other groups.
+	 */
+	if (grp == &rgcs_subsys.su_group)
+		return &default_res_group;
+	rgroup = group_to_rgcs_rgroup(grp);
+	return rgroup->core;
+}
+
+static inline struct resource_group *item_to_res_group(
+					struct config_item *item)
+{
+	return group_to_res_group(to_config_group(item));
+}
+
+/*
+ * This is the function that is called when a 'mkdir' command
+ * is issued under our filesystem
+ */
+static struct config_group *make_rgcs_rgroup(struct config_group *group,
+					const char *name)
+{
+	struct rgcs_rgroup *rgroup, *rc_par;
+	struct resource_group *core, *parent;
+	char *new_name = NULL, *par_name = NULL;
+	int par_sz = 0;
+
+	rgroup = kzalloc(sizeof(struct rgcs_rgroup), GFP_KERNEL);
+	if (!rgroup)
+		return NULL;
+
+	parent = group_to_res_group(group);
+
+	if (parent != &default_res_group) {
+		rc_par = group_to_rgcs_rgroup(group);
+		par_name = rc_par->name;
+		par_sz = strlen(par_name);
+	}
+	new_name = kmalloc(par_sz + strlen(name) + 2, GFP_KERNEL);
+	if (!new_name)
+		goto noname;
+	if (par_name)
+		sprintf(new_name, "%s/%s", par_name, name);
+	else
+		sprintf(new_name, "%s", name);
+
+	core = alloc_res_group(parent, new_name);
+	if (!core)
+		goto nocore;
+	rgroup->core = core;
+	rgroup->name = new_name;
+
+	config_group_init_type_name(&rgroup->group, name, &rgcs_item_type);
+	return &rgroup->group;
+
+nocore:
+	kfree(new_name);
+noname:
+	kfree(rgroup);
+	return NULL;
+}
+
+/*
+ * This is the function that is called when a 'rmdir' command
+ * is issued under our filesystem
+ */
+static void rgcs_rgroup_release_item(struct config_item *item)
+{
+	struct rgcs_rgroup *rgroup = item_to_rgcs_rgroup(item);
+
+	free_res_group(rgroup->core);
+	kfree(rgroup->name);
+	kfree(rgroup);
+}
+
+static struct configfs_item_operations rgcs_rgroup_item_ops = {
+	.release	= rgcs_rgroup_release_item,
+};
+
+static struct configfs_group_operations rgcs_rgroup_group_ops = {
+	.make_group     = make_rgcs_rgroup,
+};
+
+static struct config_item_type rgcs_item_type = {
+	.ct_owner	= THIS_MODULE,
+	.ct_item_ops    = &rgcs_rgroup_item_ops,
+	.ct_group_ops	= &rgcs_rgroup_group_ops,
+};
+
+static struct configfs_subsystem rgcs_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = "res_groups",
+			.ci_type = &rgcs_item_type,
+		}
+	}
+};
+
+static int __init rgcs_init(void)
+{
+	config_group_init(&rgcs_subsys.su_group);
+	init_MUTEX(&rgcs_subsys.su_sem);
+	return configfs_register_subsystem(&rgcs_subsys);
+}
+
+static void __exit rgcs_exit(void)
+{
+	configfs_unregister_subsystem(&rgcs_subsys);
+	res_group_teardown();
+}
+
+late_initcall(rgcs_init);
+module_exit(rgcs_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("RGCS - Provides an interface to Resource Groups"
+			" and allows control of their resource usage");
Index: linux-2617-rc3/kernel/res_group/Makefile
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/Makefile	2006-04-27 09:22:16.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/Makefile	2006-04-27 10:14:38.000000000 -0700
@@ -1 +1,2 @@
 obj-y = res_group.o shares.o task.o
+obj-$(CONFIG_RGCS) += rgcs.o

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 08/12] Add attribute support to RGCS
  2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
                   ` (6 preceding siblings ...)
  2006-04-28  1:34 ` [PATCH 07/12] Resource Groups Configfs Subsystem (RGCS) Chandra Seetharaman
@ 2006-04-28  1:34 ` Chandra Seetharaman
  2006-04-28  1:35 ` [PATCH 09/12] Add stats file " Chandra Seetharaman
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:34 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

08/12 - user_interface_attr_support

Adds the basic attribute store and show functions.
--

Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Shailabh Nagar <nagar@watson.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>

 rgcs.c |   53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 52 insertions(+), 1 deletion(-)

Index: linux-2617-rc3/kernel/res_group/rgcs.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/rgcs.c	2006-04-27 10:18:39.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/rgcs.c	2006-04-27 10:18:44.000000000 -0700
@@ -14,13 +14,21 @@
  * as published by the Free Software Foundation.
  *
  */
+#include <linux/ctype.h>
 #include <linux/module.h>
 #include <linux/configfs.h>
+#include <linux/parser.h>
 #include "local.h"
 
 static struct configfs_subsystem rgcs_subsys;
 static struct config_item_type rgcs_item_type;
 
+struct rgroup_attribute {
+	struct configfs_attribute configfs_attr;
+	ssize_t (*show)(struct resource_group *, char *);
+	int (*store)(struct resource_group *, const char *);
+};
+
 struct rgcs_rgroup {
 	char *name;
 	struct resource_group *core;
@@ -58,6 +66,42 @@ static inline struct resource_group *ite
 	return group_to_res_group(to_config_group(item));
 }
 
+static ssize_t rgcs_attr_show(struct config_item *item,
+	      		      struct configfs_attribute *attr, char *buf)
+{
+	struct rgroup_attribute *rgroup_attr;
+	struct resource_group *rgroup = item_to_res_group(item);
+
+	rgroup_attr = container_of(attr, struct rgroup_attribute,
+							configfs_attr);
+	return rgroup_attr->show(rgroup, buf);
+}
+
+static ssize_t rgcs_attr_store(struct config_item *item,
+		       struct configfs_attribute *attr, const char *buf,
+		       size_t count)
+{
+	char *filtered_buf, *p;
+	ssize_t rc;
+	struct rgroup_attribute *rgroup_attr;
+	struct resource_group *rgroup = item_to_res_group(item);
+
+	rgroup_attr = container_of(attr, struct rgroup_attribute,
+							configfs_attr);
+	filtered_buf = kzalloc(count + 1, GFP_KERNEL);
+	if (!filtered_buf)
+		return -ENOMEM;
+	strncpy(filtered_buf, buf, count);
+	for (p = filtered_buf; isprint(*p); ++p)
+		;
+	*p = '\0';
+	rc = rgroup_attr->store(rgroup, filtered_buf);
+	kfree(filtered_buf);
+	if (rc)
+		return rc;
+	return count;
+}
+
 /*
  * This is the function that is called when a 'mkdir' command
  * is issued under our filesystem
@@ -119,17 +163,24 @@ static void rgcs_rgroup_release_item(str
 }
 
 static struct configfs_item_operations rgcs_rgroup_item_ops = {
-	.release	= rgcs_rgroup_release_item,
+	.release		= rgcs_rgroup_release_item,
+	.show_attribute		= rgcs_attr_show,
+	.store_attribute	= rgcs_attr_store,
 };
 
 static struct configfs_group_operations rgcs_rgroup_group_ops = {
 	.make_group     = make_rgcs_rgroup,
 };
 
+static struct configfs_attribute *rgroup_attrs[] = {
+	NULL
+};
+
 static struct config_item_type rgcs_item_type = {
 	.ct_owner	= THIS_MODULE,
 	.ct_item_ops    = &rgcs_rgroup_item_ops,
 	.ct_group_ops	= &rgcs_rgroup_group_ops,
+	.ct_attrs       = rgroup_attrs
 };
 
 static struct configfs_subsystem rgcs_subsys = {

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 09/12] Add stats file support to RGCS
  2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
                   ` (7 preceding siblings ...)
  2006-04-28  1:34 ` [PATCH 08/12] Add attribute support to RGCS Chandra Seetharaman
@ 2006-04-28  1:35 ` Chandra Seetharaman
  2006-04-28  1:35 ` [PATCH 10/12] Add shares " Chandra Seetharaman
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:35 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

09/12 - user_interface_stats

Adds attr_store and attr_show support for stats file.
--

Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Shailabh Nagar <nagar@watson.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>

 rgcs.c |  112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 110 insertions(+), 2 deletions(-)

Index: linux-2617-rc3/kernel/res_group/rgcs.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/rgcs.c	2006-04-27 10:18:44.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/rgcs.c	2006-04-27 10:18:45.000000000 -0700
@@ -20,8 +20,102 @@
 #include <linux/parser.h>
 #include "local.h"
 
-static struct configfs_subsystem rgcs_subsys;
-static struct config_item_type rgcs_item_type;
+#define RES_STRING "res"
+
+static ssize_t show_stats(struct resource_group *rgroup, char *buf)
+{
+	int i, j = 0, rc = 0;
+	size_t buf_size = PAGE_SIZE-1; /* allow only PAGE_SIZE # of bytes */
+	struct res_controller *ctlr;
+	struct res_shares *shares;
+
+	for (i = 0; i < MAX_RES_CTLRS; i++, j = 0) {
+		if (buf_size <= 0)
+			break;
+		ctlr = get_controller_by_id(i);
+		if (!ctlr)
+			 continue;
+		shares = get_controller_shares(rgroup, ctlr);
+		if (shares && ctlr->show_stats)
+			j = ctlr->show_stats(shares, buf, buf_size);
+		put_controller(ctlr);
+		rc += j;
+		buf += j;
+		buf_size -= j;
+	}
+	if (i < MAX_RES_CTLRS)
+		rc = -ENOSPC;
+	return rc;
+}
+
+enum parse_token_t {
+	parse_res_type, parse_err
+};
+
+static match_table_t parse_tokens = {
+	{parse_res_type, RES_STRING"=%s"},
+	{parse_err, NULL}
+};
+
+static int stats_parse(const char *options,
+				char **resname, char **remaining_line)
+{
+	char *p, *str;
+	int rc = -EINVAL;
+
+	if (!options)
+		return -EINVAL;
+
+	while ((p = strsep((char **)&options, ",")) != NULL) {
+		substring_t args[MAX_OPT_ARGS];
+		int token;
+
+		if (!*p)
+			continue;
+		token = match_token(p, parse_tokens, args);
+		if (token == parse_res_type) {
+			*resname = match_strdup(args);
+			str = p + strlen(p) + 1;
+			*remaining_line = kmalloc(strlen(str) + 1, GFP_KERNEL);
+			if (*remaining_line == NULL) {
+				kfree(*resname);
+				*resname = NULL;
+				rc = -ENOMEM;
+			} else {
+				strcpy(*remaining_line, str);
+				rc = 0;
+			}
+			break;
+		}
+	}
+	return rc;
+}
+
+static int reset_stats(struct resource_group *rgroup, const char *str)
+{
+	int rc;
+	char *resname = NULL, *statstr = NULL;
+	struct res_controller *ctlr;
+	struct res_shares *shares;
+
+	rc = stats_parse(str, &resname, &statstr);
+	if (rc)
+		return rc;
+
+	ctlr = get_controller_by_name(resname);
+	if (!ctlr) {
+		rc = -EINVAL;
+		goto done;
+	}
+	shares = get_controller_shares(rgroup, ctlr);
+	if (shares && ctlr->reset_stats)
+		rc = ctlr->reset_stats(shares, statstr);
+	put_controller(ctlr);
+done:
+	kfree(resname);
+	kfree(statstr);
+	return rc;
+}
 
 struct rgroup_attribute {
 	struct configfs_attribute configfs_attr;
@@ -29,6 +123,19 @@ struct rgroup_attribute {
 	int (*store)(struct resource_group *, const char *);
 };
 
+struct rgroup_attribute stats_attr = {
+	.configfs_attr = {
+		.ca_name = "stats",
+		.ca_owner = THIS_MODULE,
+		.ca_mode = S_IRUGO | S_IWUSR
+	},
+	.show = show_stats,
+	.store = reset_stats
+};
+
+static struct configfs_subsystem rgcs_subsys;
+static struct config_item_type rgcs_item_type;
+
 struct rgcs_rgroup {
 	char *name;
 	struct resource_group *core;
@@ -173,6 +280,7 @@ static struct configfs_group_operations 
 };
 
 static struct configfs_attribute *rgroup_attrs[] = {
+	&stats_attr.configfs_attr,
 	NULL
 };
 

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 10/12] Add shares file support to RGCS
  2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
                   ` (8 preceding siblings ...)
  2006-04-28  1:35 ` [PATCH 09/12] Add stats file " Chandra Seetharaman
@ 2006-04-28  1:35 ` Chandra Seetharaman
  2006-04-28  1:35 ` [PATCH 11/12] Add members " Chandra Seetharaman
  2006-04-28  1:35 ` [PATCH 12/12] Documentation for Resource Groups Chandra Seetharaman
  11 siblings, 0 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:35 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

10/12 - user_interface_shares

Adds attr_store and attr_show support for shares file.
--

Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Shailabh Nagar <nagar@watson.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>

 rgcs.c |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 136 insertions(+)

Index: linux-2617-rc3/kernel/res_group/rgcs.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/rgcs.c	2006-04-27 10:18:45.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/rgcs.c	2006-04-27 10:18:47.000000000 -0700
@@ -21,6 +21,9 @@
 #include "local.h"
 
 #define RES_STRING "res"
+#define MIN_SHARES_STRING "min_shares"
+#define MAX_SHARES_STRING "max_shares"
+#define CHILD_SHARES_DIVISOR_STRING "child_shares_divisor"
 
 static ssize_t show_stats(struct resource_group *rgroup, char *buf)
 {
@@ -117,6 +120,128 @@ done:
 	return rc;
 }
 
+
+enum share_token_t {
+	MIN_SHARES_TOKEN,
+	MAX_SHARES_TOKEN,
+	CHILD_SHARES_DIVISOR_TOKEN,
+	RESOURCE_TYPE_TOKEN,
+	ERROR_TOKEN
+};
+
+/* Token matching for parsing input to this magic file */
+static match_table_t shares_tokens = {
+	{RESOURCE_TYPE_TOKEN, RES_STRING"=%s"},
+	{MIN_SHARES_TOKEN, MIN_SHARES_STRING"=%d"},
+	{MAX_SHARES_TOKEN, MAX_SHARES_STRING"=%d"},
+	{CHILD_SHARES_DIVISOR_TOKEN, CHILD_SHARES_DIVISOR_STRING"=%d"},
+	{ERROR_TOKEN, NULL}
+};
+
+static int shares_parse(const char *options, char **resname,
+					struct res_shares *shares)
+{
+	char *p;
+	int option, rc = -EINVAL;
+
+	*resname = NULL;
+	if (!options)
+		goto done;
+	while ((p = strsep((char **)&options, ",")) != NULL) {
+		substring_t args[MAX_OPT_ARGS];
+		int token;
+
+		if (!*p)
+			continue;
+		token = match_token(p, shares_tokens, args);
+		switch (token) {
+		case RESOURCE_TYPE_TOKEN:
+			if (*resname)
+				goto done;
+			*resname = match_strdup(args);
+			break;
+		case MIN_SHARES_TOKEN:
+			if (match_int(args, &option))
+				goto done;
+			shares->min_shares = option;
+			break;
+		case MAX_SHARES_TOKEN:
+			if (match_int(args, &option))
+				goto done;
+			shares->max_shares = option;
+			break;
+		case CHILD_SHARES_DIVISOR_TOKEN:
+			if (match_int(args, &option))
+				goto done;
+			shares->child_shares_divisor = option;
+			break;
+		default:
+			goto done;
+		}
+	}
+	rc = 0;
+done:
+	if (rc) {
+		kfree(*resname);
+		*resname = NULL;
+	}
+	return rc;
+}
+
+static int set_shares(struct resource_group *rgroup, const char *str)
+{
+	char *resname = NULL;
+	int rc;
+	struct res_controller *ctlr;
+	struct res_shares shares = {
+		.min_shares = SHARE_UNCHANGED,
+		.max_shares = SHARE_UNCHANGED,
+		.child_shares_divisor = SHARE_UNCHANGED,
+	};
+
+	rc = shares_parse(str, &resname, &shares);
+	if (!rc) {
+		ctlr = get_controller_by_name(resname);
+		if (ctlr) {
+			rc = set_controller_shares(rgroup, ctlr, &shares);
+			put_controller(ctlr);
+		} else
+			rc = -EINVAL;
+		kfree(resname);
+	}
+	return rc;
+}
+
+static ssize_t show_shares(struct resource_group *rgroup, char *buf)
+{
+	int i;
+	ssize_t j, rc = 0, bufsize = PAGE_SIZE;
+	struct res_shares *shares;
+	struct res_controller *ctlr;
+
+	for (i = 0; i < MAX_RES_CTLRS; i++) {
+		ctlr = get_controller_by_id(i);
+		if (!ctlr)
+			continue;
+		shares = get_controller_shares(rgroup, ctlr);
+		if (shares) {
+			if (bufsize <= 0)
+				break;
+			j = snprintf(buf, bufsize, "%s=%s,%s=%d,%s=%d,%s=%d\n",
+				RES_STRING, ctlr->name,
+				MIN_SHARES_STRING, shares->min_shares,
+				MAX_SHARES_STRING, shares->max_shares,
+				CHILD_SHARES_DIVISOR_STRING,
+				shares->child_shares_divisor);
+			rc += j; buf += j; bufsize -= j;
+		}
+		put_controller(ctlr);
+	}
+	if (i < MAX_RES_CTLRS)
+		rc = -ENOSPC;
+	return rc;
+}
+
 struct rgroup_attribute {
 	struct configfs_attribute configfs_attr;
 	ssize_t (*show)(struct resource_group *, char *);
@@ -133,6 +258,16 @@ struct rgroup_attribute stats_attr = {
 	.store = reset_stats
 };
 
+struct rgroup_attribute shares_attr = {
+	.configfs_attr = {
+		.ca_name = "shares",
+		.ca_owner = THIS_MODULE,
+		.ca_mode = S_IRUGO | S_IWUSR
+	},
+	.show = show_shares,
+	.store = set_shares
+};
+
 static struct configfs_subsystem rgcs_subsys;
 static struct config_item_type rgcs_item_type;
 
@@ -281,6 +416,7 @@ static struct configfs_group_operations 
 
 static struct configfs_attribute *rgroup_attrs[] = {
 	&stats_attr.configfs_attr,
+	&shares_attr.configfs_attr,
 	NULL
 };
 

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 11/12] Add members file support to RGCS
  2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
                   ` (9 preceding siblings ...)
  2006-04-28  1:35 ` [PATCH 10/12] Add shares " Chandra Seetharaman
@ 2006-04-28  1:35 ` Chandra Seetharaman
  2006-04-28  1:35 ` [PATCH 12/12] Documentation for Resource Groups Chandra Seetharaman
  11 siblings, 0 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:35 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

11/12 - user_interface_members

Adds attr_store and attr_show support for members file.
--

Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Shailabh Nagar <nagar@watson.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>

 rgcs.c |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 49 insertions(+)

Index: linux-2617-rc3/kernel/res_group/rgcs.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/rgcs.c	2006-04-27 10:18:47.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/rgcs.c	2006-04-27 10:18:47.000000000 -0700
@@ -242,6 +242,43 @@ static ssize_t show_shares(struct resour
 	return rc;
 }
 
+/*
+ * Given a buffer with a pid in it, add the task with that pid to the
+ * resource group. Ignores entire buffer after the first pid is parsed.
+ */
+static int add_member(struct resource_group *rgroup, const char *str)
+{
+	pid_t pid;
+
+	pid = (pid_t) simple_strtol(str, NULL, 0);
+	if (pid <= 0)
+		return -EINVAL; /* Not a valid pid */
+	return set_res_group(pid, rgroup);
+}
+
+/*
+ * Lists pids of tasks that belong to the given rgroup.
+ */
+static ssize_t show_members(struct resource_group *rgroup, char *buf)
+{
+	ssize_t i, rc = 0, bufsize = PAGE_SIZE;
+	struct task_struct *tsk;
+
+	spin_lock(&rgroup->group_lock);
+	list_for_each_entry(tsk, &rgroup->task_list, member_list) {
+		if (bufsize <= 0) {
+			rc = -ENOSPC;
+			break;
+		}
+		if (!tsk->pid)	/* Ignore swappers */
+			continue;
+		i = snprintf(buf, bufsize, "%ld\n", (long)tsk->pid);
+		buf += i; rc += i; bufsize -= i;
+	}
+	spin_unlock(&rgroup->group_lock);
+	return rc;
+}
+
 struct rgroup_attribute {
 	struct configfs_attribute configfs_attr;
 	ssize_t (*show)(struct resource_group *, char *);
@@ -268,6 +305,17 @@ struct rgroup_attribute shares_attr = {
 	.store = set_shares
 };
 
+struct rgroup_attribute members_attr = {
+	.configfs_attr = {
+		.ca_name = "members",
+		.ca_owner = THIS_MODULE,
+		.ca_mode = S_IRUGO | S_IWUSR
+	},
+	.show = show_members,
+	.store = add_member
+};
+
+
 static struct configfs_subsystem rgcs_subsys;
 static struct config_item_type rgcs_item_type;
 
@@ -417,6 +465,7 @@ static struct configfs_group_operations 
 static struct configfs_attribute *rgroup_attrs[] = {
 	&stats_attr.configfs_attr,
 	&shares_attr.configfs_attr,
+	&members_attr.configfs_attr,
 	NULL
 };
 

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 12/12] Documentation for Resource Groups
  2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
                   ` (10 preceding siblings ...)
  2006-04-28  1:35 ` [PATCH 11/12] Add members " Chandra Seetharaman
@ 2006-04-28  1:35 ` Chandra Seetharaman
  11 siblings, 0 replies; 13+ messages in thread
From: Chandra Seetharaman @ 2006-04-28  1:35 UTC (permalink / raw)
  To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman

12/12 - res_groups_docs

Documentation describing important Resource Groups components such as
resource group, shares, controllers, and the configfs based user interface.
--

Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Hubertus Franke <frankeh@us.ibm.com>
Signed-Off-By: Shailabh Nagar <nagar@watson.ibm.com>
Signed-Off-By: Gerrit Huizenga <gh@us.ibm.com>
Signed-Off-By: Vivek Kashyap <kashyapv@us.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>

 res_groups_basics  |   71 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 res_groups_install |   29 +++++++++++++++++++++
 res_groups_usage   |   53 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 153 insertions(+)

Index: linux-2617-rc3/Documentation/res_groups/res_groups_basics
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/Documentation/res_groups/res_groups_basics	2006-04-27 10:18:48.000000000 -0700
@@ -0,0 +1,71 @@
+Resource Groups Basics
+-------------
+A brief review of Resoruce Groups concepts and terminology will help make
+installation and testing easier. For more details, please visit
+http://ckrm.sf.net.
+
+Concept:
+User defines a resource group, attaches some amount of resources to
+the resource group, and associates tasks with that resource group. Tasks
+belonging to that resource group will be bound by the amount of resource
+that is assigned to that group.
+
+User interface for the Resource Groups is through configfs. Resource group
+is depicted as as a directory. Hierarchy of resource groups can be
+created in which children of a resource group share resources allotted to
+the parent. Tasks can be attached to any resource group which is at any level.
+There is no correlation between parent-child relationship of tasks and
+the parent-child relationship of the resource groups they belong to.
+
+During fork(), resource group is inherited by a task. A privileged user can
+reassign a task to any resource group.
+
+Characteristics of a resource group can be accessed/changed through the
+following files under the directory representing the resource group:
+
+shares:  allows changing shares of different resources managed by the
+         resource group
+stats:   shows statistics associated with each resources managed by the
+         resource group
+members: allows assignment of tasks to a resource group and shows tasks
+         that are assigned to a resource group.
+
+Resource allocations of a resource group is resource group to the amount
+of resources available to the resource group's parent.
+Resource allocations for a resource group is controlled by the parameters:
+
+min_shares: Minimum amount shares that can be allocated by a resource group. A
+            special value of DONT_CARE(-3) means that there is no minimum
+	    shares of a resource is specified. This resource group may not get
+	    any resource if the system is running short on resources.
+max_shares: Specifies the maximum amount of resource that is allowed to be
+           allocated by a resource group. A special value DONT_CARE(-3) mean
+	   that there is no specific limit is specified, this resource group
+	   can get all the resources available.
+child_shares_divisor: total guarantee that is allowed among the children of
+           this resource group. In other words, the sum of "guarantee"s of all
+	   children of this resource group cannot exit this number.
+
+Any of these parameter can have a special value, UNSUPPORTED(-2) meaning
+that the specific controller does not support this parameter. User's
+request to change the value will be ignored.
+
+None of this parameters neither absolute nor have any units associated with
+them. These are just numbers that are used to calculate the absolute number
+of resource available for a specific resource group.
+
+Absolute amount of minimum shares available for a resource group is
+calculuated as:
+
+	absolute minimum shares = (parent's absolute amount of resource) *
+		(resource group's min_shares / parent's child_shares_divisor)
+
+Maximum shares is also calculated in the same way.
+
+Root resource group is allocated all the resources available in the system.
+In other words absolute amount of resource available for the root resource
+group is same as that of what is available in the system.
+
+min_shares and max_shares are related to the parent, these values on
+the root resource group have no effect. Similarly, child_shares_divisor
+is related to children, and hence it has no effect on leaf resource groups.
Index: linux-2617-rc3/Documentation/res_groups/res_groups_install
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/Documentation/res_groups/res_groups_install	2006-04-27 10:18:48.000000000 -0700
@@ -0,0 +1,29 @@
+1. Configure
+
+Select appropriate configuration options:
+
+   Enable configfs filesystem:
+   File systems --->
+     Pseudo filesystems --->
+       <M> Userspace-driven configuration filesystem (EXPERIMENTAL)
+
+   Enable Resource Group components:
+   General Setup --->
+     Resource Groups --->
+        [*] Resource Groups
+        <M> Resource Groups Configfs Subsystem (User API)
+        [*]     Number of Tasks Resource Manager
+
+
+2. Build, boot the kernel
+
+3. Enable rgcs
+
+    # insmod <patchestree>/fs/configfs/configfs.ko # if compiled as module
+    # insmod <patchedtree>/kernel/res_config/rgcs.ko # if compiled in as module
+    # mount -t configfs none /config
+
+    This will create the directory /config/res_groups which is the root of
+    classes.
+
+4. Work with class hierarchy as explained in the file res_groups_usage
Index: linux-2617-rc3/Documentation/res_groups/res_groups_usage
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/Documentation/res_groups/res_groups_usage	2006-04-27 10:18:48.000000000 -0700
@@ -0,0 +1,53 @@
+Usage of Resoruce Groups
+------------------------
+
+1. Create a resource group
+
+   # mkdir /config/res_groups/c1
+   creates a resource group named c1, while
+
+The newly created directory is automatically populated by magic files
+shares, stats, members, and attrib.
+
+2. View default shares of a resource group
+
+   # cat /config/res_groups/c1/shares
+   res=numtasks,min_shares=-3,max_shares=-3,child_total_divisor=100
+
+   Above is the default value set for resources that have controllers
+   registered with Resource Groups framework.
+
+3. change shares of a specific resource in a resource group
+
+   One or more of the following fields can/must be specified
+       res=<res_name> #mandatory
+       min_shares=<number>
+       max_shares=<number>
+       child_total_divisor=<number>
+   e.g.
+	# echo "res=numtasks,max_shares=20" > /config/res_groups/c1/shares
+
+   If any of these parameters are not specified, the current value will be
+   retained.
+
+4. Move a task to a different resource group
+
+   write the pid of the process to the destination resource group's members
+   file
+   # echo 1004 > /config/res_groups/c1/members
+
+5. Get a list of tasks assigned to a resource group
+
+   # cat /config/res_groups/c1/members
+   lists pids of tasks belonging to c1
+
+6. Get statictics of different resources of a resource group
+
+   # cat /config/res_groups/c1/stats
+   shows c1's statistics for each registered resource controller.
+
+7. Configuration settings for controllers
+   Configuration values for controller are available through module
+   parameter interfaces. Consult the controller specific documents for
+   details. For example, numtasks has it available through
+   /sys/module/numtasks/parameters.

-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2006-04-28  1:44 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-28  1:34 [PATCH 00/12] Resource Groups... formerly CKRM Chandra Seetharaman
2006-04-28  1:34 ` [PATCH 01/12] Register/Unregister interface for Controllers Chandra Seetharaman
2006-04-28  1:34 ` [PATCH 02/12] Resource group creation/deletion Chandra Seetharaman
2006-04-28  1:34 ` [PATCH 03/12] Share Handling Chandra Seetharaman
2006-04-28  1:34 ` [PATCH 04/12] Add task logic to resource groups Chandra Seetharaman
2006-04-28  1:34 ` [PATCH 05/12] Init and clear resource group info in task Chandra Seetharaman
2006-04-28  1:34 ` [PATCH 06/12] Add proc interface to get resource group info of task Chandra Seetharaman
2006-04-28  1:34 ` [PATCH 07/12] Resource Groups Configfs Subsystem (RGCS) Chandra Seetharaman
2006-04-28  1:34 ` [PATCH 08/12] Add attribute support to RGCS Chandra Seetharaman
2006-04-28  1:35 ` [PATCH 09/12] Add stats file " Chandra Seetharaman
2006-04-28  1:35 ` [PATCH 10/12] Add shares " Chandra Seetharaman
2006-04-28  1:35 ` [PATCH 11/12] Add members " Chandra Seetharaman
2006-04-28  1:35 ` [PATCH 12/12] Documentation for Resource Groups Chandra Seetharaman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox