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