*** empty log message ***
[yaffs/.git] / yaffsdev.c
1 /*
2  * YAFFS: Yet another FFS. A NAND-flash specific file system. 
3  * yaffsdev.c
4  *
5  * Copyright (C) 2002 Aleph One Ltd.
6  *   for Toby Churchill Ltd and Brightstar Engineering
7  *
8  * Created by Charles Manning <charles@aleph1.co.uk>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  */
15  
16 #include "yaffsinterface.h"
17 #include "yportenv.h"
18
19 #if YAFFS_FILEEM        
20 #include "yaffs_fileem.h"
21 #else
22 #include "yaffs_nandemul.h" 
23 #endif
24
25 #include "yaffs_guts.h"
26 #include <stdlib.h>
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32
33
34
35 unsigned yaffs_traceMask = 0xFFFFFFFF;
36
37 yaffs_Device device;
38
39
40 char *testStr = "this is a test string";
41
42 char *testStr2 = "abcdefghijklmnopqrstuvwxyz1234567890";
43
44 void TestTimexxx(yaffs_Device *dev)
45 {
46         yaffs_Object *f;
47         int x;
48         
49         
50         printf("Start\n");
51         
52
53         f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
54         if(f)
55         {
56                 printf("Found\n");
57         }
58         else
59         {
60                 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
61                 printf("Created\n");
62         }
63         
64         
65         x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename");
66                 
67 }
68
69
70 void TestTimeasasas(yaffs_Device *dev)
71 {
72         yaffs_Object *f; 
73         int x;
74         int i;
75         int b;
76         char data[200];
77         int written;
78         
79         
80         printf("Start\n");
81         
82
83         f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
84         if(f)
85         {
86                 printf("Found\n");
87         }
88         else
89         {
90                 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
91                 printf("Created\n");
92         }
93         
94         
95         x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename");
96         
97         
98         
99         for(i = 0; i < 10000; i+=20)
100         {
101         
102                 b++;
103                 if(b & 1)
104                         written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr));
105                 else
106                         written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
107         }
108         
109         
110         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
111         
112         printf("Flush\n");
113         
114         yaffs_FlushFile(f,1);
115
116         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
117         
118         yaffs_ReadDataFromFile(f,data,1000,50);
119         data[50] = 0;
120         
121         printf("Read data is \"%s\"\n",data);
122         
123         yaffs_DumpObject(f);
124
125         printf("Resize to 3000\n");     
126         yaffs_ResizeFile(f,3000);
127         printf("Resize to 2048\n");     
128         yaffs_ResizeFile(f,2048);
129         
130         yaffs_DumpObject(f);
131
132         yaffs_FlushFile(f,1);
133         
134         
135                 
136
137 }
138
139 void TestTimeBigDeletes(yaffs_Device *dev)
140 {
141         yaffs_Object *f;
142         yaffs_Object *sl;
143         yaffs_Object *lnf;
144         
145         yaffs_Object *hl1;
146         yaffs_Object *hl2;
147         yaffs_Object *hl3;
148         yaffs_Object *d, *df;
149         
150         int x;
151         int i;
152         int b;
153         char data[200];
154         
155         char * alias;
156         int written;
157         
158         
159         printf("Exisiting objects\n");
160         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
161         printf("Exisiting objects in lost+found\n");
162         lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME);
163         yaffs_ApplyToDirectoryChildren(lnf,yaffs_DumpObject);
164
165         printf("Start\n");
166         
167         
168
169         f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
170         if(f)
171         {
172                 printf("Found\n");
173         }
174         else
175         {
176                 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
177                 printf("Created\n");
178         }
179         
180         for(i = 0; i < 100000; i+=20)
181         { 
182         
183                 b++;
184                 if(b & 1)
185                         written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr));
186                 else
187                         written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
188         }
189         
190         yaffs_FlushFile(f,1);
191         yaffs_DeleteFile(f);
192
193         f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
194         if(f)
195         {
196                 printf("Found\n");
197         }
198         else
199         {
200                 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
201                 printf("Created\n");
202         }
203         
204         for(i = 0; i < 100000; i+=20)
205         { 
206         
207                 b++;
208                 if(b & 1)
209                         written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr));
210                 else
211                         written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
212         }
213         
214         yaffs_FlushFile(f,1);
215         yaffs_DeleteFile(f);
216
217         f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
218         if(f)
219         {
220                 printf("Found\n");
221         }
222         else
223         {
224                 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
225                 printf("Created\n");
226         }
227         
228         for(i = 0; i < 100000; i+=20)
229         { 
230         
231                 b++;
232                 if(b & 1)
233                         written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr));
234                 else
235                         written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
236         }
237         
238         yaffs_FlushFile(f,1);
239         yaffs_DeleteFile(f);
240         
241 }
242
243 void TestTime(yaffs_Device *dev)
244 {
245         yaffs_Object *f;
246         yaffs_Object *sl;
247         yaffs_Object *lnf;
248         
249         yaffs_Object *hl1;
250         yaffs_Object *hl2;
251         yaffs_Object *hl3;
252         yaffs_Object *d, *df;
253         
254         int x;
255         int i;
256         int b;
257         char data[200];
258         
259         char * alias;
260         int written;
261         
262         
263         printf("Exisiting objects\n");
264         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
265         printf("Exisiting objects in lost+found\n");
266         lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME);
267         yaffs_ApplyToDirectoryChildren(lnf,yaffs_DumpObject);
268
269         printf("Start\n");
270         
271         
272         // Test the problem of:
273         // Create file
274         // Delete file
275         // Create file with same name
276         // Delete file <== crash
277
278         f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
279         if(f)
280         {
281                 printf("Found\n");
282         }
283         else
284         {
285                 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
286                 printf("Created\n");
287         }
288         yaffs_Unlink(yaffs_Root(dev),"Name1");
289
290
291         f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
292         if(f)
293         {
294                 printf("Found\n");
295         }
296         else
297         {
298                 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
299                 printf("Created\n");
300         }
301         yaffs_Unlink(yaffs_Root(dev),"Name1");
302         
303         
304         
305         // Other tests
306         
307         f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
308         if(f)
309         {
310                 printf("Found\n");
311         }
312         else
313         {
314                 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
315                 printf("Created\n");
316         }
317         
318         
319         x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename");
320         
321 // Write a file with overwrite, then read it back and save outside yaffs
322 // This is to test that write caching works.
323
324         for(i = 0; i < 100; i++)
325         { 
326                 unsigned char x[500];
327         
328                 memset(x,i,500);
329                 
330                 written = yaffs_WriteDataToFile(f,x,i*500,500);         
331         }
332
333         for(i = 0; i < 100; i++)
334         { 
335                 unsigned char x;
336         
337                 x = i+5;
338                 
339                 written = yaffs_WriteDataToFile(f,&x,i*500 + 2,1);              
340         }
341         
342         
343         {
344                 int h;
345                 
346                 h = open("bork",O_RDWR | O_CREAT | O_TRUNC,0666);
347                 for(i = 0; i < 100; i++)
348                 { 
349                         unsigned char x[500];
350         
351                         yaffs_ReadDataFromFile(f,x,i*500,500);
352                         write(h,x,500);
353                 }
354                 close(h);
355                 
356                 
357         }
358         
359 // Big write to fill disk
360
361         written = 1;
362         for(i = 0; i < 1000000 && written > 0; i++)
363         { 
364                 unsigned char x[500];
365         
366                 memset(x,i,500);
367                 
368                 written = yaffs_WriteDataToFile(f,x,i*500,500);         
369         }
370         if(written <= 0)
371         {
372                 printf("YAFFS full\n");
373         }
374         
375         // some short reads
376         for(i = 1000; i < 50000; i+=2)
377         { 
378                 yaffs_ReadDataFromFile(f,data,i,20);
379         }
380         
381                 
382         yaffs_ReadDataFromFile(f,data,1000,50); 
383         data[50] = 0;
384         
385         printf("Read data is \"%s\"\n",data);
386
387         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
388         yaffs_ReadDataFromFile(f,data,1000,50);
389         data[50] = 0;
390         
391         printf("Read data is \"%s\"\n",data);
392         
393         printf("Flush\n");
394         
395         yaffs_FlushFile(f,1);
396         yaffs_ReadDataFromFile(f,data,1000,50);
397         data[50] = 0;
398         
399         printf("Read data is \"%s\"\n",data);
400         
401         printf("File length is %d\n",yaffs_GetObjectFileLength(f));
402         
403         sl = yaffs_MknodSymLink(yaffs_Root(dev),"sym-link",0,0,0,"/tmp/alias");
404         yaffs_ReadDataFromFile(f,data,1000,50);
405         data[50] = 0;
406         
407         printf("Read data is \"%s\"\n",data);
408
409
410         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
411         
412         printf("\n\nsymlink alias is \"%s\"\n",alias = yaffs_GetSymlinkAlias(sl));
413         
414         free(alias);
415         
416         printf("Unlink symlink %d\n",yaffs_Unlink(yaffs_Root(dev),"sym-link"));
417         
418         
419         yaffs_ReadDataFromFile(f,data,1000,50);
420         data[50] = 0;
421         
422         printf("Read data is \"%s\"\n",data);
423         
424         yaffs_DumpObject(f);
425
426         printf("Resize 3000\n");        
427         yaffs_ResizeFile(f,3000);
428
429         printf("Resize 2050\n");        
430         yaffs_ResizeFile(f,2050);
431         printf("Resize 2049\n");        
432         yaffs_ResizeFile(f,2049);
433         printf("Resize 2048\n");        
434         yaffs_ResizeFile(f,2048);
435
436
437         printf("Resize 2000\n");        
438         yaffs_ResizeFile(f,2000);
439         
440         yaffs_DumpObject(f);
441         
442         lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME);
443         
444         
445
446         yaffs_FlushFile(f,1);
447                 
448
449         printf("Unlink file: %d\n",yaffs_Unlink(yaffs_Root(dev),"Rename"));
450         
451         yaffs_DeleteFile(f);
452         
453         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
454         
455         // Create a directory and play with it
456         
457
458         printf("Find or Create directory and play with it\n");
459         d =  yaffs_FindObjectByName(yaffs_Root(dev),"direct");
460         if(!d)
461         {
462                 d = yaffs_MknodDirectory(yaffs_Root(dev),"direct",0,0,0);
463         }
464         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
465         yaffs_ApplyToDirectoryChildren(d,yaffs_DumpObject);
466         
467         printf("Make file in directory\n");
468         
469         df = yaffs_MknodFile(d,"file-in-directory",0,0,0);
470         yaffs_ApplyToDirectoryChildren(d,yaffs_DumpObject);
471         
472         
473         // Do some stuff with hardlinks
474         //
475         // NB Deleting hardlinked objects can mess up pointers to hardlinks.
476         // The mechanism is as follows:
477         // * If you unlink a file,softlink or directory that has one or more hardlinks,
478         // then the object is renamed to one of the hardlinks and that hardlink is unlinked.
479         // This means that a pointer to a hardlink so deleted will point to an invalid address.
480         // Thus, make sure that pointers to hardlinks are immediately dereferenced.
481
482
483         printf("Hard link tests\n");
484                 
485         f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
486         hl1 = yaffs_Link(yaffs_Root(dev),"HardLink 1",f);
487         hl2 = yaffs_Link(yaffs_Root(dev),"HardLink 2",f);
488         hl3 = yaffs_Link(yaffs_Root(dev),"HardLink 3",hl2);
489
490         printf("\n\nHard links created\n");
491         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
492         
493         yaffs_Unlink(yaffs_Root(dev),"HardLink 1");
494         printf("\n\nHard link deleted\n");
495         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
496         
497         yaffs_Unlink(yaffs_Root(dev),"Name1");
498         printf("\n\nHard linked file deleted\n");
499         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
500         
501         yaffs_Unlink(yaffs_Root(dev),"HardLink 2");
502         printf("\n\nHard link 2 deleted\n");
503         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
504         
505         yaffs_Unlink(yaffs_Root(dev),"HardLink 3");
506
507         printf("\n\nHard link 3 deleted\n");
508         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
509         
510         // NB We don't allow unlinking or rename of the root or lost+found
511         // We allow setting attributes, but these must not be written to
512         // NAND since they are not real objects.
513         
514         printf("Attempt to rename lost+found - should have failed\n");
515         x = yaffs_RenameObject(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME,NULL,"Renamed");
516         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
517
518         f = yaffs_MknodFile(yaffs_Root(dev),"pfile",0,0,0);
519         if(f)
520         {
521                 yaffs_WriteDataToFile(f,testStr,0,strlen(testStr));
522         }
523
524         yaffs_Link(yaffs_Root(dev),"phl4",f);
525 }
526
527 void TestTimeDeleteFocussed(yaffs_Device *dev)
528 {
529         yaffs_Object *f;
530         yaffs_Object *lnf;
531         
532         
533         int x;
534         int i;
535         int b;
536         int written;
537         
538         
539         printf("Exisiting objects\n");
540         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
541         printf("Exisiting objects in lost+found\n");
542         lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME);
543         yaffs_ApplyToDirectoryChildren(lnf,yaffs_DumpObject);
544
545         printf("Start\n");
546         
547         
548         
549
550         f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
551         if(f)
552         {
553                 printf("Found\n");
554         }
555         else
556         {
557                 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
558                 printf("Created\n");
559         }
560         
561         
562         x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename");
563         
564         for(i = 0; i < 100000; i+=20)
565         { 
566         
567                 b++;
568                 if(b & 1)
569                         written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr));
570                 else
571                         written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
572         }
573         
574         
575
576         yaffs_FlushFile(f,1);
577                 
578
579         printf("Unlink file: %d\n",yaffs_Unlink(yaffs_Root(dev),"Rename"));
580         
581         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
582         
583 }
584
585 void TestTimeTnodeFocussed(yaffs_Device *dev)
586 {
587         yaffs_Object *f;
588         yaffs_Object *lnf;
589         
590         
591         int x;
592         int i;
593         int b;
594         int written;
595         
596         
597         printf("Exisiting objects\n");
598         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
599         printf("Exisiting objects in lost+found\n");
600         lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME);
601         yaffs_ApplyToDirectoryChildren(lnf,yaffs_DumpObject);
602
603         printf("Start\n");
604         
605         
606         
607
608         f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
609         if(f)
610         {
611                 printf("Found\n");
612         }
613         else
614         {
615                 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
616                 printf("Created\n");
617         }
618         
619         
620         x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename");
621         
622         for(i = 0; i < 10000; i+=20)
623         {
624         
625                 b++;
626                 if(b & 1)
627                         written = yaffs_WriteDataToFile(f,testStr,0,strlen(testStr));
628                 else
629                         written = yaffs_WriteDataToFile(f,testStr2,0,strlen(testStr2));
630         }
631         
632 }
633 void TestTimeBackgroundDeleteFocussed(yaffs_Device *dev)
634 {
635         yaffs_Object *f;
636         yaffs_Object *lnf;
637         
638         
639         int x;
640         int i,j;
641         int b;
642         int written;
643         
644         
645         printf("Exisiting objects\n");
646         yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
647         printf("Exisiting objects in lost+found\n");
648         lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME);
649         yaffs_ApplyToDirectoryChildren(lnf,yaffs_DumpObject);
650
651         printf("Start\n");
652         
653         
654         for(j = 0; j < 20; j++)
655         {
656                 printf("Run %d\n",j);
657
658                 f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
659                 if(f)
660                 {
661                         printf("Found\n");
662                 }
663                 else
664                 {
665                         f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
666                         printf("Created\n");
667                 }
668         
669                 printf("@@@@@@@ Run %d, object %d\n",j,f->objectId);
670         
671                 for(i = 0; i < 1000000; i+=20)
672                 {
673         
674                         written = yaffs_WriteDataToFile(f,testStr,i,100);
675                 }
676                 
677                 yaffs_FlushFile(f,1);
678                 
679                 yaffs_DeleteFile(f);
680         }
681         
682 }
683
684 int main(int argc,char *argv[])
685 {
686
687         int nBlocks;
688         
689 #if YAFFS_FILEEM        
690         nBlocks =(2 * 1024 * 1024) / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK) ;
691         device.writeChunkToNAND = yaffs_FEWriteChunkToNAND;
692         device.readChunkFromNAND = yaffs_FEReadChunkFromNAND;
693         device.eraseBlockInNAND = yaffs_FEEraseBlockInNAND;
694         device.initialiseNAND = yaffs_FEInitialiseNAND;
695
696         printf("Testing on file emulation\n");
697 #else
698         nBlocks = (2 * 1024 * 1024) / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
699         device.writeChunkToNAND = nandemul_WriteChunkToNAND;
700         device.readChunkFromNAND = nandemul_ReadChunkFromNAND;
701         device.eraseBlockInNAND = nandemul_EraseBlockInNAND;
702         device.initialiseNAND = nandemul_InitialiseNAND;
703         
704         printf("Testing on RAM emulation\n");
705 #endif
706
707 #ifdef YAFFS_START
708         device.startBlock = YAFFS_START;  // Don't use block 0
709         device.endBlock = YAFFS_END;
710 #else
711         device.startBlock = 1;  // Don't use block 0
712         device.endBlock = nBlocks;
713 #endif
714
715         device.nShortOpCaches = 10;
716
717
718         yaffs_GutsInitialise(&device);
719         
720         // yaffs_GutsTest();
721         
722         TestTimeBackgroundDeleteFocussed(&device);
723         
724         printf("Cache hits %d\n",device.cacheHits);
725         printf("Retired blocks %d\n",device.nRetiredBlocks);
726         
727         printf("Deletions %d\n",device.nDeletions);
728         printf("Unmarked deletions %d\n",device.nUnmarkedDeletions);
729         
730         exit(0);
731 }