*/
const char *yaffs_guts_c_version =
- "$Id: yaffs_guts.c,v 1.24 2005-12-07 21:49:18 charles Exp $";
+ "$Id: yaffs_guts.c,v 1.31 2006-03-08 07:59:20 charles Exp $";
#include "yportenv.h"
static Y_INLINE int yaffs_HashFunction(int n)
{
+ n = abs(n);
return (n % YAFFS_NOBJECT_BUCKETS);
}
int tnodeSize;
yaffs_Tnode *newTnodes;
__u8 *mem;
- yaffs_Tnode *current;
+ yaffs_Tnode *curr;
yaffs_Tnode *next;
yaffs_TnodeList *tnl;
/* make these things */
- mem = newTnodes = YMALLOC(nTnodes * tnodeSize);
+ newTnodes = YMALLOC(nTnodes * tnodeSize);
+ mem = (__u8 *)newTnodes;
if (!newTnodes) {
T(YAFFS_TRACE_ERROR,
#else
/* New hookup for wide tnodes */
for(i = 0; i < nTnodes -1; i++) {
- current = (yaffs_Tnode *) &mem[i * tnodeSize];
+ curr = (yaffs_Tnode *) &mem[i * tnodeSize];
next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize];
- current->internal[0] = next;
+ curr->internal[0] = next;
}
- current = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize];
- current->internal[0] = dev->freeTnodes;
+ curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize];
+ curr->internal[0] = dev->freeTnodes;
dev->freeTnodes = (yaffs_Tnode *)mem;
#endif
("yaffs: About to finally delete object %d"
TENDSTR), object->objectId));
yaffs_DoGenericObjectDeletion(object);
+ object->myDev->nDeletedFiles--;
}
}
}
+/*yaffs_FlushEntireDeviceCache(dev)
+ *
+ *
+ */
+
+void yaffs_FlushEntireDeviceCache(yaffs_Device *dev)
+{
+ yaffs_Object *obj;
+ int nCaches = dev->nShortOpCaches;
+ int i;
+
+ /* Find a dirty object in the cache and flush it...
+ * until there are no further dirty objects.
+ */
+ do {
+ obj = NULL;
+ for( i = 0; i < nCaches && !obj; i++) {
+ if (dev->srCache[i].object &&
+ dev->srCache[i].dirty)
+ obj = dev->srCache[i].object;
+
+ }
+ if(obj)
+ yaffs_FlushFilesChunkCache(obj);
+
+ } while(obj);
+
+}
+
+
/* Grab us a cache chunk for use.
* First look for an empty one.
* Then look for the least recently used non-dirty one.
return YAFFS_OK;
}
+static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in)
+{
+ __u8 *chunkData;
+ yaffs_ObjectHeader *oh;
+ yaffs_Device *dev = in->myDev;
+
+ if(in->lazyLoaded){
+ in->lazyLoaded = 0;
+ chunkData = yaffs_GetTempBuffer(dev, __LINE__);
+
+ yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,NULL);
+ oh = (yaffs_ObjectHeader *) chunkData;
+
+ in->yst_mode = oh->yst_mode;
+#ifdef CONFIG_YAFFS_WINCE
+ in->win_atime[0] = oh->win_atime[0];
+ in->win_ctime[0] = oh->win_ctime[0];
+ in->win_mtime[0] = oh->win_mtime[0];
+ in->win_atime[1] = oh->win_atime[1];
+ in->win_ctime[1] = oh->win_ctime[1];
+ in->win_mtime[1] = oh->win_mtime[1];
+#else
+ in->yst_uid = oh->yst_uid;
+ in->yst_gid = oh->yst_gid;
+ in->yst_atime = oh->yst_atime;
+ in->yst_mtime = oh->yst_mtime;
+ in->yst_ctime = oh->yst_ctime;
+ in->yst_rdev = oh->yst_rdev;
+
+#endif
+ yaffs_SetObjectName(in, oh->name);
+
+ if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK)
+ in->variant.symLinkVariant.alias =
+ yaffs_CloneString(oh->alias);
+
+ yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__);
+ }
+}
+
static int yaffs_ScanBackwards(yaffs_Device * dev)
{
yaffs_ExtendedTags tags;
yaffs_Object *in;
yaffs_Object *parent;
int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
-
+ int itsUnlinked;
__u8 *chunkData;
+
+ int fileSize;
+ int isShrink;
+ int equivalentObjectId;
+
yaffs_BlockIndex *blockIndex = NULL;
tags.extraObjectType);
}
- if (!in || !in->valid) {
+ if (!in ||
+#ifdef CONFIG_YAFFS_DISABLE_LAZY_LOAD
+ !in->valid ||
+#endif
+ tags.extraShadows ||
+ (!in->valid &&
+ (tags.objectId == YAFFS_OBJECTID_ROOT ||
+ tags.objectId == YAFFS_OBJECTID_LOSTNFOUND))
+ ) {
/* If we don't have valid info then we need to read the chunk
* TODO In future we can probably defer reading the chunk and
* we first have to suck out resize info if it is a file.
*/
- if ((in->variantType ==
- YAFFS_OBJECT_TYPE_FILE) && ((oh
- &&
- oh->
- type
- ==
- YAFFS_OBJECT_TYPE_FILE)
- ||
- (tags.
- extraHeaderInfoAvailable
- &&
- tags.
- extraObjectType
- ==
- YAFFS_OBJECT_TYPE_FILE))
+ if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) &&
+ ((oh &&
+ oh-> type == YAFFS_OBJECT_TYPE_FILE)||
+ (tags.extraHeaderInfoAvailable &&
+ tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE))
) {
__u32 thisSize =
(oh) ? oh->fileSize : tags.
YAFFS_OBJECTID_LOSTNFOUND)) {
/* We only load some info, don't fiddle with directory structure */
in->valid = 1;
- in->variantType = oh->type;
+
+ if(oh) {
+ in->variantType = oh->type;
- in->yst_mode = oh->yst_mode;
+ in->yst_mode = oh->yst_mode;
#ifdef CONFIG_YAFFS_WINCE
- in->win_atime[0] = oh->win_atime[0];
- in->win_ctime[0] = oh->win_ctime[0];
- in->win_mtime[0] = oh->win_mtime[0];
- in->win_atime[1] = oh->win_atime[1];
- in->win_ctime[1] = oh->win_ctime[1];
- in->win_mtime[1] = oh->win_mtime[1];
+ in->win_atime[0] = oh->win_atime[0];
+ in->win_ctime[0] = oh->win_ctime[0];
+ in->win_mtime[0] = oh->win_mtime[0];
+ in->win_atime[1] = oh->win_atime[1];
+ in->win_ctime[1] = oh->win_ctime[1];
+ in->win_mtime[1] = oh->win_mtime[1];
#else
- in->yst_uid = oh->yst_uid;
- in->yst_gid = oh->yst_gid;
- in->yst_atime = oh->yst_atime;
- in->yst_mtime = oh->yst_mtime;
- in->yst_ctime = oh->yst_ctime;
- in->yst_rdev = oh->yst_rdev;
+ in->yst_uid = oh->yst_uid;
+ in->yst_gid = oh->yst_gid;
+ in->yst_atime = oh->yst_atime;
+ in->yst_mtime = oh->yst_mtime;
+ in->yst_ctime = oh->yst_ctime;
+ in->yst_rdev = oh->yst_rdev;
+
#endif
+ } else {
+ in->variantType = tags.extraObjectType;
+ in->lazyLoaded = 1;
+ }
+
in->chunkId = chunk;
} else if (!in->valid) {
/* we need to load this info */
in->valid = 1;
- in->variantType = oh->type;
+ in->chunkId = chunk;
+
+ if(oh) {
+ in->variantType = oh->type;
- in->yst_mode = oh->yst_mode;
+ in->yst_mode = oh->yst_mode;
#ifdef CONFIG_YAFFS_WINCE
- in->win_atime[0] = oh->win_atime[0];
- in->win_ctime[0] = oh->win_ctime[0];
- in->win_mtime[0] = oh->win_mtime[0];
- in->win_atime[1] = oh->win_atime[1];
- in->win_ctime[1] = oh->win_ctime[1];
- in->win_mtime[1] = oh->win_mtime[1];
+ in->win_atime[0] = oh->win_atime[0];
+ in->win_ctime[0] = oh->win_ctime[0];
+ in->win_mtime[0] = oh->win_mtime[0];
+ in->win_atime[1] = oh->win_atime[1];
+ in->win_ctime[1] = oh->win_ctime[1];
+ in->win_mtime[1] = oh->win_mtime[1];
#else
- in->yst_uid = oh->yst_uid;
- in->yst_gid = oh->yst_gid;
- in->yst_atime = oh->yst_atime;
- in->yst_mtime = oh->yst_mtime;
- in->yst_ctime = oh->yst_ctime;
- in->yst_rdev = oh->yst_rdev;
+ in->yst_uid = oh->yst_uid;
+ in->yst_gid = oh->yst_gid;
+ in->yst_atime = oh->yst_atime;
+ in->yst_mtime = oh->yst_mtime;
+ in->yst_ctime = oh->yst_ctime;
+ in->yst_rdev = oh->yst_rdev;
#endif
- in->chunkId = chunk;
- if (oh->shadowsObject > 0) {
- yaffs_HandleShadowedObject(dev,
+ if (oh->shadowsObject > 0)
+ yaffs_HandleShadowedObject(dev,
oh->
shadowsObject,
1);
+
+
+ yaffs_SetObjectName(in, oh->name);
+ parent =
+ yaffs_FindOrCreateObjectByNumber
+ (dev, oh->parentObjectId,
+ YAFFS_OBJECT_TYPE_DIRECTORY);
+
+ fileSize = oh->fileSize;
+ isShrink = oh->isShrink;
+ equivalentObjectId = oh->equivalentObjectId;
+
}
+ else {
+ in->variantType = tags.extraObjectType;
+ parent =
+ yaffs_FindOrCreateObjectByNumber
+ (dev, tags.extraParentObjectId,
+ YAFFS_OBJECT_TYPE_DIRECTORY);
+ fileSize = tags.extraFileLength;
+ isShrink = tags.extraIsShrinkHeader;
+ equivalentObjectId = tags.extraEquivalentObjectId;
+ in->lazyLoaded = 1;
- yaffs_SetObjectName(in, oh->name);
+ }
in->dirty = 0;
/* directory stuff...
* hook up to parent
*/
- parent =
- yaffs_FindOrCreateObjectByNumber
- (dev, oh->parentObjectId,
- YAFFS_OBJECT_TYPE_DIRECTORY);
if (parent->variantType ==
YAFFS_OBJECT_TYPE_UNKNOWN) {
/* Set up as a directory */
yaffs_AddObjectToDirectory(parent, in);
- if ((parent == dev->deletedDir ||
- parent == dev->unlinkedDir)) {
- /* If it is unlinked at start up then it wants deleting */
- in->deleted = 1;
- }
+ itsUnlinked = (parent == dev->deletedDir) ||
+ (parent == dev->unlinkedDir);
- if (oh->isShrink) {
+ if (isShrink) {
/* Mark the block as having a shrinkHeader */
bi->hasShrinkHeader = 1;
}
case YAFFS_OBJECT_TYPE_FILE:
if (in->variant.fileVariant.
- scannedFileSize <
- oh->fileSize) {
+ scannedFileSize < fileSize) {
/* This covers the case where the file size is greater
* than where the data is
* This will happen if the file is resized to be larger
* than its current data extents.
*/
- in->variant.fileVariant.fileSize =
- oh->fileSize;
+ in->variant.fileVariant.fileSize = fileSize;
in->variant.fileVariant.scannedFileSize =
in->variant.fileVariant.fileSize;
}
- if (oh->isShrink &&
- in->variant.fileVariant.shrinkSize >
- oh->fileSize) {
- in->variant.fileVariant.shrinkSize =
- oh->fileSize;
+ if (isShrink &&
+ in->variant.fileVariant.shrinkSize > fileSize) {
+ in->variant.fileVariant.shrinkSize = fileSize;
}
break;
case YAFFS_OBJECT_TYPE_HARDLINK:
- in->variant.hardLinkVariant.equivalentObjectId =
- oh->equivalentObjectId;
- in->hardLinks.next =
+ if(!itsUnlinked) {
+ in->variant.hardLinkVariant.equivalentObjectId =
+ equivalentObjectId;
+ in->hardLinks.next =
(struct list_head *) hardList;
- hardList = in;
+ hardList = in;
+ }
break;
case YAFFS_OBJECT_TYPE_DIRECTORY:
/* Do nothing */
/* Do nothing */
break;
case YAFFS_OBJECT_TYPE_SYMLINK:
- in->variant.symLinkVariant.
- alias =
+ if(oh)
+ in->variant.symLinkVariant.alias =
yaffs_CloneString(oh->
alias);
break;
list_for_each(i, &directory->variant.directoryVariant.children) {
if (i) {
l = list_entry(i, yaffs_Object, siblings);
+
+ yaffs_CheckObjectDetailsLoaded(l);
/* Special case for lost-n-found */
if (l->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize)
{
memset(name, 0, buffSize * sizeof(YCHAR));
+
+ yaffs_CheckObjectDetailsLoaded(obj);
if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1);
nFree = yaffs_CountFreeChunks(dev);
#endif
+ nFree += dev->nDeletedFiles;
+
/* Now count the number of dirty chunks in the cache and subtract those */
{