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