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

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

 



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 [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