usbmodeswitch: Updated to v.1.2.6 from shibby's branch.
[tomato.git] / release / src / router / jffsfilegen / filegen.c
blobc96a0036837fd79f9a8af377c63a70c1750f3955
1 /* Create & delete files at random, with random sizes.
2 This is for testing the jffs filesystem code.
4 Before you run filegen, you almost certainly want to set up jffs
5 so that it runs out of RAM instead of flash.
6 Edit linux/fs/jffs/jffs_fm.h, change: "#define JFFS_RAM_BLOCKS 0"
7 to be non-zero.
8 */
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <math.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
21 /*****************************************************/
22 void usage()
24 puts("Usage: filegen [options]");
25 puts("\t-v = verbose");
26 puts("\t-n# = Number to do. Default 1000");
27 puts("\t-s# = number of initial ones to skip.");
28 puts("\t-f# = floor - min size.");
29 puts("\t-c# = ceiling - max size.");
30 puts("\t-x# = Write 4KB at a time until the disk is full.");
34 extern char *optarg;
35 extern int optind, opterr, optopt;
38 int num_eb = 1; /* # of EB's to use for files. */
41 #define MAX_FIL 107 /* Max # of files. */
42 #define MAX_SIZE (75 * 1024) /* Max file size. */
44 unsigned floor_siz = 0;
45 unsigned ceiling = MAX_SIZE;
46 unsigned mean, spread;
48 int slack = 8*1024;
50 int eb_size = 64 * 1024; /* Erase block size (bytes). */
51 int num_to_do = 10; /* The number of actions to do. */
52 int skip_to = 0;
54 int num_cr = 0;
55 int num_ov = 0;
56 int num_del = 0;
57 int act_num = 0; /* Activity item number. */
59 #define FPATH "/jffs/fil_"
61 int size_on_disk = 0; /* # of bytes currently on disk, not incl overhead. */
62 int max_on_disk = 0; /* Max ever on disk (incl ohd) */
63 int num_on_disk = 0; /* # of files currently on disk. */
65 int min_siz = 999999;
66 int max_siz = 0;
68 int verb = 0; /* Verbose */
70 /* File overhead--approximate.
71 * 64 byte nodeheader per 4k page.
73 #define FI_OHD(sz) (((sz+4095)/4096) * 72)
75 struct file_info {
76 int fi_exist; /* >0 = file exists, 0 = not. <0 = exist but skipped. */
77 int fi_siz; /* Size of the file. */
80 struct file_info files[MAX_FIL] = {{0}};
81 char *wbf;
83 void write_file();
84 void pr_info();
85 void do_err(char *what, char *fn);
86 int size_random();
87 void delete_a_file();
88 void del_to_fit(int s);
89 int pick_fil();
90 void goup();
93 /** MWC generator. */
94 long int random()
96 static unsigned long z=362436069, w=521288629;
97 long int iuni;
99 z = 36969 * (z & 65535) + (z >> 16);
100 w = 18000 * (w & 65535) + (w >> 16);
101 iuni = ((z << 16) + w) & RAND_MAX;
102 return(iuni);
105 #define ranf() ((double)random() / RAND_MAX)
108 /*******************************************************/
109 int main(int argc, char **argv)
111 int c;
112 int j;
114 while((c = getopt(argc, argv, "vn:s:c:f:x")) != -1) {
115 switch (c) {
116 case 'v':
117 ++verb;
118 break;
120 case 'n':
121 num_to_do = atoi(optarg);
122 break;
124 case 's':
125 skip_to = atoi(optarg);
126 break;
128 case 'f':
129 floor_siz = atoi(optarg);
130 break;
132 case 'c':
133 ceiling = atoi(optarg);
134 break;
136 case 'x':
137 goup();
138 exit(1);
139 break;
141 case '?':
142 usage();
143 exit(1);
148 if (ceiling > num_eb * 64 * 1024 - slack)
149 ceiling = num_eb * 64 * 1024 - slack;
151 if (ceiling < floor_siz) {
152 puts("Error: ceiling is below floor.");
153 exit(1);
156 if (ceiling > 100000) {
157 puts("Error: ceiling too large.");
158 exit(1);
161 mean = (ceiling - floor_siz) / 3 + floor_siz;
162 spread = (4 * (ceiling - floor_siz)) / 10 + floor_siz;
164 //while (num_to_do--) { printf("%5u\n", size_random());} ; exit(0);
165 wbf = malloc(ceiling);
166 if (wbf == NULL)
167 do_err("alloc", "");
169 while (act_num < num_to_do) {
170 j = random() % 100;
171 if (j > 75)
172 delete_a_file();
173 else
174 write_file();
175 if (act_num % 100 == 0)
176 pr_info();
179 printf("Done.\n");
180 pr_info();
181 return (0);
186 /*******************************************************/
187 /* Select a file to do. */
188 /* Return its index in 'files'. */
189 int pick_fil()
191 int i;
193 i = random() % MAX_FIL;
194 return(i);
198 /*******************************************************/
199 /* Write a file.
200 * Pick random file & size. */
201 void write_file()
203 int f, s;
204 char fn[80];
205 FILE *fp;
206 int i;
208 //printf("wrt\n");
209 f = pick_fil();
210 s = size_random();
211 if (s > max_siz) max_siz = s;
212 if (s < min_siz) min_siz = s;
213 if (s + FI_OHD(s) > num_eb * eb_size - slack)
214 return; /* This file cannot fit. */
215 del_to_fit(s);
217 if (act_num >= num_to_do)
218 return;
219 ++act_num;
220 sprintf(fn, "%s%02d", FPATH, f);
221 if (verb)
222 printf("Create %s of %5d #%d%s\n", fn, s, act_num,
223 act_num >= skip_to?"": " [skip]");
224 if (act_num >= skip_to) {
225 fp = fopen(fn, "w");
226 if (!fp)
227 do_err("open", fn);
228 i = fwrite(wbf, 1, s, fp);
229 if (i < s) {
230 printf("Req size: %d Wrote: %d\n", s, i);
231 do_err("write", fn);
233 fclose(fp);
235 if (files[f].fi_exist) { /* Over-write existing file. */
236 size_on_disk -= files[f].fi_siz;
237 --num_on_disk;
238 ++num_ov;
240 else
241 ++num_cr;
243 if (act_num >= skip_to)
244 files[f].fi_exist = 1;
245 else
246 files[f].fi_exist = -1;
247 files[f].fi_siz = s;
248 size_on_disk += files[f].fi_siz;
249 i = size_on_disk + FI_OHD(size_on_disk);
250 if (max_on_disk < i)
251 max_on_disk = i;
252 ++num_on_disk;
253 if (verb > 1)
254 printf("\t\t\tEst used: %d\n", size_on_disk + FI_OHD(size_on_disk));
257 /*******************************************************/
258 /* Delete enough file(s) so that this new one will fit. */
259 /* Allow for an extra PAGE on the write. */
260 void del_to_fit(int s)
262 int i = 100;
265 while (i-- && s + FI_OHD(s) + size_on_disk + FI_OHD(size_on_disk)
266 > num_eb * eb_size - slack) {
267 /* printf("must delete to fit\n"); */
268 /* printf("This: %6d exist: %6d tot: %6d vs. %6d diff: %6d\n", */
269 /* s + FI_OHD(s), size_on_disk + FI_OHD(size_on_disk), */
270 /* s + FI_OHD(s) + size_on_disk + FI_OHD(size_on_disk), */
271 /* num_eb * eb_size - slack, */
272 /* num_eb * eb_size - slack - (s + FI_OHD(s) + size_on_disk + FI_OHD(size_on_disk))); */
273 delete_a_file();
275 /* printf("atxt: %6d exist: %6d tot: %6d vs. %6d diff: %6d\n", */
276 /* s + FI_OHD(s), size_on_disk + FI_OHD(size_on_disk), */
277 /* s + FI_OHD(s) + size_on_disk + FI_OHD(size_on_disk), */
278 /* num_eb * eb_size - slack, */
279 /* num_eb * eb_size - slack - (s + FI_OHD(s) + size_on_disk + FI_OHD(size_on_disk))); */
282 /*******************************************************/
283 /* Pick a random file to delete. */
284 void delete_a_file()
286 int f;
287 char fn[80];
288 int i = 0;
290 //printf("daf\n");
291 if (num_on_disk) {
292 f = random() % MAX_FIL;
293 for( ; !files[f].fi_exist ; ++f) {
294 if (f >= MAX_FIL-1)
295 f = -1;
297 ++act_num;
298 sprintf(fn, "%s%02d", FPATH, f);
299 if (verb)
300 printf("Delete %s #%d%s\n", fn, act_num,
301 act_num >= skip_to ?"": " [skip]");
302 if (act_num >= skip_to) {
303 if (files[f].fi_exist > 0)
304 i = unlink(fn);
305 else
306 i = 0;
308 if (i != 0)
309 do_err("delete", fn);
310 ++num_del;
311 files[f].fi_exist = 0;
312 size_on_disk -= files[f].fi_siz;
313 files[f].fi_siz = 0;
314 --num_on_disk;
316 if (verb > 1)
317 printf("\t\t\tEst used: %d\n", size_on_disk + FI_OHD(size_on_disk));
321 /*******************************************************/
322 /* Return a gaussian distributed random number,
323 between 0 and 74000. */
324 float box_muller(float m, float s) /* normal random variate generator */
325 { /* mean m, standard deviation s */
326 float x1, x2, w, y1;
327 static float y2;
328 static int use_last = 0;
330 if (use_last) /* use value from previous call */
332 y1 = y2;
333 use_last = 0;
335 else
337 do {
338 x1 = 2.0 * ranf() - 1.0;
339 x2 = 2.0 * ranf() - 1.0;
340 w = x1 * x1 + x2 * x2;
341 } while ( w >= 1.0 );
343 w = sqrt( (-2.0 * log( w ) ) / w );
344 y1 = x1 * w;
345 y2 = x2 * w;
346 use_last = 1;
348 return( m + y1 * s );
352 /*******************************************************/
353 int size_random()
355 int z;
356 int try = 25;
358 if (ceiling- floor_siz > 5000) {
359 /* Small range -- use uniform distribution, */
360 z = random() >> 3;
361 z %= (ceiling- floor_siz);
362 z += floor_siz;
363 return z;
366 /* Larger range, use gausian (mormal) distribution. */
367 do {
368 z = box_muller(mean, spread);
369 } while (try-- && (z < floor_siz || z >= ceiling));
371 if (z < floor_siz) z = floor_siz;
372 if (z > ceiling) z = ((z- floor_siz) % (ceiling- floor_siz)) + floor_siz;
373 return z;
376 /*******************************************************/
377 void pr_info()
379 printf("actions: %6d created: %6d over-written: %6d deleted: %6d\n",
380 act_num, num_cr, num_ov, num_del);
381 printf("Min filesize: %5d Max filesize: %5d Max on disk: %5d\n",
382 min_siz, max_siz, max_on_disk);
383 printf("%d files on disk totaling %d bytes\n",
384 num_on_disk, size_on_disk);
385 printf("\t\t\tEst used: %d\n", size_on_disk + FI_OHD(size_on_disk));
388 /*******************************************************/
389 /* Write 4kb at a time until we get an error. */
390 void goup()
392 int fd;
393 int i;
394 int tsiz;
396 wbf = malloc(2*4096);
397 fd = open("/jffs/try", O_CREAT|O_WRONLY|O_TRUNC | O_SYNC, 0666);
398 if (fd <= 0) {
399 perror("open");
400 exit(1);
402 for(tsiz = 0; tsiz < 512 ; ++tsiz) {
403 i = write(fd, wbf, 4 * 1024);
404 if (i < 1) {
405 perror("Died");
406 printf("Error. Wrote %d*4kb %dKB okay. %5x\n", tsiz,
407 tsiz * 4, tsiz*4096);
408 exit(1);
411 printf("Wrote %d*4kb okay. %5x\n", tsiz, tsiz*4096 );
412 close(fd);
415 /*******************************************************/
416 void do_err(char *what, char *fn)
418 int i = errno;
420 printf("Fatal error on %s filename '%s'. Action # %d\n",
421 what, fn, act_num);
422 errno = i;
423 perror("");
424 pr_info();
425 exit(1);