[RFC][PATCH 0/4] Aggregated beancounters (v3)

From: Balbir Singh
Date: Sun Sep 17 2006 - 13:54:00 EST


Attempt #3 to build aggregated beancounters on top of beancounters.
The earlier patch built per tgid beancounters, but that did not work
well. Subsystems keep track of references to beancounters. This patch
creates an aggregated beancounters - they aggregate beancounters. A
beancounter is created for every tgid.

This patch is an RFC for early comments and discussion and a proof of
concept approach to check if this approach can be used as a basis to support
task migration. Dave Hansen initially suggested the idea.

TODOs (some of so many)

1. Add limit checking before migrating tasks
2. Add support for reclamation.
3. Add support for guarantees
4. Add support for per-task beancounters (cpu controller is likely to
require it)

series
------
per-tgid-beancounters.patch
add-aggr-bc.patch
aggr-bc-syscalls.patch
aggr-bc-charging-support.patch

This patch was minimally tested on a x86-64 box.

Comments?

Balbir Singh


Utility ctl.c for controlling and creating beancounters
-------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <getopt.h>
#include <string.h>
#include <asm/unistd.h>

#ifdef DEBUG
#define debug(x...) printf(x)
#else
#define debug(x...)
#endif

#define err(stream, msg...) fprintf(stream, msg), exit(1);

char *resources[] = {
"kmemsize",
"lockedpages",
"privvmpages",
};

/*
* For i386
*/
#if 0
#define __NR_get_bcid 319
#define __NR_set_bcid 320
#define __NR_set_bclimit 321
#define __NR_get_bcstat 322
#endif

/* For ia64 */
#define __NR_get_bcid 280
#define __NR_set_bcid 281
#define __NR_set_bclimit 282
#define __NR_get_bcstat 283

struct ab_resource_parm {
unsigned long barrier;
unsigned long held;
unsigned long limit; /* hard resource limit */
unsigned long failcnt; /* count of failed charges */
};

struct bc_resource_parm {
unsigned long barrier; /* A barrier over which resource allocations
* are failed gracefully. e.g. if the amount
* of consumed memory is over the barrier
* further sbrk() or mmap() calls fail, the
* existing processes are not killed.
*/
unsigned long limit; /* hard resource limit */
unsigned long held; /* consumed resources */
unsigned long maxheld; /* maximum amount of consumed resources */
unsigned long minheld; /* minumum amount of consumed resources */
unsigned long failcnt; /* count of failed charges */
};

_syscall2(long, set_bcid, int, id, int, pid)
_syscall0(long, get_bcid)
_syscall3(long, set_bclimit, int, id, unsigned long, resource, unsigned long *,
limits)
_syscall5(long, get_bcstat, int, ab_id, int, bc_id,
unsigned long, resource, struct bc_resource_parm *,
bc_parm, struct ab_resource_parm *, ab_parm)

int main(int argc, char *argv[])
{
int opt;
int ab_id = 0, bc_id;
unsigned long limit[2] = { 0, 0 };
int rc = 0;
int set_limit = 0;
struct bc_resource_parm bc_parm;
struct ab_resource_parm ab_parm;
int res_id = 0;
int pid = getpid();

do {
opt = getopt(argc, argv, "i:c:b:l:d:gr:p:");
if (opt < 0)
break;
switch (opt) {
case 'i':
ab_id = atoi(optarg);
debug("id %d\n", ab_id);
break;
case 'p':
pid = atoi(optarg);
debug("pid %d\n", pid);
break;
case 'r':
res_id = atoi(optarg);
debug("resource %s\n", resources[res_id]);
break;
case 'c':
ab_id = atoi(optarg);
debug("ab_id %d\n", ab_id);
rc = set_bcid(ab_id, pid);
if (rc < 0) {
perror("set_bcid failed:");
break;
}
break;
case 'g':
rc = get_bcid();
if (rc < 0) {
perror("set_bcid failed:");
break;
}
printf("current id %d\n", rc);
break;
case 'd':
bc_id = atoi(optarg);
rc = get_bcstat(bc_id, ab_id, res_id, &bc_parm,
&ab_parm);
if (rc < 0) {
perror("getstat failed:");
break;
}
printf("BC: %d, limit %lu, barrier %lu held %lu\n",
bc_id, bc_parm.barrier, bc_parm.limit,
bc_parm.held);
printf("AB: %d, limit %lu, barrier %lu held %lu\n",
ab_id, ab_parm.barrier, ab_parm.limit,
ab_parm.held);
break;
case 'b':
limit[0] = atoi(optarg);
if (limit[0] == 0)
err(stderr,
"Invalid barrier, please try again barrier"
" %lu\n", limit[0]);
debug("barrier is %lu\n", limit[0]);
break;
case 'l':
set_limit = 1;
limit[1] = atoi(optarg);
if (limit[1] == 0)
err(stderr,
"Invalid limit, please try again limit %lu\n",
limit[1]);
debug("limit is %lu\n", limit[1]);
break;
default:
err(stderr, "unknown option %c\n", opt);
}
} while (1);

if (set_limit && ab_id && limit[0] && limit[1]) {
rc = set_bclimit(ab_id, 0UL, limit);
if (rc < 0)
perror("set_bclimit failed: ");
}
return rc;
}

--

Balbir Singh,
Linux Technology Center,
IBM Software Labs
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/