1 /*
2 * random_exercise.c --- Test program which exercises an ext2
3 * filesystem. It creates a lot of random files in the current
4 * directory, while holding some files open while they are being
5 * deleted. This exercises the orphan list code, as well as
6 * creating lots of fodder for the ext3 journal.
7 *
8 * Copyright (C) 2000 Theodore Ts'o.
9 *
10 * %Begin-Header%
11 * This file may be redistributed under the terms of the GNU Public
12 * License.
13 * %End-Header%
14 */
15
16 #include "config.h"
17 #include <unistd.h>
18 #include <stdio.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22
23 #define MAXFDS 128
24
25 struct state {
26 char name[16];
27 int state;
28 int isdir;
29 };
30
31 #define STATE_CLEAR 0
32 #define STATE_CREATED 1
33 #define STATE_DELETED 2
34
35 struct state state_array[MAXFDS];
36
37 #define DATA_SIZE 65536
38
39 char data_buffer[DATA_SIZE];
40
clear_state_array()41 void clear_state_array()
42 {
43 int i;
44
45 for (i = 0; i < MAXFDS; i++)
46 state_array[i].state = STATE_CLEAR;
47 }
48
get_random_fd()49 int get_random_fd()
50 {
51 int fd;
52
53 while (1) {
54 fd = ((int) random()) % MAXFDS;
55 if (fd > 2)
56 return fd;
57 }
58 }
59
get_inode_num(int fd)60 unsigned int get_inode_num(int fd)
61 {
62 struct stat st;
63
64 if (fstat(fd, &st) < 0) {
65 perror("fstat");
66 return 0;
67 }
68 return st.st_ino;
69 }
70
71
create_random_file()72 void create_random_file()
73 {
74 char template[16] = "EX.XXXXXX";
75 int fd;
76 int isdir = 0;
77 int size;
78
79 mktemp(template);
80 isdir = random() & 1;
81 if (isdir) {
82 if (mkdir(template, 0700) < 0)
83 return;
84 fd = open(template, O_RDONLY, 0600);
85 printf("Created temp directory %s, fd = %d\n",
86 template, fd);
87 } else {
88 size = random() & (DATA_SIZE-1);
89 fd = open(template, O_CREAT|O_RDWR, 0600);
90 write(fd, data_buffer, size);
91 printf("Created temp file %s, fd = %d, size=%d\n",
92 template, fd, size);
93 }
94 state_array[fd].isdir = isdir;
95 if (fd < 0)
96 return;
97 state_array[fd].isdir = isdir;
98 state_array[fd].state = STATE_CREATED;
99 strcpy(state_array[fd].name, template);
100 }
101
truncate_file(int fd)102 void truncate_file(int fd)
103 {
104 int size;
105
106 size = random() & (DATA_SIZE-1);
107
108 if (state_array[fd].isdir)
109 return;
110
111 ftruncate(fd, size);
112 printf("Truncating temp file %s, fd = %d, ino=%u, size=%d\n",
113 state_array[fd].name, fd, get_inode_num(fd), size);
114 }
115
116
unlink_file(int fd)117 void unlink_file(int fd)
118 {
119 char *filename = state_array[fd].name;
120
121 printf("Deleting %s, fd = %d, ino = %u\n", filename, fd,
122 get_inode_num(fd));
123
124 if (state_array[fd].isdir)
125 rmdir(filename);
126 else
127 unlink(filename);
128 state_array[fd].state = STATE_DELETED;
129 }
130
close_file(int fd)131 void close_file(int fd)
132 {
133 char *filename = state_array[fd].name;
134
135 printf("Closing %s, fd = %d, ino = %u\n", filename, fd,
136 get_inode_num(fd));
137
138 close(fd);
139 state_array[fd].state = STATE_CLEAR;
140 }
141
142
main(int argc,char ** argv)143 main(int argc, char **argv)
144 {
145 int i, fd;
146
147 memset(data_buffer, 0, sizeof(data_buffer));
148 sprintf(data_buffer, "This is a test file created by the "
149 "random_exerciser program\n");
150
151 for (i=0; i < 100000; i++) {
152 fd = get_random_fd();
153 switch (state_array[fd].state) {
154 case STATE_CLEAR:
155 create_random_file();
156 break;
157 case STATE_CREATED:
158 if ((state_array[fd].isdir == 0) &&
159 (random() & 2))
160 truncate_file(fd);
161 else
162 unlink_file(fd);
163 break;
164 case STATE_DELETED:
165 close_file(fd);
166 break;
167 }
168 }
169 }
170
171
172