1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
3f08c3bdfSopenharmony_ci */
4f08c3bdfSopenharmony_ci
5f08c3bdfSopenharmony_ci#include <stdlib.h>
6f08c3bdfSopenharmony_ci#include <stdio.h>
7f08c3bdfSopenharmony_ci#include <string.h>
8f08c3bdfSopenharmony_ci#include <math.h>
9f08c3bdfSopenharmony_ci#include <sys/types.h>
10f08c3bdfSopenharmony_ci#include <unistd.h>
11f08c3bdfSopenharmony_ci#include <sys/stat.h>
12f08c3bdfSopenharmony_ci#include <fcntl.h>
13f08c3bdfSopenharmony_ci#include <errno.h>
14f08c3bdfSopenharmony_cichar tdir[256];
15f08c3bdfSopenharmony_cichar path[256];
16f08c3bdfSopenharmony_cilong stats = 0;
17f08c3bdfSopenharmony_ci
18f08c3bdfSopenharmony_civoid print_usage()
19f08c3bdfSopenharmony_ci{
20f08c3bdfSopenharmony_ci	printf("
21f08c3bdfSopenharmony_ciThis program creates files in a tree of random depth and branching. Files vary
22f08c3bdfSopenharmony_ciin size randomly according to a distribution function which seems to model real
23f08c3bdfSopenharmony_cifile systems.  This distribution function has a median size of median_file_size
24f08c3bdfSopenharmony_ci(Median file size is hypothesized to be proportional to the average per file
25f08c3bdfSopenharmony_cispace wastage. Notice how that implies that with a more efficient file system
26f08c3bdfSopenharmony_cifile size usage patterns will in the long term move to a lower median file
27f08c3bdfSopenharmony_cisize), and a maximum size of max_file_size.  Directories vary in size according
28f08c3bdfSopenharmony_cito the same distribution function but with separate parameters to control median
29f08c3bdfSopenharmony_ciand maximum size for the number of files within them, and the number of
30f08c3bdfSopenharmony_cisubdirectories within them.  This program prunes some empty subdirectories in a
31f08c3bdfSopenharmony_ciway that causes parents of leaf directories to branch less than
32f08c3bdfSopenharmony_cimedian_dir_branching.
33f08c3bdfSopenharmony_ci
34f08c3bdfSopenharmony_ci To avoid having one large file distort the results such that you have
35f08c3bdfSopenharmony_cito benchmark many times set max_file_size to not more than
36f08c3bdfSopenharmony_cibytes_to_consume/10.  If maximum/median is a small integer, then
37f08c3bdfSopenharmony_cirandomness is very poor.  This is a bug, Nikita, please find some
38f08c3bdfSopenharmony_ciclever way to fix it.  If it is 0, then the program crashes....
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ciFor isolating performance consequences of design variations on
41f08c3bdfSopenharmony_ciparticular file or directory size ranges, try setting their median size and
42f08c3bdfSopenharmony_cimax_size to both equal the max size of the file size range you want
43f08c3bdfSopenharmony_cito test.
44f08c3bdfSopenharmony_ci
45f08c3bdfSopenharmony_ciTo avoid having one large file distort the results set max_file_size to
46f08c3bdfSopenharmony_cinot more than bytes_to_consume/10.  Using a distribution function for
47f08c3bdfSopenharmony_cithe sizes of writes would be a natural next step in developing this program.\n\n");
48f08c3bdfSopenharmony_ci
49f08c3bdfSopenharmony_ci	printf
50f08c3bdfSopenharmony_ci	    ("Usage: reiser_fract_tree bytes_to_consume median_file_size max_file_size median_dir_nr_files max_directory_nr_files median_dir_branching max_dir_branching write_buffer_size /testfs_mount_point print_stats_flag\n\n");
51f08c3bdfSopenharmony_ci}
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_ci/* #define DEBUG */
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_cichar *write_buffer;		/* buffer from which we write */
56f08c3bdfSopenharmony_ciint write_buffer_size = 0;	/* gets reset to an argv  */
57f08c3bdfSopenharmony_cistatic int already_whined = 0;	/* keep out of disk space errors from being
58f08c3bdfSopenharmony_ci				   endless by tracking whether we already
59f08c3bdfSopenharmony_ci				   printed the message */
60f08c3bdfSopenharmony_cilong bytes_to_consume = 0;	/* create files until their total number of
61f08c3bdfSopenharmony_ci				   bytes exceeds this number, but not by more
62f08c3bdfSopenharmony_ci				   than 1/10th */
63f08c3bdfSopenharmony_cilong byte_total = 0;		/* bytes created so far */
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ci/* statistics on sizes of files we attempted to create */
66f08c3bdfSopenharmony_ciint fsz_0_100 = 0;
67f08c3bdfSopenharmony_ciint fsz_100_1k = 0;
68f08c3bdfSopenharmony_ciint fsz_1k_10k = 0;
69f08c3bdfSopenharmony_ciint fsz_10k_100k = 0;
70f08c3bdfSopenharmony_ciint fsz_100k_1m = 0;
71f08c3bdfSopenharmony_ciint fsz_1m_10m = 0;
72f08c3bdfSopenharmony_ciint fsz_10m_larger = 0;
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_civoid chngdir(char *name)
75f08c3bdfSopenharmony_ci{
76f08c3bdfSopenharmony_ci	int i;
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci	if (name[0] == '.' && name[1] == '.') {
79f08c3bdfSopenharmony_ci		for (i = strlen(path); i > 0; i--) {
80f08c3bdfSopenharmony_ci			if (path[i] == '/') {
81f08c3bdfSopenharmony_ci				path[i] = 0;
82f08c3bdfSopenharmony_ci				break;
83f08c3bdfSopenharmony_ci			}
84f08c3bdfSopenharmony_ci		}
85f08c3bdfSopenharmony_ci	} else {
86f08c3bdfSopenharmony_ci		strcat(path, "/");
87f08c3bdfSopenharmony_ci		strcat(path, name);
88f08c3bdfSopenharmony_ci	}
89f08c3bdfSopenharmony_ci}
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_ci/* this is the core statistical distribution function, and it is used for file
92f08c3bdfSopenharmony_ci   sizes, directory sizes, etc. */
93f08c3bdfSopenharmony_ciint determine_size(double median_size,
94f08c3bdfSopenharmony_ci		   double max_size /* The maximal value of size */ )
95f08c3bdfSopenharmony_ci{
96f08c3bdfSopenharmony_ci	/* when x is half of its random range (max_size/median_size), result is
97f08c3bdfSopenharmony_ci	   median_size */
98f08c3bdfSopenharmony_ci	int nr_random, granularity_reducer;
99f08c3bdfSopenharmony_ci	double size, double_nr_random;
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ci	/* it is a feature for us that this repeats identically every time it is run,
102f08c3bdfSopenharmony_ci	   as otherwise meaningless variances would affect our results and require us
103f08c3bdfSopenharmony_ci	   to use a higher number of benchmarks to achieve low noise results.  */
104f08c3bdfSopenharmony_ci	nr_random = rand();
105f08c3bdfSopenharmony_ci	median_size++;		/* avoids divide by zero errors */
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	/* this code does poorly when max_size is not a lot more than median size,
108f08c3bdfSopenharmony_ci	   and that needs fixing */
109f08c3bdfSopenharmony_ci
110f08c3bdfSopenharmony_ci	/* THE NEXT 2 LINES ARE THE HEART OF THE PROGRAM */
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_ci	/* keep x below the value that when multiplied by median size on the next
113f08c3bdfSopenharmony_ci	   line will equal max_size */
114f08c3bdfSopenharmony_ci	/* the granularity_reducer is to handle the case where max_size is near
115f08c3bdfSopenharmony_ci	   median_size, since '%' can only take ints, we need this complicated what
116f08c3bdfSopenharmony_ci	   of handling that for small values of max_size/median_size by making
117f08c3bdfSopenharmony_ci	   large ints out of small ints temporarily.  */
118f08c3bdfSopenharmony_ci	if (max_size / median_size < 1024)
119f08c3bdfSopenharmony_ci		granularity_reducer = 1024 * 1024;
120f08c3bdfSopenharmony_ci	else
121f08c3bdfSopenharmony_ci		granularity_reducer = 1;
122f08c3bdfSopenharmony_ci	nr_random =
123f08c3bdfSopenharmony_ci	    nr_random %
124f08c3bdfSopenharmony_ci	    ((int)
125f08c3bdfSopenharmony_ci	     (granularity_reducer *
126f08c3bdfSopenharmony_ci	      (((double)max_size) / ((double)median_size))));
127f08c3bdfSopenharmony_ci	double_nr_random = ((double)nr_random) / (granularity_reducer);
128f08c3bdfSopenharmony_ci	size =
129f08c3bdfSopenharmony_ci	    median_size * (1 /
130f08c3bdfSopenharmony_ci			   (1 -
131f08c3bdfSopenharmony_ci			    (double_nr_random) / (((double)max_size) /
132f08c3bdfSopenharmony_ci						  ((double)median_size))) - 1);
133f08c3bdfSopenharmony_ci	return ((int)size);
134f08c3bdfSopenharmony_ci}
135f08c3bdfSopenharmony_ci
136f08c3bdfSopenharmony_ci/* generate a unique filename */
137f08c3bdfSopenharmony_civoid get_name_by_number(long this_files_number, char *str)
138f08c3bdfSopenharmony_ci{
139f08c3bdfSopenharmony_ci	sprintf(str, "%lu", this_files_number);
140f08c3bdfSopenharmony_ci}
141f08c3bdfSopenharmony_ci
142f08c3bdfSopenharmony_ci/* make a file of a specified size */
143f08c3bdfSopenharmony_civoid make_file(int size)
144f08c3bdfSopenharmony_ci{
145f08c3bdfSopenharmony_ci	char string[128] = { 0 };
146f08c3bdfSopenharmony_ci	char *str = string;
147f08c3bdfSopenharmony_ci	char fname[256];
148f08c3bdfSopenharmony_ci	int fd = 0;
149f08c3bdfSopenharmony_ci	int error;
150f08c3bdfSopenharmony_ci	static long this_files_number = 1;
151f08c3bdfSopenharmony_ci
152f08c3bdfSopenharmony_ci	/* collect statistics about the size of files created, or more precisely, the
153f08c3bdfSopenharmony_ci	   size of files that we will attempt to create. */
154f08c3bdfSopenharmony_ci	if (size <= 100)
155f08c3bdfSopenharmony_ci		fsz_0_100++;
156f08c3bdfSopenharmony_ci	else if (size <= 1000)
157f08c3bdfSopenharmony_ci		fsz_100_1k++;
158f08c3bdfSopenharmony_ci	else if (size <= 10 * 1000)
159f08c3bdfSopenharmony_ci		fsz_1k_10k++;
160f08c3bdfSopenharmony_ci	else if (size <= 100 * 1000)
161f08c3bdfSopenharmony_ci		fsz_10k_100k++;
162f08c3bdfSopenharmony_ci	else if (size <= 1000 * 1000)
163f08c3bdfSopenharmony_ci		fsz_100k_1m++;
164f08c3bdfSopenharmony_ci	else if (size <= 10 * 1000 * 1000)
165f08c3bdfSopenharmony_ci		fsz_1m_10m++;
166f08c3bdfSopenharmony_ci	else
167f08c3bdfSopenharmony_ci		fsz_10m_larger++;
168f08c3bdfSopenharmony_ci
169f08c3bdfSopenharmony_ci	/* construct a name for the file */
170f08c3bdfSopenharmony_ci	get_name_by_number(this_files_number++, str);
171f08c3bdfSopenharmony_ci	strcpy(fname, path);
172f08c3bdfSopenharmony_ci	strcat(fname, "/");
173f08c3bdfSopenharmony_ci	strcat(fname, str);
174f08c3bdfSopenharmony_ci
175f08c3bdfSopenharmony_ci	/* open the file, and deal with the various errors that can occur */
176f08c3bdfSopenharmony_ci
177f08c3bdfSopenharmony_ci	if ((fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0777)) == -1) {
178f08c3bdfSopenharmony_ci		if (errno == ENOSPC) {
179f08c3bdfSopenharmony_ci			if (!already_whined) {
180f08c3bdfSopenharmony_ci				printf
181f08c3bdfSopenharmony_ci				    ("reiser-2021A: out of disk (or inodes) space, will keep trying\n");
182f08c3bdfSopenharmony_ci				already_whined = 1;	/* we continue other file creation in out of
183f08c3bdfSopenharmony_ci							   space conditions */
184f08c3bdfSopenharmony_ci			}
185f08c3bdfSopenharmony_ci			return;
186f08c3bdfSopenharmony_ci		}
187f08c3bdfSopenharmony_ci		/*  it is sometimes useful to be able to run this program more than once
188f08c3bdfSopenharmony_ci		   inside the same directory, and that means skipping over filenames that
189f08c3bdfSopenharmony_ci		   already exist.  Thus we ignore EEXIST, and pay attention to all
190f08c3bdfSopenharmony_ci		   else. */
191f08c3bdfSopenharmony_ci		if (errno == EEXIST) {	/* just skip existing file */
192f08c3bdfSopenharmony_ci			return;
193f08c3bdfSopenharmony_ci		}
194f08c3bdfSopenharmony_ci		perror("open");
195f08c3bdfSopenharmony_ci		exit(errno);
196f08c3bdfSopenharmony_ci	}
197f08c3bdfSopenharmony_ci	/* write to the file until it is the right size, handling the various error
198f08c3bdfSopenharmony_ci	   conditions appropriately */
199f08c3bdfSopenharmony_ci
200f08c3bdfSopenharmony_ci	while (size > 0) {
201f08c3bdfSopenharmony_ci		size -= (error =
202f08c3bdfSopenharmony_ci			 write(fd, write_buffer,
203f08c3bdfSopenharmony_ci			       (size <
204f08c3bdfSopenharmony_ci				write_buffer_size -
205f08c3bdfSopenharmony_ci				1) ? size : (write_buffer_size - 1)));
206f08c3bdfSopenharmony_ci		if (error == -1) {
207f08c3bdfSopenharmony_ci			if (errno == ENOSPC) {
208f08c3bdfSopenharmony_ci				if (!already_whined) {
209f08c3bdfSopenharmony_ci					printf
210f08c3bdfSopenharmony_ci					    ("reiser-2022: out of disk space, will keep trying\n");
211f08c3bdfSopenharmony_ci					already_whined = 1;
212f08c3bdfSopenharmony_ci				}
213f08c3bdfSopenharmony_ci				close(fd);
214f08c3bdfSopenharmony_ci				return;
215f08c3bdfSopenharmony_ci			}
216f08c3bdfSopenharmony_ci			perror("write() failed");
217f08c3bdfSopenharmony_ci			exit(errno);
218f08c3bdfSopenharmony_ci		}
219f08c3bdfSopenharmony_ci	}
220f08c3bdfSopenharmony_ci
221f08c3bdfSopenharmony_ci	/* close the file */
222f08c3bdfSopenharmony_ci	if (close(fd)) {
223f08c3bdfSopenharmony_ci		perror("close() failed");
224f08c3bdfSopenharmony_ci		exit(errno);
225f08c3bdfSopenharmony_ci	}
226f08c3bdfSopenharmony_ci}
227f08c3bdfSopenharmony_ci
228f08c3bdfSopenharmony_ci/* print the statistics on how many files were created of what size */
229f08c3bdfSopenharmony_ci
230f08c3bdfSopenharmony_civoid print_stats()
231f08c3bdfSopenharmony_ci{
232f08c3bdfSopenharmony_ci	if (!stats)
233f08c3bdfSopenharmony_ci		return;
234f08c3bdfSopenharmony_ci
235f08c3bdfSopenharmony_ci	printf("\n");
236f08c3bdfSopenharmony_ci	printf("File stats: Units are decimal (1k = 1000)\n");
237f08c3bdfSopenharmony_ci	printf("files 0-100    : %i\n", fsz_0_100);
238f08c3bdfSopenharmony_ci	printf("files 100-1K   : %i\n", fsz_100_1k);
239f08c3bdfSopenharmony_ci	printf("files 1K-10K   : %i\n", fsz_1k_10k);
240f08c3bdfSopenharmony_ci	printf("files 10K-100K : %i\n", fsz_10k_100k);
241f08c3bdfSopenharmony_ci	printf("files 100K-1M  : %i\n", fsz_100k_1m);
242f08c3bdfSopenharmony_ci	printf("files 1M-10M    : %i\n", fsz_1m_10m);
243f08c3bdfSopenharmony_ci	printf("files 10M-larger    : %i\n", fsz_10m_larger);
244f08c3bdfSopenharmony_ci	printf("total bytes written    : %lu\n", byte_total);
245f08c3bdfSopenharmony_ci
246f08c3bdfSopenharmony_ci}
247f08c3bdfSopenharmony_ci
248f08c3bdfSopenharmony_ci/* predict the number of files that will be created before max_bytes total
249f08c3bdfSopenharmony_ci   length of files is reached */
250f08c3bdfSopenharmony_cilong determine_nr_of_files(int median_file_size, double max_file_size,
251f08c3bdfSopenharmony_ci			   long bytes_to_consume)
252f08c3bdfSopenharmony_ci{
253f08c3bdfSopenharmony_ci	long nr_of_files = 0, byte_total = 0;
254f08c3bdfSopenharmony_ci
255f08c3bdfSopenharmony_ci	/* the next line is not necessary as 1 is the default, it is just cautious
256f08c3bdfSopenharmony_ci	   coding */
257f08c3bdfSopenharmony_ci	srand(1);
258f08c3bdfSopenharmony_ci	while (byte_total < bytes_to_consume) {
259f08c3bdfSopenharmony_ci		byte_total += determine_size(median_file_size, max_file_size);
260f08c3bdfSopenharmony_ci		nr_of_files++;
261f08c3bdfSopenharmony_ci	}
262f08c3bdfSopenharmony_ci	/* reset the random number generator so that when we determine_size() of the
263f08c3bdfSopenharmony_ci	   files later they will be created with the same "random" sequence used in
264f08c3bdfSopenharmony_ci	   this calculation */
265f08c3bdfSopenharmony_ci	srand(1);
266f08c3bdfSopenharmony_ci#ifdef DEBUG
267f08c3bdfSopenharmony_ci	printf("number of files is %d\n", (int)nr_of_files);
268f08c3bdfSopenharmony_ci#endif /* DEBUG */
269f08c3bdfSopenharmony_ci	fflush(NULL);
270f08c3bdfSopenharmony_ci	return nr_of_files;
271f08c3bdfSopenharmony_ci}
272f08c3bdfSopenharmony_ci
273f08c3bdfSopenharmony_ci/* fill the current working directory with nr_files_this_directory number of
274f08c3bdfSopenharmony_ci   files*/
275f08c3bdfSopenharmony_ci
276f08c3bdfSopenharmony_civoid fill_this_directory(long nr_files_this_directory, long median_file_size,
277f08c3bdfSopenharmony_ci			 long maximum_size)
278f08c3bdfSopenharmony_ci{
279f08c3bdfSopenharmony_ci	long size;
280f08c3bdfSopenharmony_ci
281f08c3bdfSopenharmony_ci#ifdef DEBUG
282f08c3bdfSopenharmony_ci	printf("filling with %lu files, ", nr_files_this_directory);
283f08c3bdfSopenharmony_ci#endif
284f08c3bdfSopenharmony_ci	while (nr_files_this_directory--) {
285f08c3bdfSopenharmony_ci		size = determine_size(median_file_size, maximum_size);
286f08c3bdfSopenharmony_ci		byte_total += size;
287f08c3bdfSopenharmony_ci		make_file(size);
288f08c3bdfSopenharmony_ci	}
289f08c3bdfSopenharmony_ci}
290f08c3bdfSopenharmony_ci
291f08c3bdfSopenharmony_ci/* this will unfortunately handle out of disk space by forever trying */
292f08c3bdfSopenharmony_ci/* What we should do in out of space situaltion ? I think we must skip this
293f08c3bdfSopenharmony_ci   directory and continue files/dirs creation process. Error value (!= 0)
294f08c3bdfSopenharmony_ci   indicates that we can't go to this directory. -zam */
295f08c3bdfSopenharmony_ciint make_directory(char *dirname)
296f08c3bdfSopenharmony_ci{
297f08c3bdfSopenharmony_ci	static long this_directory_number = 0;
298f08c3bdfSopenharmony_ci
299f08c3bdfSopenharmony_ci	strcpy(tdir, path);
300f08c3bdfSopenharmony_ci	strcat(tdir, "/");
301f08c3bdfSopenharmony_ci	strcat(tdir, dirname);
302f08c3bdfSopenharmony_ci
303f08c3bdfSopenharmony_ci	if (mkdir(tdir, 0755) == -1) {
304f08c3bdfSopenharmony_ci		if (errno == ENOSPC) {
305f08c3bdfSopenharmony_ci			if (!already_whined) {
306f08c3bdfSopenharmony_ci				printf("reiser-2021: out of disk space, ");
307f08c3bdfSopenharmony_ci				already_whined = 1;
308f08c3bdfSopenharmony_ci			}
309f08c3bdfSopenharmony_ci			return errno;
310f08c3bdfSopenharmony_ci		}
311f08c3bdfSopenharmony_ci		/*  it is sometimes useful to be able to run this program more than once
312f08c3bdfSopenharmony_ci		   inside the same directory, and that means skipping over filenames that
313f08c3bdfSopenharmony_ci		   already exist.  Thus we ignore EEXIST, and pay attention to all else. */
314f08c3bdfSopenharmony_ci		if (errno != EEXIST) {
315f08c3bdfSopenharmony_ci			perror("mkdir");
316f08c3bdfSopenharmony_ci			exit(errno);
317f08c3bdfSopenharmony_ci		}
318f08c3bdfSopenharmony_ci	}
319f08c3bdfSopenharmony_ci	sprintf(dirname, "d%lu", this_directory_number++);
320f08c3bdfSopenharmony_ci	strcpy(tdir, path);
321f08c3bdfSopenharmony_ci	strcat(tdir, "/");
322f08c3bdfSopenharmony_ci	strcat(tdir, dirname);
323f08c3bdfSopenharmony_ci
324f08c3bdfSopenharmony_ci	return 0;
325f08c3bdfSopenharmony_ci}
326f08c3bdfSopenharmony_ci
327f08c3bdfSopenharmony_ci/* assumes we are already chdir'd into a directory that the subtree is rooted
328f08c3bdfSopenharmony_ci   at.  Fills the directory with files and subdirectories, cd's into those
329f08c3bdfSopenharmony_ci   subdirectories, and recurses upon itself */
330f08c3bdfSopenharmony_ci
331f08c3bdfSopenharmony_civoid do_subtree(
332f08c3bdfSopenharmony_ci		       /* the start and end of the portion of the directory sizes
333f08c3bdfSopenharmony_ci		          array which corresponds to the sizes of the directories
334f08c3bdfSopenharmony_ci		          composing this subtree */
335f08c3bdfSopenharmony_ci		       /* sizes_end minus sizes_start is equal to the number of
336f08c3bdfSopenharmony_ci		          directories in this subtree */
337f08c3bdfSopenharmony_ci		       long *sizes_start, long *sizes_end,
338f08c3bdfSopenharmony_ci		       long median_file_size, long maximum_file_size,
339f08c3bdfSopenharmony_ci		       long median_dir_branching, long max_dir_branching)
340f08c3bdfSopenharmony_ci{
341f08c3bdfSopenharmony_ci	long *p;
342f08c3bdfSopenharmony_ci	long *sub_start;
343f08c3bdfSopenharmony_ci	long *sub_end;
344f08c3bdfSopenharmony_ci	int index_subdirectory_to_add_directory_to;
345f08c3bdfSopenharmony_ci	long *dirs_in_subtrees;
346f08c3bdfSopenharmony_ci	char *subtree_name;
347f08c3bdfSopenharmony_ci	long *sizes_index = sizes_start;
348f08c3bdfSopenharmony_ci	char subtree_name_array[128];
349f08c3bdfSopenharmony_ci	long this_directory_branching;
350f08c3bdfSopenharmony_ci	static long this_directorys_number;
351f08c3bdfSopenharmony_ci
352f08c3bdfSopenharmony_ci	subtree_name = subtree_name_array;
353f08c3bdfSopenharmony_ci	/* fill this directory with its number of files */
354f08c3bdfSopenharmony_ci	fill_this_directory(*sizes_index, median_file_size, maximum_file_size);
355f08c3bdfSopenharmony_ci	sizes_index++;
356f08c3bdfSopenharmony_ci	/* ok, now randomly assign directories (and their number of files) among the
357f08c3bdfSopenharmony_ci	   subdirectories that will be created if at least one directory is assigned
358f08c3bdfSopenharmony_ci	   to it */
359f08c3bdfSopenharmony_ci
360f08c3bdfSopenharmony_ci	/* this will cause the random number sequence to not match the one used in
361f08c3bdfSopenharmony_ci	   determine_nr_files() I need to accumulate my values in an array
362f08c3bdfSopenharmony_ci	   beforehand. I'll code that later.  */
363f08c3bdfSopenharmony_ci	/* worry about whether 0 or 1 is a problem value */
364f08c3bdfSopenharmony_ci	this_directory_branching =
365f08c3bdfSopenharmony_ci	    determine_size(median_dir_branching, max_dir_branching) + 1;
366f08c3bdfSopenharmony_ci
367f08c3bdfSopenharmony_ci	/* create an array holding the number of directories assigned to each
368f08c3bdfSopenharmony_ci	   potential subdirectory */
369f08c3bdfSopenharmony_ci	dirs_in_subtrees = calloc(this_directory_branching, sizeof(long));
370f08c3bdfSopenharmony_ci	while (sizes_index <= sizes_end) {
371f08c3bdfSopenharmony_ci		index_subdirectory_to_add_directory_to =
372f08c3bdfSopenharmony_ci		    (rand() % this_directory_branching);
373f08c3bdfSopenharmony_ci		(*
374f08c3bdfSopenharmony_ci		 (dirs_in_subtrees + index_subdirectory_to_add_directory_to))++;
375f08c3bdfSopenharmony_ci		sizes_index++;
376f08c3bdfSopenharmony_ci	}
377f08c3bdfSopenharmony_ci	/* the +1 is for the fill_directory() we did above */
378f08c3bdfSopenharmony_ci	sizes_index = sizes_start + 1;
379f08c3bdfSopenharmony_ci
380f08c3bdfSopenharmony_ci	/* go through each potential subdirectory, and if at least one directory has
381f08c3bdfSopenharmony_ci	   been assigned to it, create it and recurse */
382f08c3bdfSopenharmony_ci	for (p = dirs_in_subtrees;
383f08c3bdfSopenharmony_ci	     p < (dirs_in_subtrees + this_directory_branching); p++) {
384f08c3bdfSopenharmony_ci		if (*p) {
385f08c3bdfSopenharmony_ci			int nocd;
386f08c3bdfSopenharmony_ci			sprintf(subtree_name, "d%lu", this_directorys_number++);
387f08c3bdfSopenharmony_ci			nocd = make_directory(subtree_name);
388f08c3bdfSopenharmony_ci			/* if make_dir.. may fails (in out of space situation), we continue
389f08c3bdfSopenharmony_ci			   creation process in same dir */
390f08c3bdfSopenharmony_ci			if (!nocd)
391f08c3bdfSopenharmony_ci				chngdir(subtree_name);
392f08c3bdfSopenharmony_ci			sub_start = sizes_index;
393f08c3bdfSopenharmony_ci			/* the minus one is because *p is the number of elements and arrays start at 0 */
394f08c3bdfSopenharmony_ci			sub_end = (sizes_index + (*p - 1));
395f08c3bdfSopenharmony_ci
396f08c3bdfSopenharmony_ci#ifdef DEBUG
397f08c3bdfSopenharmony_ci			/* comment this back in if the array logic has you going cross-eyed */
398f08c3bdfSopenharmony_ci			/*      printf ("sizes_start is %p, sizes_index is %p, sizes_index+p is %p, sizes_end is %p\n", sizes_start, sub_start, sub_end, sizes_end); */
399f08c3bdfSopenharmony_ci#endif
400f08c3bdfSopenharmony_ci			do_subtree(sub_start, sub_end, median_file_size,
401f08c3bdfSopenharmony_ci				   maximum_file_size, median_dir_branching,
402f08c3bdfSopenharmony_ci				   max_dir_branching);
403f08c3bdfSopenharmony_ci			if (!nocd)
404f08c3bdfSopenharmony_ci				chngdir("..");
405f08c3bdfSopenharmony_ci		}
406f08c3bdfSopenharmony_ci		sizes_index += *p;
407f08c3bdfSopenharmony_ci	}
408f08c3bdfSopenharmony_ci}
409f08c3bdfSopenharmony_ci
410f08c3bdfSopenharmony_ci/* We have already determined that nr_files can fit in bytes_to_consume space.
411f08c3bdfSopenharmony_ci   Fill the sizes array with the number of files to be in each directory, and
412f08c3bdfSopenharmony_ci   then call do_subtree to fill the tree with files and directories.  */
413f08c3bdfSopenharmony_ci
414f08c3bdfSopenharmony_civoid make_fractal_tree(long median_file_size, long maximum_file_size,
415f08c3bdfSopenharmony_ci		       long median_dir_nr_files, long max_dir_nr_files,
416f08c3bdfSopenharmony_ci		       long median_dir_branching, long max_dir_branching,
417f08c3bdfSopenharmony_ci		       long nr_files)
418f08c3bdfSopenharmony_ci{
419f08c3bdfSopenharmony_ci	long *sizes_start;
420f08c3bdfSopenharmony_ci	long *sizes_end;
421f08c3bdfSopenharmony_ci	long *sizes_index;
422f08c3bdfSopenharmony_ci	long remaining_files = nr_files;
423f08c3bdfSopenharmony_ci
424f08c3bdfSopenharmony_ci	/* collect together array of directory sizes for whole filesystem.  This
425f08c3bdfSopenharmony_ci	   cannot easily be done recursively without distorting the directory sizes
426f08c3bdfSopenharmony_ci	   and making deeper directories smaller.  Send me the code if you
427f08c3bdfSopenharmony_ci	   disagree.:-) */
428f08c3bdfSopenharmony_ci	/* we almost certainly don't need this much space, but so what.... */
429f08c3bdfSopenharmony_ci	sizes_index = sizes_start = malloc(nr_files * sizeof(long));
430f08c3bdfSopenharmony_ci	for (; remaining_files > 0;) {
431f08c3bdfSopenharmony_ci		*sizes_index =
432f08c3bdfSopenharmony_ci		    determine_size(median_dir_nr_files, max_dir_nr_files);
433f08c3bdfSopenharmony_ci		// we alloc space for nr_files, so we should avoid
434f08c3bdfSopenharmony_ci		// number of files in directory = 0 -grev.
435f08c3bdfSopenharmony_ci		if (*sizes_index == 0)
436f08c3bdfSopenharmony_ci			*sizes_index = 1;
437f08c3bdfSopenharmony_ci		*sizes_index =
438f08c3bdfSopenharmony_ci		    (*sizes_index <
439f08c3bdfSopenharmony_ci		     remaining_files) ? *sizes_index : remaining_files;
440f08c3bdfSopenharmony_ci
441f08c3bdfSopenharmony_ci#ifdef DEBUG
442f08c3bdfSopenharmony_ci		printf("*sizes_index == %lu, ", *sizes_index);
443f08c3bdfSopenharmony_ci#endif
444f08c3bdfSopenharmony_ci		remaining_files -= *sizes_index;
445f08c3bdfSopenharmony_ci		sizes_index++;
446f08c3bdfSopenharmony_ci	}
447f08c3bdfSopenharmony_ci	/* don't decrement below sizes_start if nr_files is 0 */
448f08c3bdfSopenharmony_ci	sizes_end = (sizes_index-- > sizes_start) ? sizes_index : sizes_start;
449f08c3bdfSopenharmony_ci
450f08c3bdfSopenharmony_ci	sizes_index = sizes_start;
451f08c3bdfSopenharmony_ci	srand(1);
452f08c3bdfSopenharmony_ci	do_subtree(sizes_start, sizes_end, median_file_size, maximum_file_size,
453f08c3bdfSopenharmony_ci		   median_dir_branching, max_dir_branching);
454f08c3bdfSopenharmony_ci
455f08c3bdfSopenharmony_ci}
456f08c3bdfSopenharmony_ci
457f08c3bdfSopenharmony_ciint main(int argc, char *argv[])
458f08c3bdfSopenharmony_ci{
459f08c3bdfSopenharmony_ci	/* initialized from argv[] */
460f08c3bdfSopenharmony_ci	long median_file_size,
461f08c3bdfSopenharmony_ci	    median_dir_branching,
462f08c3bdfSopenharmony_ci	    median_dir_nr_files,
463f08c3bdfSopenharmony_ci	    max_dir_nr_files, max_dir_branching, max_file_size;
464f08c3bdfSopenharmony_ci	long nr_of_files = 0;	/* files to be created */
465f08c3bdfSopenharmony_ci
466f08c3bdfSopenharmony_ci	if (argc != 11) {
467f08c3bdfSopenharmony_ci		print_usage();
468f08c3bdfSopenharmony_ci		exit(1);
469f08c3bdfSopenharmony_ci	}
470f08c3bdfSopenharmony_ci
471f08c3bdfSopenharmony_ci	write_buffer_size = atoi(argv[8]);
472f08c3bdfSopenharmony_ci	write_buffer = malloc(write_buffer_size);
473f08c3bdfSopenharmony_ci	memset(write_buffer, 'a', write_buffer_size);
474f08c3bdfSopenharmony_ci
475f08c3bdfSopenharmony_ci	/* the number of bytes that we desire this tree to consume.  It will actually
476f08c3bdfSopenharmony_ci	   consume more, because the last file will overshoot by a random amount, and
477f08c3bdfSopenharmony_ci	   because the directories and metadata will consume space.  */
478f08c3bdfSopenharmony_ci	bytes_to_consume = atol(argv[1]);
479f08c3bdfSopenharmony_ci	max_file_size = atol(argv[3]);
480f08c3bdfSopenharmony_ci	median_file_size = atol(argv[2]);
481f08c3bdfSopenharmony_ci	/* Figure out how many random files will fit into bytes_to_consume bytes. We
482f08c3bdfSopenharmony_ci	   depend on resetting rand() to get the same result later. */
483f08c3bdfSopenharmony_ci	nr_of_files =
484f08c3bdfSopenharmony_ci	    determine_nr_of_files(median_file_size, max_file_size,
485f08c3bdfSopenharmony_ci				  bytes_to_consume);
486f08c3bdfSopenharmony_ci
487f08c3bdfSopenharmony_ci	strcpy(path, argv[9]);
488f08c3bdfSopenharmony_ci	mkdir(path, 0755);
489f08c3bdfSopenharmony_ci	stats = atol(argv[10]);
490f08c3bdfSopenharmony_ci	median_dir_branching = atol(argv[6]);
491f08c3bdfSopenharmony_ci	max_dir_branching = atol(argv[7]);
492f08c3bdfSopenharmony_ci	median_dir_nr_files = atol(argv[4]);
493f08c3bdfSopenharmony_ci	max_dir_nr_files = atol(argv[5]);
494f08c3bdfSopenharmony_ci	make_fractal_tree(median_file_size, max_file_size, median_dir_nr_files,
495f08c3bdfSopenharmony_ci			  max_dir_nr_files, median_dir_branching,
496f08c3bdfSopenharmony_ci			  max_dir_branching, nr_of_files);
497f08c3bdfSopenharmony_ci	print_stats();
498f08c3bdfSopenharmony_ci	if (stats)
499f08c3bdfSopenharmony_ci		printf("\nreiser_fract_tree finished\n");
500f08c3bdfSopenharmony_ci
501f08c3bdfSopenharmony_ci	return 0;
502f08c3bdfSopenharmony_ci}
503