* [PATCH 0/6] Number of Tasks Resource controller
@ 2006-04-28 1:35 Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 1/6] numtasks - Initialization routines Chandra Seetharaman
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Chandra Seetharaman @ 2006-04-28 1:35 UTC (permalink / raw)
To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman
Andrew,
Numtasks controller is a simple resource controller that provides user the
ability to
- control the number of tasks a class can have
- control the rate at which forks happen in the system
on top of Resource Groups.
Please consider these for inclusion in -mm tree.
--
Patch descriptions:
1/6: numtasks_init
Hooks up with Resource Groups core by defining the basic alloc/free
functions and registering the controller with the core.
2/6: numtasks_tasksupport
Adds task management support by defining a function to be called from
fork() to see if the resource group is within its share allocation
Sets interface to be called from core when a task is moved to a resource
group.
3/6: numtasks_shares_n_stats
Sets interface to be called from core when a resource group's shares are
changes or when stats are requested.
4/6: numtasks_config
Use module parameters to dynamically set the total numtasks and maximum
forkrate allowed.
5/6: numtasks_forkrate
Adds support to control the forkrate in the system.
6/6: numtasks_docs
Documents what the numtasks controller does and how to use it.
--
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- sekharan@us.ibm.com | .......you may get it.
----------------------------------------------------------------------
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/6] numtasks - Initialization routines
2006-04-28 1:35 [PATCH 0/6] Number of Tasks Resource controller Chandra Seetharaman
@ 2006-04-28 1:35 ` Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 2/6] numtasks - Add task control support Chandra Seetharaman
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Chandra Seetharaman @ 2006-04-28 1:35 UTC (permalink / raw)
To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman
1/6: numtasks_init
Hooks up with Resource Groups core by defining the basic alloc/free
functions and registering the controller with the core.
--
Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>
init/Kconfig | 10 ++++
kernel/res_group/Makefile | 1
kernel/res_group/numtasks.c | 90 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 101 insertions(+)
Index: linux-2617-rc3/kernel/res_group/Makefile
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/Makefile 2006-04-27 10:14:38.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/Makefile 2006-04-27 10:18:49.000000000 -0700
@@ -1,2 +1,3 @@
obj-y = res_group.o shares.o task.o
+obj-$(CONFIG_RES_GROUPS_NUMTASKS) += numtasks.o
obj-$(CONFIG_RGCS) += rgcs.o
Index: linux-2617-rc3/kernel/res_group/numtasks.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/kernel/res_group/numtasks.c 2006-04-27 10:18:49.000000000 -0700
@@ -0,0 +1,90 @@
+/* numtasks.c - "Number of tasks" resource controller for Resource Groups
+ *
+ * Copyright (C) Chandra Seetharaman, IBM Corp. 2003-2006
+ * (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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+/*
+ * Resource controller for tracking number of tasks in a resource group.
+ */
+#include <linux/module.h>
+#include <linux/res_group_rc.h>
+
+static const char res_ctlr_name[] = "numtasks";
+
+struct numtasks {
+ struct res_shares shares;
+};
+
+struct res_controller numtasks_ctlr;
+
+static struct numtasks *get_shares_numtasks(struct res_shares *shares)
+{
+ if (shares)
+ return container_of(shares, struct numtasks, shares);
+ return NULL;
+}
+
+/* Initialize share struct values */
+static void numtasks_res_init_one(struct numtasks *numtasks_res)
+{
+ numtasks_res->shares.min_shares = SHARE_DONT_CARE;
+ numtasks_res->shares.max_shares = SHARE_DONT_CARE;
+ numtasks_res->shares.child_shares_divisor = SHARE_DEFAULT_DIVISOR;
+ numtasks_res->shares.unused_min_shares = SHARE_DEFAULT_DIVISOR;
+}
+
+static struct res_shares *numtasks_alloc_shares_struct(
+ struct resource_group *rgroup)
+{
+ struct numtasks *res;
+
+ res = kzalloc(sizeof(struct numtasks), GFP_KERNEL);
+ if (!res)
+ return NULL;
+ numtasks_res_init_one(res);
+ return &res->shares;
+}
+
+/*
+ * No locking of this resource group object necessary as we are not
+ * supposed to be assigned (or used) when/after this function is called.
+ */
+static void numtasks_free_shares_struct(struct res_shares *my_res)
+{
+ kfree(get_shares_numtasks(my_res));
+}
+
+struct res_controller numtasks_ctlr = {
+ .name = res_ctlr_name,
+ .depth_supported = 3,
+ .ctlr_id = NO_RES_ID,
+ .alloc_shares_struct = numtasks_alloc_shares_struct,
+ .free_shares_struct = numtasks_free_shares_struct,
+};
+
+int __init init_numtasks_res(void)
+{
+ if (numtasks_ctlr.ctlr_id != NO_RES_ID)
+ return -EBUSY; /* already registered */
+ return register_controller(&numtasks_ctlr);
+}
+
+void __exit exit_numtasks_res(void)
+{
+ int rc;
+ do {
+ rc = unregister_controller(&numtasks_ctlr);
+ } while (rc == -EBUSY);
+ BUG_ON(rc != 0);
+}
+module_init(init_numtasks_res)
+module_exit(exit_numtasks_res)
Index: linux-2617-rc3/init/Kconfig
===================================================================
--- linux-2617-rc3.orig/init/Kconfig 2006-04-27 10:17:11.000000000 -0700
+++ linux-2617-rc3/init/Kconfig 2006-04-27 10:18:49.000000000 -0700
@@ -175,6 +175,16 @@ config RGCS
Say M if unsure, Y to save on module loading. N doesn't make sense
when Resource Groups has been configured.
+config RES_GROUPS_NUMTASKS
+ bool "Number of Tasks Resource Controller"
+ depends on RES_GROUPS
+ default y
+ help
+ Provides a Resource Controller for Resource Groups that allows
+ limiting number of tasks a resource group can have.
+
+ Say N if unsure, Y to use the feature.
+
endmenu
config SYSCTL
bool "Sysctl support"
--
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- sekharan@us.ibm.com | .......you may get it.
----------------------------------------------------------------------
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/6] numtasks - Add task control support
2006-04-28 1:35 [PATCH 0/6] Number of Tasks Resource controller Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 1/6] numtasks - Initialization routines Chandra Seetharaman
@ 2006-04-28 1:35 ` Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 3/6] numtasks - Add shares and stats support Chandra Seetharaman
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Chandra Seetharaman @ 2006-04-28 1:35 UTC (permalink / raw)
To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman
2/6: numtasks_tasksupport
Adds task management support by defining a function to be called from
fork() to see if the resource group is within its share allocation
Sets interface to be called from core when a task is moved to a resource
group.
--
Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
include/linux/numtasks.h | 28 +++++++++++
kernel/fork.c | 7 ++
kernel/res_group/numtasks.c | 104 +++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 137 insertions(+), 2 deletions(-)
Index: linux-2617-rc3/include/linux/numtasks.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/include/linux/numtasks.h 2006-04-27 10:18:50.000000000 -0700
@@ -0,0 +1,28 @@
+/* numtasks.h - No. of tasks resource controller for Resource Groups
+ *
+ * Copyright (C) Chandra Seetharaman, IBM Corp. 2003, 2004, 2005
+ *
+ * Provides No. of tasks resource controller 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 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_NUMTASKS_H
+#define _LINUX_NUMTASKS_H
+
+#ifdef CONFIG_RES_GROUPS_NUMTASKS
+#include <linux/res_group_rc.h>
+
+extern int numtasks_allow_fork(struct resource_group *);
+
+#else /* CONFIG_RES_GROUPS_NUMTASKS */
+
+#define numtasks_allow_fork(rgroup) (0)
+
+#endif /* CONFIG_RES_GROUPS_NUMTASKS */
+#endif /* _LINUX_NUMTASKS_H */
Index: linux-2617-rc3/kernel/res_group/numtasks.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/numtasks.c 2006-04-27 10:18:49.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/numtasks.c 2006-04-27 10:18:50.000000000 -0700
@@ -21,7 +21,19 @@
static const char res_ctlr_name[] = "numtasks";
struct numtasks {
+ struct resource_group *rgroup;/* resource group i am part of... */
struct res_shares shares;
+ int cnt_min_shares; /* num_tasks min_shares in local units */
+ int cnt_unused; /* has to borrow if more than this is needed */
+ int cnt_max_shares; /* no tasks over this limit. */
+ /* Three above cnt_* fields are protected
+ * by resource group's group_lock */
+ atomic_t cnt_cur_alloc; /* current alloc from self */
+ atomic_t cnt_borrowed; /* borrowed from the parent */
+
+ /* stats */
+ int successes;
+ int failures;
};
struct res_controller numtasks_ctlr;
@@ -33,6 +45,84 @@ static struct numtasks *get_shares_numta
return NULL;
}
+static struct numtasks *get_numtasks(struct resource_group *rgroup)
+{
+ return get_shares_numtasks(get_controller_shares(rgroup,
+ &numtasks_ctlr));
+}
+
+int numtasks_allow_fork(struct resource_group *rgroup)
+{
+ struct numtasks *res;
+
+ /* controller is not registered; no resource group is given */
+ if ((numtasks_ctlr.ctlr_id == NO_RES_ID) || (rgroup == NULL))
+ return 0;
+ res = get_numtasks(rgroup);
+
+ /* numtasks not available for this resource group */
+ if (!res)
+ return 0;
+
+ if (res->cnt_max_shares == SHARE_DONT_CARE)
+ return 0;
+
+ /* Over the limit ? */
+ if (atomic_read(&res->cnt_cur_alloc) >= res->cnt_max_shares) {
+ res->failures++;
+ return -ENOSPC;
+ }
+
+ return 0;
+}
+
+static void inc_usage_count(struct numtasks *res)
+{
+ atomic_inc(&res->cnt_cur_alloc);
+
+ if (is_res_group_root(res->rgroup)) {
+ res->successes++;
+ return;
+ }
+ /* Do we need to borrow from our parent ? */
+ if ((res->cnt_unused == SHARE_DONT_CARE) ||
+ (atomic_read(&res->cnt_cur_alloc) > res->cnt_unused)) {
+ inc_usage_count(get_numtasks(res->rgroup->parent));
+ atomic_inc(&res->cnt_borrowed);
+ } else
+ res->successes++;
+}
+
+static void dec_usage_count(struct numtasks *res)
+{
+ if (atomic_read(&res->cnt_cur_alloc) == 0)
+ return;
+ atomic_dec(&res->cnt_cur_alloc);
+ if (atomic_read(&res->cnt_borrowed) > 0) {
+ atomic_dec(&res->cnt_borrowed);
+ dec_usage_count(get_numtasks(res->rgroup->parent));
+ }
+}
+
+static void numtasks_move_task(struct task_struct *task,
+ struct res_shares *old, struct res_shares *new)
+{
+ struct numtasks *oldres, *newres;
+
+ if (old == new)
+ return;
+
+ /* Decrement usage count of old resource group */
+ oldres = get_shares_numtasks(old);
+ if (oldres)
+ dec_usage_count(oldres);
+
+ /* Increment usage count of new resource group */
+ newres = get_shares_numtasks(new);
+ if (newres)
+ inc_usage_count(newres);
+}
+
/* Initialize share struct values */
static void numtasks_res_init_one(struct numtasks *numtasks_res)
{
@@ -50,6 +140,7 @@ static struct res_shares *numtasks_alloc
res = kzalloc(sizeof(struct numtasks), GFP_KERNEL);
if (!res)
return NULL;
+ res->rgroup = rgroup;
numtasks_res_init_one(res);
return &res->shares;
}
@@ -60,7 +151,17 @@ static struct res_shares *numtasks_alloc
*/
static void numtasks_free_shares_struct(struct res_shares *my_res)
{
- kfree(get_shares_numtasks(my_res));
+ struct numtasks *res, *parres;
+ int i, borrowed;
+
+ res = get_shares_numtasks(my_res);
+ if (!is_res_group_root(res->rgroup)) {
+ parres = get_numtasks(res->rgroup->parent);
+ borrowed = atomic_read(&res->cnt_borrowed);
+ for (i = 0; i < borrowed; i++)
+ dec_usage_count(parres);
+ }
+ kfree(res);
}
struct res_controller numtasks_ctlr = {
@@ -69,6 +170,7 @@ struct res_controller numtasks_ctlr = {
.ctlr_id = NO_RES_ID,
.alloc_shares_struct = numtasks_alloc_shares_struct,
.free_shares_struct = numtasks_free_shares_struct,
+ .move_task = numtasks_move_task,
};
int __init init_numtasks_res(void)
Index: linux-2617-rc3/kernel/fork.c
===================================================================
--- linux-2617-rc3.orig/kernel/fork.c 2006-04-27 10:14:38.000000000 -0700
+++ linux-2617-rc3/kernel/fork.c 2006-04-27 10:18:50.000000000 -0700
@@ -45,6 +45,7 @@
#include <linux/acct.h>
#include <linux/cn_proc.h>
#include <linux/res_group.h>
+#include <linux/numtasks.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -1311,7 +1312,7 @@ long do_fork(unsigned long clone_flags,
int __user *child_tidptr)
{
struct task_struct *p;
- int trace = 0;
+ int trace = 0, rc;
struct pid *pid = alloc_pid();
long nr;
@@ -1324,6 +1325,10 @@ long do_fork(unsigned long clone_flags,
clone_flags |= CLONE_PTRACE;
}
+ rc = numtasks_allow_fork(current->res_group);
+ if (rc)
+ return rc;
+
p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, nr);
/*
* Do this prior waking up the new thread - the thread pointer
--
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- sekharan@us.ibm.com | .......you may get it.
----------------------------------------------------------------------
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/6] numtasks - Add shares and stats support
2006-04-28 1:35 [PATCH 0/6] Number of Tasks Resource controller Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 1/6] numtasks - Initialization routines Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 2/6] numtasks - Add task control support Chandra Seetharaman
@ 2006-04-28 1:35 ` Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 4/6] numtasks - Add configuration support Chandra Seetharaman
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Chandra Seetharaman @ 2006-04-28 1:35 UTC (permalink / raw)
To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman
3/6: numtasks_shares_n_stats
Sets interface to be called from core when a resource group's shares are
changes or when stats are requested.
--
Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-off-by: MAEDA Naoaki <maeda.naoaki@jp.fujitsu.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>
numtasks.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 134 insertions(+)
Index: linux-2617-rc3/kernel/res_group/numtasks.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/numtasks.c 2006-04-27 10:18:50.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/numtasks.c 2006-04-27 10:18:50.000000000 -0700
@@ -130,6 +130,10 @@ static void numtasks_res_init_one(struct
numtasks_res->shares.max_shares = SHARE_DONT_CARE;
numtasks_res->shares.child_shares_divisor = SHARE_DEFAULT_DIVISOR;
numtasks_res->shares.unused_min_shares = SHARE_DEFAULT_DIVISOR;
+
+ numtasks_res->cnt_min_shares = SHARE_DONT_CARE;
+ numtasks_res->cnt_unused = SHARE_DONT_CARE;
+ numtasks_res->cnt_max_shares = SHARE_DONT_CARE;
}
static struct res_shares *numtasks_alloc_shares_struct(
@@ -164,6 +168,134 @@ static void numtasks_free_shares_struct(
kfree(res);
}
+static int recalc_shares(int self_shares, int parent_shares, int parent_divisor)
+{
+ u64 numerator;
+
+ if ((self_shares == SHARE_DONT_CARE) ||
+ (parent_shares == SHARE_DONT_CARE))
+ return SHARE_DONT_CARE;
+ if (parent_divisor == 0)
+ return 0;
+ numerator = (u64) self_shares * parent_shares;
+ do_div(numerator, parent_divisor);
+ return numerator;
+}
+
+static int recalc_unused_shares(int self_cnt_min_shares,
+ int self_unused_min_shares, int self_divisor)
+{
+ u64 numerator;
+
+ if (self_cnt_min_shares == SHARE_DONT_CARE)
+ return SHARE_DONT_CARE;
+ if (self_divisor == 0)
+ return 0;
+ numerator = (u64) self_unused_min_shares * self_cnt_min_shares;
+ do_div(numerator, self_divisor);
+ return numerator;
+}
+
+static void recalc_self(struct numtasks *res,
+ struct numtasks *parres)
+{
+ struct res_shares *par = &parres->shares;
+ struct res_shares *self = &res->shares;
+
+ res->cnt_min_shares = recalc_shares(self->min_shares,
+ parres->cnt_min_shares,
+ par->child_shares_divisor);
+ res->cnt_max_shares = recalc_shares(self->max_shares,
+ parres->cnt_max_shares,
+ par->child_shares_divisor);
+
+ /*
+ * Now that we know the new cnt_min/cnt_max boundaries we can update
+ * the unused quantity.
+ */
+ res->cnt_unused = recalc_unused_shares(res->cnt_min_shares,
+ self->unused_min_shares,
+ self->child_shares_divisor);
+}
+
+
+/*
+ * Recalculate the min_shares and max_shares in real units and propagate the
+ * same to children.
+ * Called with parent's (resource group to which parres belongs) lock held.
+ */
+static void recalc_and_propagate(struct numtasks *res,
+ struct numtasks *parres)
+{
+ struct resource_group *child = NULL;
+ struct numtasks *childres;
+
+ if (parres)
+ recalc_self(res, parres);
+
+ /* propagate to children */
+ spin_lock(&res->rgroup->group_lock);
+ for_each_child(child, res->rgroup) {
+ childres = get_numtasks(child);
+ BUG_ON(!childres);
+ spin_lock(&child->group_lock);
+ recalc_and_propagate(childres, res);
+ spin_unlock(&child->group_lock);
+ }
+ spin_unlock(&res->rgroup->group_lock);
+}
+
+static void numtasks_shares_changed(struct res_shares *my_res)
+{
+ struct numtasks *parres, *res;
+ struct res_shares *cur, *par;
+
+ res = get_shares_numtasks(my_res);
+ if (!res)
+ return;
+ cur = &res->shares;
+
+ if (!is_res_group_root(res->rgroup)) {
+ spin_lock(&res->rgroup->parent->group_lock);
+ parres = get_numtasks(res->rgroup->parent);
+ par = &parres->shares;
+ } else {
+ parres = NULL;
+ par = NULL;
+ }
+ if (parres)
+ parres->cnt_unused = recalc_unused_shares(
+ parres->cnt_min_shares,
+ par->unused_min_shares,
+ par->child_shares_divisor);
+ recalc_and_propagate(res, parres);
+ if (!is_res_group_root(res->rgroup))
+ spin_unlock(&res->rgroup->parent->group_lock);
+}
+
+static ssize_t numtasks_show_stats(struct res_shares *my_res,
+ char *buf, size_t buf_size)
+{
+ ssize_t i, j = 0;
+ struct numtasks *res;
+
+ res = get_shares_numtasks(my_res);
+ if (!res)
+ return -EINVAL;
+
+ i = snprintf(buf, buf_size, "%s: Current usage %d\n",
+ res_ctlr_name,
+ atomic_read(&res->cnt_cur_alloc));
+ buf += i; j += i; buf_size -= i;
+ i = snprintf(buf, buf_size, "%s: Number of successes %d\n",
+ res_ctlr_name, res->successes);
+ buf += i; j += i; buf_size -= i;
+ i = snprintf(buf, buf_size, "%s: Number of failures %d\n",
+ res_ctlr_name, res->failures);
+ j += i;
+ return j;
+}
+
struct res_controller numtasks_ctlr = {
.name = res_ctlr_name,
.depth_supported = 3,
@@ -171,6 +303,8 @@ struct res_controller numtasks_ctlr = {
.alloc_shares_struct = numtasks_alloc_shares_struct,
.free_shares_struct = numtasks_free_shares_struct,
.move_task = numtasks_move_task,
+ .shares_changed = numtasks_shares_changed,
+ .show_stats = numtasks_show_stats,
};
int __init init_numtasks_res(void)
--
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- sekharan@us.ibm.com | .......you may get it.
----------------------------------------------------------------------
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 4/6] numtasks - Add configuration support
2006-04-28 1:35 [PATCH 0/6] Number of Tasks Resource controller Chandra Seetharaman
` (2 preceding siblings ...)
2006-04-28 1:35 ` [PATCH 3/6] numtasks - Add shares and stats support Chandra Seetharaman
@ 2006-04-28 1:35 ` Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 5/6] numtasks - Add fork rate control support Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 6/6] numtasks - Documentation for Numtasks controller Chandra Seetharaman
5 siblings, 0 replies; 7+ messages in thread
From: Chandra Seetharaman @ 2006-04-28 1:35 UTC (permalink / raw)
To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman
4/6: numtasks_config
Use module parameters to dynamically set the total numtasks and maximum
forkrate allowed
--
Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>
include/linux/moduleparam.h | 12 ++++++--
kernel/res_group/numtasks.c | 64 +++++++++++++++++++++++++++++++++++++++++---
2 files changed, 70 insertions(+), 6 deletions(-)
Index: linux-2617-rc3/include/linux/moduleparam.h
===================================================================
--- linux-2617-rc3.orig/include/linux/moduleparam.h 2006-04-27 10:14:36.000000000 -0700
+++ linux-2617-rc3/include/linux/moduleparam.h 2006-04-27 10:18:50.000000000 -0700
@@ -75,11 +75,17 @@ struct kparam_array
/* Helper functions: type is byte, short, ushort, int, uint, long,
ulong, charp, bool or invbool, or XXX if you define param_get_XXX,
param_set_XXX and param_check_XXX. */
-#define module_param_named(name, value, type, perm) \
- param_check_##type(name, &(value)); \
- module_param_call(name, param_set_##type, param_get_##type, &value, perm); \
+#define module_param_named_call(name, value, type, set, perm) \
+ param_check_##type(name, &(value)); \
+ module_param_call(name, set, param_get_##type, &(value), perm); \
__MODULE_PARM_TYPE(name, #type)
+#define module_param_named(name, value, type, perm) \
+ module_param_named_call(name, value, type, param_set_##type, perm)
+
+#define module_param_set_call(name, type, setfn, perm) \
+ module_param_named_call(name, name, type, setfn, perm)
+
#define module_param(name, type, perm) \
module_param_named(name, name, type, perm)
Index: linux-2617-rc3/kernel/res_group/numtasks.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/numtasks.c 2006-04-27 10:18:50.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/numtasks.c 2006-04-27 10:18:50.000000000 -0700
@@ -20,6 +20,13 @@
static const char res_ctlr_name[] = "numtasks";
+#define UNLIMITED INT_MAX
+#define DEF_TOTAL_NUM_TASKS UNLIMITED
+static int total_numtasks __read_mostly = DEF_TOTAL_NUM_TASKS;
+
+static struct resource_group *root_rgroup;
+static int total_cnt_alloc = 0;
+
struct numtasks {
struct resource_group *rgroup;/* resource group i am part of... */
struct res_shares shares;
@@ -81,6 +88,7 @@ static void inc_usage_count(struct numta
atomic_inc(&res->cnt_cur_alloc);
if (is_res_group_root(res->rgroup)) {
+ total_cnt_alloc++;
res->successes++;
return;
}
@@ -89,8 +97,10 @@ static void inc_usage_count(struct numta
(atomic_read(&res->cnt_cur_alloc) > res->cnt_unused)) {
inc_usage_count(get_numtasks(res->rgroup->parent));
atomic_inc(&res->cnt_borrowed);
- } else
- res->successes++;
+ } else {
+ total_cnt_alloc++;
+ res->successes++;
+ }
}
static void dec_usage_count(struct numtasks *res)
@@ -101,7 +111,9 @@ static void dec_usage_count(struct numta
if (atomic_read(&res->cnt_borrowed) > 0) {
atomic_dec(&res->cnt_borrowed);
dec_usage_count(get_numtasks(res->rgroup->parent));
- }
+ } else
+ total_cnt_alloc--;
+
}
static void numtasks_move_task(struct task_struct *task,
@@ -146,6 +158,8 @@ static struct res_shares *numtasks_alloc
return NULL;
res->rgroup = rgroup;
numtasks_res_init_one(res);
+ if (is_res_group_root(rgroup))
+ root_rgroup = rgroup; /* store root's resource group. */
return &res->shares;
}
@@ -307,6 +321,50 @@ struct res_controller numtasks_ctlr = {
.show_stats = numtasks_show_stats,
};
+/*
+ * Writeable module parameters use these set_<parameter> functions to respond
+ * to changes. Otherwise the values can be read and used any time.
+ */
+static int set_numtasks_config_val(int *var, int old_value, const char *val,
+ struct kernel_param *kp)
+{
+ int rc = param_set_int(val, kp);
+
+ if (rc < 0)
+ return rc;
+ if (*var < 1) {
+ *var = old_value;
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int set_total_numtasks(const char *val, struct kernel_param *kp)
+{
+ int prev = total_numtasks;
+ int rc = set_numtasks_config_val(&total_numtasks, prev, val, kp);
+ struct numtasks *res = NULL;
+
+ if (!root_rgroup)
+ return 0;
+ if (rc < 0)
+ return rc;
+ if (total_numtasks <= total_cnt_alloc) {
+ total_numtasks = prev;
+ return -EINVAL;
+ }
+ res = get_numtasks(root_rgroup);
+ spin_lock(&root_rgroup->group_lock);
+ res->cnt_min_shares = total_numtasks;
+ res->cnt_unused = total_numtasks;
+ res->cnt_max_shares = total_numtasks;
+ recalc_and_propagate(res, NULL);
+ spin_unlock(&root_rgroup->group_lock);
+ return 0;
+}
+module_param_set_call(total_numtasks, int, set_total_numtasks,
+ S_IRUGO | S_IWUSR);
+
int __init init_numtasks_res(void)
{
if (numtasks_ctlr.ctlr_id != NO_RES_ID)
--
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- sekharan@us.ibm.com | .......you may get it.
----------------------------------------------------------------------
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 5/6] numtasks - Add fork rate control support
2006-04-28 1:35 [PATCH 0/6] Number of Tasks Resource controller Chandra Seetharaman
` (3 preceding siblings ...)
2006-04-28 1:35 ` [PATCH 4/6] numtasks - Add configuration support Chandra Seetharaman
@ 2006-04-28 1:35 ` Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 6/6] numtasks - Documentation for Numtasks controller Chandra Seetharaman
5 siblings, 0 replies; 7+ messages in thread
From: Chandra Seetharaman @ 2006-04-28 1:35 UTC (permalink / raw)
To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman
5/6: numtasks_forkrate
Adds support to control the forkrate in the system.
--
Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>
numtasks.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 75 insertions(+)
Index: linux-2617-rc3/kernel/res_group/numtasks.c
===================================================================
--- linux-2617-rc3.orig/kernel/res_group/numtasks.c 2006-04-27 10:18:50.000000000 -0700
+++ linux-2617-rc3/kernel/res_group/numtasks.c 2006-04-27 10:18:51.000000000 -0700
@@ -27,6 +27,11 @@ static int total_numtasks __read_mostly
static struct resource_group *root_rgroup;
static int total_cnt_alloc = 0;
+#define DEF_FORKRATE UNLIMITED
+#define DEF_FORKRATE_INTERVAL (1)
+static int forkrate __read_mostly = DEF_FORKRATE;
+static int forkrate_interval __read_mostly = DEF_FORKRATE_INTERVAL;
+
struct numtasks {
struct resource_group *rgroup;/* resource group i am part of... */
struct res_shares shares;
@@ -41,6 +46,11 @@ struct numtasks {
/* stats */
int successes;
int failures;
+ int forkrate_failures;
+
+ /* Fork rate fields */
+ int forks_in_period;
+ unsigned long period_start;
};
struct res_controller numtasks_ctlr;
@@ -58,8 +68,24 @@ static struct numtasks *get_numtasks(str
&numtasks_ctlr));
}
+static inline int check_forkrate(struct numtasks *res)
+{
+ if (time_after(jiffies, res->period_start + forkrate_interval * HZ)) {
+ res->period_start = jiffies;
+ res->forks_in_period = 0;
+ }
+
+ if (res->forks_in_period >= forkrate) {
+ res->forkrate_failures++;
+ return -ENOSPC;
+ }
+ res->forks_in_period++;
+ return 0;
+}
+
int numtasks_allow_fork(struct resource_group *rgroup)
{
+ int rc;
struct numtasks *res;
/* controller is not registered; no resource group is given */
@@ -71,6 +97,11 @@ int numtasks_allow_fork(struct resource_
if (!res)
return 0;
+ /* Check forkrate before checking resource group's usage */
+ rc = check_forkrate(res);
+ if (rc)
+ return rc;
+
if (res->cnt_max_shares == SHARE_DONT_CARE)
return 0;
@@ -146,6 +177,7 @@ static void numtasks_res_init_one(struct
numtasks_res->cnt_min_shares = SHARE_DONT_CARE;
numtasks_res->cnt_unused = SHARE_DONT_CARE;
numtasks_res->cnt_max_shares = SHARE_DONT_CARE;
+ numtasks_res->period_start = jiffies;
}
static struct res_shares *numtasks_alloc_shares_struct(
@@ -306,6 +338,9 @@ static ssize_t numtasks_show_stats(struc
buf += i; j += i; buf_size -= i;
i = snprintf(buf, buf_size, "%s: Number of failures %d\n",
res_ctlr_name, res->failures);
+ buf += i; j += i; buf_size -= i;
+ i = snprintf(buf, buf_size, "%s: Number of forkrate failures %d\n",
+ res_ctlr_name, res->forkrate_failures);
j += i;
return j;
}
@@ -365,6 +400,46 @@ static int set_total_numtasks(const char
module_param_set_call(total_numtasks, int, set_total_numtasks,
S_IRUGO | S_IWUSR);
+static void reset_forkrates(struct resource_group *rgroup, unsigned long now)
+{
+ struct numtasks *res;
+ struct resource_group *child = NULL;
+
+ res = get_numtasks(rgroup);
+ if (!res)
+ return;
+ res->forks_in_period = 0;
+ res->period_start = now;
+
+ spin_lock(&rgroup->group_lock);
+ for_each_child(child, rgroup)
+ reset_forkrates(child, now);
+ spin_unlock(&rgroup->group_lock);
+}
+
+static int set_forkrate(const char *val, struct kernel_param *kp)
+{
+ int prev = forkrate;
+ int rc = set_numtasks_config_val(&forkrate, prev, val, kp);
+ if (rc < 0)
+ return rc;
+ reset_forkrates(root_rgroup, jiffies);
+ return 0;
+}
+module_param_set_call(forkrate, int, set_forkrate, S_IRUGO | S_IWUSR);
+
+static int set_forkrate_interval(const char *val, struct kernel_param *kp)
+{
+ int prev = forkrate_interval;
+ int rc = set_numtasks_config_val(&forkrate_interval, prev, val, kp);
+ if (rc < 0)
+ return rc;
+ reset_forkrates(root_rgroup, jiffies);
+ return 0;
+}
+module_param_set_call(forkrate_interval, int, set_forkrate_interval,
+ S_IRUGO | S_IWUSR);
+
int __init init_numtasks_res(void)
{
if (numtasks_ctlr.ctlr_id != NO_RES_ID)
--
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- sekharan@us.ibm.com | .......you may get it.
----------------------------------------------------------------------
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 6/6] numtasks - Documentation for Numtasks controller
2006-04-28 1:35 [PATCH 0/6] Number of Tasks Resource controller Chandra Seetharaman
` (4 preceding siblings ...)
2006-04-28 1:35 ` [PATCH 5/6] numtasks - Add fork rate control support Chandra Seetharaman
@ 2006-04-28 1:35 ` Chandra Seetharaman
5 siblings, 0 replies; 7+ messages in thread
From: Chandra Seetharaman @ 2006-04-28 1:35 UTC (permalink / raw)
To: akpm, linux-kernel, ckrm-tech; +Cc: Chandra Seetharaman
6/6: numtasks_docs
Documents what the numtasks controller does and how to use it.
--
Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Matt Helsley <matthltc@us.ibm.com>
numtasks | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 133 insertions(+)
Index: linux-2617-rc3/Documentation/res_groups/numtasks
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2617-rc3/Documentation/res_groups/numtasks 2006-04-27 10:14:30.000000000 -0700
@@ -0,0 +1,133 @@
+Introduction
+-------------
+
+Numtasks is a resource controller under the Resource Groups framework that
+allows the user/sysadmin to
+ - manage the number of tasks a resource group can create.
+ - limit the fork rate across the system.
+
+As with any other resource under the Resource Groups framework, numtasks also
+assigns all the resources to the default resource group(/config/res_groups).
+Since, the number of tasks in a system is not limited, this resource controller
+provides a way to set the total number of tasks available in the system through
+the config file. The config variable that affect this is total_numtasks.
+
+This resource controller also allows the sysadmin to limit the number of forks
+that are allowed in the system within the specified number of seconds. This
+can be acheived by changing the attributes forkrate and forkrate_interval in
+the config file. Using this feature one can protect the system from being
+attacked by fork bomb type applications.
+
+Configuration parameters of numtasks controller (forkrate, total_numtasks
+and forkrate_interval) can be read/changed through the modparam interface
+/sys/module/numtasks/parameters/
+
+Installation
+-------------
+
+1. Configure "Number of Tasks Resource Manager" under Resource Groups (see
+ Documentation/res_groups/installation).
+
+2. Reboot the system with the new kernel.
+
+3. Verify the controller's presence by reading the file
+ /config/res_groups/shares (should show a line with res=numtasks)
+
+Usage
+-----
+
+For brevity, unless otherwise specified all the following commands are
+executed in the default resource group(/config/res_groups).
+
+As explained above, files in /sys/module/numtasks/parameters/
+shows total_numtasks and forkrate info.
+
+ # cd /sys/module/numtasks/parameters/
+ # ls
+ . .. forkrate forkrate_interval total_numtasks
+ # cat total_numtasks
+ 2147483647
+ # value is INT_MAX which means unlimited
+ # cat forkrate
+ 2147483647
+ # value is INT_MAX which means unlimited
+ # cat forkrate_interval
+ 1
+ # forkrate forks are allowed per 1 sec
+
+By default, the total_numtasks is set to "unlimited", forkrate is set
+to "unlimited" and forkrate_interval is set to 1 second. Which means the
+total number of tasks in a system is unlimited and the forks per second is
+also unlimited.
+
+sysadmin can change these values by just writing the attribute/value pair
+to the config file.
+
+ # echo 10000 > forkrate
+ # cat forkrate
+ 10000
+ # echo 100001 > total_numtasks
+ # cat total_numtasks
+ 100001
+
+By making child_shares_divisor to be same as total_numtasks, sysadmin can
+make the numbers in shares file be same as the number of tasks for a
+resource group.
+In other words, the numbers in shares file will be the absolute number of
+tasks a resource group is allowed.
+
+ # cd /config/res_groups
+ # cat shares
+ res=numtasks,min_shares=-3,max_shares=-3,child_shares_divisor=100
+ # echo res=numtasks,child_shares_divisor=1000 > shares
+ # cat shares
+ res=numtasks,min_shares=-3,max_shares=-3,child_shares_divisor=1000
+
+Class creation
+--------------
+
+ # mkdir c1
+
+Its initial share is don't care. The parent's share values will be unchanged.
+
+Setting a new resource group share
+-------------------------
+
+'min_shares' specifies the number of tasks this resource group is entitled
+to get
+'max_shares' is the maximum number of tasks this resource group can get.
+
+Following command will set the min_shares of resource group c1 to be 250
+and max_shares to be 500
+
+ # echo 'res=numtasks,min_shares=250,max_shares=500' > c1/shares
+ # cat c1/shares
+ res=numtasks,min_shares=250,max_shares=500,child_shares_divisor=100
+
+Note that the min_shares of 250 and max_shares of 500 is w.r.t the
+paren't's 1000 above, and not the absolute numbers.
+
+Limiting forks in a time period
+-------------------------------
+By default, this resource controller allows unlimited forks per second.
+
+Following commands would change it to allow only 100 forks per 10 seconds
+
+ # cd /sys/module/numtasks/parameters
+ # cat 100 > forkrate
+ # cat 10 > forkrate_interval
+
+Note that the same set of values is used across the system. In other words,
+each individual resource group will be allowed 'forkrate' forks in
+'forkrate_interval' seconds.
+
+Monitoring
+----------
+
+stats file shows statistics of the number of tasks usage of a resource
+group
+ # cd /config/res_groups
+ # cat stats
+ numtasks: Number of successes 12554
+ numtasks: Number of failures 0
+ numtasks: Number of forkrate failures 0
--
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- sekharan@us.ibm.com | .......you may get it.
----------------------------------------------------------------------
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2006-04-28 1:42 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-28 1:35 [PATCH 0/6] Number of Tasks Resource controller Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 1/6] numtasks - Initialization routines Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 2/6] numtasks - Add task control support Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 3/6] numtasks - Add shares and stats support Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 4/6] numtasks - Add configuration support Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 5/6] numtasks - Add fork rate control support Chandra Seetharaman
2006-04-28 1:35 ` [PATCH 6/6] numtasks - Documentation for Numtasks controller Chandra Seetharaman
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.