📄 yaffs_guts.c
字号:
}yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number){ int bucket = yaffs_HashFunction(number); struct ylist_head *i; yaffs_Object *in; ylist_for_each(i, &dev->objectBucket[bucket].list) { /* Look if it is in the list */ if (i) { in = ylist_entry(i, yaffs_Object, hashLink); if (in->objectId == number) {#ifdef __KERNEL__ /* Don't tell the VFS about this one if it is defered free */ if (in->deferedFree) return NULL;#endif return in; } } } return NULL;}yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number, yaffs_ObjectType type){ yaffs_Object *theObject; yaffs_Tnode *tn = NULL; if (number < 0) { number = yaffs_CreateNewObjectNumber(dev); } theObject = yaffs_AllocateEmptyObject(dev); if(!theObject) return NULL; if(type == YAFFS_OBJECT_TYPE_FILE){ tn = yaffs_GetTnode(dev); if(!tn){ yaffs_FreeObject(theObject); return NULL; } } 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 theObject->yst_atime = theObject->yst_mtime = theObject->yst_ctime = Y_CURRENT_TIME;#endif#if 0 theObject->sum_prev = 12345; theObject->sum_trailer = 6789;#endif switch (type) { case YAFFS_OBJECT_TYPE_FILE: theObject->variant.fileVariant.fileSize = 0; theObject->variant.fileVariant.scannedFileSize = 0; theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF; /* max __u32 */ theObject->variant.fileVariant.topLevel = 0; theObject->variant.fileVariant.top = tn; break; case YAFFS_OBJECT_TYPE_DIRECTORY: YINIT_LIST_HEAD(&theObject->variant.directoryVariant. children); break; case YAFFS_OBJECT_TYPE_SYMLINK: case YAFFS_OBJECT_TYPE_HARDLINK: case YAFFS_OBJECT_TYPE_SPECIAL: /* No action required */ break; case YAFFS_OBJECT_TYPE_UNKNOWN: /* todo this should not happen */ break; } } return theObject;}static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device * dev, int number, yaffs_ObjectType type){ yaffs_Object *theObject = NULL; if (number > 0) { theObject = yaffs_FindObjectByNumber(dev, number); } if (!theObject) { theObject = yaffs_CreateNewObject(dev, number, type); } return theObject;} static YCHAR *yaffs_CloneString(const YCHAR * str){ YCHAR *newStr = NULL; if (str && *str) { newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR)); if(newStr) yaffs_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) */ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, yaffs_Object * parent, const YCHAR * name, __u32 mode, __u32 uid, __u32 gid, yaffs_Object * equivalentObject, const YCHAR * aliasString, __u32 rdev){ yaffs_Object *in; YCHAR *str = NULL; 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); if(!in) return YAFFS_FAIL; if(type == YAFFS_OBJECT_TYPE_SYMLINK){ str = yaffs_CloneString(aliasString); if(!str){ yaffs_FreeObject(in); return NULL; } } if (in) { in->hdrChunk = 0; in->valid = 1; in->variantType = type; in->yst_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 in->yst_atime = in->yst_mtime = in->yst_ctime = Y_CURRENT_TIME; in->yst_rdev = rdev; in->yst_uid = uid; in->yst_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 = str; break; case YAFFS_OBJECT_TYPE_HARDLINK: in->variant.hardLinkVariant.equivalentObject = equivalentObject; in->variant.hardLinkVariant.equivalentObjectId = equivalentObject->objectId; ylist_add(&in->hardLinks, &equivalentObject->hardLinks); break; case YAFFS_OBJECT_TYPE_FILE: case YAFFS_OBJECT_TYPE_DIRECTORY: case YAFFS_OBJECT_TYPE_SPECIAL: case YAFFS_OBJECT_TYPE_UNKNOWN: /* do nothing */ break; } if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0) < 0) { /* Could not create the object header, fail the creation */ yaffs_DestroyObject(in); in = NULL; } } return in;}yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * 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 YCHAR * 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 YCHAR * name, __u32 mode, __u32 uid, __u32 gid, __u32 rdev){ return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode, uid, gid, NULL, NULL, rdev);}yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name, __u32 mode, __u32 uid, __u32 gid, const YCHAR * alias){ return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode, uid, gid, NULL, alias, 0);}/* yaffs_Link returns the object id of the equivalent object.*/yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * 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 YCHAR * newName, int force, int shadows){ int unlinkOp; int deleteOp; yaffs_Object *existingTarget; if (newDir == NULL) { newDir = obj->parent; /* use the old directory */ } if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { T(YAFFS_TRACE_ALWAYS, (TSTR ("tragedy: yaffs_ChangeObjectName: newDir is not a directory" TENDSTR))); YBUG(); } /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */ if (obj->myDev->isYaffs2) { unlinkOp = (newDir == obj->myDev->unlinkedDir); } else { unlinkOp = (newDir == obj->myDev->unlinkedDir && obj->variantType == YAFFS_OBJECT_TYPE_FILE); } deleteOp = (newDir == obj->myDev->deletedDir); existingTarget = yaffs_FindObjectByName(newDir, newName); /* 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. * else only proceed if the new name does not exist and if we're putting * it into a directory. */ if ((unlinkOp || deleteOp || force || (shadows > 0) || !existingTarget) && newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) { yaffs_SetObjectName(obj, newName); obj->dirty = 1; yaffs_AddObjectToDirectory(newDir, obj); if (unlinkOp) obj->unlinked = 1; /* If it is a deletion then we mark it as a shrink for gc purposes. */ if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows)>= 0) return YAFFS_OK; } return YAFFS_FAIL;}int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, yaffs_Object * newDir, const YCHAR * newName){ yaffs_Object *obj=NULL; yaffs_Object *existingTarget=NULL; int force = 0; if(!oldDir || oldDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) YBUG(); if(!newDir || newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) YBUG();#ifdef CONFIG_YAFFS_CASE_INSENSITIVE /* Special case for case insemsitive systems (eg. 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 && yaffs_strcmp(oldName, newName) == 0) { force = 1; }#endif else if (yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH) /* ENAMETOOLONG */ return YAFFS_FAIL; obj = yaffs_FindObjectByName(oldDir, oldName); if (obj && obj->renameAllowed) { /* Now do the handling for an existing target, if there is one */ existingTarget = yaffs_FindObjectByName(newDir, newName); if (existingTarget && existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && !ylist_empty(&existingTarget->variant.directoryVariant.children)) { /* There is a target that is a non-empty directory, so we fail */ return YAFFS_FAIL; /* EEXIST or ENOTEMPTY */ } else if (existingTarget && existingTarget != obj) { /* Nuke the target first, using shadowing, * but only if it isn't the same object */ yaffs_ChangeObjectName(obj, newDir, newName, force, existingTarget->objectId); yaffs_UnlinkObject(existingTarget); } return yaffs_ChangeObjectName(obj, newDir, newName, 1, 0); } return YAFFS_FAIL;}/*------------------------- Block Management and Page Allocation ----------------*/static int yaffs_InitialiseBlocks(yaffs_Device * dev){ int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; dev->blockInfo = NULL; dev->chunkBits = NULL; dev->allocationBlock = -1; /* force it to get a new one */ /* If the first allocation strategy fails, thry the alternate one */ dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo)); if(!dev->blockInfo){ dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo)); dev->blockInfoAlt = 1; } else dev->blockInfoAlt = 0; if(dev->blockInfo){ /* Set up dynamic blockinfo stuff. */ dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */ dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks); if(!dev->chunkBits){ dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks); dev->chunkBitsAlt = 1; } else dev->chunkBitsAlt = 0; } 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){ if(dev->blockInfoAlt && dev->blockInfo) YFREE_ALT(dev->blockInfo); else if(dev->blockInfo) YFREE(dev->blockInfo); dev->blockInfoAlt = 0; dev->blockInfo = NULL; if(dev->chunkBitsAlt && dev->chunkBits) YFREE_ALT(dev->chunkBits); else if(dev->chunkBits) YFREE(dev->chunkBits); dev->chunkBitsAlt = 0; dev->chunkBits = NULL;}static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device * dev, yaffs_BlockInfo * bi){ int i; __u32 seq; yaffs_BlockInfo *b; if (!dev->isYaffs2) return 1; /* disqualification only applies to yaffs2. */ if (!bi->hasShrinkHeader) return 1; /* can gc */ /* Find the oldest dirty sequence number if we don't know it and save it * so we don't have to keep recomputing it. */ if (!dev->oldestDirtySequence) { seq = dev->sequenceNumber; for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { b = yaffs_GetBlockInfo(dev, i); if (b->blockState == YAFFS_BLOCK_STATE_FULL && (b->pagesInUse - b->softDeletions) < dev->nChunksPerBlock && b->sequenceNumber < seq) { seq = b->sequenceNumber; } } dev->oldestDirtySequence = seq; } /* Can't do gc of this block if there are any blocks older than this one that have * discarded pages. */ return (bi->sequenceNumber <= dev->oldestDirtySequence);}/* FindDiretiestBlock is used to select the dirtiest block (or close enough) * for garbage collection. */static int yaffs_FindBlockForGarbageCollection(yaffs_Device * dev, int aggressive){ int b = dev->currentDirtyChecker; int i; int iterations; int dirtiest = -1; int pagesInUse = 0; int prioritised=0; yaffs_BlockInfo *bi; int pendingPrioritisedExist = 0; /* First let's see if we need to grab a prioritised block */ if(dev->hasPendingPrioritisedGCs){ for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){ bi = yaffs_GetBlockInfo(dev, i); //yaffs_VerifyBlock(dev,bi,i); if(bi->gcPrioritise) { pendingPrioritisedExist = 1; if(bi->blockState == YAFFS_BLOCK_STATE_FULL && yaffs_BlockNotDisqualifiedFromGC(dev, bi)){ pagesInUse = (bi->pagesInUse - bi->softDeletions); dirtiest = i; prioritised = 1; aggressive = 1; /* Fool the non-aggressive skip logiv below */ } } } if(!pendingPrioritisedExist) /* None found, so we can clear this */ dev->hasPendingPrioritisedGCs = 0; } /* If we're doing aggressive GC t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -