diff options
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; +} |