OpenVZ Forum


Home » Mailing lists » Devel » Re: [PATCH] ltp controllers: block device i/o bandwidth controller testcase (was: Re: [LTP] [PATCH 0
Re: [PATCH] ltp controllers: block device i/o bandwidth controller testcase (was: Re: [LTP] [PATCH 0 [message #31699] Mon, 07 July 2008 10:24 Go to previous message
Subrata Modak is currently offline  Subrata Modak
Messages: 16
Registered: August 2007
Junior Member
Thanks Andrea for contributing these tests to LTP. I will take some time
before testing this and coming back to you. Give me some time. Meanwhile
it would be great if Balbir/Dhaval/others can provide some review
comments as well.

Regards--
Subrata

On Mon, 2008-07-07 at 12:05 +0200, Andrea Righi wrote:
> Add the block device I/O bandwidth controller (io-throttle) testcase.
> 
> See testcase documentation for design and implementation details.
> See also: http://lkml.org/lkml/2008/7/4/143
> 
> Signed-off-by: Andrea Righi <righi.andrea@gmail.com>
> ---
> diff --exclude CVS -urpN ltp/testcases/kernel/controllers.orig/io-throttle/iobw.c ltp/testcases/kernel/controllers/io-throttle/iobw.c
> --- ltp/testcases/kernel/controllers.orig/io-throttle/iobw.c	1970-01-01 01:00:00.000000000 +0100
> +++ ltp/testcases/kernel/controllers/io-throttle/iobw.c	2008-07-07 11:44:51.000000000 +0200
> @@ -0,0 +1,279 @@
> +/*
> + * iobw.c - simple I/O bandwidth benchmark
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public
> + * License along with this program; if not, write to the
> + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
> + * Boston, MA 021110-1307, USA.
> + *
> + * Copyright (C) 2008 Andrea Righi <righi.andrea@gmail.com>
> + */
> +
> +#define _GNU_SOURCE
> +#define __USE_GNU
> +
> +#include <errno.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <malloc.h>
> +#include <fcntl.h>
> +#include <signal.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <sys/time.h>
> +#include <sys/wait.h>
> +#include <asm/page.h>
> +
> +#define ALIGN(x,a)		__ALIGN_MASK(x,(typeof(x))(a)-1)
> +#define __ALIGN_MASK(x,mask)	(((x)+(mask))&~(mask))
> +#define KB(x)			((x) >> 10)
> +
> +const char usage[] = "Usage: iobw [-direct] threads chunk_size data_size\n";
> +const char child_fmt[] =
> +		"(%s) task %3d: time %4lu.%03lu bw %7lu KiB/s (%s)\n";
> +const char parent_fmt[] =
> +		"(%s) parent %d: time %4lu.%03lu bw %7lu KiB/s (%s)\n";
> +
> +static int directio = 0;
> +static size_t data_size = 0;
> +static size_t chunk_size = 0;
> +
> +typedef enum {
> +	OP_WRITE,
> +	OP_READ,
> +	NUM_IOPS,
> +} iops_t;
> +
> +static const char *iops[] = {
> +	"WRITE",
> +	"READ ",
> +	"TOTAL",
> +};
> +
> +static int threads;
> +pid_t *children;
> +
> +char *mygroup;
> +
> +static void print_results(int id, iops_t op, size_t bytes, struct timeval *diff)
> +{
> +	fprintf(stdout, id ? child_fmt : parent_fmt,
> +		mygroup, id, diff->tv_sec, diff->tv_usec / 1000,
> +		(bytes / (diff->tv_sec * 1000000L + diff->tv_usec))
> +		* 1000000L / 1024, iops[op]);
> +}
> +
> +static void thread(int id)
> +{
> +	struct timeval start, stop, diff;
> +	int fd, i, ret;
> +	size_t n;
> +	void *buf;
> +	int flags = O_CREAT | O_RDWR | O_LARGEFILE;
> +	char filename[32];
> +
> +	ret = posix_memalign(&buf, PAGE_SIZE, chunk_size);
> +	if (ret < 0) {
> +		fprintf(stderr,
> +			"ERROR: task %d couldn't allocate %lu bytes (%s)\n",
> +			id, chunk_size, strerror(errno));
> +		exit(1);
> +	}
> +	memset(buf, 0xaa, chunk_size);
> +
> +	snprintf(filename, sizeof(filename), "%s-%d-iobw.tmp", mygroup, id);
> +	if (directio)
> +		flags |= O_DIRECT;
> +	fd = open(filename, flags, 0600);
> +	if (fd < 0) {
> +		fprintf(stderr, "ERROR: task %d couldn't open %s (%s)\n",
> +			id, filename, strerror(errno));
> +		free(buf);
> +		exit(1);
> +	}
> +
> +	/* Write */
> +	lseek(fd, 0, SEEK_SET);
> +	n = 0;
> +	gettimeofday(&start, NULL);
> +	while (n < data_size) {
> +		i = write(fd, buf, chunk_size);
> +		if (i < 0) {
> +			fprintf(stderr, "ERROR: task %d writing to %s (%s)\n",
> +				id, filename, strerror(errno));
> +			ret = 1;
> +			goto out;
> +		}
> +		n += i;
> +	}
> +        gettimeofday(&stop, NULL);
> +        timersub(&stop, &start, &diff);
> +	print_results(id + 1, OP_WRITE, data_size, &diff);
> +
> +	/* Read */
> +	lseek(fd, 0, SEEK_SET);
> +	n = 0;
> +	gettimeofday(&start, NULL);
> +	while (n < data_size) {
> +		i = read(fd, buf, chunk_size);
> +		if (i < 0) {
> +			fprintf(stderr, "ERROR: task %d reading to %s (%s)\n",
> +				id, filename, strerror(errno));
> +			ret = 1;
> +			goto out;
> +		}
> +		n += i;
> +	}
> +        gettimeofday(&stop, NULL);
> +        timersub(&stop, &start, &diff);
> +	print_results(id + 1, OP_READ, data_size, &diff);
> +out:
> +	close(fd);
> +	unlink(filename);
> +	free(buf);
> +	exit(ret);
> +}
> +
> +static void spawn(int id)
> +{
> +	pid_t pid;
> +
> +	pid = fork();
> +	switch (pid) {
> +	case -1:
> +		fprintf(stderr, "ERROR: couldn't fork thread %d\n", id);
> +		exit(1);
> +	case 0:
> +		thread(id);
> +	default:
> +		children[id] = pid;
> +	}
> +}
> +
> +void signal_handler(int sig)
> +{
> +	char filename[32];
> +	int i;
> +
> +	for (i = 0; i < threads; i++)
> +		if (children[i])
> +			kill(children[i], SIGKILL);
> +
> +	for (i = 0; i < threads; i++) {
> +		struct stat mystat;
> +
> +		snprintf(filename, sizeof(filename), "%s-%d-iobw.tmp",
> +				mygroup,i);
> +		if (stat(filename, &mystat) < 0)
> +			continue;
> +		unlink(filename);
> +	}
> +
> +	fprintf(stdout, "received signal %d, exiting\n", sig);
> +	exit(0);
> +}
> +
> +unsigned long long memparse(char *ptr, char **retptr)
> +{
> +	unsigned long long ret = strtoull(ptr, retptr, 0);
> +
> +	switch (**retptr) {
> +	case 'G':
> +	case 'g':
> +		ret <<= 10;
> +	case 'M':
> +	case 'm':
> +		ret <<= 10;
> +	case 'K':
> +	case 'k':
> +		ret <<= 10;
> +		(*retptr)++;
> +	default:
> +		break;
> +	}
> +	return ret;
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +	struct timeval start, stop, diff;
> +	char *end;
> +	int i;
> +
> +	if (argv[1] && strcmp(argv[1], "-direct") == 0) {
> +		directio = 1;
> +		argc--;
> +		argv++;
> +	}
> +	if (argc != 4) {
> +		fprintf(stderr, usage);
> +		exit(1);
> +	}
> +	if ((threads = atoi(argv[1])) == 0) {
> +		fprintf(stderr, usage);
> +		exit(1);
> +	}
> +	chunk_size = ALIGN(memparse(argv[2], &end), PAGE_SIZE);
> +	if (*end) {
> +		fprintf(stderr, usage);
> +		exit(1);
> +	}
> +	data_size = ALIGN(memparse(argv[3], &end), PAGE_SIZE);
> +	if (*end) {
> +		fprintf(stderr, usage);
> +		exit(1);
> +	}
> +
> +	/* retrieve group name */
> +	mygroup = getenv("MYGROUP");
> +	if (!mygroup) {
> +		fprintf(stderr,
> +			"ERROR: undefined environment variable MYGROUP\n");
> +		exit(1);
> +	}
> +
> +	children = malloc(sizeof(pid_t) * threads);
> +	if (!children) {
> +		fprintf(stderr, "ERROR: not enough memory\n");
> +		exit(1);
> +	}
> +
> +	/* handle user interrupt */
> +	signal(SIGINT, signal_handler);
> +	/* handle kill from shell */
> +	signal(SIGTERM, signal_handler);
> +
> +	fprintf(stdout, "chunk_size %luKiB, data_size %luKiB\n",
> +		KB(chunk_size), KB(data_size));
> +	fflush(stdout);
> +
> +        gettimeofday(&start, NULL);
> +        for (i = 0; i < threads ; i++)
> +                spawn(i);
> +        for (i = 0; i < threads; i++) {
> +                int status;
> +                wait(&status);
> +                if (!WIFEXITED(status))
> +                        exit(1);
> +        }
> +        gettimeofday(&stop, NULL);
> +
> +        timersub(&stop, &start, &diff);
> +	print_results(0, NUM_IOPS, data_size * threads * NUM_IOPS, &diff);
> +	fflush(stdout);
> +	free(children);
> +
> +        exit(0);
> +}
> diff --exclude CVS -urpN ltp/testcases/kernel/controllers.orig/io-throttle/io_throttle_testplan.txt ltp/testcases/kernel/controllers/io-throttle/io_throttle_testplan.txt
> --- ltp/testcases/kernel/controllers.orig/io-throttle/io_throttle_testplan.txt	1970-01-01 01:00:00.000000000 +0100
> +++ ltp/testcases/kernel/controllers/io-throttle/io_throttle_testplan.txt	2008-07-07 11:25:25.000000000 +0200
> @@ -0,0 +1,36 @@
> +The I/O bandwidth controller testplan includes a complete set of testcases to
> +verify the effectiveness of the block device I/O throttling capabilities for
> +cgroups.
> +
> +I/O bandwidth limitations are imposed by the testcase script and verified doing
> +I/O activity on a limited block device. Tests are supposed to be passed if the
> +I/O rates of all the different workloads always respect the I/O
...

 
Read Message
Read Message
Read Message
Previous Topic: mini-summit conf#
Next Topic: [RFC] Transactional CGroup task attachment
Goto Forum:
  


Current Time: Fri Oct 18 16:58:28 GMT 2024

Total time taken to generate the page: 0.05716 seconds