summaryrefslogtreecommitdiff
path: root/tests/fs-tests/stress
diff options
context:
space:
mode:
Diffstat (limited to 'tests/fs-tests/stress')
-rw-r--r--tests/fs-tests/stress/Makefile11
-rw-r--r--tests/fs-tests/stress/atoms/Makefile40
-rw-r--r--tests/fs-tests/stress/atoms/fwrite00.c209
-rw-r--r--tests/fs-tests/stress/atoms/gcd_hupper.c259
-rw-r--r--tests/fs-tests/stress/atoms/pdfrun.c143
-rw-r--r--tests/fs-tests/stress/atoms/rmdir00.c133
-rw-r--r--tests/fs-tests/stress/atoms/rndrm00.c157
-rw-r--r--tests/fs-tests/stress/atoms/rndrm99.c431
-rw-r--r--tests/fs-tests/stress/atoms/rndwrite00.c201
-rw-r--r--tests/fs-tests/stress/atoms/stress_1.c109
-rw-r--r--tests/fs-tests/stress/atoms/stress_2.c120
-rw-r--r--tests/fs-tests/stress/atoms/stress_3.c122
-rwxr-xr-xtests/fs-tests/stress/stress00.sh53
-rwxr-xr-xtests/fs-tests/stress/stress01.sh40
14 files changed, 2028 insertions, 0 deletions
diff --git a/tests/fs-tests/stress/Makefile b/tests/fs-tests/stress/Makefile
new file mode 100644
index 0000000..c24ff3f
--- /dev/null
+++ b/tests/fs-tests/stress/Makefile
@@ -0,0 +1,11 @@
+
+SUBDIRS = atoms
+
+all tests: $(SUBDIRS)
+
+clean: $(SUBDIRS)
+ rm -rf run_pdf_test_file_*
+
+.PHONY: $(SUBDIRS)
+$(SUBDIRS):
+ $(MAKE) -C $@ $(MAKECMDGOALS)
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;
+}
diff --git a/tests/fs-tests/stress/stress00.sh b/tests/fs-tests/stress/stress00.sh
new file mode 100755
index 0000000..be95d7c
--- /dev/null
+++ b/tests/fs-tests/stress/stress00.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+TEST_DIR=$TEST_FILE_SYSTEM_MOUNT_DIR
+if test -z "$TEST_DIR";
+then
+ TEST_DIR="/mnt/test_file_system"
+fi
+
+FREESPACE=`../utils/free_space "$TEST_DIR"`
+
+if test -z "$FREESPACE";
+then
+ echo "Failed to determine free space"
+ exit 1
+fi
+
+if test -n "$1";
+then
+ DURATION="-d$1";
+else
+ DURATION="";
+fi
+
+FWRITE00=atoms/fwrite00
+RNDWR=atoms/rndwrite00
+GCHUP=atoms/gcd_hupper
+PDFLUSH=atoms/pdfrun
+FSIZE=$(( $FREESPACE/15 ));
+
+../utils/fstest_monitor $DURATION \
+"$FWRITE00 -z $FSIZE -n0 -p 20" \
+"$FWRITE00 -z $FSIZE -n0 -p 10 -s" \
+"$FWRITE00 -z $FSIZE -n0 -p 20 -u" \
+"$FWRITE00 -z $FSIZE -n0 -p 70 -o" \
+"$FWRITE00 -z $FSIZE -n0 -p 15 -s -o -u" \
+"$FWRITE00 -z $FSIZE -n0 -p 10 -u -c" \
+"$FWRITE00 -z $FSIZE -n0 -p 10 -u -o -c" \
+"$FWRITE00 -z $FSIZE -n0 -p 10 -o -c" \
+"$FWRITE00 -z $FSIZE -n0 -p 100 -o -u" \
+"$FWRITE00 -z $FSIZE -n0 -p 100 -s -o -u -c" \
+"$FWRITE00 -z $FSIZE -n0 -p 100 -o -u" \
+"$FWRITE00 -z $FSIZE -n0 -p 100 -u" \
+"$FWRITE00 -z $FSIZE -n0 -p 100 -s -o" \
+"$RNDWR -z $FSIZE -n0 -p 10 -e" \
+"$RNDWR -z $FSIZE -n0 -p 100 -e" \
+"$PDFLUSH -z 1073741824 -n0" \
+"$GCHUP -n0"
+
+STATUS=$?
+
+rm -rf ${TEST_DIR}/*
+
+exit $STATUS
diff --git a/tests/fs-tests/stress/stress01.sh b/tests/fs-tests/stress/stress01.sh
new file mode 100755
index 0000000..5913c1c
--- /dev/null
+++ b/tests/fs-tests/stress/stress01.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+TEST_DIR=$TEST_FILE_SYSTEM_MOUNT_DIR
+if test -z "$TEST_DIR";
+then
+ TEST_DIR="/mnt/test_file_system"
+fi
+
+FREESPACE=`../utils/free_space "$TEST_DIR"`
+
+if test -z "$FREESPACE";
+then
+ echo "Failed to determine free space"
+ exit 1
+fi
+
+if test -n "$1";
+then
+ DURATION="-d$1";
+else
+ DURATION="";
+fi
+
+FWRITE00=atoms/fwrite00
+RNDWR=atoms/rndwrite00
+PDFLUSH=atoms/pdfrun
+FSIZE=$(( $FREESPACE/15 ));
+
+../utils/fstest_monitor $DURATION \
+"$FWRITE00 -z $FSIZE -n0 -p 300" \
+"$FWRITE00 -z $FSIZE -n0 -u" \
+"$FWRITE00 -z $FSIZE -n0 -u -c" \
+"$FWRITE00 -z $FSIZE -n0 -s -o" \
+"$RNDWR -z $FSIZE -n0 -e"
+
+STATUS=$?
+
+rm -rf ${TEST_DIR}/*
+
+exit $STATUS