const __u8 *data,
yaffs_ExtendedTags *tags);
+
+static void yaffs_LoadNameFromObjectHeader(yaffs_Device *dev,YCHAR *name, const YCHAR *ohName, int bufferSize);
+static void yaffs_LoadObjectHeaderFromName(yaffs_Device *dev,YCHAR *ohName, const YCHAR *name);
+
+
/* Function to calculate chunk and offset */
static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut,
obj->sum = yaffs_CalcNameSum(name);
}
+void yaffs_SetObjectNameFromOH(yaffs_Object *obj, const yaffs_ObjectHeader *oh)
+{
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+ YCHAR tmpName[YAFFS_MAX_NAME_LENGTH+1];
+ memset(tmpName,0,sizeof(tmpName));
+ yaffs_LoadNameFromObjectHeader(obj->myDev,tmpName,oh->name,YAFFS_MAX_NAME_LENGTH+1);
+ yaffs_SetObjectName(obj,tmpName);
+#else
+ yaffs_SetObjectName(obj,oh->name);
+#endif
+}
+
/*-------------------- TNODES -------------------
* List of spare tnodes
int newChunk;
int markNAND;
int retVal = YAFFS_OK;
- int cleanups = 0;
int i;
int isCheckpointBlock;
int matchingChunk;
* We have to decrement free chunks so this works out properly.
*/
dev->nFreeChunks--;
+ bi->softDeletions--;
object->nDataChunks--;
if (object->nDataChunks <= 0) {
/* remeber to clean up the object */
- dev->gcCleanupList[cleanups] =
+ dev->gcCleanupList[dev->nCleanups] =
tags.objectId;
- cleanups++;
+ dev->nCleanups++;
}
markNAND = 0;
} else if (0) {
yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
+
+ }
+
+ yaffs_VerifyCollectedBlock(dev, bi, block);
+
+
+
+ if (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) {
+ /*
+ * The gc did not complete. Set block state back to FULL
+ * because checkpointing does not restore gc.
+ */
+ bi->blockState = YAFFS_BLOCK_STATE_FULL;
+ } else {
+ /* The gc completed. */
/* Do any required cleanups */
- for (i = 0; i < cleanups; i++) {
+ for (i = 0; i < dev->nCleanups; i++) {
/* Time to delete the file too */
object =
yaffs_FindObjectByNumber(dev,
}
- }
-
- yaffs_VerifyCollectedBlock(dev, bi, block);
-
-
- if (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) {
- /*
- * The gc did not complete. Set block state back to FULL
- * because checkpointing does not restore gc.
- */
- bi->blockState = YAFFS_BLOCK_STATE_FULL;
- } else {
- /* The gc completed. */
chunksAfter = yaffs_GetErasedChunks(dev);
if (chunksBefore >= chunksAfter) {
T(YAFFS_TRACE_GC,
}
dev->gcBlock = 0;
dev->gcChunk = 0;
+ dev->nCleanups = 0;
}
dev->gcDisable = 0;
threshold = dev->param.nChunksPerBlock;
iterations = nBlocks;
} else {
- int maxThreshold = dev->param.nChunksPerBlock/2;
+ int maxThreshold;
+
+ if(background)
+ maxThreshold = dev->param.nChunksPerBlock/2;
+ else
+ maxThreshold = dev->param.nChunksPerBlock/8;
+
+ if(maxThreshold < YAFFS_GC_PASSIVE_THRESHOLD)
+ maxThreshold = YAFFS_GC_PASSIVE_THRESHOLD;
+
threshold = background ?
(dev->gcNotDone + 2) * 2 : 0;
if(threshold <YAFFS_GC_PASSIVE_THRESHOLD)
dev->param.nChunksPerBlock - dev->gcPagesInUse,
prioritised));
+ dev->nGCBlocks++;
if(background)
dev->backgroundGCs++;
+
dev->gcDirtiest = 0;
dev->gcPagesInUse = 0;
dev->gcNotDone = 0;
int aggressive = 0;
int gcOk = YAFFS_OK;
int maxTries = 0;
-
int minErased;
int erasedChunks;
-
int checkpointBlockAdjust;
if(dev->param.gcControl &&
if (dev->nErasedBlocks < minErased)
aggressive = 1;
else {
+ if(!background && erasedChunks > (dev->nFreeChunks / 4))
+ break;
+
if(dev->gcSkip > 20)
dev->gcSkip = 20;
if(erasedChunks < dev->nFreeChunks/2 ||
if (dev->gcBlock < 1 && !aggressive) {
dev->gcBlock = yaffs2_FindRefreshBlock(dev);
dev->gcChunk = 0;
+ dev->nCleanups=0;
}
if (dev->gcBlock < 1) {
dev->gcBlock = yaffs_FindBlockForGarbageCollection(dev, aggressive, background);
dev->gcChunk = 0;
+ dev->nCleanups=0;
}
if (dev->gcBlock > 0) {
if (name && *name) {
memset(oh->name, 0, sizeof(oh->name));
- yaffs_strncpy(oh->name, name, YAFFS_MAX_NAME_LENGTH);
+ yaffs_LoadObjectHeaderFromName(dev,oh->name,name);
} else if (prevChunkId > 0)
memcpy(oh->name, oldName, sizeof(oh->name));
else
struct ylist_head *n;
yaffs_Object *l;
+ if (dev->readOnly)
+ return;
+
/* Soft delete all the unlinked files */
ylist_for_each_safe(i, n,
&dev->unlinkedDir->variant.directoryVariant.children) {
int depthLimit;
int hanging;
+ if (dev->readOnly)
+ return;
/* Iterate through the objects in each hash entry,
* looking at each object.
in->yst_rdev = oh->yst_rdev;
#endif
- yaffs_SetObjectName(in, oh->name);
+ yaffs_SetObjectNameFromOH(in, oh);
if (in->variantType == YAFFS_OBJECT_TYPE_SYMLINK) {
in->variant.symLinkVariant.alias =
yaffs_Device *dev;
if(!obj)
return;
+#ifndef CONFIG_YAFFS_WINCE
dev = obj->myDev;
obj->dirty = 1;
} else
yaffs_UpdateObjectHeader(obj, NULL, 0, 0, 0, NULL);
+#endif
}
void yaffs_UpdateDirtyDirectories(yaffs_Device *dev)
return obj;
}
-int yaffs_GetObjectName(yaffs_Object *obj, YCHAR *name, int buffSize)
-{
- memset(name, 0, buffSize * sizeof(YCHAR));
-
- yaffs_CheckObjectDetailsLoaded(obj);
+/*
+ * A note or two on object names.
+ * * If the object name is missing, we then make one up in the form objnnn
+ *
+ * * ASCII names are stored in the object header's name field from byte zero
+ * * Unicode names are historically stored starting from byte zero.
+ *
+ * Then there are automatic Unicode names...
+ * The purpose of these is to save names in a way that can be read as
+ * ASCII or Unicode names as appropriate, thus allowing a Unicode and ASCII
+ * system to share files.
+ *
+ * These automatic unicode are stored slightly differently...
+ * - If the name can fit in the ASCII character space then they are saved as
+ * ascii names as per above.
+ * - If the name needs Unicode then the name is saved in Unicode
+ * starting at oh->name[1].
- if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
- yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1);
- } else if (obj->hdrChunk <= 0) {
+ */
+static void yaffs_FixNullName(yaffs_Object * obj,YCHAR * name, int buffSize)
+{
+ /* Create an object name if we could not find one. */
+ if(yaffs_strnlen(name,YAFFS_MAX_NAME_LENGTH) == 0){
YCHAR locName[20];
YCHAR numString[20];
YCHAR *x = &numString[19];
unsigned v = obj->objectId;
numString[19] = 0;
- while (v > 0) {
+ while(v>0){
x--;
*x = '0' + (v % 10);
v /= 10;
}
/* make up a name */
yaffs_strcpy(locName, YAFFS_LOSTNFOUND_PREFIX);
- yaffs_strcat(locName, x);
+ yaffs_strcat(locName,x);
yaffs_strncpy(name, locName, buffSize - 1);
+ }
+}
+
+static void yaffs_LoadNameFromObjectHeader(yaffs_Device *dev,YCHAR *name, const YCHAR *ohName, int bufferSize)
+{
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+ if(dev->param.autoUnicode){
+ if(*ohName){
+ /* It is an ASCII name, so do an ASCII to unicode conversion */
+ const char *asciiOhName = (const char *)ohName;
+ int n = bufferSize - 1;
+ while(n > 0 && *asciiOhName){
+ *name = *asciiOhName;
+ name++;
+ asciiOhName++;
+ n--;
+ }
+ } else
+ yaffs_strncpy(name,ohName+1, bufferSize -1);
+ } else
+#endif
+ yaffs_strncpy(name, ohName, bufferSize - 1);
+}
+
+
+static void yaffs_LoadObjectHeaderFromName(yaffs_Device *dev, YCHAR *ohName, const YCHAR *name)
+{
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+
+ int isAscii;
+ YCHAR *w;
+
+ if(dev->param.autoUnicode){
+
+ isAscii = 1;
+ w = name;
+
+ /* Figure out if the name will fit in ascii character set */
+ while(isAscii && *w){
+ if((*w) & 0xff00)
+ isAscii = 0;
+ w++;
+ }
+ if(isAscii){
+ /* It is an ASCII name, so do a unicode to ascii conversion */
+ char *asciiOhName = (char *)ohName;
+ int n = YAFFS_MAX_NAME_LENGTH - 1;
+ while(n > 0 && *name){
+ *asciiOhName= *name;
+ name++;
+ asciiOhName++;
+ n--;
+ }
+ } else{
+ /* It is a unicode name, so save starting at the second YCHAR */
+ *ohName = 0;
+ yaffs_strncpy(ohName+1,name, YAFFS_MAX_NAME_LENGTH -2);
+ }
}
+ else
+#endif
+ yaffs_strncpy(ohName,name, YAFFS_MAX_NAME_LENGTH - 1);
+
+}
+
+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);
+ }
#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
- else if (obj->shortName[0])
- yaffs_strncpy(name, obj->shortName,YAFFS_SHORT_NAME_LENGTH+1);
+ else if (obj->shortName[0]) {
+ yaffs_strcpy(name, obj->shortName);
+ }
#endif
- else {
+ else if(obj->hdrChunk > 0) {
int result;
__u8 *buffer = yaffs_GetTempBuffer(obj->myDev, __LINE__);
obj->hdrChunk, buffer,
NULL);
}
- yaffs_strncpy(name, oh->name, buffSize - 1);
- name[buffSize-1]=0;
+ yaffs_LoadNameFromObjectHeader(obj->myDev,name,oh->name,buffSize);
yaffs_ReleaseTempBuffer(obj->myDev, buffer, __LINE__);
}
- return yaffs_strnlen(name,buffSize-1);
+ yaffs_FixNullName(obj,name,buffSize);
+
+ return yaffs_strnlen(name,YAFFS_MAX_NAME_LENGTH);
}
+
int yaffs_GetObjectFileLength(yaffs_Object *obj)
{
/* Dereference any hard linking */
#endif
-static int yaffs_DoXMod(yaffs_Object *obj, int set, const char *name, const void *value, int size, int flags)
+static int yaffs_DoXMod(yaffs_Object *obj, int set, const YCHAR *name, const void *value, int size, int flags)
{
yaffs_XAttrMod xmod;
return retval;
}
-static int yaffs_DoXFetch(yaffs_Object *obj, const char *name, void *value, int size)
+static int yaffs_DoXFetch(yaffs_Object *obj, const YCHAR *name, void *value, int size)
{
char *buffer = NULL;
int result;
return retval;
}
-int yaffs_SetXAttribute(yaffs_Object *obj, const char *name, const void * value, int size, int flags)
+int yaffs_SetXAttribute(yaffs_Object *obj, const YCHAR *name, const void * value, int size, int flags)
{
return yaffs_DoXMod(obj, 1, name, value, size, flags);
}
-int yaffs_RemoveXAttribute(yaffs_Object *obj, const char *name)
+int yaffs_RemoveXAttribute(yaffs_Object *obj, const YCHAR *name)
{
return yaffs_DoXMod(obj, 0, name, NULL, 0, 0);
}
-int yaffs_GetXAttribute(yaffs_Object *obj, const char *name, void *value, int size)
+int yaffs_GetXAttribute(yaffs_Object *obj, const YCHAR *name, void *value, int size)
{
return yaffs_DoXFetch(obj, name, value, size);
}