*/
const char *yaffs_guts_c_version =
- "$Id: yaffs_guts.c,v 1.54 2007-12-13 15:35:17 wookey Exp $";
+ "$Id: yaffs_guts.c,v 1.55 2008-05-05 07:58:58 charles Exp $";
#include "yportenv.h"
#include "yaffsinterface.h"
#include "yaffs_guts.h"
#include "yaffs_tagsvalidity.h"
+#include "yaffs_getblockinfo.h"
#include "yaffs_tagscompat.h"
#ifndef CONFIG_YAFFS_USE_OWN_SORT
static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo);
-static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
-static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
- int lineNo);
static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
int chunkInNAND);
/* Function to calculate chunk and offset */
-static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset)
+static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, __u32 *offsetOut)
{
- if(dev->chunkShift){
- /* Easy-peasy power of 2 case */
- *chunk = (__u32)(addr >> dev->chunkShift);
- *offset = (__u32)(addr & dev->chunkMask);
- }
- else if(dev->crumbsPerChunk)
+ int chunk;
+ __u32 offset;
+
+ chunk = (__u32)(addr >> dev->chunkShift);
+
+ if(dev->chunkDiv == 1)
{
- /* Case where we're using "crumbs" */
- *offset = (__u32)(addr & dev->crumbMask);
- addr >>= dev->crumbShift;
- *chunk = ((__u32)addr)/dev->crumbsPerChunk;
- *offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift);
+ /* easy power of 2 case */
+ offset = (__u32)(addr & dev->chunkMask);
}
else
- YBUG();
+ {
+ /* Non power-of-2 case */
+
+ loff_t chunkBase;
+
+ chunk /= dev->chunkDiv;
+
+ chunkBase = ((loff_t)chunk) * dev->nDataBytesPerChunk;
+ offset = (__u32)(addr - chunkBase);
+ }
+
+ *chunkOut = chunk;
+ *offsetOut = offset;
}
/* Function to return the number of shifts for a power of 2 greater than or equal
/* Function to return the number of shifts to get a 1 in bit 0
*/
-static __u32 ShiftDiv(__u32 x)
+static __u32 Shifts(__u32 x)
{
int nShifts;
for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {
dev->tempBuffer[i].line = 0; /* not in use */
dev->tempBuffer[i].buffer = buf =
- YMALLOC_DMA(dev->nDataBytesPerChunk);
+ YMALLOC_DMA(dev->totalBytesPerChunk);
}
return buf ? YAFFS_OK : YAFFS_FAIL;
}
-static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
+__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
{
int i, j;
+
+ dev->tempInUse++;
+ if(dev->tempInUse > dev->maxTemp)
+ dev->maxTemp = dev->tempInUse;
+
for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
if (dev->tempBuffer[i].line == 0) {
dev->tempBuffer[i].line = lineNo;
}
-static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
+void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
int lineNo)
{
int i;
+
+ dev->tempInUse--;
+
for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
if (dev->tempBuffer[i].buffer == buffer) {
dev->tempBuffer[i].line = 0;
return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
}
+#if 0
static int yaffs_SkipFullVerification(yaffs_Device *dev)
{
return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_FULL));
}
+#endif
+
static int yaffs_SkipNANDVerification(yaffs_Device *dev)
{
return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND));
int i;
yaffs_Device *dev = obj->myDev;
int ok = 1;
- int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
if (tn) {
if (level > 0) {
__u32 lastChunk;
__u32 x;
__u32 i;
- int ok;
yaffs_Device *dev;
yaffs_ExtendedTags tags;
yaffs_Tnode *tn;
{
yaffs_Object *obj;
int i;
- struct list_head *lh;
+ struct ylist_head *lh;
if(yaffs_SkipVerification(dev))
return;
/* Iterate through the objects in each hash entry */
for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++){
- list_for_each(lh, &dev->objectBucket[i].list) {
+ ylist_for_each(lh, &dev->objectBucket[i].list) {
if (lh) {
- obj = list_entry(lh, yaffs_Object, hashLink);
+ obj = ylist_entry(lh, yaffs_Object, hashLink);
yaffs_VerifyObject(obj);
}
}
/* Hook them into the free list */
for (i = 0; i < nObjects - 1; i++) {
newObjects[i].siblings.next =
- (struct list_head *)(&newObjects[i + 1]);
+ (struct ylist_head *)(&newObjects[i + 1]);
}
newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
tn->myDev = dev;
tn->chunkId = -1;
tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
- INIT_LIST_HEAD(&(tn->hardLinks));
- INIT_LIST_HEAD(&(tn->hashLink));
- INIT_LIST_HEAD(&tn->siblings);
+ YINIT_LIST_HEAD(&(tn->hardLinks));
+ YINIT_LIST_HEAD(&(tn->hashLink));
+ YINIT_LIST_HEAD(&tn->siblings);
/* Add it to the lost and found directory.
* NB Can't put root or lostNFound in lostNFound so
yaffs_Device *dev = tn->myDev;
/* If it is still linked into the bucket list, free from the list */
- if (!list_empty(&tn->hashLink)) {
- list_del_init(&tn->hashLink);
+ if (!ylist_empty(&tn->hashLink)) {
+ ylist_del_init(&tn->hashLink);
bucket = yaffs_HashFunction(tn->objectId);
dev->objectBucket[bucket].count--;
}
yaffs_UnhashObject(tn);
/* Link into the free list. */
- tn->siblings.next = (struct list_head *)(dev->freeObjects);
+ tn->siblings.next = (struct ylist_head *)(dev->freeObjects);
dev->freeObjects = tn;
dev->nFreeObjects++;
dev->nFreeObjects = 0;
for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
- INIT_LIST_HEAD(&dev->objectBucket[i].list);
+ YINIT_LIST_HEAD(&dev->objectBucket[i].list);
dev->objectBucket[i].count = 0;
}
*/
int found = 0;
- struct list_head *i;
+ struct ylist_head *i;
__u32 n = (__u32) bucket;
found = 1;
n += YAFFS_NOBJECT_BUCKETS;
if (1 || dev->objectBucket[bucket].count > 0) {
- list_for_each(i, &dev->objectBucket[bucket].list) {
+ ylist_for_each(i, &dev->objectBucket[bucket].list) {
/* If there is already one in the list */
if (i
- && list_entry(i, yaffs_Object,
+ && ylist_entry(i, yaffs_Object,
hashLink)->objectId == n) {
found = 0;
}
int bucket = yaffs_HashFunction(in->objectId);
yaffs_Device *dev = in->myDev;
- list_add(&in->hashLink, &dev->objectBucket[bucket].list);
+ ylist_add(&in->hashLink, &dev->objectBucket[bucket].list);
dev->objectBucket[bucket].count++;
}
yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number)
{
int bucket = yaffs_HashFunction(number);
- struct list_head *i;
+ struct ylist_head *i;
yaffs_Object *in;
- list_for_each(i, &dev->objectBucket[bucket].list) {
+ ylist_for_each(i, &dev->objectBucket[bucket].list) {
/* Look if it is in the list */
if (i) {
- in = list_entry(i, yaffs_Object, hashLink);
+ 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 */
{
yaffs_Object *theObject;
- yaffs_Tnode *tn;
+ yaffs_Tnode *tn = NULL;
if (number < 0) {
number = yaffs_CreateNewObjectNumber(dev);
theObject->variant.fileVariant.top = tn;
break;
case YAFFS_OBJECT_TYPE_DIRECTORY:
- INIT_LIST_HEAD(&theObject->variant.directoryVariant.
+ YINIT_LIST_HEAD(&theObject->variant.directoryVariant.
children);
break;
case YAFFS_OBJECT_TYPE_SYMLINK:
const YCHAR * aliasString, __u32 rdev)
{
yaffs_Object *in;
- YCHAR *str;
+ YCHAR *str = NULL;
yaffs_Device *dev = parent->myDev;
equivalentObject;
in->variant.hardLinkVariant.equivalentObjectId =
equivalentObject->objectId;
- list_add(&in->hardLinks, &equivalentObject->hardLinks);
+ ylist_add(&in->hardLinks, &equivalentObject->hardLinks);
break;
case YAFFS_OBJECT_TYPE_FILE:
case YAFFS_OBJECT_TYPE_DIRECTORY:
existingTarget = yaffs_FindObjectByName(newDir, newName);
if (existingTarget &&
existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
- !list_empty(&existingTarget->variant.directoryVariant.children)) {
+ !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) {
yaffs_ObjectHeader *oh;
oh = (yaffs_ObjectHeader *)buffer;
oh->isShrink = 0;
- oh->shadowsObject = -1;
+ oh->shadowsObject = oh->inbandShadowsObject = -1;
tags.extraShadows = 0;
tags.extraIsShrinkHeader = 0;
oh->type = in->variantType;
oh->yst_mode = in->yst_mode;
- oh->shadowsObject = shadows;
+ oh->shadowsObject = oh->inbandShadowsObject = shadows;
#ifdef CONFIG_YAFFS_WINCE
oh->win_atime[0] = in->win_atime[0];
yaffs_CheckpointObject cp;
int i;
int ok = 1;
- struct list_head *lh;
+ struct ylist_head *lh;
/* Iterate through the objects in each hash entry,
*/
for(i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++){
- list_for_each(lh, &dev->objectBucket[i].list) {
+ ylist_for_each(lh, &dev->objectBucket[i].list) {
if (lh) {
- obj = list_entry(lh, yaffs_Object, hashLink);
+ obj = ylist_entry(lh, yaffs_Object, hashLink);
if (!obj->deferedFree) {
yaffs_ObjectToCheckpointObject(&cp,obj);
cp.structType = sizeof(cp);
ok = yaffs_ReadCheckpointTnodes(obj);
} else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
obj->hardLinks.next =
- (struct list_head *)
+ (struct ylist_head *)
hardList;
hardList = obj;
}
{
int chunk;
- int start;
+ __u32 start;
int nToCopy;
int n = nBytes;
int nDone = 0;
cache = yaffs_FindChunkCache(in, chunk);
/* If the chunk is already in the cache or it is less than a whole chunk
- * then use the cache (if there is caching)
+ * or we're using inband tags then use the cache (if there is caching)
* else bypass the cache.
*/
- if (cache || nToCopy != dev->nDataBytesPerChunk) {
+ if (cache || nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
if (dev->nShortOpCaches > 0) {
/* If we can't find the data in the cache, then load it up. */
{
int chunk;
- int start;
+ __u32 start;
int nToCopy;
int n = nBytes;
int nDone = 0;
nToWriteBack = dev->nDataBytesPerChunk;
}
- if (nToCopy != dev->nDataBytesPerChunk) {
- /* An incomplete start or end chunk (or maybe both start and end chunk) */
+ if (nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
+ /* An incomplete start or end chunk (or maybe both start and end chunk),
+ * or we're using inband tags, so we want to use the cache buffers.
+ */
if (dev->nShortOpCaches > 0) {
yaffs_ChunkCache *cache;
/* If we can't find the data in the cache, then load the cache */
}
} else {
-
+ /* A full chunk. Write directly from the supplied buffer. */
+
#ifdef CONFIG_YAFFS_WINCE
/* Under WinCE can't do direct transfer. Need to use a local buffer.
* This is because we otherwise screw up WinCE's memory mapper
0);
yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
#else
- /* A full chunk. Write directly from the supplied buffer. */
+
chunkWritten =
yaffs_WriteChunkDataToObject(in, chunk, buffer,
dev->nDataBytesPerChunk,
{
int oldFileSize = in->variant.fileVariant.fileSize;
- int newSizeOfPartialChunk;
+ __u32 newSizeOfPartialChunk;
int newFullChunks;
yaffs_Device *dev = in->myDev;
yaffs_CheckGarbageCollection(dev);
if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
- return yaffs_GetFileSize(in);
+ return YAFFS_FAIL;
}
if (newSize == oldFileSize) {
- return oldFileSize;
+ return YAFFS_OK;
}
if (newSize < oldFileSize) {
if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) {
/* Move to the unlinked directory so we have a record that it was deleted. */
- yaffs_ChangeObjectName(in, in->myDev->deletedDir,"deleted", 0, 0);
+ yaffs_ChangeObjectName(in, in->myDev->deletedDir,_Y("deleted"), 0, 0);
}
if (immediateDeletion) {
retVal =
yaffs_ChangeObjectName(in, in->myDev->deletedDir,
- "deleted", 0, 0);
+ _Y("deleted"), 0, 0);
T(YAFFS_TRACE_TRACING,
(TSTR("yaffs: immediate deletion of file %d" TENDSTR),
in->objectId));
} else {
retVal =
yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
- "unlinked", 0, 0);
+ _Y("unlinked"), 0, 0);
}
}
static int yaffs_DeleteDirectory(yaffs_Object * in)
{
/* First check that the directory is empty. */
- if (list_empty(&in->variant.directoryVariant.children)) {
+ if (ylist_empty(&in->variant.directoryVariant.children)) {
return yaffs_DoGenericObjectDeletion(in);
}
/* remove this hardlink from the list assocaited with the equivalent
* object
*/
- list_del(&in->hardLinks);
+ ylist_del(&in->hardLinks);
return yaffs_DoGenericObjectDeletion(in);
}
if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
return yaffs_DeleteHardLink(obj);
- } else if (!list_empty(&obj->hardLinks)) {
+ } else if (!ylist_empty(&obj->hardLinks)) {
/* Curve ball: We're unlinking an object that has a hardlink.
*
* This problem arises because we are not strictly following
int retVal;
YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
- hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
+ hl = ylist_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
- list_del_init(&hl->hardLinks);
- list_del_init(&hl->siblings);
+ ylist_del_init(&hl->hardLinks);
+ ylist_del_init(&hl->siblings);
yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
if (in) {
/* Add the hardlink pointers */
hl->variant.hardLinkVariant.equivalentObject = in;
- list_add(&hl->hardLinks, &in->hardLinks);
+ ylist_add(&hl->hardLinks, &in->hardLinks);
} else {
/* Todo Need to report/handle this better.
* Got a problem... hardlink to a non-existant object
*/
hl->variant.hardLinkVariant.equivalentObject = NULL;
- INIT_LIST_HEAD(&hl->hardLinks);
+ YINIT_LIST_HEAD(&hl->hardLinks);
}
yaffs_BlockState state;
yaffs_Object *hardList = NULL;
yaffs_BlockInfo *bi;
- int sequenceNumber;
+ __u32 sequenceNumber;
yaffs_ObjectHeader *oh;
yaffs_Object *in;
yaffs_Object *parent;
bi->sequenceNumber)) {
T(YAFFS_TRACE_ALWAYS,
(TSTR
- ("yaffs: Allocation block %d was not highest sequence id:"
- " block seq = %d, dev seq = %d"
+ ("yaffs: Allocation block %d was not highest sequence id: block seq = %d, dev seq = %d"
TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber));
}
}
/* Set up as a directory */
parent->variantType =
YAFFS_OBJECT_TYPE_DIRECTORY;
- INIT_LIST_HEAD(&parent->variant.
+ YINIT_LIST_HEAD(&parent->variant.
directoryVariant.
children);
} else if (parent->variantType !=
T(YAFFS_TRACE_ERROR,
(TSTR
- ("yaffs tragedy: attempting to use non-directory as"
- " a directory in scan. Put in lost+found."
+ ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
TENDSTR)));
parent = dev->lostNFoundDir;
}
equivalentObjectId =
oh->equivalentObjectId;
in->hardLinks.next =
- (struct list_head *)
+ (struct ylist_head *)
hardList;
hardList = in;
break;
* just delete them.
*/
{
- struct list_head *i;
- struct list_head *n;
+ struct ylist_head *i;
+ struct ylist_head *n;
yaffs_Object *l;
/* Soft delete all the unlinked files */
- list_for_each_safe(i, n,
+ ylist_for_each_safe(i, n,
&dev->unlinkedDir->variant.directoryVariant.
children) {
if (i) {
- l = list_entry(i, yaffs_Object, siblings);
+ l = ylist_entry(i, yaffs_Object, siblings);
yaffs_DestroyObject(l);
}
}
yaffs_BlockState state;
yaffs_Object *hardList = NULL;
yaffs_BlockInfo *bi;
- int sequenceNumber;
+ __u32 sequenceNumber;
yaffs_ObjectHeader *oh;
yaffs_Object *in;
yaffs_Object *parent;
NULL);
oh = (yaffs_ObjectHeader *) chunkData;
+
+ if(dev->inbandTags){
+ /* Fix up the header if they got corrupted by inband tags */
+ oh->shadowsObject = oh->inbandShadowsObject;
+ oh->isShrink = oh->inbandIsShrink;
+ }
if (!in)
in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type);
/* TODO Hoosterman we have a problem! */
T(YAFFS_TRACE_ERROR,
(TSTR
- ("yaffs tragedy: Could not make object for object %d "
- "at chunk %d during scan"
+ ("yaffs tragedy: Could not make object for object %d at chunk %d during scan"
TENDSTR), tags.objectId, chunk));
}
/* Set up as a directory */
parent->variantType =
YAFFS_OBJECT_TYPE_DIRECTORY;
- INIT_LIST_HEAD(&parent->variant.
+ YINIT_LIST_HEAD(&parent->variant.
directoryVariant.
children);
} else if (parent->variantType !=
T(YAFFS_TRACE_ERROR,
(TSTR
- ("yaffs tragedy: attempting to use non-directory as"
- " a directory in scan. Put in lost+found."
+ ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
TENDSTR)));
parent = dev->lostNFoundDir;
}
in->variant.hardLinkVariant.equivalentObjectId =
equivalentObjectId;
in->hardLinks.next =
- (struct list_head *) hardList;
+ (struct ylist_head *) hardList;
hardList = in;
}
break;
* Sort out state of unlinked and deleted objects.
*/
{
- struct list_head *i;
- struct list_head *n;
+ struct ylist_head *i;
+ struct ylist_head *n;
yaffs_Object *l;
/* Soft delete all the unlinked files */
- list_for_each_safe(i, n,
+ ylist_for_each_safe(i, n,
&dev->unlinkedDir->variant.directoryVariant.
children) {
if (i) {
- l = list_entry(i, yaffs_Object, siblings);
+ l = ylist_entry(i, yaffs_Object, siblings);
yaffs_DestroyObject(l);
}
}
/* Soft delete all the deletedDir files */
- list_for_each_safe(i, n,
+ ylist_for_each_safe(i, n,
&dev->deletedDir->variant.directoryVariant.
children) {
if (i) {
- l = list_entry(i, yaffs_Object, siblings);
+ l = ylist_entry(i, yaffs_Object, siblings);
yaffs_DestroyObject(l);
}
if(dev && dev->removeObjectCallback)
dev->removeObjectCallback(obj);
- list_del_init(&obj->siblings);
+ ylist_del_init(&obj->siblings);
obj->parent = NULL;
}
if (obj->siblings.prev == NULL) {
/* Not initialised */
- INIT_LIST_HEAD(&obj->siblings);
+ YINIT_LIST_HEAD(&obj->siblings);
- } else if (!list_empty(&obj->siblings)) {
+ } else if (!ylist_empty(&obj->siblings)) {
/* If it is holed up somewhere else, un hook it */
yaffs_RemoveObjectFromDirectory(obj);
}
/* Now add it */
- list_add(&obj->siblings, &directory->variant.directoryVariant.children);
+ ylist_add(&obj->siblings, &directory->variant.directoryVariant.children);
obj->parent = directory;
if (directory == obj->myDev->unlinkedDir
{
int sum;
- struct list_head *i;
+ struct ylist_head *i;
YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
yaffs_Object *l;
sum = yaffs_CalcNameSum(name);
- list_for_each(i, &directory->variant.directoryVariant.children) {
+ ylist_for_each(i, &directory->variant.directoryVariant.children) {
if (i) {
- l = list_entry(i, yaffs_Object, siblings);
+ l = ylist_entry(i, yaffs_Object, siblings);
yaffs_CheckObjectDetailsLoaded(l);
int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
int (*fn) (yaffs_Object *))
{
- struct list_head *i;
+ struct ylist_head *i;
yaffs_Object *l;
if (!theDir) {
YBUG();
}
- list_for_each(i, &theDir->variant.directoryVariant.children) {
+ ylist_for_each(i, &theDir->variant.directoryVariant.children) {
if (i) {
- l = list_entry(i, yaffs_Object, siblings);
+ l = ylist_entry(i, yaffs_Object, siblings);
if (l && !fn(l)) {
return YAFFS_FAIL;
}
int yaffs_GetObjectLinkCount(yaffs_Object * obj)
{
int count = 0;
- struct list_head *i;
+ struct ylist_head *i;
if (!obj->unlinked) {
count++; /* the object itself */
}
- list_for_each(i, &obj->hardLinks) {
+ ylist_for_each(i, &obj->hardLinks) {
count++; /* add the hard links; */
}
return count;
/* Check geometry parameters. */
- if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) ||
- (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) ||
+ if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) ||
+ (!dev->isYaffs2 && dev->totalBytesPerChunk != 512) ||
+ (dev->inbandTags && !dev->isYaffs2 ) ||
dev->nChunksPerBlock < 2 ||
dev->nReservedBlocks < 2 ||
dev->internalStartBlock <= 0 ||
) {
T(YAFFS_TRACE_ALWAYS,
(TSTR
- ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s "
- TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : ""));
+ ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s, inbandTags %d "
+ TENDSTR), dev->totalBytesPerChunk, dev->isYaffs2 ? "2" : "", dev->inbandTags));
return YAFFS_FAIL;
}
(TSTR("yaffs: InitialiseNAND failed" TENDSTR)));
return YAFFS_FAIL;
}
+
+ /* Sort out space for inband tags, if required */
+ if(dev->inbandTags)
+ dev->nDataBytesPerChunk = dev->totalBytesPerChunk - sizeof(yaffs_PackedTags2TagsPart);
+ else
+ dev->nDataBytesPerChunk = dev->totalBytesPerChunk;
/* Got the right mix of functions? */
if (!yaffs_CheckDevFunctions(dev)) {
/*
* Calculate all the chunk size manipulation numbers:
*/
- /* Start off assuming it is a power of 2 */
- dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk);
- dev->chunkMask = (1<<dev->chunkShift) - 1;
-
- if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){
- /* Yes it is a power of 2, disable crumbs */
- dev->crumbMask = 0;
- dev->crumbShift = 0;
- dev->crumbsPerChunk = 0;
- } else {
- /* Not a power of 2, use crumbs instead */
- dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart));
- dev->crumbMask = (1<<dev->crumbShift)-1;
- dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift);
- dev->chunkShift = 0;
- dev->chunkMask = 0;
+ {
+ __u32 x = dev->nDataBytesPerChunk;
+ /* We always use dev->chunkShift and dev->chunkDiv */
+ dev->chunkShift = Shifts(x);
+ x >>= dev->chunkShift;
+ dev->chunkDiv = x;
+ /* We only use chunk mask if chunkDiv is 1 */
+ dev->chunkMask = (1<<dev->chunkShift) - 1;
}
if (!init_failed &&
dev->nShortOpCaches > 0) {
int i;
- __u8 *buf;
+ void *buf;
int srCacheBytes = dev->nShortOpCaches * sizeof(yaffs_ChunkCache);
if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) {
dev->srCache[i].object = NULL;
dev->srCache[i].lastUse = 0;
dev->srCache[i].dirty = 0;
- dev->srCache[i].data = buf = YMALLOC_DMA(dev->nDataBytesPerChunk);
+ dev->srCache[i].data = buf = YMALLOC_DMA(dev->totalBytesPerChunk);
}
if(!buf)
init_failed = 1;
YFREE(dev->tempBuffer[i].buffer);
}
+
dev->isMounted = 0;
}
/*---------------------------------------- YAFFS test code ----------------------*/
#define yaffs_CheckStruct(structure,syze, name) \
+ do { \
if(sizeof(structure) != syze) \
{ \
T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\
name,syze,sizeof(structure))); \
return YAFFS_FAIL; \
- }
+ } \
+ } while(0)
static int yaffs_CheckStructures(void)
{
-/* yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */
-/* yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */
-/* yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */
+/* yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags"); */
+/* yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion"); */
+/* yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare"); */
#ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG
- yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode")
+ yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode");
+#endif
+#ifndef CONFIG_YAFFS_WINCE
+ yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader");
#endif
- yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader")
-
return YAFFS_OK;
}