[PATCH 3/6] numtasks - Add shares and stats support

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

 



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 <[email protected]>
Signed-off-by: MAEDA Naoaki <[email protected]>
Signed-Off-By: Matt Helsley <[email protected]>

 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....
              - [email protected]   |      .......you may get it.
----------------------------------------------------------------------
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux