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
24struct 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
34struct state state_array[MAXFDS];
35
36#define DATA_SIZE 65536
37
38char data_buffer[DATA_SIZE];
39
40void clear_state_array()
41{
42	int	i;
43
44	for (i = 0; i < MAXFDS; i++)
45		state_array[i].state = STATE_CLEAR;
46}
47
48int 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
59unsigned 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
71void 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
101void 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
116void 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
130void 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
142main(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