2 * YAFFS: Yet another FFS. A NAND-flash specific file system.
5 * Copyright (C) 2002 Aleph One Ltd.
6 * for Toby Churchill Ltd and Brightstar Engineering
8 * Created by Charles Manning <charles@aleph1.co.uk>
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.
16 #include "yaffsinterface.h"
20 #include "yaffs_fileem.h"
22 #include "yaffs_nandemul.h"
25 #include "yaffs_guts.h"
35 unsigned yaffs_traceMask = 0xFFFFFFFF;
40 char *testStr = "this is a test string";
42 char *testStr2 = "abcdefghijklmnopqrstuvwxyz1234567890";
44 void TestTimexxx(yaffs_Device *dev)
53 f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
60 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
65 x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename");
70 void TestTimeasasas(yaffs_Device *dev)
83 f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
90 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
95 x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename");
99 for(i = 0; i < 10000; i+=20)
104 written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr));
106 written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
110 yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
114 yaffs_FlushFile(f,1);
116 yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
118 yaffs_ReadDataFromFile(f,data,1000,50);
121 printf("Read data is \"%s\"\n",data);
125 printf("Resize to 3000\n");
126 yaffs_ResizeFile(f,3000);
127 printf("Resize to 2048\n");
128 yaffs_ResizeFile(f,2048);
132 yaffs_FlushFile(f,1);
139 void TestTimeBigDeletes(yaffs_Device *dev)
148 yaffs_Object *d, *df;
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);
169 f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
176 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
180 for(i = 0; i < 100000; i+=20)
185 written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr));
187 written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
190 yaffs_FlushFile(f,1);
193 f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
200 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
204 for(i = 0; i < 100000; i+=20)
209 written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr));
211 written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
214 yaffs_FlushFile(f,1);
217 f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
224 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
228 for(i = 0; i < 100000; i+=20)
233 written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr));
235 written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
238 yaffs_FlushFile(f,1);
243 void TestTime(yaffs_Device *dev)
252 yaffs_Object *d, *df;
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);
272 // Test the problem of:
275 // Create file with same name
276 // Delete file <== crash
278 f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
285 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
288 yaffs_Unlink(yaffs_Root(dev),"Name1");
291 f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
298 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
301 yaffs_Unlink(yaffs_Root(dev),"Name1");
307 f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
314 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
319 x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename");
321 // Write a file with overwrite, then read it back and save outside yaffs
322 // This is to test that write caching works.
324 for(i = 0; i < 100; i++)
326 unsigned char x[500];
330 written = yaffs_WriteDataToFile(f,x,i*500,500);
333 for(i = 0; i < 100; i++)
339 written = yaffs_WriteDataToFile(f,&x,i*500 + 2,1);
346 h = open("bork",O_RDWR | O_CREAT | O_TRUNC,0666);
347 for(i = 0; i < 100; i++)
349 unsigned char x[500];
351 yaffs_ReadDataFromFile(f,x,i*500,500);
359 // Big write to fill disk
362 for(i = 0; i < 1000000 && written > 0; i++)
364 unsigned char x[500];
368 written = yaffs_WriteDataToFile(f,x,i*500,500);
372 printf("YAFFS full\n");
376 for(i = 1000; i < 50000; i+=2)
378 yaffs_ReadDataFromFile(f,data,i,20);
382 yaffs_ReadDataFromFile(f,data,1000,50);
385 printf("Read data is \"%s\"\n",data);
387 yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
388 yaffs_ReadDataFromFile(f,data,1000,50);
391 printf("Read data is \"%s\"\n",data);
395 yaffs_FlushFile(f,1);
396 yaffs_ReadDataFromFile(f,data,1000,50);
399 printf("Read data is \"%s\"\n",data);
401 printf("File length is %d\n",yaffs_GetObjectFileLength(f));
403 sl = yaffs_MknodSymLink(yaffs_Root(dev),"sym-link",0,0,0,"/tmp/alias");
404 yaffs_ReadDataFromFile(f,data,1000,50);
407 printf("Read data is \"%s\"\n",data);
410 yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
412 printf("\n\nsymlink alias is \"%s\"\n",alias = yaffs_GetSymlinkAlias(sl));
416 printf("Unlink symlink %d\n",yaffs_Unlink(yaffs_Root(dev),"sym-link"));
419 yaffs_ReadDataFromFile(f,data,1000,50);
422 printf("Read data is \"%s\"\n",data);
426 printf("Resize 3000\n");
427 yaffs_ResizeFile(f,3000);
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);
437 printf("Resize 2000\n");
438 yaffs_ResizeFile(f,2000);
442 lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME);
446 yaffs_FlushFile(f,1);
449 printf("Unlink file: %d\n",yaffs_Unlink(yaffs_Root(dev),"Rename"));
453 yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
455 // Create a directory and play with it
458 printf("Find or Create directory and play with it\n");
459 d = yaffs_FindObjectByName(yaffs_Root(dev),"direct");
462 d = yaffs_MknodDirectory(yaffs_Root(dev),"direct",0,0,0);
464 yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
465 yaffs_ApplyToDirectoryChildren(d,yaffs_DumpObject);
467 printf("Make file in directory\n");
469 df = yaffs_MknodFile(d,"file-in-directory",0,0,0);
470 yaffs_ApplyToDirectoryChildren(d,yaffs_DumpObject);
473 // Do some stuff with hardlinks
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.
483 printf("Hard link tests\n");
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);
490 printf("\n\nHard links created\n");
491 yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
493 yaffs_Unlink(yaffs_Root(dev),"HardLink 1");
494 printf("\n\nHard link deleted\n");
495 yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
497 yaffs_Unlink(yaffs_Root(dev),"Name1");
498 printf("\n\nHard linked file deleted\n");
499 yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
501 yaffs_Unlink(yaffs_Root(dev),"HardLink 2");
502 printf("\n\nHard link 2 deleted\n");
503 yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
505 yaffs_Unlink(yaffs_Root(dev),"HardLink 3");
507 printf("\n\nHard link 3 deleted\n");
508 yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
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.
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);
518 f = yaffs_MknodFile(yaffs_Root(dev),"pfile",0,0,0);
521 yaffs_WriteDataToFile(f,testStr,0,strlen(testStr));
524 yaffs_Link(yaffs_Root(dev),"phl4",f);
527 void TestTimeDeleteFocussed(yaffs_Device *dev)
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);
550 f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
557 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
562 x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename");
564 for(i = 0; i < 100000; i+=20)
569 written = yaffs_WriteDataToFile(f,testStr,i,strlen(testStr));
571 written = yaffs_WriteDataToFile(f,testStr2,i,strlen(testStr2));
576 yaffs_FlushFile(f,1);
579 printf("Unlink file: %d\n",yaffs_Unlink(yaffs_Root(dev),"Rename"));
581 yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
585 void TestTimeTnodeFocussed(yaffs_Device *dev)
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);
608 f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
615 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
620 x = yaffs_RenameObject(yaffs_Root(dev),"Name1",NULL,"Rename");
622 for(i = 0; i < 10000; i+=20)
627 written = yaffs_WriteDataToFile(f,testStr,0,strlen(testStr));
629 written = yaffs_WriteDataToFile(f,testStr2,0,strlen(testStr2));
633 void TestTimeBackgroundDeleteFocussed(yaffs_Device *dev)
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);
654 for(j = 0; j < 20; j++)
656 printf("Run %d\n",j);
658 f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
665 f = yaffs_MknodFile(yaffs_Root(dev),"Name1",0,0,0);
669 printf("@@@@@@@ Run %d, object %d\n",j,f->objectId);
671 for(i = 0; i < 1000000; i+=20)
674 written = yaffs_WriteDataToFile(f,testStr,i,100);
677 yaffs_FlushFile(f,1);
684 int main(int argc,char *argv[])
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;
696 printf("Testing on file emulation\n");
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;
704 printf("Testing on RAM emulation\n");
708 device.startBlock = YAFFS_START; // Don't use block 0
709 device.endBlock = YAFFS_END;
711 device.startBlock = 1; // Don't use block 0
712 device.endBlock = nBlocks;
715 device.nShortOpCaches = 10;
718 yaffs_GutsInitialise(&device);
722 TestTimeBackgroundDeleteFocussed(&device);
724 printf("Cache hits %d\n",device.cacheHits);
725 printf("Retired blocks %d\n",device.nRetiredBlocks);
727 printf("Deletions %d\n",device.nDeletions);
728 printf("Unmarked deletions %d\n",device.nUnmarkedDeletions);