📄 yaffs_guts.c
字号:
} 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 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_DeleteObject(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 then we are happy to take a less-dirty block, and * search harder. * else (we're doing a leasurely gc), then we only bother to do this if the * block has only a few pages in use. */ dev->nonAggressiveSkip--; if (!aggressive && (dev->nonAggressiveSkip > 0)) return -1; if (!prioritised) pagesInUse = (aggressive) ? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1; if (aggressive) iterations = dev->internalEndBlock - dev->internalStartBlock + 1; else { iterations = dev->internalEndBlock - dev->internalStartBlock + 1; iterations = iterations / 16; if (iterations > 200) iterations = 200; } for (i = 0; i <= iterations && pagesInUse > 0 && !prioritised; i++) { b++; if (b < dev->internalStartBlock || b > dev->internalEndBlock) b = dev->internalStartBlock; if (b < dev->internalStartBlock || b > dev->internalEndBlock) { 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 && yaffs_BlockNotDisqualifiedFromGC(dev, bi)) { dirtiest = b; pagesInUse = (bi->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -