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"
17 #include <sys/types.h>
21 /*****************************************************/
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.");
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
;
50 int eb_size
= 64 * 1024; /* Erase block size (bytes). */
51 int num_to_do
= 10; /* The number of actions to do. */
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. */
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)
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}};
85 void do_err(char *what
, char *fn
);
88 void del_to_fit(int s
);
96 static unsigned long z
=362436069, w
=521288629;
99 z
= 36969 * (z
& 65535) + (z
>> 16);
100 w
= 18000 * (w
& 65535) + (w
>> 16);
101 iuni
= ((z
<< 16) + w
) & RAND_MAX
;
105 #define ranf() ((double)random() / RAND_MAX)
108 /*******************************************************/
109 int main(int argc
, char **argv
)
114 while((c
= getopt(argc
, argv
, "vn:s:c:f:x")) != -1) {
121 num_to_do
= atoi(optarg
);
125 skip_to
= atoi(optarg
);
129 floor_siz
= atoi(optarg
);
133 ceiling
= atoi(optarg
);
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.");
156 if (ceiling
> 100000) {
157 puts("Error: ceiling too large.");
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
);
169 while (act_num
< num_to_do
) {
175 if (act_num
% 100 == 0)
186 /*******************************************************/
187 /* Select a file to do. */
188 /* Return its index in 'files'. */
193 i
= random() % MAX_FIL
;
198 /*******************************************************/
200 * Pick random file & size. */
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. */
217 if (act_num
>= num_to_do
)
220 sprintf(fn
, "%s%02d", FPATH
, f
);
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
) {
228 i
= fwrite(wbf
, 1, s
, fp
);
230 printf("Req size: %d Wrote: %d\n", s
, i
);
235 if (files
[f
].fi_exist
) { /* Over-write existing file. */
236 size_on_disk
-= files
[f
].fi_siz
;
243 if (act_num
>= skip_to
)
244 files
[f
].fi_exist
= 1;
246 files
[f
].fi_exist
= -1;
248 size_on_disk
+= files
[f
].fi_siz
;
249 i
= size_on_disk
+ FI_OHD(size_on_disk
);
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
)
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))); */
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. */
292 f
= random() % MAX_FIL
;
293 for( ; !files
[f
].fi_exist
; ++f
) {
298 sprintf(fn
, "%s%02d", FPATH
, f
);
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)
309 do_err("delete", fn
);
311 files
[f
].fi_exist
= 0;
312 size_on_disk
-= files
[f
].fi_siz
;
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 */
328 static int use_last
= 0;
330 if (use_last
) /* use value from previous call */
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
);
348 return( m
+ y1
* s
);
352 /*******************************************************/
358 if (ceiling
- floor_siz
> 5000) {
359 /* Small range -- use uniform distribution, */
361 z
%= (ceiling
- floor_siz
);
366 /* Larger range, use gausian (mormal) distribution. */
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
;
376 /*******************************************************/
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. */
396 wbf
= malloc(2*4096);
397 fd
= open("/jffs/try", O_CREAT
|O_WRONLY
|O_TRUNC
| O_SYNC
, 0666);
402 for(tsiz
= 0; tsiz
< 512 ; ++tsiz
) {
403 i
= write(fd
, wbf
, 4 * 1024);
406 printf("Error. Wrote %d*4kb %dKB okay. %5x\n", tsiz
,
407 tsiz
* 4, tsiz
*4096);
411 printf("Wrote %d*4kb okay. %5x\n", tsiz
, tsiz
*4096 );
415 /*******************************************************/
416 void do_err(char *what
, char *fn
)
420 printf("Fatal error on %s filename '%s'. Action # %d\n",