172 lines
3.1 KiB
C
172 lines
3.1 KiB
C
/*
|
|
* 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 "config.h"
|
|
#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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|