diff options
| author | Adrian Hunter <ext-adrian.hunter@nokia.com> | 2007-03-15 08:45:19 -0500 | 
|---|---|---|
| committer | Josh Boyer <jwboyer@gmail.com> | 2007-03-15 08:45:19 -0500 | 
| commit | 726ac243f051f0daee6149db66ac21ba621fb454 (patch) | |
| tree | 257483dc155e539e5d7f08fb8009c57181919962 /tests/fs-tests/stress/atoms | |
| parent | 876476b7bbf158c64868d379460a7b6bce7e95e0 (diff) | |
Add fs-tests from Adrian Hunter
Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com>
Signed-off-by: Josh Boyer <jwboyer@gmail.com>
Diffstat (limited to 'tests/fs-tests/stress/atoms')
| -rw-r--r-- | tests/fs-tests/stress/atoms/Makefile | 40 | ||||
| -rw-r--r-- | tests/fs-tests/stress/atoms/fwrite00.c | 209 | ||||
| -rw-r--r-- | tests/fs-tests/stress/atoms/gcd_hupper.c | 259 | ||||
| -rw-r--r-- | tests/fs-tests/stress/atoms/pdfrun.c | 143 | ||||
| -rw-r--r-- | tests/fs-tests/stress/atoms/rmdir00.c | 133 | ||||
| -rw-r--r-- | tests/fs-tests/stress/atoms/rndrm00.c | 157 | ||||
| -rw-r--r-- | tests/fs-tests/stress/atoms/rndrm99.c | 431 | ||||
| -rw-r--r-- | tests/fs-tests/stress/atoms/rndwrite00.c | 201 | ||||
| -rw-r--r-- | tests/fs-tests/stress/atoms/stress_1.c | 109 | ||||
| -rw-r--r-- | tests/fs-tests/stress/atoms/stress_2.c | 120 | ||||
| -rw-r--r-- | tests/fs-tests/stress/atoms/stress_3.c | 122 | 
11 files changed, 1924 insertions, 0 deletions
| diff --git a/tests/fs-tests/stress/atoms/Makefile b/tests/fs-tests/stress/atoms/Makefile new file mode 100644 index 0000000..9fbfd39 --- /dev/null +++ b/tests/fs-tests/stress/atoms/Makefile @@ -0,0 +1,40 @@ + +ifeq ($(origin CC),default) +CC = gcc +endif + +CFLAGS := $(CFLAGS) -Wall -g -O2 -I../../lib + +LDFLAGS := $(LDFLAGS) + +TARGETS = stress_1 \ +	stress_2 \ +	stress_3 \ +	pdfrun \ +	rndwrite00 \ +	fwrite00 \ +	rmdir00 \ +	rndrm00 \ +	rndrm99 \ +	gcd_hupper + +all: $(TARGETS) + +$(TARGETS): ../../lib/tests.o + +../lib/tests.o: ../../lib/tests.h + +clean: +	rm -f *.o $(TARGETS) run_pdf_test_file + +tests: all +	./stress_1 -e +	./stress_2 +	./stress_3 -e +	./pdfrun +	./rndwrite00 -e +	./fwrite00 +	./rmdir00 +	./rndrm00 +	./rndrm99 +	./gcd_hupper diff --git a/tests/fs-tests/stress/atoms/fwrite00.c b/tests/fs-tests/stress/atoms/fwrite00.c new file mode 100644 index 0000000..2f40b3d --- /dev/null +++ b/tests/fs-tests/stress/atoms/fwrite00.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2007 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Author: Adrian Hunter + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include "tests.h" + +#define WRITE_BUFFER_SIZE 32768 + +#define HOLE_BLOCK_SIZE 10000000 + +void filestress00(void) +{ +	int fd, i, deleted; +	pid_t pid; +	ssize_t written; +	int64_t remains; +	int64_t repeat; +	size_t block; +	char file_name[256]; +	char buf[WRITE_BUFFER_SIZE]; + +	fd = -1; +	deleted = 1; +	pid = getpid(); +	tests_cat_pid(file_name, "filestress00_test_file_", pid); +	srand(pid); +	repeat = tests_repeat_parameter; +	for (;;) { +		/* Open the file */ +		if (fd == -1) { +			fd = open(file_name, O_CREAT | O_WRONLY, +			  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); +			CHECK(fd != -1); +			deleted = 0; +			if (tests_unlink_flag) { +				CHECK(unlink(file_name) != -1); +				deleted = 1; +			} +		} +		/* Get a different set of random data */ +		for (i = 0; i < WRITE_BUFFER_SIZE;++i) +			buf[i] = rand(); +		if (tests_hole_flag) { +			/* Make a hole */ +			CHECK(lseek(fd, tests_size_parameter, SEEK_SET) != -1); +			written = write(fd, "!", 1); +			if (written <= 0) { +				/* File system full */ +				CHECK(errno == ENOSPC); +				errno = 0; +			} +			CHECK(lseek(fd, 0, SEEK_SET) != -1); +			/* Write at set points into the hole */ +			remains = tests_size_parameter; +			while (remains > HOLE_BLOCK_SIZE) { +				CHECK(lseek(fd, HOLE_BLOCK_SIZE, +						SEEK_CUR) != -1); +				written = write(fd, "!", 1); +				remains -= HOLE_BLOCK_SIZE; +				if (written <= 0) { +					/* File system full */ +					CHECK(errno == ENOSPC); +					errno = 0; +					break; +				} +			} +		} else { +			/* Write data into the file */ +			CHECK(lseek(fd, 0, SEEK_SET) != -1); +			remains = tests_size_parameter; +			while (remains > 0) { +				if (remains > WRITE_BUFFER_SIZE) +					block = WRITE_BUFFER_SIZE; +				else +					block = remains; +				written = write(fd, buf, block); +				if (written <= 0) { +					/* File system full */ +					CHECK(errno == ENOSPC); +					errno = 0; +					break; +				} +				remains -= written; +			} +		} +		/* Break if repeat count exceeded */ +		if (tests_repeat_parameter > 0 && --repeat <= 0) +			break; +		/* Close if tests_close_flag */ +		if (tests_close_flag) { +			CHECK(close(fd) != -1); +			fd = -1; +		} +		/* Sleep */ +		if (tests_sleep_parameter > 0) { +			unsigned us = tests_sleep_parameter * 1000; +			unsigned rand_divisor = RAND_MAX / us; +			unsigned s = (us / 2) + (rand() / rand_divisor); +			usleep(s); +		} +		/* Delete if tests_delete flag */ +		if (!deleted && tests_delete_flag) { +			CHECK(unlink(file_name) != -1); +			deleted = 1; +		} +	} +	CHECK(close(fd) != -1); +	/* Sleep */ +	if (tests_sleep_parameter > 0) { +		unsigned us = tests_sleep_parameter * 1000; +		unsigned rand_divisor = RAND_MAX / us; +		unsigned s = (us / 2) + (rand() / rand_divisor); +		usleep(s); +	} +	/* Tidy up */ +	if (!deleted) +		CHECK(unlink(file_name) != -1); +} + +/* Title of this test */ + +const char *filestress00_get_title(void) +{ +	return "File stress test 00"; +} + +/* Description of this test */ + +const char *filestress00_get_description(void) +{ +	return +		"Create a file named filestress00_test_file_pid, where " \ +		"pid is the process id.  If the unlink option " \ +		"(-u or --unlink) is specified, " \ +		"unlink the file while holding the open file descriptor. " \ +		"If the hole option (-o or --hole) is specified, " \ +		"write a single character at the end of the file, creating a " \ +		"hole. " \ +		"Write a single character in the hole every 10 million " \ +		"bytes. " \ +		"If the hole option is not specified, then the file is " \ +		"filled with random data. " \ +		"If the close option (-c or --close) is specified the file " \ +		"is closed. " \ +		"If a sleep value is specified, the process sleeps. " \ +		"If the delete option (-e or --delete) is specified, then " \ +		"the file is deleted. " \ +		"If a repeat count is specified, then the task repeats " \ +		"that number of times. " \ +		"The repeat count is given by the -n or --repeat option, " \ +		"otherwise it defaults to 1. " \ +		"A repeat count of zero repeats forever. " \ +		"The file size is given by the -z or --size option, " \ +		"otherwise it defaults to 1000000. " \ +		"The sleep value is given by the -p or --sleep option, " \ +		"otherwise it defaults to 0. " \ +		"Sleep is specified in milliseconds."; +} + +int main(int argc, char *argv[]) +{ +	int run_test; + +	/* Set default test file size */ +	tests_size_parameter = 1000000; + +	/* Set default test repetition */ +	tests_repeat_parameter = 1; + +	/* Set default test sleep */ +	tests_sleep_parameter = 0; + +	/* Handle common arguments */ +	run_test = tests_get_args(argc, argv, filestress00_get_title(), +			filestress00_get_description(), "znpuoce"); +	if (!run_test) +		return 1; +	/* Change directory to the file system and check it is ok for testing */ +	tests_check_test_file_system(); +	/* Do the actual test */ +	filestress00(); +	return 0; +} diff --git a/tests/fs-tests/stress/atoms/gcd_hupper.c b/tests/fs-tests/stress/atoms/gcd_hupper.c new file mode 100644 index 0000000..31c175d --- /dev/null +++ b/tests/fs-tests/stress/atoms/gcd_hupper.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2007 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Author: Adrian Hunter + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <ctype.h> +#include <dirent.h> +#include <mntent.h> +#include <signal.h> + +#include "tests.h" + +#define MAX_NAME_SIZE 1024 + +struct gcd_pid +{ +	struct gcd_pid *next; +	int pid; +	char *name; +	int mtd_index; +}; + +struct gcd_pid *gcd_pid_list = NULL; + +int add_gcd_pid(const char *number) +{ +	int pid; +	FILE *f; +	char file_name[MAX_NAME_SIZE]; +	char program_name[MAX_NAME_SIZE]; + +	pid = atoi(number); +	if (pid <= 0) +		return 0; +	snprintf(file_name, MAX_NAME_SIZE, "/proc/%s/stat", number); +	f = fopen(file_name, "r"); +	if (f == NULL) +		return 0; +	if (fscanf(f, "%d %s", &pid, program_name) != 2) { +		fclose(f); +		return 0; +	} +	if (strncmp(program_name, "(jffs2_gcd_mtd", 14) != 0) +		pid = 0; +	if (pid) { +		size_t sz; +		struct gcd_pid *g; + +		sz = sizeof(struct gcd_pid); +		g = (struct gcd_pid *) malloc(sz); +		g->pid = pid; +		g->name = (char *) malloc(strlen(program_name) + 1); +		if (g->name) +			strcpy(g->name, program_name); +		else +			exit(1); +		g->mtd_index = atoi(program_name + 14); +		g->next = gcd_pid_list; +		gcd_pid_list = g; +	} +	fclose(f); +	return pid; +} + +int get_pid_list(void) +{ +	DIR *dir; +	struct dirent *entry; + +	dir = opendir("/proc"); +	if (dir == NULL) +		return 1; +	for (;;) { +		entry = readdir(dir); +		if (entry) { +			if (strcmp(".",entry->d_name) != 0 && +					strcmp("..",entry->d_name) != 0) +				add_gcd_pid(entry->d_name); +		} else +			break; +	} +	closedir(dir); +	return 0; +} + +int parse_index_number(const char *name) +{ +	const char *p, *q; +	int all_zero; +	int index; + +	p = name; +	while (*p && !isdigit(*p)) +		++p; +	if (!*p) +		return -1; +	all_zero = 1; +	for (q = p; *q; ++q) { +		if (!isdigit(*q)) +			return -1; +		if (*q != '0') +			all_zero = 0; +	} +	if (all_zero) +		return 0; +	index = atoi(p); +	if (index <= 0) +		return -1; +	return index; +} + +int get_mtd_index(void) +{ +	FILE *f; +	struct mntent *entry; +	struct stat f_info; +	struct stat curr_f_info; +	int found; +	int mtd_index = -1; + +	if (stat(tests_file_system_mount_dir, &f_info) == -1) +		return -1; +	f = fopen("/proc/mounts", "rb"); +	if (!f) +		f = fopen("/etc/mtab", "rb"); +	if (f == NULL) +		return -1; +	found = 0; +	for (;;) { +		entry = getmntent(f); +		if (!entry) +			break; +		if (stat(entry->mnt_dir, &curr_f_info) == -1) +			continue; +		if (f_info.st_dev == curr_f_info.st_dev) { +			int i; + +			i = parse_index_number(entry->mnt_fsname); +			if (i != -1) { +				if (found && i != mtd_index) +					return -1; +				found = 1; +				mtd_index = i; +			} +		} +	} +	fclose(f); +	return mtd_index; +} + +int get_gcd_pid() +{ +	struct gcd_pid *g; +	int mtd_index; + +	if (get_pid_list()) +		return 0; +	mtd_index = get_mtd_index(); +	if (mtd_index == -1) +		return 0; +	for (g = gcd_pid_list; g; g = g->next) +		if (g->mtd_index == mtd_index) +			return g->pid; +	return 0; +} + +void gcd_hupper(void) +{ +	int64_t repeat; +	int pid; + +	pid = get_gcd_pid(); +	CHECK(pid != 0); +	repeat = tests_repeat_parameter; +	for (;;) { +		CHECK(kill(pid, SIGHUP) != -1); +		/* Break if repeat count exceeded */ +		if (tests_repeat_parameter > 0 && --repeat <= 0) +			break; +		/* Sleep */ +		if (tests_sleep_parameter > 0) { +			unsigned us = tests_sleep_parameter * 1000; +			unsigned rand_divisor = RAND_MAX / us; +			unsigned s = (us / 2) + (rand() / rand_divisor); +			usleep(s); +		} +	} +} + +/* Title of this test */ + +const char *gcd_hupper_get_title(void) +{ +	return "Send HUP signals to gcd"; +} + +/* Description of this test */ + +const char *gcd_hupper_get_description(void) +{ +	return +		"Determine the PID of the gcd process. " \ +		"Send it SIGHUP (may require root privileges). " \ +		"If a sleep value is specified, the process sleeps. " \ +		"If a repeat count is specified, then the task repeats " \ +		"that number of times. " \ +		"The repeat count is given by the -n or --repeat option, " \ +		"otherwise it defaults to 1. " \ +		"A repeat count of zero repeats forever. " \ +		"The sleep value is given by the -p or --sleep option, " \ +		"otherwise it defaults to 1. " +		"Sleep is specified in milliseconds."; +} + +int main(int argc, char *argv[]) +{ +	int run_test; + +	/* Set default test repetition */ +	tests_repeat_parameter = 1; + +	/* Set default test sleep */ +	tests_sleep_parameter = 1; + +	/* Handle common arguments */ +	run_test = tests_get_args(argc, argv, gcd_hupper_get_title(), +			gcd_hupper_get_description(), "np"); +	if (!run_test) +		return 1; +	/* Change directory to the file system and check it is ok for testing */ +	tests_check_test_file_system(); +	/* Do the actual test */ +	gcd_hupper(); +	return 0; +} diff --git a/tests/fs-tests/stress/atoms/pdfrun.c b/tests/fs-tests/stress/atoms/pdfrun.c new file mode 100644 index 0000000..3536580 --- /dev/null +++ b/tests/fs-tests/stress/atoms/pdfrun.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2007 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Author: Adrian Hunter + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include "tests.h" + +#define WRITE_BUFFER_SIZE 32768 + +void adjust_size(void) +{ +	char dummy[1024]; +	unsigned long total_memory; +	FILE *f; + +	total_memory = 0; +	f = fopen("/proc/meminfo", "r"); +	fscanf(f, "%s %lu", dummy, &total_memory); +	fclose(f); +	if (total_memory > 0 && tests_size_parameter > total_memory / 2) +		tests_size_parameter = total_memory / 2; +} + +void run_pdf(void) +{ +	int fd, i; +	pid_t pid; +	int64_t repeat; +	ssize_t written; +	int64_t remains; +	size_t block; +	char file_name[256]; +	char buf[WRITE_BUFFER_SIZE]; + +	if (tests_fs_is_currfs()) +		return; +	adjust_size(); +	pid = getpid(); +	tests_cat_pid(file_name, "run_pdf_test_file_", pid); +	fd = open(file_name, O_CREAT | O_WRONLY, +		S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); +	CHECK(fd != -1); +	pid = getpid(); +	srand(pid); +	repeat = tests_repeat_parameter; +	for (;;) { +		for (i = 0; i < WRITE_BUFFER_SIZE;++i) +			buf[i] = rand(); +		remains = tests_size_parameter; +		while (remains > 0) { +			if (remains > WRITE_BUFFER_SIZE) +				block = WRITE_BUFFER_SIZE; +			else +				block = remains; +			written = write(fd, buf, block); +			if (written <= 0) { +				CHECK(errno == ENOSPC); /* File system full */ +				errno = 0; +				break; +			} +			remains -= written; +		} +		/* Break if repeat count exceeded */ +		if (tests_repeat_parameter > 0 && --repeat <= 0) +			break; +		CHECK(lseek(fd, 0, SEEK_SET) == 0); +	} +	CHECK(close(fd) != -1); +	CHECK(unlink(file_name) != -1); +} + +/* Title of this test */ + +const char *run_pdf_get_title(void) +{ +	return "Create / overwrite a large file in the current directory"; +} + +/* Description of this test */ + +const char *run_pdf_get_description(void) +{ +	return +		"Create a file named run_pdf_test_file_pid, " \ +		"where pid is the process id.  The file is created " \ +		"in the current directory, " \ +		"if the current directory is NOT on the test " \ +		"file system, otherwise no action is taken. " \ +		"If a repeat count is specified, then the task repeats " \ +		"that number of times. " \ +		"The repeat count is given by the -n or --repeat option, " \ +		"otherwise it defaults to 1. " \ +		"A repeat count of zero repeats forever. " \ +		"The size is given by the -z or --size option, " \ +		"otherwise it defaults to 1000000. " \ +		"The size is adjusted so that it is not more than " \ +		"half the size of total memory."; +} + +int main(int argc, char *argv[]) +{ +	int run_test; + +	/* Set default test file size */ +	tests_size_parameter = 1000000; + +	/* Set default test repetition */ +	tests_repeat_parameter = 1; + +	/* Handle common arguments */ +	run_test = tests_get_args(argc, argv, run_pdf_get_title(), +			run_pdf_get_description(), "zn"); +	if (!run_test) +		return 1; +	/* Do the actual test */ +	run_pdf(); +	return 0; +} diff --git a/tests/fs-tests/stress/atoms/rmdir00.c b/tests/fs-tests/stress/atoms/rmdir00.c new file mode 100644 index 0000000..c1d0729 --- /dev/null +++ b/tests/fs-tests/stress/atoms/rmdir00.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2007 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Author: Adrian Hunter + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include "tests.h" + +void rmdir00(void) +{ +	int64_t repeat; +	int64_t size, this_size; +	pid_t pid; +	char dir_name[256]; + +	/* Create a directory to test in */ +	pid = getpid(); +	tests_cat_pid(dir_name, "rmdir00_test_dir_", pid); +	if (chdir(dir_name) == -1) +		CHECK(mkdir(dir_name, 0777) != -1); +	CHECK(chdir(dir_name) != -1); +	/* Repeat loop */ +	repeat = tests_repeat_parameter; +	size = 0; +	for (;;) { +		/* Remove everything in the directory */ +		tests_clear_dir("."); +		/* Fill with sub-dirs and small files */ +		do { +			this_size = tests_create_entry(NULL); +			if (!this_size) +				break; +			size += this_size; +		} while (this_size && +			(tests_size_parameter == 0 || +			size < tests_size_parameter)); +		/* Break if repeat count exceeded */ +		if (tests_repeat_parameter > 0 && --repeat <= 0) +			break; +		/* Sleep */ +		if (tests_sleep_parameter > 0) { +			unsigned us = tests_sleep_parameter * 1000; +			unsigned rand_divisor = RAND_MAX / us; +			unsigned s = (us / 2) + (rand() / rand_divisor); +			usleep(s); +		} +	} +	/* Tidy up by removing everything */ +	tests_clear_dir("."); +	CHECK(chdir("..") != -1); +	CHECK(rmdir(dir_name) != -1); +} + +/* Title of this test */ + +const char *rmdir00_get_title(void) +{ +	return "Create and remove directories and files"; +} + +/* Description of this test */ + +const char *rmdir00_get_description(void) +{ +	return +		"Create a directory named rmdir00_test_dir_pid, where " \ +		"pid is the process id.  Within that directory, create " \ +		"a number of sub-directories and small files. " \ +		"The total size of all sub-directories and files " \ +		"is specified by the size parameter. " \ +		"The size parameter is given by the -z or --size option, " \ +		"otherwise it defaults to 1000000. " \ +		"A size of zero fills the file system until there is no " +		"space left. " \ +		"The task repeats, sleeping in between each iteration, " \ +		"and then removing the sub-directories and files created " \ +		"during the last iteration. " \ +		"The repeat count is set by the -n or --repeat option, " \ +		"otherwise it defaults to 1. " \ +		"A repeat count of zero repeats forever. " \ +		"The sleep value is given by the -p or --sleep option, " \ +		"otherwise it defaults to 0. " +		"Sleep is specified in milliseconds."; +} + +int main(int argc, char *argv[]) +{ +	int run_test; + +	/* Set default test size */ +	tests_size_parameter = 1000000; + +	/* Set default test repetition */ +	tests_repeat_parameter = 1; + +	/* Set default test sleep */ +	tests_sleep_parameter = 0; + +	/* Handle common arguments */ +	run_test = tests_get_args(argc, argv, rmdir00_get_title(), +			rmdir00_get_description(), "znp"); +	if (!run_test) +		return 1; +	/* Change directory to the file system and check it is ok for testing */ +	tests_check_test_file_system(); +	/* Do the actual test */ +	rmdir00(); +	return 0; +} diff --git a/tests/fs-tests/stress/atoms/rndrm00.c b/tests/fs-tests/stress/atoms/rndrm00.c new file mode 100644 index 0000000..724b1c3 --- /dev/null +++ b/tests/fs-tests/stress/atoms/rndrm00.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2007 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Author: Adrian Hunter + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include "tests.h" + +void rndrm00(void) +{ +	int64_t repeat; +	int64_t size, this_size; +	pid_t pid; +	char dir_name[256]; + +	/* Create a directory to test in */ +	pid = getpid(); +	tests_cat_pid(dir_name, "rndrm00_test_dir_", pid); +	if (chdir(dir_name) == -1) +		CHECK(mkdir(dir_name, 0777) != -1); +	CHECK(chdir(dir_name) != -1); +	/* Repeat loop */ +	repeat = tests_repeat_parameter; +	size = 0; +	for (;;) { +		/* Create and remove sub-dirs and small files, */ +		/* but tending to grow */ +		do { +			if (tests_random_no(3)) { +				this_size = tests_create_entry(NULL); +				if (!this_size) +					break; +				size += this_size; +			} else { +				this_size = tests_remove_entry(); +				size -= this_size; +				if (size < 0) +					size = 0; +				if (!this_size) +					this_size = 1; +			} +		} while (this_size && +			(tests_size_parameter == 0 || +			size < tests_size_parameter)); +		/* Create and remove sub-dirs and small files, but */ +		/* but tending to shrink */ +		do { +			if (!tests_random_no(3)) { +				this_size = tests_create_entry(NULL); +				size += this_size; +			} else { +				this_size = tests_remove_entry(); +				size -= this_size; +				if (size < 0) +					size = 0; +			} +		} while ((tests_size_parameter != 0 && +			size > tests_size_parameter / 10) || +			(tests_size_parameter == 0 && size > 100000)); +		/* Break if repeat count exceeded */ +		if (tests_repeat_parameter > 0 && --repeat <= 0) +			break; +		/* Sleep */ +		if (tests_sleep_parameter > 0) { +			unsigned us = tests_sleep_parameter * 1000; +			unsigned rand_divisor = RAND_MAX / us; +			unsigned s = (us / 2) + (rand() / rand_divisor); +			usleep(s); +		} +	} +	/* Tidy up by removing everything */ +	tests_clear_dir("."); +	CHECK(chdir("..") != -1); +	CHECK(rmdir(dir_name) != -1); +} + +/* Title of this test */ + +const char *rndrm00_get_title(void) +{ +	return "Randomly create and remove directories and files"; +} + +/* Description of this test */ + +const char *rndrm00_get_description(void) +{ +	return +		"Create a directory named rndrm00_test_dir_pid, where " \ +		"pid is the process id.  Within that directory, " \ +		"randomly create and remove " \ +		"a number of sub-directories and small files, " \ +		"but do more creates than removes. " \ +		"When the total size of all sub-directories and files " \ +		"is greater than the size specified by the size parameter, " \ +		"start to do more removes than creates. " \ +		"The size parameter is given by the -z or --size option, " \ +		"otherwise it defaults to 1000000. " \ +		"A size of zero fills the file system until there is no " +		"space left. " \ +		"The task repeats, sleeping in between each iteration. " \ +		"The repeat count is set by the -n or --repeat option, " \ +		"otherwise it defaults to 1. " \ +		"A repeat count of zero repeats forever. " \ +		"The sleep value is given by the -p or --sleep option, " \ +		"otherwise it defaults to 0. " +		"Sleep is specified in milliseconds."; +} + +int main(int argc, char *argv[]) +{ +	int run_test; + +	/* Set default test size */ +	tests_size_parameter = 1000000; + +	/* Set default test repetition */ +	tests_repeat_parameter = 1; + +	/* Set default test sleep */ +	tests_sleep_parameter = 0; + +	/* Handle common arguments */ +	run_test = tests_get_args(argc, argv, rndrm00_get_title(), +			rndrm00_get_description(), "znp"); +	if (!run_test) +		return 1; +	/* Change directory to the file system and check it is ok for testing */ +	tests_check_test_file_system(); +	/* Do the actual test */ +	rndrm00(); +	return 0; +} diff --git a/tests/fs-tests/stress/atoms/rndrm99.c b/tests/fs-tests/stress/atoms/rndrm99.c new file mode 100644 index 0000000..7751839 --- /dev/null +++ b/tests/fs-tests/stress/atoms/rndrm99.c @@ -0,0 +1,431 @@ +/* + * Copyright (C) 2007 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Author: Adrian Hunter + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/time.h> +#include <time.h> +#include <sys/vfs.h> +#include <sys/statvfs.h> +#include <dirent.h> +#include <ctype.h> +#include <limits.h> + +#include "tests.h" + +uint32_t files_created = 0; +uint32_t files_removed = 0; +uint32_t dirs_created = 0; +uint32_t dirs_removed = 0; +int64_t *size_ptr = 0; + +void display_stats(void) +{ +	printf(	"\nrndrm99 stats:\n" +		"\tNumber of files created = %u\n" +		"\tNumber of files deleted = %u\n" +		"\tNumber of directories created = %u\n" +		"\tNumber of directories deleted = %u\n" +		"\tCurrent net size of creates and deletes = %lld\n", +		(unsigned) files_created, +		(unsigned) files_removed, +		(unsigned) dirs_created, +		(unsigned) dirs_removed, +		(long long) (size_ptr ? *size_ptr : 0)); +	fflush(stdout); +} + +struct timeval tv_before; +struct timeval tv_after; + +void before(void) +{ +	CHECK(gettimeofday(&tv_before, NULL) != -1); +} + +void after(const char *msg) +{ +	time_t diff; +	CHECK(gettimeofday(&tv_after, NULL) != -1); +	diff = tv_after.tv_sec - tv_before.tv_sec; +	if (diff >= 8) { +		printf("\nrndrm99: the following fn took more than 8 seconds: %s (took %u secs)\n",msg,(unsigned) diff); +		fflush(stdout); +		display_stats(); +	} +} + +#define WRITE_BUFFER_SIZE 32768 + +static char write_buffer[WRITE_BUFFER_SIZE]; + +static void init_write_buffer() +{ +	static int init = 0; + +	if (!init) { +		int i, d; +		uint64_t u; + +		u = RAND_MAX; +		u += 1; +		u /= 256; +		d = (int) u; +		srand(1); +		for (i = 0; i < WRITE_BUFFER_SIZE; ++i) +			write_buffer[i] = rand() / d; +		init = 1; +	} +} + +/* Write size random bytes into file descriptor fd at the current position, +   returning the number of bytes actually written */ +uint64_t fill_file(int fd, uint64_t size) +{ +	ssize_t written; +	size_t sz; +	unsigned start = 0, length; +	uint64_t remains; +	uint64_t actual_size = 0; + +	init_write_buffer(); +	remains = size; +	while (remains > 0) { +		length = WRITE_BUFFER_SIZE - start; +		if (remains > length) +			sz = length; +		else +			sz = (size_t) remains; +		before(); +		written = write(fd, write_buffer + start, sz); +		if (written <= 0) { +			CHECK(errno == ENOSPC); /* File system full */ +			errno = 0; +			after("write"); +			fprintf(stderr,"\nrndrm99: write failed with ENOSPC\n");fflush(stderr); +			display_stats(); +			break; +		} +		after("write"); +		remains -= written; +		actual_size += written; +		if ((size_t) written == sz) +			start = 0; +		else +			start += written; +	} +	return actual_size; +} + +/* Create a file of size file_size */ +uint64_t create_file(const char *file_name, uint64_t file_size) +{ +	int fd; +	int flags; +	mode_t mode; +	uint64_t actual_size; /* Less than size if the file system is full */ + +	flags = O_CREAT | O_TRUNC | O_WRONLY; +	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; +	before(); +	fd = open(file_name, flags, mode); +	if (fd == -1 && errno == ENOSPC) { +		errno = 0; +		after("open"); +		fprintf(stderr,"\nrndrm99: open failed with ENOSPC\n");fflush(stderr); +		display_stats(); +		return 0; /* File system full */ +	} +	CHECK(fd != -1); +	after("open"); +	actual_size = fill_file(fd, file_size); +	before(); +	CHECK(close(fd) != -1); +	after("close"); +	if (file_size != 0 && actual_size == 0) { +		printf("\nrndrm99: unlinking zero size file\n");fflush(stdout); +		before(); +		CHECK(unlink(file_name) != -1); +		after("unlink (create_file)"); +	} +	return actual_size; +} + +/* Create an empty sub-directory or small file in the current directory */ +int64_t create_entry(char *return_name) +{ +	int fd; +	char name[256]; +	int64_t res; + +	for (;;) { +		sprintf(name, "%u", (unsigned) tests_random_no(10000000)); +		before(); +		fd = open(name, O_RDONLY); +		after("open (create_entry)"); +		if (fd == -1) +			break; +		before(); +		close(fd); +		after("close (create_entry)"); +	} +	if (return_name) +		strcpy(return_name, name); +	if (tests_random_no(2)) { +		res = create_file(name, tests_random_no(4096)); +		if (res > 0) +			files_created += 1; +		return res; +	} else { +		before(); +		if (mkdir(name, 0777) == -1) { +			CHECK(errno == ENOSPC); +			after("mkdir"); +			errno = 0; +			fprintf(stderr,"\nrndrm99: mkdir failed with ENOSPC\n");fflush(stderr); +			display_stats(); +			return 0; +		} +		after("mkdir"); +		dirs_created += 1; +		return TESTS_EMPTY_DIR_SIZE; +	} +} + +/* Remove a random file of empty sub-directory from the current directory */ +int64_t remove_entry(void) +{ +	DIR *dir; +	struct dirent *entry; +	unsigned count = 0, pos; +	int64_t result = 0; + +	before(); +	dir = opendir("."); +	CHECK(dir != NULL); +	after("opendir"); +	for (;;) { +		errno = 0; +		before(); +		entry = readdir(dir); +		if (entry) { +			after("readdir 1"); +			if (strcmp(".",entry->d_name) != 0 && +					strcmp("..",entry->d_name) != 0) +				++count; +		} else { +			CHECK(errno == 0); +			after("readdir 1"); +			break; +		} +	} +	pos = tests_random_no(count); +	count = 0; +	before(); +	rewinddir(dir); +	after("rewinddir"); +	for (;;) { +		errno = 0; +		before(); +		entry = readdir(dir); +		if (!entry) { +			CHECK(errno == 0); +			after("readdir 2"); +			break; +		} +		after("readdir 2"); +		if (strcmp(".",entry->d_name) != 0 && +				strcmp("..",entry->d_name) != 0) { +			if (count == pos) { +				if (entry->d_type == DT_DIR) { +					before(); +					tests_clear_dir(entry->d_name); +					after("tests_clear_dir"); +					before(); +					CHECK(rmdir(entry->d_name) != -1); +					after("rmdir"); +					result = TESTS_EMPTY_DIR_SIZE; +					dirs_removed += 1; +				} else { +					struct stat st; +					before(); +					CHECK(stat(entry->d_name, &st) != -1); +					after("stat"); +					result = st.st_size; +					before(); +					CHECK(unlink(entry->d_name) != -1); +					after("unlink"); +					files_removed += 1; +				} +			} +			++count; +		} +	} +	before(); +	CHECK(closedir(dir) != -1); +	after("closedir"); +	return result; +} + +void rndrm99(void) +{ +	int64_t repeat, loop_cnt; +	int64_t size, this_size; +	pid_t pid; +	char dir_name[256]; + +	size_ptr = &size; +	/* Create a directory to test in */ +	pid = getpid(); +	tests_cat_pid(dir_name, "rndrm99_test_dir_", pid); +	if (chdir(dir_name) == -1) +		CHECK(mkdir(dir_name, 0777) != -1); +	CHECK(chdir(dir_name) != -1); +	/* Repeat loop */ +	repeat = tests_repeat_parameter; +	size = 0; +	for (;;) { +		/* Create and remove sub-dirs and small files, */ +		/* but tending to grow */ +		printf("\nrndrm99: growing\n");fflush(stdout); +		loop_cnt = 0; +		do { +			if (loop_cnt++ % 2000 == 0) +				display_stats(); +			if (tests_random_no(3)) { +				this_size = create_entry(NULL); +				if (!this_size) +					break; +				size += this_size; +			} else { +				this_size = remove_entry(); +				size -= this_size; +				if (size < 0) +					size = 0; +				if (!this_size) +					this_size = 1; +			} +		} while (this_size && +			(tests_size_parameter == 0 || +			size < tests_size_parameter)); +		/* Create and remove sub-dirs and small files, but */ +		/* but tending to shrink */ +		printf("\nrndrm99: shrinking\n");fflush(stdout); +		loop_cnt = 0; +		do { +			if (loop_cnt++ % 2000 == 0) +				display_stats(); +			if (!tests_random_no(3)) { +				this_size = create_entry(NULL); +				size += this_size; +			} else { +				this_size = remove_entry(); +				size -= this_size; +				if (size < 0) +					size = 0; +			} +		} while ((tests_size_parameter != 0 && +			size > tests_size_parameter / 10) || +			(tests_size_parameter == 0 && size > 100000)); +		/* Break if repeat count exceeded */ +		if (tests_repeat_parameter > 0 && --repeat <= 0) +			break; +		/* Sleep */ +		if (tests_sleep_parameter > 0) { +			unsigned us = tests_sleep_parameter * 1000; +			unsigned rand_divisor = RAND_MAX / us; +			unsigned s = (us / 2) + (rand() / rand_divisor); +			printf("\nrndrm99: sleeping\n");fflush(stdout); +			usleep(s); +		} +	} +	printf("\nrndrm99: tidying\n");fflush(stdout); +	display_stats(); +	/* Tidy up by removing everything */ +	tests_clear_dir("."); +	CHECK(chdir("..") != -1); +	CHECK(rmdir(dir_name) != -1); +	size_ptr = 0; +} + +/* Title of this test */ + +const char *rndrm99_get_title(void) +{ +	return "Randomly create and remove directories and files"; +} + +/* Description of this test */ + +const char *rndrm99_get_description(void) +{ +	return +		"Create a directory named rndrm99_test_dir_pid, where " \ +		"pid is the process id.  Within that directory, " \ +		"randomly create and remove " \ +		"a number of sub-directories and small files, " \ +		"but do more creates than removes. " \ +		"When the total size of all sub-directories and files " \ +		"is greater than the size specified by the size parameter, " \ +		"start to do more removes than creates. " \ +		"The size parameter is given by the -z or --size option, " \ +		"otherwise it defaults to 1000000. " \ +		"A size of zero fills the file system until there is no " +		"space left. " \ +		"The task repeats, sleeping in between each iteration. " \ +		"The repeat count is set by the -n or --repeat option, " \ +		"otherwise it defaults to 1. " \ +		"A repeat count of zero repeats forever. " \ +		"The sleep value is given by the -p or --sleep option, " \ +		"otherwise it defaults to 0. " +		"Sleep is specified in milliseconds."; +} + +int main(int argc, char *argv[]) +{ +	int run_test; + +	/* Set default test size */ +	tests_size_parameter = 1000000; + +	/* Set default test repetition */ +	tests_repeat_parameter = 1; + +	/* Set default test sleep */ +	tests_sleep_parameter = 0; + +	/* Handle common arguments */ +	run_test = tests_get_args(argc, argv, rndrm99_get_title(), +			rndrm99_get_description(), "znp"); +	if (!run_test) +		return 1; +	/* Change directory to the file system and check it is ok for testing */ +	tests_check_test_file_system(); +	/* Do the actual test */ +	rndrm99(); +	return 0; +} diff --git a/tests/fs-tests/stress/atoms/rndwrite00.c b/tests/fs-tests/stress/atoms/rndwrite00.c new file mode 100644 index 0000000..655d9cc --- /dev/null +++ b/tests/fs-tests/stress/atoms/rndwrite00.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2007 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Author: Adrian Hunter + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <limits.h> + +#include "tests.h" + +#define BLOCK_SIZE 32768 +#define BUFFER_SIZE 32768 + +static void check_file(int fd, char *data, size_t length) +{ +	size_t n, i; +	char buf[BUFFER_SIZE]; + +	CHECK(lseek(fd, 0, SEEK_SET) != -1); +	n = 0; +	for (;;) { +		i = read(fd, buf, BUFFER_SIZE); +		CHECK(i >= 0); +		if (i == 0) +			break; +		CHECK(memcmp(buf, data + n, i) == 0); +		n += i; +	} +	CHECK(n == length); +} + +void rndwrite00(void) +{ +	int fd; +	pid_t pid; +	ssize_t written; +	size_t remains; +	size_t block; +	size_t actual_size; +	size_t check_every; +	char *data, *p, *q; +	off_t offset; +	size_t size; +	int64_t repeat; +	char file_name[256]; +	char buf[4096]; + +	/* Create file */ +	pid = getpid(); +	tests_cat_pid(file_name, "rndwrite00_test_file_", pid); +	fd = open(file_name, O_CREAT | O_RDWR | O_TRUNC, +		S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); +	CHECK(fd != -1); +	/* Allocate memory to hold file data */ +	CHECK(tests_size_parameter > 0); +	CHECK(tests_size_parameter <= SIZE_MAX); +	data = (char *) malloc(tests_size_parameter); +	CHECK(data != NULL); +	/* Fill with random data */ +	srand(pid); +	for (p = data, q = data + tests_size_parameter; p != q; ++p) +		*p = rand(); +	/* Write to file */ +	p = data; +	remains = tests_size_parameter; +	while (remains > 0) { +		if (remains > BLOCK_SIZE) +			block = BLOCK_SIZE; +		else +			block = remains; +		written = write(fd, p, block); +		if (written <= 0) { +			CHECK(errno == ENOSPC); /* File system full */ +			errno = 0; +			break; +		} +		remains -= written; +		p += written; +	} +	actual_size = p - data; +	/* Repeating bit */ +	repeat = tests_repeat_parameter; +	check_every = actual_size / 8192; +	for (;;) { +		offset = tests_random_no(actual_size); +		size = tests_random_no(4096); +		/* Don't change the file size */ +		if (offset + size > actual_size) +			size = actual_size - offset; +		if (!size) +			continue; +		for (p = buf, q = p + size; p != q; ++p) +			*p = rand(); +		CHECK(lseek(fd, offset, SEEK_SET) != -1); +		written = write(fd, buf, size); +		if (written <= 0) { +			CHECK(errno == ENOSPC); /* File system full */ +			errno = 0; +		} else +			memcpy(data + offset, buf, written); +		/* Break if repeat count exceeded */ +		if (tests_repeat_parameter > 0 && --repeat <= 0) +			break; +		if (repeat % check_every == 0) +			check_file(fd, data, actual_size); +		/* Sleep */ +		if (tests_sleep_parameter > 0) { +			unsigned us = tests_sleep_parameter * 1000; +			unsigned rand_divisor = RAND_MAX / us; +			unsigned s = (us / 2) + (rand() / rand_divisor); +			usleep(s); +		} +	} +	/* Check and close file */ +	check_file(fd, data, actual_size); +	CHECK(close(fd) != -1); +	if (tests_delete_flag) +		CHECK(unlink(file_name) != -1); +} + +/* Title of this test */ + +const char *rndwrite00_get_title(void) +{ +	return "Randomly write a large test file"; +} + +/* Description of this test */ + +const char *rndwrite00_get_description(void) +{ +	return +		"Create a file named rndwrite00_test_file_pid, where " \ +		"pid is the process id. " \ +		"The file is filled with random data. " \ +		"The size of the file is given by the -z or --size option, " \ +		"otherwise it defaults to 1000000. " \ +		"Then a randomly sized block of random data is written at a " \ +		"random location in the file. "\ +		"The block size is always in the range 1 to 4095. " \ +		"If a sleep value is specified, the process sleeps. " \ +		"The number of writes is given by the repeat count. " \ +		"The repeat count is set by the -n or --repeat option, " \ +		"otherwise it defaults to 10000. " \ +		"A repeat count of zero repeats forever. " \ +		"The sleep value is given by the -p or --sleep option, " \ +		"otherwise it defaults to 0. " +		"Sleep is specified in milliseconds. " \ +		"Periodically the data in the file is checked with a copy " \ +		"held in memory. " \ +		"If the delete option is specified the file is finally " \ +		"deleted."; +} + +int main(int argc, char *argv[]) +{ +	int run_test; + +	/* Set default test file size */ +	tests_size_parameter = 1000000; + +	/* Set default test repetition */ +	tests_repeat_parameter = 10000; + +	/* Set default test sleep */ +	tests_sleep_parameter = 0; + +	/* Handle common arguments */ +	run_test = tests_get_args(argc, argv, rndwrite00_get_title(), +			rndwrite00_get_description(), "zne"); +	if (!run_test) +		return 1; +	/* Change directory to the file system and check it is ok for testing */ +	tests_check_test_file_system(); +	/* Do the actual test */ +	rndwrite00(); +	return 0; +} diff --git a/tests/fs-tests/stress/atoms/stress_1.c b/tests/fs-tests/stress/atoms/stress_1.c new file mode 100644 index 0000000..86f94c2 --- /dev/null +++ b/tests/fs-tests/stress/atoms/stress_1.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2007 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Author: Adrian Hunter + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include "tests.h" + +#define WRITE_BUFFER_SIZE 32768 + +void stress_1(void) +{ +	int fd, i; +	pid_t pid; +	ssize_t written; +	int64_t remains; +	size_t block; +	char file_name[256]; +	char buf[WRITE_BUFFER_SIZE]; + +	pid = getpid(); +	tests_cat_pid(file_name, "stress_1_test_file_", pid); +	fd = open(file_name, O_CREAT | O_WRONLY, +		S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); +	CHECK(fd != -1); +	srand(pid); +	for (i = 0; i < WRITE_BUFFER_SIZE;++i) +		buf[i] = rand(); +	remains = tests_size_parameter; +	while (remains > 0) { +		if (remains > WRITE_BUFFER_SIZE) +			block = WRITE_BUFFER_SIZE; +		else +			block = remains; +		written = write(fd, buf, block); +		if (written <= 0) { +			CHECK(errno == ENOSPC); /* File system full */ +			errno = 0; +			break; +		} +		remains -= written; +	} +	CHECK(close(fd) != -1); +	if (tests_delete_flag) +		CHECK(unlink(file_name) != -1); +} + +/* Title of this test */ + +const char *stress_1_get_title(void) +{ +	return "Create / overwrite a large file"; +} + +/* Description of this test */ + +const char *stress_1_get_description(void) +{ +	return +		"Create a file named stress_1_test_file_pid, " \ +		"where pid is the process id. " \ +		"The size is given by the -z or --size option, " \ +		"otherwise it defaults to 1000000. " \ +		"The file will be deleted if the delete option " \ +		"is specified. "; +} + +int main(int argc, char *argv[]) +{ +	int run_test; + +	/* Set default test file size */ +	tests_size_parameter = 1000000; + +	/* Handle common arguments */ +	run_test = tests_get_args(argc, argv, stress_1_get_title(), +			stress_1_get_description(), "ze"); +	if (!run_test) +		return 1; +	/* Change directory to the file system and check it is ok for testing */ +	tests_check_test_file_system(); +	/* Do the actual test */ +	stress_1(); +	return 0; +} diff --git a/tests/fs-tests/stress/atoms/stress_2.c b/tests/fs-tests/stress/atoms/stress_2.c new file mode 100644 index 0000000..a9bc31a --- /dev/null +++ b/tests/fs-tests/stress/atoms/stress_2.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2007 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Author: Adrian Hunter + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include "tests.h" + +#define WRITE_BUFFER_SIZE 32768 + +void stress_2(void) +{ +	int fd, i; +	pid_t pid; +	ssize_t written; +	int64_t remains; +	int64_t repeat; +	size_t block; +	char *file_name; +	char buf[WRITE_BUFFER_SIZE]; + +	file_name = "stress_2_test_file"; +	fd = open(file_name, O_CREAT | O_WRONLY, +		S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); +	CHECK(fd != -1); +	CHECK(unlink(file_name) != -1); +	pid = getpid(); +	srand(pid); +	repeat = tests_repeat_parameter; +	for (;;) { +		for (i = 0; i < WRITE_BUFFER_SIZE;++i) +			buf[i] = rand(); +		CHECK(lseek(fd, 0, SEEK_SET) != -1); +		remains = tests_size_parameter; +		while (remains > 0) { +			if (remains > WRITE_BUFFER_SIZE) +				block = WRITE_BUFFER_SIZE; +			else +				block = remains; +			written = write(fd, buf, block); +			if (written <= 0) { +				CHECK(errno == ENOSPC); /* File system full */ +				errno = 0; +				break; +			} +			remains -= written; +		} +		if (tests_repeat_parameter > 0 && --repeat <= 0) +			break; +	} +	CHECK(close(fd) != -1); +} + +/* Title of this test */ + +const char *stress_2_get_title(void) +{ +	return "Create / overwrite a large deleted file"; +} + +/* Description of this test */ + +const char *stress_2_get_description(void) +{ +	return +		"Create a file named stress_2_test_file. " \ +		"Open it, delete it while holding the open file descriptor, " \ +		"then fill it with random data. " \ +		"Repeated re-write the file some number of times. " \ +		"The repeat count is given by the -n or --repeat option, " \ +		"otherwise it defaults to 10. " \ +		"The file size is given by the -z or --size option, " \ +		"otherwise it defaults to 1000000."; +} + +int main(int argc, char *argv[]) +{ +	int run_test; + +	/* Set default test file size */ +	tests_size_parameter = 1000000; + +	/* Set default test repetition */ +	tests_repeat_parameter = 10; + +	/* Handle common arguments */ +	run_test = tests_get_args(argc, argv, stress_2_get_title(), +			stress_2_get_description(), "zn"); +	if (!run_test) +		return 1; +	/* Change directory to the file system and check it is ok for testing */ +	tests_check_test_file_system(); +	/* Do the actual test */ +	stress_2(); +	return 0; +} diff --git a/tests/fs-tests/stress/atoms/stress_3.c b/tests/fs-tests/stress/atoms/stress_3.c new file mode 100644 index 0000000..99fb05d --- /dev/null +++ b/tests/fs-tests/stress/atoms/stress_3.c @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2007 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Author: Adrian Hunter + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include "tests.h" + +#define WRITE_BUFFER_SIZE 32768 + +void stress_3(void) +{ +	int fd, i; +	pid_t pid; +	ssize_t written; +	int64_t remains; +	size_t block; +	char file_name[256]; +	char buf[WRITE_BUFFER_SIZE]; + +	pid = getpid(); +	tests_cat_pid(file_name, "stress_3_test_file_", pid); +	fd = open(file_name, O_CREAT | O_WRONLY, +		S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); +	CHECK(fd != -1); +	pid = getpid(); +	srand(pid); +	for (i = 0; i < WRITE_BUFFER_SIZE;++i) +		buf[i] = rand(); +	CHECK(lseek(fd, tests_size_parameter, SEEK_SET) != -1); +	CHECK(write(fd, "!", 1) == 1); +	CHECK(lseek(fd, 0, SEEK_SET) != -1); +	remains = tests_size_parameter; +	while (remains > 0) { +		if (remains > WRITE_BUFFER_SIZE) +			block = WRITE_BUFFER_SIZE; +		else +			block = remains; +		written = write(fd, buf, block); +		if (written <= 0) { +			CHECK(errno == ENOSPC); /* File system full */ +			errno = 0; +			break; +		} +		remains -= written; +	} +	if (ftruncate(fd, 0) == -1) { +		CHECK(errno == ENOSPC); /* File system full */ +		errno = 0; +	} +	CHECK(close(fd) != -1); +	if (tests_delete_flag) +		CHECK(unlink(file_name) != -1); +} + +/* Title of this test */ + +const char *stress_3_get_title(void) +{ +	return "Create a file with a large hole and fill it"; +} + +/* Description of this test */ + +const char *stress_3_get_description(void) +{ +	return +		"Create a file named stress_3_test_file_pid, " \ +		"where pid is the process id. " \ +		"Write a single character past the end of the file, " \ +		"based on the specified file size, " \ +		"which creates a hole in the file. " +		"Fill the hole with random data. " \ +		"Then truncate the file length to zero. " \ +		"The size is given by the -z or --size option, " \ +		"otherwise it defaults to 1000000. " \ +		"The file will be deleted if the delete option " \ +		"is specified."; +} + +int main(int argc, char *argv[]) +{ +	int run_test; + +	/* Set default test file size */ +	tests_size_parameter = 1000000; + +	/* Handle common arguments */ +	run_test = tests_get_args(argc, argv, stress_3_get_title(), +			stress_3_get_description(), "ze"); +	if (!run_test) +		return 1; +	/* Change directory to the file system and check it is ok for testing */ +	tests_check_test_file_system(); +	/* Do the actual test */ +	stress_3(); +	return 0; +} | 
