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