| /* |
| * random_exercise.c --- Test program which exercises an ext2 |
| * filesystem. It creates a lot of random files in the current |
| * directory, while holding some files open while they are being |
| * deleted. This exercises the orphan list code, as well as |
| * creating lots of fodder for the ext3 journal. |
| * |
| * Copyright (C) 2000 Theodore Ts'o. |
| * |
| * %Begin-Header% |
| * This file may be redistributed under the terms of the GNU Public |
| * License. |
| * %End-Header% |
| */ |
| |
| #include <unistd.h> |
| #include <stdio.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| |
| #define MAXFDS 128 |
| |
| struct state { |
| char name[16]; |
| int state; |
| int isdir; |
| }; |
| |
| #define STATE_CLEAR 0 |
| #define STATE_CREATED 1 |
| #define STATE_DELETED 2 |
| |
| struct state state_array[MAXFDS]; |
| |
| #define DATA_SIZE 65536 |
| |
| char data_buffer[DATA_SIZE]; |
| |
| void clear_state_array() |
| { |
| int i; |
| |
| for (i = 0; i < MAXFDS; i++) |
| state_array[i].state = STATE_CLEAR; |
| } |
| |
| int get_random_fd() |
| { |
| int fd; |
| |
| while (1) { |
| fd = ((int) random()) % MAXFDS; |
| if (fd > 2) |
| return fd; |
| } |
| } |
| |
| unsigned int get_inode_num(int fd) |
| { |
| struct stat st; |
| |
| if (fstat(fd, &st) < 0) { |
| perror("fstat"); |
| return 0; |
| } |
| return st.st_ino; |
| } |
| |
| |
| void create_random_file() |
| { |
| char template[16] = "EX.XXXXXX"; |
| int fd; |
| int isdir = 0; |
| int size; |
| |
| mktemp(template); |
| isdir = random() & 1; |
| if (isdir) { |
| if (mkdir(template, 0700) < 0) |
| return; |
| fd = open(template, O_RDONLY, 0600); |
| printf("Created temp directory %s, fd = %d\n", |
| template, fd); |
| } else { |
| size = random() & (DATA_SIZE-1); |
| fd = open(template, O_CREAT|O_RDWR, 0600); |
| write(fd, data_buffer, size); |
| printf("Created temp file %s, fd = %d, size=%d\n", |
| template, fd, size); |
| } |
| state_array[fd].isdir = isdir; |
| if (fd < 0) |
| return; |
| state_array[fd].isdir = isdir; |
| state_array[fd].state = STATE_CREATED; |
| strcpy(state_array[fd].name, template); |
| } |
| |
| void truncate_file(int fd) |
| { |
| int size; |
| |
| size = random() & (DATA_SIZE-1); |
| |
| if (state_array[fd].isdir) |
| return; |
| |
| ftruncate(fd, size); |
| printf("Truncating temp file %s, fd = %d, ino=%u, size=%d\n", |
| state_array[fd].name, fd, get_inode_num(fd), size); |
| } |
| |
| |
| void unlink_file(int fd) |
| { |
| char *filename = state_array[fd].name; |
| |
| printf("Deleting %s, fd = %d, ino = %u\n", filename, fd, |
| get_inode_num(fd)); |
| |
| if (state_array[fd].isdir) |
| rmdir(filename); |
| else |
| unlink(filename); |
| state_array[fd].state = STATE_DELETED; |
| } |
| |
| void close_file(int fd) |
| { |
| char *filename = state_array[fd].name; |
| |
| printf("Closing %s, fd = %d, ino = %u\n", filename, fd, |
| get_inode_num(fd)); |
| |
| close(fd); |
| state_array[fd].state = STATE_CLEAR; |
| } |
| |
| |
| main(int argc, char **argv) |
| { |
| int i, fd; |
| |
| memset(data_buffer, 0, sizeof(data_buffer)); |
| sprintf(data_buffer, "This is a test file created by the " |
| "random_exerciser program\n"); |
| |
| for (i=0; i < 100000; i++) { |
| fd = get_random_fd(); |
| switch (state_array[fd].state) { |
| case STATE_CLEAR: |
| create_random_file(); |
| break; |
| case STATE_CREATED: |
| if ((state_array[fd].isdir == 0) && |
| (random() & 2)) |
| truncate_file(fd); |
| else |
| unlink_file(fd); |
| break; |
| case STATE_DELETED: |
| close_file(fd); |
| break; |
| } |
| } |
| } |
| |
| |