📄 yaffs_guts.cpp
字号:
//描述:从HASH表里把该number的yaffs_Object找出来yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev,__u32 number){ int bucket = yaffs_HashFunction(number); struct list_head *i; yaffs_Object *in; list_for_each(i,&dev->objectBucket[bucket].list) { // Look if it is in the list if(i) { in = list_entry(i, yaffs_Object,hashLink); if(in->objectId == number) { return in; } } } return NULL;}//描述:新建一个yaffs_Object,并对它进行初始化yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectType type){ yaffs_Object *theObject; if(number < 0) //number<0,则表示创建 { number = yaffs_CreateNewObjectNumber(dev); //新建一个没被使用的objectId } theObject = yaffs_AllocateEmptyObject(dev); if(theObject) { theObject->fake = 0; theObject->renameAllowed = 1; theObject->unlinkAllowed = 1; theObject->objectId = number; yaffs_HashObject(theObject); theObject->variantType = type;#ifdef CONFIG_YAFFS_WINCE yfsd_WinFileTimeNow(theObject->win_atime); theObject->win_ctime[0] = theObject->win_mtime[0] = theObject->win_atime[0]; theObject->win_ctime[1] = theObject->win_mtime[1] = theObject->win_atime[1];#else#if defined(CONFIG_KERNEL_2_5) theObject->st_atime = theObject->st_mtime = theObject->st_ctime = CURRENT_TIME.tv_sec; #else theObject->st_atime = theObject->st_mtime = theObject->st_ctime = CURRENT_TIME; #endif#endif switch(type) { case YAFFS_OBJECT_TYPE_FILE: theObject->variant.fileVariant.fileSize = 0; theObject->variant.fileVariant.scannedFileSize = 0; theObject->variant.fileVariant.topLevel = 0; theObject->variant.fileVariant.top = yaffs_GetTnode(dev); break; case YAFFS_OBJECT_TYPE_DIRECTORY: INIT_LIST_HEAD(&theObject->variant.directoryVariant.children); break; case YAFFS_OBJECT_TYPE_SYMLINK: // No action required break; case YAFFS_OBJECT_TYPE_HARDLINK: // No action required break; case YAFFS_OBJECT_TYPE_SPECIAL: // No action required break; case YAFFS_OBJECT_TYPE_UNKNOWN: // todo this should not happen break; } } return theObject;}//描述:从HASH表里把该number的yaffs_Object找出来,如果找不出来则新建一个//参数:@number yaffs_Tags.objectId(注意不是chunkId),如果number<0,则表示创建yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev, int number,yaffs_ObjectType type){ yaffs_Object *theObject = NULL; if(number > 0) { theObject = yaffs_FindObjectByNumber(dev,number); //从HASH表里把该number的yaffs_Object找出来 } if(!theObject) { theObject = yaffs_CreateNewObject(dev,number,type); //新建一个yaffs_Object,并对它进行初始化 } return theObject;}char *yaffs_CloneString(const char *str){ char *newStr = NULL; if(str && *str) { newStr = (char* )YMALLOC(strlen(str) + 1); strcpy(newStr,str); } return newStr; }//// Mknod (create) a new object.// equivalentObject only has meaning for a hard link;// aliasString only has meaning for a sumlink.// rdev only has meaning for devices (a subset of special objects)//描述:创建一个yaffs_Object,并初始化,把该yaffs_Object加入到的文件系统目录结构// 生成该文件的yaffs_ObjectHeader并把它作为新chunk的数据写到FLASH,yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type, yaffs_Object *parent, const char *name, __u32 mode, __u32 uid, __u32 gid, yaffs_Object *equivalentObject, const char *aliasString, __u32 rdev){ yaffs_Object *in; yaffs_Device *dev = parent->myDev; // Check if the entry exists. If it does then fail the call since we don't want a dup. if(yaffs_FindObjectByName(parent,name)) { return NULL; } in = yaffs_CreateNewObject(dev,-1,type); //新建一个yaffs_Object,并对它进行初始化 if(in) { in->chunkId = -1; //此chunkId就是chunkInNAND,是yaffs_ObjectHeader的chunkInNAND in->valid = 1; in->variantType = type; in->st_mode = mode; #ifdef CONFIG_YAFFS_WINCE yfsd_WinFileTimeNow(in->win_atime); in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0]; in->win_ctime[1] = in->win_mtime[1] = in->win_atime[1]; #else#if defined(CONFIG_KERNEL_2_5) in->st_atime = in->st_mtime = in->st_ctime = CURRENT_TIME.tv_sec;#else in->st_atime = in->st_mtime = in->st_ctime = CURRENT_TIME;#endif in->st_rdev = rdev; in->st_uid = uid; in->st_gid = gid;#endif in->nDataChunks = 0; yaffs_SetObjectName(in,name); in->dirty = 1; yaffs_AddObjectToDirectory(parent,in); in->myDev = parent->myDev; switch(type) { case YAFFS_OBJECT_TYPE_SYMLINK: in->variant.symLinkVariant.alias = yaffs_CloneString(aliasString); break; case YAFFS_OBJECT_TYPE_HARDLINK: in->variant.hardLinkVariant.equivalentObject = equivalentObject; in->variant.hardLinkVariant.equivalentObjectId = equivalentObject->objectId; list_add(&in->hardLinks,&equivalentObject->hardLinks); break; case YAFFS_OBJECT_TYPE_FILE: // do nothing case YAFFS_OBJECT_TYPE_DIRECTORY: // do nothing case YAFFS_OBJECT_TYPE_SPECIAL: // do nothing case YAFFS_OBJECT_TYPE_UNKNOWN: break; } if(/*yaffs_GetNumberOfFreeChunks(dev) <= 0 || */ yaffs_UpdateObjectHeader(in,name,0) < 0) { //根据in的字段,参数name作为文件名,生成yaffs_ObjectHeader并把它作为新chunk的数据写到FLASH, //返回写到的chunkInNAMD // Could not create the object header, fail the creation yaffs_AbortHalfCreatedObject(in); in = NULL; } } return in;}yaffs_Object *yaffs_MknodFile(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid){ return yaffs_MknodObject(YAFFS_OBJECT_TYPE_FILE,parent,name,mode,uid,gid,NULL,NULL,0);}yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid){ return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY,parent,name,mode,uid,gid,NULL,NULL,0);}yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid, __u32 rdev){ return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY,parent,name,mode,uid,gid,NULL,NULL,rdev);}yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid,const char *alias){ return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SYMLINK,parent,name,mode,uid,gid,NULL,alias,0);}// NB yaffs_Link returns the object id of the equivalent object.yaffs_Object *yaffs_Link(yaffs_Object *parent, const char *name, yaffs_Object *equivalentObject){ // Get the real object in case we were fed a hard link as an equivalent object equivalentObject = yaffs_GetEquivalentObject(equivalentObject); if(yaffs_MknodObject(YAFFS_OBJECT_TYPE_HARDLINK,parent,name,0,0,0,equivalentObject,NULL,0)) { return equivalentObject; } else { return NULL; } }static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const char *newName,int force){ int unlinkOp; if(newDir == NULL) { newDir = obj->parent; // use the old directory } unlinkOp = (newDir == obj->myDev->unlinkedDir && obj->variantType == YAFFS_OBJECT_TYPE_FILE); // If the object is a file going into the unlinked directory, then it is OK to just stuff it in since // duplicate names are allowed. // Otherwise only proceed if the new name does not exist and if we're putting it into a directory. if( (unlinkOp|| force || !yaffs_FindObjectByName(newDir,newName)) && newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) { yaffs_SetObjectName(obj,newName); obj->dirty = 1; yaffs_AddObjectToDirectory(newDir,obj); if(unlinkOp) obj->unlinked = 1; if(yaffs_UpdateObjectHeader(obj,newName,0) >= 0) { return YAFFS_OK; } } return YAFFS_FAIL;}int yaffs_RenameObject(yaffs_Object *oldDir, const char *oldName, yaffs_Object *newDir, const char *newName){ yaffs_Object *obj; int force = 0; #ifdef CONFIG_YAFFS_CASE_INSENSITIVE // Special case for WinCE. // While look-up is case insensitive, the name isn't. // THerefore we might want to change x.txt to X.txt if(oldDir == newDir && _stricmp(oldName,newName) == 0) { force = 1; } #endif obj = yaffs_FindObjectByName(oldDir,oldName); if(obj && obj->renameAllowed) { return yaffs_ChangeObjectName(obj,newDir,newName,force); } return YAFFS_FAIL;}static int yaffs_CheckObjectHashSanity(yaffs_Device *dev){ // Scan the buckets and check that the lists // have as many members as the count says there are int bucket; int countEm; struct list_head *j; int ok = YAFFS_OK; for(bucket = 0; bucket < YAFFS_NOBJECT_BUCKETS; bucket++) { countEm = 0; list_for_each(j,&dev->objectBucket[bucket].list) { countEm++; } if(countEm != dev->objectBucket[bucket].count) { T(YAFFS_TRACE_ERROR,(TSTR("Inode hash inconsistency" TENDSTR))); ok = YAFFS_FAIL; } } return ok;}#if 0void yaffs_ObjectTest(yaffs_Device *dev){ yaffs_Object *in[1000]; int inNo[1000]; yaffs_Object *inold[1000]; int i; int j; memset(in,0,1000*sizeof(yaffs_Object *)); memset(inold,0,1000*sizeof(yaffs_Object *)); yaffs_CheckObjectHashSanity(dev); for(j = 0; j < 10; j++) { //T(("%d\n",j)); for(i = 0; i < 1000; i++) { in[i] = yaffs_CreateNewObject(dev,-1,YAFFS_OBJECT_TYPE_FILE); if(!in[i]) { YINFO("No more inodes"); } else { inNo[i] = in[i]->objectId; } } for(i = 0; i < 1000; i++) { if(yaffs_FindObjectByNumber(dev,inNo[i]) != in[i]) { //T(("Differnce in look up test\n")); } else { // T(("Look up ok\n")); } } yaffs_CheckObjectHashSanity(dev); for(i = 0; i < 1000; i+=3) { yaffs_FreeObject(in[i]); in[i] = NULL; } yaffs_CheckObjectHashSanity(dev); } }#endif/////////////////////////// Block Management and Page Allocation ///////////////////static int yaffs_InitialiseBlocks(yaffs_Device *dev,int nBlocks){ dev->allocationBlock = -1; // force it to get a new one //Todo we're assuming the malloc will pass. dev->blockInfo = (yaffs_BlockInfo* )YMALLOC(nBlocks * sizeof(yaffs_BlockInfo)); // Set up dynamic blockinfo stuff. dev->chunkBitmapStride = (dev->nChunksPerBlock+7)/8; dev->chunkBits = (__u8* )YMALLOC(dev->chunkBitmapStride * nBlocks); if(dev->blockInfo && dev->chunkBits) { memset(dev->blockInfo,0,nBlocks * sizeof(yaffs_BlockInfo)); memset(dev->chunkBits,0,dev->chunkBitmapStride * nBlocks); return YAFFS_OK; } return YAFFS_FAIL; }static void yaffs_DeinitialiseBlocks(yaffs_Device *dev){ YFREE(dev->blockInfo); dev->blockInfo = NULL; YFREE(dev->chunkBits); dev->chunkBits = NULL;}// FindDiretiestBlock is used to select the dirtiest block (or close enough)// for garbage collection.//描述:找出已经写满并且有用页面最少的块,并返回块号static int yaffs_FindDirtiestBlock(yaffs_Device *dev,int aggressive){ int b = dev->currentDirtyChecker; int i; int iterations; int dirtiest = -1; int pagesInUse; yaffs_BlockInfo *bi; // If we're doing aggressive GC then we are happy to take a less-dirty block, and // search further. pagesInUse = (aggressive)? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1; //有用页面最少的最低标准 //aggressive与否决定扫描块的个数 if(aggressive) { iterations = dev->endBlock - dev->startBlock + 1; } else { iterations = dev->endBlock - dev->startBlock + 1; iterations = iterations / 16; if(iterations > 200) { iterations = 200; } } for(i = 0; i <= iterations && pagesInUse > 0 ; i++) { b++; if ( b < dev->startBlock || b > dev->endBlock) { b = dev->startBlock; } if(b < dev->startBlock || b > dev->endBlock) //????:有了上一步的判断,这里的判断应该不会成立 { T(YAFFS_TRACE_ERROR,(TSTR("**>> Block %d is not valid" TENDSTR),b)); YBUG(); } bi = yaffs_GetBlockInfo(dev,b); if(bi->blockState == YAFFS_BLOCK_STATE_FULL && (bi->pagesInUse - bi->softDeletions )< pagesInUse) //找出已经写满并且有用页面最少的块 { //####:这样的话每页必须用完才能写下一页 dirtiest = b; pagesInUse = (bi->pagesInUse - bi->softDeletions); } } dev->currentDirtyChecker = b; return dirtiest;}//描述:把脏的块擦除使之变成YAFFS_BLOCK_STATE_EMPTY的块static void yaffs_BlockBecameDirty(yaffs_Device *dev,int blockNo){ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,blockNo); int erasedOk = 0; // If the block is still healthy erase it and mark as clean. // If the block has had a data failure, then retire it. bi->blockState = YAFFS_BLOCK_STATE_DIRTY; //if(!bi->needsRetiring) //BY CEN 不产生坏块 { erasedOk = yaffs_EraseBlockInNAND(dev,blockNo); if(!erasedOk) { T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>> Erasure failed %d" TENDSTR),blockNo)); } } if( erasedOk ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -