From: Chandra Seetharaman <sekharan@us.ibm.com>
To: ckrm-tech <ckrm-tech@lists.sourceforge.net>,
linux-mm <linux-mm@kvack.org>
Subject: [PATCH 3/6] CKRM: Add limit support for mem controller
Date: Fri, 24 Jun 2005 15:24:54 -0700 [thread overview]
Message-ID: <1119651894.5105.20.camel@linuxchandra> (raw)
Patch 3 of 6 patches to support memory controller under CKRM framework.
This patch provides the limit support for the controller.
----------------------------------------
include/linux/ckrm_mem.h | 2
kernel/ckrm/ckrm_memcore.c | 156 +++++++++++++++++++++++++++++++++++++
++++++--
kernel/ckrm/ckrm_memctlr.c | 15 ++++
3 files changed, 168 insertions(+), 5 deletions(-)
Content-Disposition: inline; filename=11-03-mem_core-limit
Index: linux-2.6.12/include/linux/ckrm_mem.h
===================================================================
--- linux-2.6.12.orig/include/linux/ckrm_mem.h
+++ linux-2.6.12/include/linux/ckrm_mem.h
@@ -44,6 +44,8 @@ struct ckrm_mem_res {
* parent if more than this is needed.
*/
int hier; /* hiearchy level, root = 0 */
+ int implicit_guar; /* for classes with don't care guar */
+ int nr_dontcare; /* # of dont care children */
};
extern atomic_t ckrm_mem_real_count;
Index: linux-2.6.12/kernel/ckrm/ckrm_memcore.c
===================================================================
--- linux-2.6.12.orig/kernel/ckrm/ckrm_memcore.c
+++ linux-2.6.12/kernel/ckrm/ckrm_memcore.c
@@ -95,9 +95,46 @@ mem_res_initcls_one(struct ckrm_mem_res
INIT_LIST_HEAD(&res->mcls_list);
res->pg_unused = 0;
+ res->nr_dontcare = 1; /* for default class */
kref_init(&res->nr_users);
}
+static void
+set_impl_guar_children(struct ckrm_mem_res *parres)
+{
+ struct ckrm_core_class *child = NULL;
+ struct ckrm_mem_res *cres;
+ int nr_dontcare = 1; /* for defaultclass */
+ int guar, impl_guar;
+ int resid = mem_rcbs.resid;
+
+ ckrm_lock_hier(parres->core);
+ while ((child = ckrm_get_next_child(parres->core, child)) != NULL) {
+ cres = ckrm_get_res_class(child, resid, struct ckrm_mem_res);
+ /* treat NULL cres as don't care as that child is just being
+ * created.
+ * FIXME: need a better way to handle this case.
+ */
+ if (!cres || cres->pg_guar == CKRM_SHARE_DONTCARE)
+ nr_dontcare++;
+ }
+
+ parres->nr_dontcare = nr_dontcare;
+ guar = (parres->pg_guar == CKRM_SHARE_DONTCARE) ?
+ parres->implicit_guar : parres->pg_unused;
+ impl_guar = guar / parres->nr_dontcare;
+
+ while ((child = ckrm_get_next_child(parres->core, child)) != NULL) {
+ cres = ckrm_get_res_class(child, resid, struct ckrm_mem_res);
+ if (cres && cres->pg_guar == CKRM_SHARE_DONTCARE) {
+ cres->implicit_guar = impl_guar;
+ set_impl_guar_children(cres);
+ }
+ }
+ ckrm_unlock_hier(parres->core);
+
+}
+
static void *
mem_res_alloc(struct ckrm_core_class *core, struct ckrm_core_class
*parent)
{
@@ -139,14 +176,106 @@ mem_res_alloc(struct ckrm_core_class *co
res->pg_limit = ckrm_tot_lru_pages;
res->hier = 0;
ckrm_mem_root_class = res;
- } else
+ } else {
+ int guar;
res->hier = pres->hier + 1;
+ set_impl_guar_children(pres);
+ guar = (pres->pg_guar == CKRM_SHARE_DONTCARE) ?
+ pres->implicit_guar : pres->pg_unused;
+ res->implicit_guar = guar / pres->nr_dontcare;
+ }
ckrm_nr_mem_classes++;
} else
printk(KERN_ERR "MEM_RC: alloc: GFP_ATOMIC failed\n");
return res;
}
+/*
+ * It is the caller's responsibility to make sure that the parent only
+ * has chilren that are to be accounted. i.e if a new child is added
+ * this function should be called after it has been added, and if a
+ * child is deleted this should be called after the child is removed.
+ */
+static void
+child_maxlimit_changed_local(struct ckrm_mem_res *parres)
+{
+ int maxlimit = 0;
+ struct ckrm_mem_res *childres;
+ struct ckrm_core_class *child = NULL;
+
+ /* run thru parent's children and get new max_limit of parent */
+ ckrm_lock_hier(parres->core);
+ while ((child = ckrm_get_next_child(parres->core, child)) != NULL) {
+ childres = ckrm_get_res_class(child, mem_rcbs.resid,
+ struct ckrm_mem_res);
+ if (maxlimit < childres->shares.my_limit)
+ maxlimit = childres->shares.my_limit;
+ }
+ ckrm_unlock_hier(parres->core);
+ parres->shares.cur_max_limit = maxlimit;
+}
+
+/*
+ * Recalculate the guarantee and limit in # of pages... and propagate
the
+ * same to children.
+ * Caller is responsible for protecting res and for the integrity of
parres
+ */
+static void
+recalc_and_propagate(struct ckrm_mem_res * res, struct ckrm_mem_res *
parres)
+{
+ struct ckrm_core_class *child = NULL;
+ struct ckrm_mem_res *cres;
+ int resid = mem_rcbs.resid;
+ struct ckrm_shares *self = &res->shares;
+
+ if (parres) {
+ struct ckrm_shares *par = &parres->shares;
+
+ /* calculate pg_guar and pg_limit */
+ if (parres->pg_guar == CKRM_SHARE_DONTCARE ||
+ self->my_guarantee == CKRM_SHARE_DONTCARE) {
+ res->pg_guar = CKRM_SHARE_DONTCARE;
+ } else if (par->total_guarantee) {
+ u64 temp = (u64) self->my_guarantee * parres->pg_guar;
+ do_div(temp, par->total_guarantee);
+ res->pg_guar = (int) temp;
+ res->implicit_guar = CKRM_SHARE_DONTCARE;
+ } else {
+ res->pg_guar = 0;
+ res->implicit_guar = CKRM_SHARE_DONTCARE;
+ }
+
+ if (parres->pg_limit == CKRM_SHARE_DONTCARE ||
+ self->my_limit == CKRM_SHARE_DONTCARE) {
+ res->pg_limit = CKRM_SHARE_DONTCARE;
+ } else if (par->max_limit) {
+ u64 temp = (u64) self->my_limit * parres->pg_limit;
+ do_div(temp, par->max_limit);
+ res->pg_limit = (int) temp;
+ } else
+ res->pg_limit = 0;
+ }
+
+ /* Calculate unused units */
+ if (res->pg_guar == CKRM_SHARE_DONTCARE)
+ res->pg_unused = CKRM_SHARE_DONTCARE;
+ else if (self->total_guarantee) {
+ u64 temp = (u64) self->unused_guarantee * res->pg_guar;
+ do_div(temp, self->total_guarantee);
+ res->pg_unused = (int) temp;
+ } else
+ res->pg_unused = 0;
+
+ /* propagate to children */
+ ckrm_lock_hier(res->core);
+ while ((child = ckrm_get_next_child(res->core, child)) != NULL) {
+ cres = ckrm_get_res_class(child, resid, struct ckrm_mem_res);
+ recalc_and_propagate(cres, res);
+ }
+ ckrm_unlock_hier(res->core);
+ return;
+}
+
static void
mem_res_free(void *my_res)
{
@@ -161,6 +290,14 @@ mem_res_free(void *my_res)
pres = ckrm_get_res_class(res->parent, mem_rcbs.resid,
struct ckrm_mem_res);
+ if (pres) {
+ child_guarantee_changed(&pres->shares,
+ res->shares.my_guarantee, 0);
+ child_maxlimit_changed_local(pres);
+ recalc_and_propagate(pres, NULL);
+ set_impl_guar_children(pres);
+ }
+
/*
* Making it all zero as freeing of data structure could
* happen later.
@@ -186,13 +323,24 @@ static int
mem_set_share_values(void *my_res, struct ckrm_shares *shares)
{
struct ckrm_mem_res *res = my_res;
+ struct ckrm_mem_res *parres;
+ int rc;
if (!res)
return -EINVAL;
- printk(KERN_INFO "set_share called for %s resource of class %s\n",
- MEM_RES_NAME, res->core->name);
- return 0;
+ parres = ckrm_get_res_class(res->parent, mem_rcbs.resid,
+ struct ckrm_mem_res);
+
+ rc = set_shares(shares, &res->shares, parres ? &parres->shares :
NULL);
+
+ if ((rc == 0) && (parres != NULL)) {
+ child_maxlimit_changed_local(parres);
+ recalc_and_propagate(parres, NULL);
+ set_impl_guar_children(parres);
+ }
+
+ return rc;
}
static int
Index: linux-2.6.12/kernel/ckrm/ckrm_memctlr.c
===================================================================
--- linux-2.6.12.orig/kernel/ckrm/ckrm_memctlr.c
+++ linux-2.6.12/kernel/ckrm/ckrm_memctlr.c
@@ -66,7 +66,20 @@ decr_use_count(struct ckrm_mem_res *cls,
int
ckrm_class_limit_ok(struct ckrm_mem_res *cls)
{
- return 1; /* stub for now */
+ int ret, i, pg_total = 0;
+
+ if ((mem_rcbs.resid == -1) || !cls)
+ return 1;
+ for (i = 0; i < MAX_NR_ZONES; i++)
+ pg_total += cls->pg_total[i];
+ if (cls->pg_limit == CKRM_SHARE_DONTCARE) {
+ struct ckrm_mem_res *parcls = ckrm_get_res_class(cls->parent,
+ mem_rcbs.resid, struct ckrm_mem_res);
+ ret = (parcls ? ckrm_class_limit_ok(parcls) : 0);
+ } else
+ ret = (pg_total <= cls->pg_limit);
+
+ return ret;
}
static void migrate_list(struct list_head *list,
--
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- sekharan@us.ibm.com | .......you may get it.
----------------------------------------------------------------------
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>
next reply other threads:[~2005-06-24 22:24 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-06-24 22:24 Chandra Seetharaman [this message]
-- strict thread matches above, loose matches on Subject: below --
2005-05-19 0:32 Chandra Seetharaman
2005-04-02 3:13 Chandra Seetharaman
2005-04-04 14:10 ` Dave Hansen
2005-04-05 17:42 ` Chandra Seetharaman
2005-04-05 17:59 ` Dave Hansen
2005-04-05 18:26 ` Chandra Seetharaman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1119651894.5105.20.camel@linuxchandra \
--to=sekharan@us.ibm.com \
--cc=ckrm-tech@lists.sourceforge.net \
--cc=linux-mm@kvack.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox