go back to using google's version of yaffs for higher stability

This commit is contained in:
rajkosto 2010-11-03 22:24:52 +01:00
parent e7a2876f71
commit e97d7c88a7
49 changed files with 4477 additions and 7000 deletions

View File

@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.32.15
# Fri Oct 29 13:59:28 2010
# Wed Nov 3 19:18:32 2010
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@ -1688,14 +1688,11 @@ CONFIG_YAFFS_YAFFS1=y
# CONFIG_YAFFS_DOES_ECC is not set
CONFIG_YAFFS_YAFFS2=y
CONFIG_YAFFS_AUTO_YAFFS2=y
CONFIG_YAFFS_DISABLE_TAGS_ECC=y
# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING=y
# CONFIG_YAFFS_DISABLE_BACKGROUND is not set
CONFIG_YAFFS_XATTR=y
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
CONFIG_SQUASHFS=y

View File

@ -90,15 +90,23 @@ config YAFFS_AUTO_YAFFS2
If unsure, say Y.
config YAFFS_DISABLE_TAGS_ECC
bool "Disable YAFFS from doing ECC on tags by default"
depends on YAFFS_FS && YAFFS_YAFFS2
config YAFFS_DISABLE_LAZY_LOAD
bool "Disable lazy loading"
depends on YAFFS_YAFFS2
default n
help
This defaults Yaffs to using its own ECC calculations on tags instead of
just relying on the MTD.
This behavior can also be overridden with tags_ecc_on and
tags_ecc_off mount options.
"Lazy loading" defers loading file details until they are
required. This saves mount time, but makes the first look-up
a bit longer.
Lazy loading will only happen if enabled by this option being 'n'
and if the appropriate tags are available, else yaffs2 will
automatically fall back to immediate loading and do the right
thing.
Lazy laoding will be required by checkpointing.
Setting this to 'y' will disable lazy loading.
If unsure, say N.
@ -148,43 +156,9 @@ config YAFFS_SHORT_NAMES_IN_RAM
If unsure, say Y.
config YAFFS_EMPTY_LOST_AND_FOUND
bool "Empty lost and found on boot"
bool "Empty lost and found on mount"
depends on YAFFS_FS
default n
help
If this is enabled then the contents of lost and found is
automatically dumped at mount.
If unsure, say N.
config YAFFS_DISABLE_BLOCK_REFRESHING
bool "Disable yaffs2 block refreshing"
depends on YAFFS_FS
default n
help
If this is set, then block refreshing is disabled.
Block refreshing infrequently refreshes the oldest block in
a yaffs2 file system. This mechanism helps to refresh flash to
mitigate against data loss. This is particularly useful for MLC.
If unsure, say N.
config YAFFS_DISABLE_BACKGROUND
bool "Disable yaffs2 background processing"
depends on YAFFS_FS
default n
help
If this is set, then background processing is disabled.
Background processing makes many foreground activities faster.
If unsure, say N.
config YAFFS_XATTR
bool "Enable yaffs2 xattr support"
depends on YAFFS_FS
default y
help
If this is set then yaffs2 will provide xattr support.
If unsure, say Y.

View File

@ -4,14 +4,7 @@
obj-$(CONFIG_YAFFS_FS) += yaffs.o
yaffs-y := yaffs_ecc.o yaffs_vfs_glue.o yaffs_guts.o yaffs_checkptrw.o
yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o
yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o
yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o
yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o
yaffs-y += yaffs_nameval.o
yaffs-y += yaffs_allocator.o
yaffs-y += yaffs_yaffs1.o
yaffs-y += yaffs_yaffs2.o
yaffs-y += yaffs_bitmap.o
yaffs-y += yaffs_verify.o

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -24,8 +24,6 @@
#define __EXTRAS_H__
#include "yportenv.h"
#if !(defined __KERNEL__)
/* Definition of types */
@ -35,6 +33,103 @@ typedef unsigned __u32;
#endif
/*
* This is a simple doubly linked list implementation that matches the
* way the Linux kernel doubly linked list implementation works.
*/
struct ylist_head {
struct ylist_head *next; /* next in chain */
struct ylist_head *prev; /* previous in chain */
};
/* Initialise a static list */
#define YLIST_HEAD(name) \
struct ylist_head name = { &(name), &(name)}
/* Initialise a list head to an empty list */
#define YINIT_LIST_HEAD(p) \
do { \
(p)->next = (p);\
(p)->prev = (p); \
} while (0)
/* Add an element to a list */
static __inline__ void ylist_add(struct ylist_head *newEntry,
struct ylist_head *list)
{
struct ylist_head *listNext = list->next;
list->next = newEntry;
newEntry->prev = list;
newEntry->next = listNext;
listNext->prev = newEntry;
}
static __inline__ void ylist_add_tail(struct ylist_head *newEntry,
struct ylist_head *list)
{
struct ylist_head *listPrev = list->prev;
list->prev = newEntry;
newEntry->next = list;
newEntry->prev = listPrev;
listPrev->next = newEntry;
}
/* Take an element out of its current list, with or without
* reinitialising the links.of the entry*/
static __inline__ void ylist_del(struct ylist_head *entry)
{
struct ylist_head *listNext = entry->next;
struct ylist_head *listPrev = entry->prev;
listNext->prev = listPrev;
listPrev->next = listNext;
}
static __inline__ void ylist_del_init(struct ylist_head *entry)
{
ylist_del(entry);
entry->next = entry->prev = entry;
}
/* Test if the list is empty */
static __inline__ int ylist_empty(struct ylist_head *entry)
{
return (entry->next == entry);
}
/* ylist_entry takes a pointer to a list entry and offsets it to that
* we can find a pointer to the object it is embedded in.
*/
#define ylist_entry(entry, type, member) \
((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
/* ylist_for_each and list_for_each_safe iterate over lists.
* ylist_for_each_safe uses temporary storage to make the list delete safe
*/
#define ylist_for_each(itervar, list) \
for (itervar = (list)->next; itervar != (list); itervar = itervar->next)
#define ylist_for_each_safe(itervar, saveVar, list) \
for (itervar = (list)->next, saveVar = (list)->next->next; \
itervar != (list); itervar = saveVar, saveVar = saveVar->next)
#if !(defined __KERNEL__)

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Martin Fouts <Martin.Fouts@palmsource.com>
@ -29,43 +29,22 @@
/* Meaning: Yaffs does its own ECC, rather than using MTD ECC */
/* #define CONFIG_YAFFS_DOES_ECC */
/* Default: Selected */
/* Meaning: Yaffs does its own ECC on tags for packed tags rather than use mtd */
#define CONFIG_YAFFS_DOES_TAGS_ECC
/* Default: Not selected */
/* Meaning: ECC byte order is 'wrong'. Only meaningful if */
/* CONFIG_YAFFS_DOES_ECC is set */
/* #define CONFIG_YAFFS_ECC_WRONG_ORDER */
/* Default: Not selected */
/* Meaning: Always test whether chunks are erased before writing to them.
Use during mtd debugging and init. */
/* #define CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED */
/* Default: Not Selected */
/* Meaning: At mount automatically empty all files from lost and found. */
/* This is done to fix an old problem where rmdir was not checking for an */
/* empty directory. This can also be achieved with a mount option. */
#define CONFIG_YAFFS_EMPTY_LOST_AND_FOUND
/* Default: Selected */
/* Meaning: Disables testing whether chunks are erased before writing to them*/
#define CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK
/* Default: Selected */
/* Meaning: Cache short names, taking more RAM, but faster look-ups */
#define CONFIG_YAFFS_SHORT_NAMES_IN_RAM
/* Default: Unselected */
/* Meaning: Select to disable block refreshing. */
/* Block Refreshing periodically rewrites the oldest block. */
/* #define CONFIG_DISABLE_BLOCK_REFRESHING */
/* Default: Unselected */
/* Meaning: Select to disable background processing */
/* #define CONFIG_DISABLE_BACKGROUND */
/* Default: Selected */
/* Meaning: Enable XATTR support */
#define CONFIG_YAFFS_XATTR
/* Default: 10 */
/* Meaning: set the count of blocks to reserve for checkpointing */
#define CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS 10
/*
Older-style on-NAND data format has a "pageStatus" byte to record

View File

@ -1,409 +0,0 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1 as
* published by the Free Software Foundation.
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*/
#include "yaffs_allocator.h"
#include "yaffs_guts.h"
#include "yaffs_trace.h"
#include "yportenv.h"
#ifdef CONFIG_YAFFS_YMALLOC_ALLOCATOR
void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev)
{
dev = dev;
}
void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev)
{
dev = dev;
}
yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev)
{
return (yaffs_Tnode *)YMALLOC(dev->tnodeSize);
}
void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn)
{
dev = dev;
YFREE(tn);
}
void yaffs_InitialiseRawObjects(yaffs_Device *dev)
{
dev = dev;
}
void yaffs_DeinitialiseRawObjects(yaffs_Device *dev)
{
dev = dev;
}
yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev)
{
dev = dev;
return (yaffs_Object *) YMALLOC(sizeof(yaffs_Object));
}
void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj)
{
dev = dev;
YFREE(obj);
}
#else
struct yaffs_TnodeList_struct {
struct yaffs_TnodeList_struct *next;
yaffs_Tnode *tnodes;
};
typedef struct yaffs_TnodeList_struct yaffs_TnodeList;
struct yaffs_ObjectList_struct {
yaffs_Object *objects;
struct yaffs_ObjectList_struct *next;
};
typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
struct yaffs_AllocatorStruct {
int nTnodesCreated;
yaffs_Tnode *freeTnodes;
int nFreeTnodes;
yaffs_TnodeList *allocatedTnodeList;
int nObjectsCreated;
yaffs_Object *freeObjects;
int nFreeObjects;
yaffs_ObjectList *allocatedObjectList;
};
typedef struct yaffs_AllocatorStruct yaffs_Allocator;
static void yaffs_DeinitialiseRawTnodes(yaffs_Device *dev)
{
yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
yaffs_TnodeList *tmp;
if(!allocator){
YBUG();
return;
}
while (allocator->allocatedTnodeList) {
tmp = allocator->allocatedTnodeList->next;
YFREE(allocator->allocatedTnodeList->tnodes);
YFREE(allocator->allocatedTnodeList);
allocator->allocatedTnodeList = tmp;
}
allocator->freeTnodes = NULL;
allocator->nFreeTnodes = 0;
allocator->nTnodesCreated = 0;
}
static void yaffs_InitialiseRawTnodes(yaffs_Device *dev)
{
yaffs_Allocator *allocator = dev->allocator;
if(allocator){
allocator->allocatedTnodeList = NULL;
allocator->freeTnodes = NULL;
allocator->nFreeTnodes = 0;
allocator->nTnodesCreated = 0;
} else
YBUG();
}
static int yaffs_CreateTnodes(yaffs_Device *dev, int nTnodes)
{
yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
int i;
yaffs_Tnode *newTnodes;
__u8 *mem;
yaffs_Tnode *curr;
yaffs_Tnode *next;
yaffs_TnodeList *tnl;
if(!allocator){
YBUG();
return YAFFS_FAIL;
}
if (nTnodes < 1)
return YAFFS_OK;
/* make these things */
newTnodes = YMALLOC(nTnodes * dev->tnodeSize);
mem = (__u8 *)newTnodes;
if (!newTnodes) {
T(YAFFS_TRACE_ERROR,
(TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));
return YAFFS_FAIL;
}
/* New hookup for wide tnodes */
for (i = 0; i < nTnodes - 1; i++) {
curr = (yaffs_Tnode *) &mem[i * dev->tnodeSize];
next = (yaffs_Tnode *) &mem[(i+1) * dev->tnodeSize];
curr->internal[0] = next;
}
curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * dev->tnodeSize];
curr->internal[0] = allocator->freeTnodes;
allocator->freeTnodes = (yaffs_Tnode *)mem;
allocator->nFreeTnodes += nTnodes;
allocator->nTnodesCreated += nTnodes;
/* Now add this bunch of tnodes to a list for freeing up.
* NB If we can't add this to the management list it isn't fatal
* but it just means we can't free this bunch of tnodes later.
*/
tnl = YMALLOC(sizeof(yaffs_TnodeList));
if (!tnl) {
T(YAFFS_TRACE_ERROR,
(TSTR
("yaffs: Could not add tnodes to management list" TENDSTR)));
return YAFFS_FAIL;
} else {
tnl->tnodes = newTnodes;
tnl->next = allocator->allocatedTnodeList;
allocator->allocatedTnodeList = tnl;
}
T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR)));
return YAFFS_OK;
}
yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev)
{
yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
yaffs_Tnode *tn = NULL;
if(!allocator){
YBUG();
return NULL;
}
/* If there are none left make more */
if (!allocator->freeTnodes)
yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES);
if (allocator->freeTnodes) {
tn = allocator->freeTnodes;
allocator->freeTnodes = allocator->freeTnodes->internal[0];
allocator->nFreeTnodes--;
}
return tn;
}
/* FreeTnode frees up a tnode and puts it back on the free list */
void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn)
{
yaffs_Allocator *allocator = dev->allocator;
if(!allocator){
YBUG();
return;
}
if (tn) {
tn->internal[0] = allocator->freeTnodes;
allocator->freeTnodes = tn;
allocator->nFreeTnodes++;
}
dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
}
static void yaffs_InitialiseRawObjects(yaffs_Device *dev)
{
yaffs_Allocator *allocator = dev->allocator;
if(allocator) {
allocator->allocatedObjectList = NULL;
allocator->freeObjects = NULL;
allocator->nFreeObjects = 0;
} else
YBUG();
}
static void yaffs_DeinitialiseRawObjects(yaffs_Device *dev)
{
yaffs_Allocator *allocator = dev->allocator;
yaffs_ObjectList *tmp;
if(!allocator){
YBUG();
return;
}
while (allocator->allocatedObjectList) {
tmp = allocator->allocatedObjectList->next;
YFREE(allocator->allocatedObjectList->objects);
YFREE(allocator->allocatedObjectList);
allocator->allocatedObjectList = tmp;
}
allocator->freeObjects = NULL;
allocator->nFreeObjects = 0;
allocator->nObjectsCreated = 0;
}
static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects)
{
yaffs_Allocator *allocator = dev->allocator;
int i;
yaffs_Object *newObjects;
yaffs_ObjectList *list;
if(!allocator){
YBUG();
return YAFFS_FAIL;
}
if (nObjects < 1)
return YAFFS_OK;
/* make these things */
newObjects = YMALLOC(nObjects * sizeof(yaffs_Object));
list = YMALLOC(sizeof(yaffs_ObjectList));
if (!newObjects || !list) {
if (newObjects){
YFREE(newObjects);
newObjects = NULL;
}
if (list){
YFREE(list);
list = NULL;
}
T(YAFFS_TRACE_ALLOCATE,
(TSTR("yaffs: Could not allocate more objects" TENDSTR)));
return YAFFS_FAIL;
}
/* Hook them into the free list */
for (i = 0; i < nObjects - 1; i++) {
newObjects[i].siblings.next =
(struct ylist_head *)(&newObjects[i + 1]);
}
newObjects[nObjects - 1].siblings.next = (void *)allocator->freeObjects;
allocator->freeObjects = newObjects;
allocator->nFreeObjects += nObjects;
allocator->nObjectsCreated += nObjects;
/* Now add this bunch of Objects to a list for freeing up. */
list->objects = newObjects;
list->next = allocator->allocatedObjectList;
allocator->allocatedObjectList = list;
return YAFFS_OK;
}
yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev)
{
yaffs_Object *obj = NULL;
yaffs_Allocator *allocator = dev->allocator;
if(!allocator) {
YBUG();
return obj;
}
/* If there are none left make more */
if (!allocator->freeObjects)
yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
if (allocator->freeObjects) {
obj = allocator->freeObjects;
allocator->freeObjects =
(yaffs_Object *) (allocator->freeObjects->siblings.next);
allocator->nFreeObjects--;
}
return obj;
}
void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj)
{
yaffs_Allocator *allocator = dev->allocator;
if(!allocator)
YBUG();
else {
/* Link into the free list. */
obj->siblings.next = (struct ylist_head *)(allocator->freeObjects);
allocator->freeObjects = obj;
allocator->nFreeObjects++;
}
}
void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev)
{
if(dev->allocator){
yaffs_DeinitialiseRawTnodes(dev);
yaffs_DeinitialiseRawObjects(dev);
YFREE(dev->allocator);
dev->allocator=NULL;
} else
YBUG();
}
void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev)
{
yaffs_Allocator *allocator;
if(!dev->allocator){
allocator = YMALLOC(sizeof(yaffs_Allocator));
if(allocator){
dev->allocator = allocator;
yaffs_InitialiseRawTnodes(dev);
yaffs_InitialiseRawObjects(dev);
}
} else
YBUG();
}
#endif

View File

@ -1,30 +0,0 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1 as
* published by the Free Software Foundation.
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*/
#ifndef __YAFFS_ALLOCATOR_H__
#define __YAFFS_ALLOCATOR_H__
#include "yaffs_guts.h"
void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev);
void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev);
yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev);
void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn);
yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev);
void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj);
#endif

View File

@ -1,105 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "yaffs_bitmap.h"
#include "yaffs_trace.h"
/*
* Chunk bitmap manipulations
*/
static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device *dev, int blk)
{
if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
T(YAFFS_TRACE_ERROR,
(TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR),
blk));
YBUG();
}
return dev->chunkBits +
(dev->chunkBitmapStride * (blk - dev->internalStartBlock));
}
void yaffs_VerifyChunkBitId(yaffs_Device *dev, int blk, int chunk)
{
if (blk < dev->internalStartBlock || blk > dev->internalEndBlock ||
chunk < 0 || chunk >= dev->param.nChunksPerBlock) {
T(YAFFS_TRACE_ERROR,
(TSTR("**>> yaffs: Chunk Id (%d:%d) invalid"TENDSTR),
blk, chunk));
YBUG();
}
}
void yaffs_ClearChunkBits(yaffs_Device *dev, int blk)
{
__u8 *blkBits = yaffs_BlockBits(dev, blk);
memset(blkBits, 0, dev->chunkBitmapStride);
}
void yaffs_ClearChunkBit(yaffs_Device *dev, int blk, int chunk)
{
__u8 *blkBits = yaffs_BlockBits(dev, blk);
yaffs_VerifyChunkBitId(dev, blk, chunk);
blkBits[chunk / 8] &= ~(1 << (chunk & 7));
}
void yaffs_SetChunkBit(yaffs_Device *dev, int blk, int chunk)
{
__u8 *blkBits = yaffs_BlockBits(dev, blk);
yaffs_VerifyChunkBitId(dev, blk, chunk);
blkBits[chunk / 8] |= (1 << (chunk & 7));
}
int yaffs_CheckChunkBit(yaffs_Device *dev, int blk, int chunk)
{
__u8 *blkBits = yaffs_BlockBits(dev, blk);
yaffs_VerifyChunkBitId(dev, blk, chunk);
return (blkBits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;
}
int yaffs_StillSomeChunkBits(yaffs_Device *dev, int blk)
{
__u8 *blkBits = yaffs_BlockBits(dev, blk);
int i;
for (i = 0; i < dev->chunkBitmapStride; i++) {
if (*blkBits)
return 1;
blkBits++;
}
return 0;
}
int yaffs_CountChunkBits(yaffs_Device *dev, int blk)
{
__u8 *blkBits = yaffs_BlockBits(dev, blk);
int i;
int n = 0;
for (i = 0; i < dev->chunkBitmapStride; i++) {
__u8 x = *blkBits;
while (x) {
if (x & 1)
n++;
x >>= 1;
}
blkBits++;
}
return n;
}

View File

@ -1,31 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* Chunk bitmap manipulations
*/
#ifndef __YAFFS_BITMAP_H__
#define __YAFFS_BITMAP_H__
#include "yaffs_guts.h"
void yaffs_VerifyChunkBitId(yaffs_Device *dev, int blk, int chunk);
void yaffs_ClearChunkBits(yaffs_Device *dev, int blk);
void yaffs_ClearChunkBit(yaffs_Device *dev, int blk, int chunk);
void yaffs_SetChunkBit(yaffs_Device *dev, int blk, int chunk);
int yaffs_CheckChunkBit(yaffs_Device *dev, int blk, int chunk);
int yaffs_StillSomeChunkBits(yaffs_Device *dev, int blk);
int yaffs_CountChunkBits(yaffs_Device *dev, int blk);
#endif

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -11,12 +11,16 @@
* published by the Free Software Foundation.
*/
const char *yaffs_checkptrw_c_version =
"$Id$";
#include "yaffs_checkptrw.h"
#include "yaffs_getblockinfo.h"
static int yaffs2_CheckpointSpaceOk(yaffs_Device *dev)
static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
{
int blocksAvailable = dev->nErasedBlocks - dev->param.nReservedBlocks;
int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
T(YAFFS_TRACE_CHECKPOINT,
(TSTR("checkpt blocks available = %d" TENDSTR),
@ -26,11 +30,11 @@ static int yaffs2_CheckpointSpaceOk(yaffs_Device *dev)
}
static int yaffs2_CheckpointErase(yaffs_Device *dev)
static int yaffs_CheckpointErase(yaffs_Device *dev)
{
int i;
if (!dev->param.eraseBlockInNAND)
if (!dev->eraseBlockInNAND)
return 0;
T(YAFFS_TRACE_CHECKPOINT, (TSTR("checking blocks %d to %d"TENDSTR),
dev->internalStartBlock, dev->internalEndBlock));
@ -42,12 +46,12 @@ static int yaffs2_CheckpointErase(yaffs_Device *dev)
dev->nBlockErasures++;
if (dev->param.eraseBlockInNAND(dev, i - dev->blockOffset /* realign */)) {
if (dev->eraseBlockInNAND(dev, i - dev->blockOffset /* realign */)) {
bi->blockState = YAFFS_BLOCK_STATE_EMPTY;
dev->nErasedBlocks++;
dev->nFreeChunks += dev->param.nChunksPerBlock;
dev->nFreeChunks += dev->nChunksPerBlock;
} else {
dev->param.markNANDBlockBad(dev, i);
dev->markNANDBlockBad(dev, i);
bi->blockState = YAFFS_BLOCK_STATE_DEAD;
}
}
@ -59,13 +63,13 @@ static int yaffs2_CheckpointErase(yaffs_Device *dev)
}
static void yaffs2_CheckpointFindNextErasedBlock(yaffs_Device *dev)
static void yaffs_CheckpointFindNextErasedBlock(yaffs_Device *dev)
{
int i;
int blocksAvailable = dev->nErasedBlocks - dev->param.nReservedBlocks;
int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
T(YAFFS_TRACE_CHECKPOINT,
(TSTR("allocating checkpt block: erased %d reserved %d avail %d next %d "TENDSTR),
dev->nErasedBlocks, dev->param.nReservedBlocks, blocksAvailable, dev->checkpointNextBlock));
dev->nErasedBlocks, dev->nReservedBlocks, blocksAvailable, dev->checkpointNextBlock));
if (dev->checkpointNextBlock >= 0 &&
dev->checkpointNextBlock <= dev->internalEndBlock &&
@ -87,7 +91,7 @@ static void yaffs2_CheckpointFindNextErasedBlock(yaffs_Device *dev)
dev->checkpointCurrentBlock = -1;
}
static void yaffs2_CheckpointFindNextCheckpointBlock(yaffs_Device *dev)
static void yaffs_CheckpointFindNextCheckpointBlock(yaffs_Device *dev)
{
int i;
yaffs_ExtendedTags tags;
@ -97,10 +101,10 @@ static void yaffs2_CheckpointFindNextCheckpointBlock(yaffs_Device *dev)
if (dev->blocksInCheckpoint < dev->checkpointMaxBlocks)
for (i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++) {
int chunk = i * dev->param.nChunksPerBlock;
int chunk = i * dev->nChunksPerBlock;
int realignedChunk = chunk - dev->chunkOffset;
dev->param.readChunkWithTagsFromNAND(dev, realignedChunk,
dev->readChunkWithTagsFromNAND(dev, realignedChunk,
NULL, &tags);
T(YAFFS_TRACE_CHECKPOINT, (TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR),
i, tags.objectId, tags.sequenceNumber, tags.eccResult));
@ -123,24 +127,24 @@ static void yaffs2_CheckpointFindNextCheckpointBlock(yaffs_Device *dev)
}
int yaffs2_CheckpointOpen(yaffs_Device *dev, int forWriting)
int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)
{
dev->checkpointOpenForWrite = forWriting;
/* Got the functions we need? */
if (!dev->param.writeChunkWithTagsToNAND ||
!dev->param.readChunkWithTagsFromNAND ||
!dev->param.eraseBlockInNAND ||
!dev->param.markNANDBlockBad)
if (!dev->writeChunkWithTagsToNAND ||
!dev->readChunkWithTagsFromNAND ||
!dev->eraseBlockInNAND ||
!dev->markNANDBlockBad)
return 0;
if (forWriting && !yaffs2_CheckpointSpaceOk(dev))
if (forWriting && !yaffs_CheckpointSpaceOk(dev))
return 0;
if (!dev->checkpointBuffer)
dev->checkpointBuffer = YMALLOC_DMA(dev->param.totalBytesPerChunk);
dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk);
if (!dev->checkpointBuffer)
return 0;
@ -157,7 +161,7 @@ int yaffs2_CheckpointOpen(yaffs_Device *dev, int forWriting)
if (forWriting) {
memset(dev->checkpointBuffer, 0, dev->nDataBytesPerChunk);
dev->checkpointByteOffset = 0;
return yaffs2_CheckpointErase(dev);
return yaffs_CheckpointErase(dev);
} else {
int i;
/* Set to a value that will kick off a read */
@ -177,7 +181,7 @@ int yaffs2_CheckpointOpen(yaffs_Device *dev, int forWriting)
return 1;
}
int yaffs2_GetCheckpointSum(yaffs_Device *dev, __u32 *sum)
int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum)
{
__u32 compositeSum;
compositeSum = (dev->checkpointSum << 8) | (dev->checkpointXor & 0xFF);
@ -185,7 +189,7 @@ int yaffs2_GetCheckpointSum(yaffs_Device *dev, __u32 *sum)
return 1;
}
static int yaffs2_CheckpointFlushBuffer(yaffs_Device *dev)
static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
{
int chunk;
int realignedChunk;
@ -193,7 +197,7 @@ static int yaffs2_CheckpointFlushBuffer(yaffs_Device *dev)
yaffs_ExtendedTags tags;
if (dev->checkpointCurrentBlock < 0) {
yaffs2_CheckpointFindNextErasedBlock(dev);
yaffs_CheckpointFindNextErasedBlock(dev);
dev->checkpointCurrentChunk = 0;
}
@ -213,7 +217,7 @@ static int yaffs2_CheckpointFlushBuffer(yaffs_Device *dev)
dev->blocksInCheckpoint++;
}
chunk = dev->checkpointCurrentBlock * dev->param.nChunksPerBlock + dev->checkpointCurrentChunk;
chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + dev->checkpointCurrentChunk;
T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR),
@ -223,12 +227,12 @@ static int yaffs2_CheckpointFlushBuffer(yaffs_Device *dev)
dev->nPageWrites++;
dev->param.writeChunkWithTagsToNAND(dev, realignedChunk,
dev->writeChunkWithTagsToNAND(dev, realignedChunk,
dev->checkpointBuffer, &tags);
dev->checkpointByteOffset = 0;
dev->checkpointPageSequence++;
dev->checkpointCurrentChunk++;
if (dev->checkpointCurrentChunk >= dev->param.nChunksPerBlock) {
if (dev->checkpointCurrentChunk >= dev->nChunksPerBlock) {
dev->checkpointCurrentChunk = 0;
dev->checkpointCurrentBlock = -1;
}
@ -238,7 +242,7 @@ static int yaffs2_CheckpointFlushBuffer(yaffs_Device *dev)
}
int yaffs2_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes)
int yaffs_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes)
{
int i = 0;
int ok = 1;
@ -267,13 +271,13 @@ int yaffs2_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes)
if (dev->checkpointByteOffset < 0 ||
dev->checkpointByteOffset >= dev->nDataBytesPerChunk)
ok = yaffs2_CheckpointFlushBuffer(dev);
ok = yaffs_CheckpointFlushBuffer(dev);
}
return i;
}
int yaffs2_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
{
int i = 0;
int ok = 1;
@ -298,7 +302,7 @@ int yaffs2_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
dev->checkpointByteOffset >= dev->nDataBytesPerChunk) {
if (dev->checkpointCurrentBlock < 0) {
yaffs2_CheckpointFindNextCheckpointBlock(dev);
yaffs_CheckpointFindNextCheckpointBlock(dev);
dev->checkpointCurrentChunk = 0;
}
@ -306,7 +310,7 @@ int yaffs2_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
ok = 0;
else {
chunk = dev->checkpointCurrentBlock *
dev->param.nChunksPerBlock +
dev->nChunksPerBlock +
dev->checkpointCurrentChunk;
realignedChunk = chunk - dev->chunkOffset;
@ -315,7 +319,7 @@ int yaffs2_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
/* read in the next chunk */
/* printf("read checkpoint page %d\n",dev->checkpointPage); */
dev->param.readChunkWithTagsFromNAND(dev,
dev->readChunkWithTagsFromNAND(dev,
realignedChunk,
dev->checkpointBuffer,
&tags);
@ -329,7 +333,7 @@ int yaffs2_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
dev->checkpointPageSequence++;
dev->checkpointCurrentChunk++;
if (dev->checkpointCurrentChunk >= dev->param.nChunksPerBlock)
if (dev->checkpointCurrentChunk >= dev->nChunksPerBlock)
dev->checkpointCurrentBlock = -1;
}
}
@ -348,12 +352,12 @@ int yaffs2_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
return i;
}
int yaffs2_CheckpointClose(yaffs_Device *dev)
int yaffs_CheckpointClose(yaffs_Device *dev)
{
if (dev->checkpointOpenForWrite) {
if (dev->checkpointByteOffset != 0)
yaffs2_CheckpointFlushBuffer(dev);
yaffs_CheckpointFlushBuffer(dev);
} else if(dev->checkpointBlockList){
int i;
for (i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++) {
@ -371,7 +375,7 @@ int yaffs2_CheckpointClose(yaffs_Device *dev)
dev->checkpointBlockList = NULL;
}
dev->nFreeChunks -= dev->blocksInCheckpoint * dev->param.nChunksPerBlock;
dev->nFreeChunks -= dev->blocksInCheckpoint * dev->nChunksPerBlock;
dev->nErasedBlocks -= dev->blocksInCheckpoint;
@ -387,15 +391,12 @@ int yaffs2_CheckpointClose(yaffs_Device *dev)
return 0;
}
int yaffs2_CheckpointInvalidateStream(yaffs_Device *dev)
int yaffs_CheckpointInvalidateStream(yaffs_Device *dev)
{
/* Erase the checkpoint data */
T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint invalidate of %d blocks"TENDSTR),
dev->blocksInCheckpoint));
return yaffs2_CheckpointErase(dev);
return yaffs_CheckpointErase(dev);
}

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -18,17 +18,18 @@
#include "yaffs_guts.h"
int yaffs2_CheckpointOpen(yaffs_Device *dev, int forWriting);
int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting);
int yaffs2_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes);
int yaffs_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes);
int yaffs2_CheckpointRead(yaffs_Device *dev, void *data, int nBytes);
int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes);
int yaffs2_GetCheckpointSum(yaffs_Device *dev, __u32 *sum);
int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum);
int yaffs2_CheckpointClose(yaffs_Device *dev);
int yaffs_CheckpointClose(yaffs_Device *dev);
int yaffs2_CheckpointInvalidateStream(yaffs_Device *dev);
int yaffs_CheckpointInvalidateStream(yaffs_Device *dev);
#endif

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -28,6 +28,9 @@
* this bytes influence on the line parity.
*/
const char *yaffs_ecc_c_version =
"$Id$";
#include "yportenv.h"
#include "yaffs_ecc.h"

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -17,7 +17,6 @@
#define __YAFFS_GETBLOCKINFO_H__
#include "yaffs_guts.h"
#include "yaffs_trace.h"
/* Function to manipulate block info */
static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -16,9 +16,8 @@
#ifndef __YAFFS_GUTS_H__
#define __YAFFS_GUTS_H__
#include "yportenv.h"
#include "devextras.h"
#include "yaffs_list.h"
#include "yportenv.h"
#define YAFFS_OK 1
#define YAFFS_FAIL 0
@ -53,6 +52,7 @@
#define YAFFS_MAX_CHUNK_ID 0x000FFFFF
#define YAFFS_UNUSED_OBJECT_ID 0x0003FFFF
#define YAFFS_ALLOCATION_NOBJECTS 100
#define YAFFS_ALLOCATION_NTNODES 100
@ -62,9 +62,8 @@
#define YAFFS_OBJECT_SPACE 0x40000
#define YAFFS_MAX_OBJECT_ID (YAFFS_OBJECT_SPACE -1)
#define YAFFS_CHECKPOINT_VERSION 4
#define YAFFS_CHECKPOINT_VERSION 3
#ifdef CONFIG_YAFFS_UNICODE
#define YAFFS_MAX_NAME_LENGTH 127
@ -82,11 +81,12 @@
#define YAFFS_OBJECTID_UNLINKED 3
#define YAFFS_OBJECTID_DELETED 4
/* Pseudo object ids for checkpointing */
/* Sseudo object ids for checkpointing */
#define YAFFS_OBJECTID_SB_HEADER 0x10
#define YAFFS_OBJECTID_CHECKPOINT_DATA 0x20
#define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x21
/* */
#define YAFFS_MAX_SHORT_OP_CACHES 20
@ -119,7 +119,11 @@ typedef struct {
int dirty;
int nBytes; /* Only valid if the cache is dirty */
int locked; /* Can't push out or flush while locked. */
#ifdef CONFIG_YAFFS_YAFFS2
__u8 *data;
#else
__u8 data[YAFFS_BYTES_PER_CHUNK];
#endif
} yaffs_ChunkCache;
@ -230,8 +234,6 @@ typedef enum {
YAFFS_BLOCK_STATE_UNKNOWN = 0,
YAFFS_BLOCK_STATE_SCANNING,
/* Being scanned */
YAFFS_BLOCK_STATE_NEEDS_SCANNING,
/* The block might have something on it (ie it is allocating or full, perhaps empty)
* but it needs to be scanned to determine its true state.
@ -247,23 +249,21 @@ typedef enum {
/* This block is partially allocated.
* At least one page holds valid data.
* This is the one currently being used for page
* allocation. Should never be more than one of these.
* If a block is only partially allocated at mount it is treated as full.
* allocation. Should never be more than one of these
*/
YAFFS_BLOCK_STATE_FULL,
/* All the pages in this block have been allocated.
* If a block was only partially allocated when mounted we treat
* it as fully allocated.
*/
YAFFS_BLOCK_STATE_DIRTY,
/* The block was full and now all chunks have been deleted.
/* All pages have been allocated and deleted.
* Erase me, reuse me.
*/
YAFFS_BLOCK_STATE_CHECKPOINT,
/* This block is assigned to holding checkpoint data. */
/* This block is assigned to holding checkpoint data.
*/
YAFFS_BLOCK_STATE_COLLECTING,
/* This block is being garbage collected */
@ -351,12 +351,23 @@ typedef struct {
/*--------------------------- Tnode -------------------------- */
union yaffs_Tnode_union {
#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL + 1];
#else
union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL];
#endif
/* __u16 level0[YAFFS_NTNODES_LEVEL0]; */
};
typedef union yaffs_Tnode_union yaffs_Tnode;
struct yaffs_TnodeList_struct {
struct yaffs_TnodeList_struct *next;
yaffs_Tnode *tnodes;
};
typedef struct yaffs_TnodeList_struct yaffs_TnodeList;
/*------------------------ Object -----------------------------*/
/* An object can be one of:
@ -376,7 +387,6 @@ typedef struct {
typedef struct {
struct ylist_head children; /* list of child links */
struct ylist_head dirty; /* Entry for list of dirty directories */
} yaffs_DirectoryStructure;
typedef struct {
@ -395,8 +405,6 @@ typedef union {
yaffs_HardLinkStructure hardLinkVariant;
} yaffs_ObjectVariant;
struct yaffs_ObjectStruct {
__u8 deleted:1; /* This should only apply to unlinked files. */
__u8 softDeleted:1; /* it has also been soft deleted */
@ -416,10 +424,7 @@ struct yaffs_ObjectStruct {
* until the inode is released.
*/
__u8 beingCreated:1; /* This object is still being created so skip some checks. */
__u8 isShadowed:1; /* This object is shadowed on the way to being renamed. */
__u8 xattrKnown:1; /* We know if this has object has xattribs or not. */
__u8 hasXattr:1; /* This object has xattribs. Valid if xattrKnown. */
__u8 isShadowed:1; /* This object is shadowed on the way to being renamed. */
__u8 serial; /* serial number of chunk in NAND. Cached here */
__u16 sum; /* sum of the name to speed searching */
@ -448,6 +453,10 @@ struct yaffs_ObjectStruct {
YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
#endif
#ifndef __KERNEL__
__u32 inUse;
#endif
#ifdef CONFIG_YAFFS_WINCE
__u32 win_ctime[2];
__u32 win_mtime[2];
@ -462,7 +471,10 @@ struct yaffs_ObjectStruct {
__u32 yst_rdev;
void *myInode;
#ifdef __KERNEL__
struct inode *myInode;
#endif
yaffs_ObjectType variantType;
@ -472,6 +484,13 @@ struct yaffs_ObjectStruct {
typedef struct yaffs_ObjectStruct yaffs_Object;
struct yaffs_ObjectList_struct {
yaffs_Object *objects;
struct yaffs_ObjectList_struct *next;
};
typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
typedef struct {
struct ylist_head list;
int count;
@ -513,18 +532,12 @@ typedef struct {
/*----------------- Device ---------------------------------*/
struct yaffs_DeviceStruct {
struct ylist_head devList;
const char *name;
struct yaffs_DeviceParamStruct {
const YCHAR *name;
/*
* Entry parameters set up way early. Yaffs sets up the rest.
* The structure should be zeroed out before use so that unused
* and defualt values are zero.
*/
int inbandTags; /* Use unband tags */
__u32 totalBytesPerChunk; /* Should be >= 512, does not need to be a power of 2 */
/* Entry parameters set up way early. Yaffs sets up the rest.*/
int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
int nChunksPerBlock; /* does not need to be a power of 2 */
int spareBytesPerChunk; /* spare area size */
int startBlock; /* Start block we're allowed to use */
@ -533,24 +546,26 @@ struct yaffs_DeviceParamStruct {
/* reserved blocks on NOR and RAM. */
/* Stuff used by the shared space checkpointing mechanism */
/* If this value is zero, then this mechanism is disabled */
/* int nCheckpointReservedBlocks; */ /* Blocks to reserve for checkpoint data */
int nShortOpCaches; /* If <= 0, then short op caching is disabled, else
* the number of short op caches (don't use too many).
* 10 to 20 is a good bet.
* the number of short op caches (don't use too many)
*/
int useNANDECC; /* Flag to decide whether or not to use NANDECC on data (yaffs1) */
int noTagsECC; /* Flag to decide whether or not to do ECC on packed tags (yaffs2) */
int isYaffs2; /* Use yaffs2 mode on this device */
int useHeaderFileSize; /* Flag to determine if we should use file sizes from the header */
int emptyLostAndFound; /* Auto-empty lost+found directory on mount */
int emptyLostAndFound; /* Flasg to determine if lst+found should be emptied on init */
int refreshPeriod; /* How often we should check to do a block refresh */
int useNANDECC; /* Flag to decide whether or not to use NANDECC */
/* Checkpoint control. Can be set before or after initialisation */
__u8 skipCheckpointRead;
__u8 skipCheckpointWrite;
int enableXattr; /* Enable xattribs */
void *genericDevice; /* Pointer to device context
* On an mtd this holds the mtd pointer.
*/
void *superBlock;
/* NAND access functions (Must be set before calling YAFFS)*/
@ -577,6 +592,8 @@ struct yaffs_DeviceParamStruct {
yaffs_BlockState *state, __u32 *sequenceNumber);
#endif
int isYaffs2;
/* The removeObjectCallback function must be supplied by OS flavours that
* need it.
* yaffs direct uses it to implement the faster readdir.
@ -584,61 +601,54 @@ struct yaffs_DeviceParamStruct {
*/
void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj);
/* Callback to mark the superblock dirty */
void (*markSuperBlockDirty)(struct yaffs_DeviceStruct *dev);
/* Callback to control garbage collection. */
unsigned (*gcControl)(struct yaffs_DeviceStruct *dev);
/* Callback to mark the superblock dirsty */
void (*markSuperBlockDirty)(void *superblock);
/* Debug control flags. Don't use unless you know what you're doing */
int useHeaderFileSize; /* Flag to determine if we should use file sizes from the header */
int disableLazyLoad; /* Disable lazy loading on this device */
int wideTnodesDisabled; /* Set to disable wide tnodes */
int disableSoftDelete; /* yaffs 1 only: Set to disable the use of softdeletion. */
int deferDirectoryUpdate; /* Set to defer directory updates */
#ifdef CONFIG_YAFFS_AUTO_UNICODE
int autoUnicode;
#endif
int alwaysCheckErased; /* Force chunk erased check always on */
};
YCHAR *pathDividers; /* String of legal path dividers */
typedef struct yaffs_DeviceParamStruct yaffs_DeviceParam;
struct yaffs_DeviceStruct {
struct yaffs_DeviceParamStruct param;
/* End of stuff that must be set before initialisation. */
/* Context storage. Holds extra OS specific data for this device */
void *osContext;
void *driverContext;
struct ylist_head devList;
/* Checkpoint control. Can be set before or after initialisation */
__u8 skipCheckpointRead;
__u8 skipCheckpointWrite;
/* Runtime parameters. Set up by YAFFS. */
int nDataBytesPerChunk;
/* Non-wide tnode stuff */
__u16 chunkGroupBits; /* Number of bits that need to be resolved if
* the tnodes are not wide enough.
*/
__u16 chunkGroupBits; /* 0 for devices <= 32MB. else log2(nchunks) - 16 */
__u16 chunkGroupSize; /* == 2^^chunkGroupBits */
/* Stuff to support wide tnodes */
__u32 tnodeWidth;
__u32 tnodeMask;
__u32 tnodeSize;
/* Stuff for figuring out file offset to chunk conversions */
__u32 chunkShift; /* Shift value */
__u32 chunkDiv; /* Divisor after shifting: 1 for power-of-2 sizes */
__u32 chunkMask; /* Mask to use for power-of-2 case */
/* Stuff to handle inband tags */
int inbandTags;
__u32 totalBytesPerChunk;
#ifdef __KERNEL__
struct semaphore sem; /* Semaphore for waiting on erasure.*/
struct semaphore grossLock; /* Gross locking semaphore */
struct rw_semaphore dirLock; /* Lock the directory structure */
__u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer
* at compile time so we have to allocate it.
*/
void (*putSuperFunc) (struct super_block *sb);
struct ylist_head searchContexts;
#endif
int isMounted;
int readOnly;
int isCheckpointed;
@ -680,31 +690,51 @@ struct yaffs_DeviceStruct {
__u32 allocationPage;
int allocationBlockFinder; /* Used to search for next allocation block */
/* Object and Tnode memory management */
void *allocator;
int nObjects;
int nTnodes;
/* Runtime state */
int nTnodesCreated;
yaffs_Tnode *freeTnodes;
int nFreeTnodes;
yaffs_TnodeList *allocatedTnodeList;
int isDoingGC;
int gcBlock;
int gcChunk;
int nObjectsCreated;
yaffs_Object *freeObjects;
int nFreeObjects;
int nHardLinks;
yaffs_ObjectList *allocatedObjectList;
yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS];
__u32 bucketFinder;
int nFreeChunks;
/* Garbage collection control */
__u32 *gcCleanupList; /* objects to delete at the end of a GC. */
__u32 nCleanups;
int currentDirtyChecker; /* Used to find current dirtiest block */
unsigned hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */
unsigned gcDisable;
unsigned gcBlockFinder;
unsigned gcDirtiest;
unsigned gcPagesInUse;
unsigned gcNotDone;
unsigned gcBlock;
unsigned gcChunk;
unsigned gcSkip;
__u32 *gcCleanupList; /* objects to delete at the end of a GC. */
int nonAggressiveSkip; /* GC state/mode */
/* Statistcs */
int nPageWrites;
int nPageReads;
int nBlockErasures;
int nErasureFailures;
int nGCCopies;
int garbageCollections;
int passiveGarbageCollections;
int nRetriedWrites;
int nRetiredBlocks;
int eccFixed;
int eccUnfixed;
int tagsEccFixed;
int tagsEccUnfixed;
int nDeletions;
int nUnmarkedDeletions;
int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */
/* Special directories */
yaffs_Object *rootDir;
@ -721,6 +751,8 @@ struct yaffs_DeviceStruct {
yaffs_ChunkCache *srCache;
int srLastUse;
int cacheHits;
/* Stuff for background deletion and unlinked files.*/
yaffs_Object *unlinkedDir; /* Directory where unlinked and deleted files live. */
yaffs_Object *deletedDir; /* Directory where deleted objects are sent to disappear. */
@ -729,6 +761,7 @@ struct yaffs_DeviceStruct {
int nUnlinkedFiles; /* Count of unlinked files. */
int nBackgroundDeletions; /* Count of background deletions. */
/* Temporary buffer management */
yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];
int maxTemp;
@ -739,36 +772,6 @@ struct yaffs_DeviceStruct {
/* yaffs2 runtime stuff */
unsigned sequenceNumber; /* Sequence number of currently allocating block */
unsigned oldestDirtySequence;
unsigned oldestDirtyBlock;
/* Block refreshing */
int refreshSkip; /* A skip down counter. Refresh happens when this gets to zero. */
/* Dirty directory handling */
struct ylist_head dirtyDirectories; /* List of dirty directories */
/* Statistcs */
__u32 nPageWrites;
__u32 nPageReads;
__u32 nBlockErasures;
__u32 nErasureFailures;
__u32 nGCCopies;
__u32 allGCs;
__u32 passiveGCs;
__u32 oldestDirtyGCs;
__u32 nGCBlocks;
__u32 backgroundGCs;
__u32 nRetriedWrites;
__u32 nRetiredBlocks;
__u32 eccFixed;
__u32 eccUnfixed;
__u32 tagsEccFixed;
__u32 tagsEccUnfixed;
__u32 nDeletions;
__u32 nUnmarkedDeletions;
__u32 refreshCount;
__u32 cacheHits;
};
@ -801,6 +804,7 @@ typedef struct {
/* yaffs2 runtime stuff */
unsigned sequenceNumber; /* Sequence number of currently allocating block */
unsigned oldestDirtySequence;
} yaffs_CheckpointDevice;
@ -813,23 +817,6 @@ typedef struct {
} yaffs_CheckpointValidity;
struct yaffs_ShadowFixerStruct {
int objectId;
int shadowedId;
struct yaffs_ShadowFixerStruct *next;
};
/* Structure for doing xattr modifications */
typedef struct {
int set; /* If 0 then this is a deletion */
const YCHAR *name;
const void *data;
int size;
int flags;
int result;
}yaffs_XAttrMod;
/*----------------------- YAFFS Functions -----------------------*/
int yaffs_GutsInitialise(yaffs_Device *dev);
@ -861,8 +848,7 @@ int yaffs_ResizeFile(yaffs_Object *obj, loff_t newSize);
yaffs_Object *yaffs_MknodFile(yaffs_Object *parent, const YCHAR *name,
__u32 mode, __u32 uid, __u32 gid);
int yaffs_FlushFile(yaffs_Object *obj, int updateTime, int dataSync);
int yaffs_FlushFile(yaffs_Object *obj, int updateTime);
/* Flushing and checkpointing */
void yaffs_FlushEntireDeviceCache(yaffs_Device *dev);
@ -895,12 +881,6 @@ YCHAR *yaffs_GetSymlinkAlias(yaffs_Object *obj);
yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent, const YCHAR *name,
__u32 mode, __u32 uid, __u32 gid, __u32 rdev);
int yaffs_SetXAttribute(yaffs_Object *obj, const YCHAR *name, const void * value, int size, int flags);
int yaffs_GetXAttribute(yaffs_Object *obj, const YCHAR *name, void *value, int size);
int yaffs_ListXAttributes(yaffs_Object *obj, char *buffer, int size);
int yaffs_RemoveXAttribute(yaffs_Object *obj, const YCHAR *name);
/* Special directories */
yaffs_Object *yaffs_Root(yaffs_Device *dev);
yaffs_Object *yaffs_LostNFound(yaffs_Device *dev);
@ -910,18 +890,18 @@ yaffs_Object *yaffs_LostNFound(yaffs_Device *dev);
void yfsd_WinFileTimeNow(__u32 target[2]);
#endif
#ifdef __KERNEL__
void yaffs_HandleDeferedFree(yaffs_Object *obj);
void yaffs_UpdateDirtyDirectories(yaffs_Device *dev);
int yaffs_BackgroundGarbageCollect(yaffs_Device *dev, unsigned urgency);
#endif
/* Debug dump */
int yaffs_DumpObject(yaffs_Object *obj);
void yaffs_GutsTest(yaffs_Device *dev);
/* A few useful functions to be used within the core files*/
/* A few useful functions */
void yaffs_InitialiseTags(yaffs_ExtendedTags *tags);
void yaffs_DeleteChunk(yaffs_Device *dev, int chunkId, int markNAND, int lyn);
int yaffs_CheckFF(__u8 *buffer, int nBytes);
void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
@ -929,41 +909,4 @@ void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
__u8 *yaffs_GetTempBuffer(yaffs_Device *dev, int lineNo);
void yaffs_ReleaseTempBuffer(yaffs_Device *dev, __u8 *buffer, int lineNo);
yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev,
int number,
yaffs_ObjectType type);
int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode,
int chunkInNAND, int inScan);
void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name);
void yaffs_SetObjectNameFromOH(yaffs_Object *obj, const yaffs_ObjectHeader *oh);
void yaffs_AddObjectToDirectory(yaffs_Object *directory,
yaffs_Object *obj);
YCHAR *yaffs_CloneString(const YCHAR *str);
void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList);
void yaffs_BlockBecameDirty(yaffs_Device *dev, int blockNo);
int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name,
int force, int isShrink, int shadows,
yaffs_XAttrMod *xop);
void yaffs_HandleShadowedObject(yaffs_Device *dev, int objId,
int backwardScanning);
int yaffs_CheckSpaceForAllocation(yaffs_Device *dev, int nChunks);
yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev);
yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device *dev,
yaffs_FileStructure *fStruct,
__u32 chunkId,
yaffs_Tnode *passedTn);
int yaffs_DoWriteDataToFile(yaffs_Object *in, const __u8 *buffer, loff_t offset,
int nBytes, int writeThrough);
void yaffs_ResizeDown( yaffs_Object *obj, loff_t newSize);
void yaffs_SkipRestOfBlock(yaffs_Device *dev);
int yaffs_CountFreeChunks(yaffs_Device *dev);
yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev,
yaffs_FileStructure *fStruct,
__u32 chunkId);
__u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos);
#endif

View File

@ -1,43 +0,0 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1 as
* published by the Free Software Foundation.
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*/
#ifndef __YAFFS_LINUX_H__
#define __YAFFS_LINUX_H__
#include "devextras.h"
#include "yportenv.h"
struct yaffs_LinuxContext {
struct ylist_head contextList; /* List of these we have mounted */
struct yaffs_DeviceStruct *dev;
struct super_block * superBlock;
struct task_struct *bgThread; /* Background thread for this device */
int bgRunning;
struct semaphore grossLock; /* Gross locking semaphore */
__u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer
* at compile time so we have to allocate it.
*/
struct ylist_head searchContexts;
void (*putSuperFunc)(struct super_block *sb);
struct task_struct *readdirProcess;
unsigned mount_id;
};
#define yaffs_DeviceToLC(dev) ((struct yaffs_LinuxContext *)((dev)->osContext))
#define yaffs_DeviceToMtd(dev) ((struct mtd_info *)((dev)->driverContext))
#endif

View File

@ -1,200 +0,0 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1 as
* published by the Free Software Foundation.
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*
* Note: Tis code is currently unused. Being checked in in case it becomes useful.
*/
#include "yaffs_allocator.h"
#include "yaffs_guts.h"
#include "yaffs_trace.h"
#include "yportenv.h"
#include "yaffs_linux.h"
/*
* Start out with the same allocator as yaffs direct.
* Todo: Change to Linux slab allocator.
*/
#define NAMELEN 20
struct yaffs_AllocatorStruct {
char tnode_name[NAMELEN+1];
char object_name[NAMELEN+1];
struct kmem_cache *tnode_cache;
struct kmem_cache *object_cache;
};
typedef struct yaffs_AllocatorStruct yaffs_Allocator;
int mount_id;
void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev)
{
yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
T(YAFFS_TRACE_ALLOCATE,(TSTR("Deinitialising yaffs allocator\n")));
if(allocator){
if(allocator->tnode_cache){
kmem_cache_destroy(allocator->tnode_cache);
allocator->tnode_cache = NULL;
} else {
T(YAFFS_TRACE_ALWAYS,
(TSTR("NULL tnode cache\n")));
YBUG();
}
if(allocator->object_cache){
kmem_cache_destroy(allocator->object_cache);
allocator->object_cache = NULL;
} else {
T(YAFFS_TRACE_ALWAYS,
(TSTR("NULL object cache\n")));
YBUG();
}
YFREE(allocator);
} else {
T(YAFFS_TRACE_ALWAYS,
(TSTR("Deinitialising NULL allocator\n")));
YBUG();
}
dev->allocator = NULL;
}
static void fake_ctor0(void *data){data = data;}
static void fake_ctor1(void *data){data = data;}
static void fake_ctor2(void *data){data = data;}
static void fake_ctor3(void *data){data = data;}
static void fake_ctor4(void *data){data = data;}
static void fake_ctor5(void *data){data = data;}
static void fake_ctor6(void *data){data = data;}
static void fake_ctor7(void *data){data = data;}
static void fake_ctor8(void *data){data = data;}
static void fake_ctor9(void *data){data = data;}
static void (*fake_ctor_list[10]) (void *) = {
fake_ctor0,
fake_ctor1,
fake_ctor2,
fake_ctor3,
fake_ctor4,
fake_ctor5,
fake_ctor6,
fake_ctor7,
fake_ctor8,
fake_ctor9,
};
void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev)
{
yaffs_Allocator *allocator;
unsigned mount_id = yaffs_DeviceToLC(dev)->mount_id;
T(YAFFS_TRACE_ALLOCATE,(TSTR("Initialising yaffs allocator\n")));
if(dev->allocator)
YBUG();
else if(mount_id >= 10){
T(YAFFS_TRACE_ALWAYS,(TSTR("Bad mount_id %u\n"),mount_id));
} else {
allocator = YMALLOC(sizeof(yaffs_Allocator));
memset(allocator,0,sizeof(yaffs_Allocator));
dev->allocator = allocator;
if(!dev->allocator){
T(YAFFS_TRACE_ALWAYS,
(TSTR("yaffs allocator creation failed\n")));
YBUG();
return;
}
sprintf(allocator->tnode_name,"yaffs_t_%u",mount_id);
sprintf(allocator->object_name,"yaffs_o_%u",mount_id);
allocator->tnode_cache =
kmem_cache_create(allocator->tnode_name,
dev->tnodeSize,
0, 0,
fake_ctor_list[mount_id]);
if(allocator->tnode_cache)
T(YAFFS_TRACE_ALLOCATE,
(TSTR("tnode cache \"%s\" %p\n"),
allocator->tnode_name,allocator->tnode_cache));
else {
T(YAFFS_TRACE_ALWAYS,
(TSTR("yaffs cache creation failed\n")));
YBUG();
}
allocator->object_cache =
kmem_cache_create(allocator->object_name,
sizeof(yaffs_Object),
0, 0,
fake_ctor_list[mount_id]);
if(allocator->object_cache)
T(YAFFS_TRACE_ALLOCATE,
(TSTR("object cache \"%s\" %p\n"),
allocator->object_name,allocator->object_cache));
else {
T(YAFFS_TRACE_ALWAYS,
(TSTR("yaffs cache creation failed\n")));
YBUG();
}
}
}
yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev)
{
yaffs_Allocator *allocator = dev->allocator;
if(!allocator || !allocator->tnode_cache){
YBUG();
return NULL;
}
return kmem_cache_alloc(allocator->tnode_cache, GFP_NOFS);
}
void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn)
{
yaffs_Allocator *allocator = dev->allocator;
kmem_cache_free(allocator->tnode_cache,tn);
}
yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev)
{
yaffs_Allocator *allocator = dev->allocator;
if(!allocator){
YBUG();
return NULL;
}
if(!allocator->object_cache){
YBUG();
return NULL;
}
return kmem_cache_alloc(allocator->object_cache, GFP_NOFS);
}
void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj)
{
yaffs_Allocator *allocator = dev->allocator;
kmem_cache_free(allocator->object_cache,obj);
}

View File

@ -1,127 +0,0 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1 as
* published by the Free Software Foundation.
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*/
/*
* This file is just holds extra declarations of macros that would normally
* be providesd in the Linux kernel. These macros have been written from
* scratch but are functionally equivalent to the Linux ones.
*
*/
#ifndef __YAFFS_LIST_H__
#define __YAFFS_LIST_H__
#include "yportenv.h"
/*
* This is a simple doubly linked list implementation that matches the
* way the Linux kernel doubly linked list implementation works.
*/
struct ylist_head {
struct ylist_head *next; /* next in chain */
struct ylist_head *prev; /* previous in chain */
};
/* Initialise a static list */
#define YLIST_HEAD(name) \
struct ylist_head name = { &(name), &(name)}
/* Initialise a list head to an empty list */
#define YINIT_LIST_HEAD(p) \
do { \
(p)->next = (p);\
(p)->prev = (p); \
} while (0)
/* Add an element to a list */
static Y_INLINE void ylist_add(struct ylist_head *newEntry,
struct ylist_head *list)
{
struct ylist_head *listNext = list->next;
list->next = newEntry;
newEntry->prev = list;
newEntry->next = listNext;
listNext->prev = newEntry;
}
static Y_INLINE void ylist_add_tail(struct ylist_head *newEntry,
struct ylist_head *list)
{
struct ylist_head *listPrev = list->prev;
list->prev = newEntry;
newEntry->next = list;
newEntry->prev = listPrev;
listPrev->next = newEntry;
}
/* Take an element out of its current list, with or without
* reinitialising the links.of the entry*/
static Y_INLINE void ylist_del(struct ylist_head *entry)
{
struct ylist_head *listNext = entry->next;
struct ylist_head *listPrev = entry->prev;
listNext->prev = listPrev;
listPrev->next = listNext;
}
static Y_INLINE void ylist_del_init(struct ylist_head *entry)
{
ylist_del(entry);
entry->next = entry->prev = entry;
}
/* Test if the list is empty */
static Y_INLINE int ylist_empty(struct ylist_head *entry)
{
return (entry->next == entry);
}
/* ylist_entry takes a pointer to a list entry and offsets it to that
* we can find a pointer to the object it is embedded in.
*/
#define ylist_entry(entry, type, member) \
((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
/* ylist_for_each and list_for_each_safe iterate over lists.
* ylist_for_each_safe uses temporary storage to make the list delete safe
*/
#define ylist_for_each(itervar, list) \
for (itervar = (list)->next; itervar != (list); itervar = itervar->next)
#define ylist_for_each_safe(itervar, saveVar, list) \
for (itervar = (list)->next, saveVar = (list)->next->next; \
itervar != (list); itervar = saveVar, saveVar = saveVar->next)
#endif

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -11,6 +11,9 @@
* published by the Free Software Foundation.
*/
const char *yaffs_mtdif_c_version =
"$Id$";
#include "yportenv.h"
@ -21,26 +24,208 @@
#include "linux/time.h"
#include "linux/mtd/nand.h"
#include "yaffs_linux.h"
#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 18))
static struct nand_oobinfo yaffs_oobinfo = {
.useecc = 1,
.eccbytes = 6,
.eccpos = {8, 9, 10, 13, 14, 15}
};
static struct nand_oobinfo yaffs_noeccinfo = {
.useecc = 0,
};
#endif
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob)
{
oob[0] = spare->tagByte0;
oob[1] = spare->tagByte1;
oob[2] = spare->tagByte2;
oob[3] = spare->tagByte3;
oob[4] = spare->tagByte4;
oob[5] = spare->tagByte5 & 0x3f;
oob[5] |= spare->blockStatus == 'Y' ? 0 : 0x80;
oob[5] |= spare->pageStatus == 0 ? 0 : 0x40;
oob[6] = spare->tagByte6;
oob[7] = spare->tagByte7;
}
static inline void translate_oob2spare(yaffs_Spare *spare, __u8 *oob)
{
struct yaffs_NANDSpare *nspare = (struct yaffs_NANDSpare *)spare;
spare->tagByte0 = oob[0];
spare->tagByte1 = oob[1];
spare->tagByte2 = oob[2];
spare->tagByte3 = oob[3];
spare->tagByte4 = oob[4];
spare->tagByte5 = oob[5] == 0xff ? 0xff : oob[5] & 0x3f;
spare->blockStatus = oob[5] & 0x80 ? 0xff : 'Y';
spare->pageStatus = oob[5] & 0x40 ? 0xff : 0;
spare->ecc1[0] = spare->ecc1[1] = spare->ecc1[2] = 0xff;
spare->tagByte6 = oob[6];
spare->tagByte7 = oob[7];
spare->ecc2[0] = spare->ecc2[1] = spare->ecc2[2] = 0xff;
nspare->eccres1 = nspare->eccres2 = 0; /* FIXME */
}
#endif
int nandmtd_WriteChunkToNAND(yaffs_Device *dev, int chunkInNAND,
const __u8 *data, const yaffs_Spare *spare)
{
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
struct mtd_oob_ops ops;
#endif
size_t dummy;
int retval = 0;
loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
__u8 spareAsBytes[8]; /* OOB */
if (data && !spare)
retval = mtd->write(mtd, addr, dev->nDataBytesPerChunk,
&dummy, data);
else if (spare) {
if (dev->useNANDECC) {
translate_spare2oob(spare, spareAsBytes);
ops.mode = MTD_OOB_AUTO;
ops.ooblen = 8; /* temp hack */
} else {
ops.mode = MTD_OOB_RAW;
ops.ooblen = YAFFS_BYTES_PER_SPARE;
}
ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen;
ops.datbuf = (u8 *)data;
ops.ooboffs = 0;
ops.oobbuf = spareAsBytes;
retval = mtd->write_oob(mtd, addr, &ops);
}
#else
__u8 *spareAsBytes = (__u8 *) spare;
if (data && spare) {
if (dev->useNANDECC)
retval =
mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
&dummy, data, spareAsBytes,
&yaffs_oobinfo);
else
retval =
mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
&dummy, data, spareAsBytes,
&yaffs_noeccinfo);
} else {
if (data)
retval =
mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
data);
if (spare)
retval =
mtd->write_oob(mtd, addr, YAFFS_BYTES_PER_SPARE,
&dummy, spareAsBytes);
}
#endif
if (retval == 0)
return YAFFS_OK;
else
return YAFFS_FAIL;
}
int nandmtd_ReadChunkFromNAND(yaffs_Device *dev, int chunkInNAND, __u8 *data,
yaffs_Spare *spare)
{
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
struct mtd_oob_ops ops;
#endif
size_t dummy;
int retval = 0;
loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
__u8 spareAsBytes[8]; /* OOB */
if (data && !spare)
retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
&dummy, data);
else if (spare) {
if (dev->useNANDECC) {
ops.mode = MTD_OOB_AUTO;
ops.ooblen = 8; /* temp hack */
} else {
ops.mode = MTD_OOB_RAW;
ops.ooblen = YAFFS_BYTES_PER_SPARE;
}
ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen;
ops.datbuf = data;
ops.ooboffs = 0;
ops.oobbuf = spareAsBytes;
retval = mtd->read_oob(mtd, addr, &ops);
if (dev->useNANDECC)
translate_oob2spare(spare, spareAsBytes);
}
#else
__u8 *spareAsBytes = (__u8 *) spare;
if (data && spare) {
if (dev->useNANDECC) {
/* Careful, this call adds 2 ints */
/* to the end of the spare data. Calling function */
/* should allocate enough memory for spare, */
/* i.e. [YAFFS_BYTES_PER_SPARE+2*sizeof(int)]. */
retval =
mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
&dummy, data, spareAsBytes,
&yaffs_oobinfo);
} else {
retval =
mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
&dummy, data, spareAsBytes,
&yaffs_noeccinfo);
}
} else {
if (data)
retval =
mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
data);
if (spare)
retval =
mtd->read_oob(mtd, addr, YAFFS_BYTES_PER_SPARE,
&dummy, spareAsBytes);
}
#endif
if (retval == 0)
return YAFFS_OK;
else
return YAFFS_FAIL;
}
int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
__u32 addr =
((loff_t) blockNumber) * dev->param.totalBytesPerChunk
* dev->param.nChunksPerBlock;
((loff_t) blockNumber) * dev->nDataBytesPerChunk
* dev->nChunksPerBlock;
struct erase_info ei;
int retval = 0;
ei.mtd = mtd;
ei.addr = addr;
ei.len = dev->param.totalBytesPerChunk * dev->param.nChunksPerBlock;
ei.len = dev->nDataBytesPerChunk * dev->nChunksPerBlock;
ei.time = 1000;
ei.retries = 2;
ei.callback = NULL;
ei.priv = (u_long) dev;
/* Todo finish off the ei if required */
sema_init(&dev->sem, 0);
retval = mtd->erase(mtd, &ei);
if (retval == 0)

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -22,6 +22,11 @@
extern struct nand_oobinfo yaffs_oobinfo;
extern struct nand_oobinfo yaffs_noeccinfo;
#endif
int nandmtd_WriteChunkToNAND(yaffs_Device *dev, int chunkInNAND,
const __u8 *data, const yaffs_Spare *spare);
int nandmtd_ReadChunkFromNAND(yaffs_Device *dev, int chunkInNAND, __u8 *data,
yaffs_Spare *spare);
int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
int nandmtd_InitialiseNAND(yaffs_Device *dev);
#endif

View File

@ -2,7 +2,7 @@
* YAFFS: Yet another FFS. A NAND-flash specific file system.
* yaffs_mtdif1.c NAND mtd interface functions for small-page NAND.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* This program is free software; you can redistribute it and/or modify
@ -24,11 +24,9 @@
*/
#include "yportenv.h"
#include "yaffs_trace.h"
#include "yaffs_guts.h"
#include "yaffs_packedtags1.h"
#include "yaffs_tagscompat.h" /* for yaffs_CalcTagsECC */
#include "yaffs_linux.h"
#include "linux/kernel.h"
#include "linux/version.h"
@ -38,6 +36,8 @@
/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
const char *yaffs_mtdif1_c_version = "$Id$";
#ifndef CONFIG_YAFFS_9BYTE_TAGS
# define YTAG1_SIZE 8
#else
@ -91,7 +91,7 @@ static struct nand_ecclayout nand_oob_16 = {
int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev,
int chunkInNAND, const __u8 *data, const yaffs_ExtendedTags *etags)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
struct mtd_info *mtd = dev->genericDevice;
int chunkBytes = dev->nDataBytesPerChunk;
loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;
struct mtd_oob_ops ops;
@ -135,9 +135,9 @@ int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev,
retval = mtd->write_oob(mtd, addr, &ops);
if (retval) {
T(YAFFS_TRACE_MTD,
(TSTR("write_oob failed, chunk %d, mtd error %d"TENDSTR),
chunkInNAND, retval));
yaffs_trace(YAFFS_TRACE_MTD,
"write_oob failed, chunk %d, mtd error %d\n",
chunkInNAND, retval);
}
return retval ? YAFFS_FAIL : YAFFS_OK;
}
@ -169,7 +169,7 @@ static int rettags(yaffs_ExtendedTags *etags, int eccResult, int retval)
int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
int chunkInNAND, __u8 *data, yaffs_ExtendedTags *etags)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
struct mtd_info *mtd = dev->genericDevice;
int chunkBytes = dev->nDataBytesPerChunk;
loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;
int eccres = YAFFS_ECC_RESULT_NO_ERROR;
@ -196,9 +196,9 @@ int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
*/
retval = mtd->read_oob(mtd, addr, &ops);
if (retval) {
T(YAFFS_TRACE_MTD,
(TSTR("read_oob failed, chunk %d, mtd error %d"TENDSTR),
chunkInNAND, retval));
yaffs_trace(YAFFS_TRACE_MTD,
"read_oob failed, chunk %d, mtd error %d\n",
chunkInNAND, retval);
}
switch (retval) {
@ -280,11 +280,11 @@ int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
*/
int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
int blocksize = dev->param.nChunksPerBlock * dev->nDataBytesPerChunk;
struct mtd_info *mtd = dev->genericDevice;
int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk;
int retval;
T(YAFFS_TRACE_BAD_BLOCKS,(TSTR("marking block %d bad"TENDSTR), blockNo));
yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad\n", blockNo);
retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo);
return (retval) ? YAFFS_FAIL : YAFFS_OK;
@ -301,9 +301,9 @@ static int nandmtd1_TestPrerequists(struct mtd_info *mtd)
int oobavail = mtd->ecclayout->oobavail;
if (oobavail < YTAG1_SIZE) {
T(YAFFS_TRACE_ERROR,
(TSTR("mtd device has only %d bytes for tags, need %d"TENDSTR),
oobavail, YTAG1_SIZE));
yaffs_trace(YAFFS_TRACE_ERROR,
"mtd device has only %d bytes for tags, need %d\n",
oobavail, YTAG1_SIZE);
return YAFFS_FAIL;
}
return YAFFS_OK;
@ -321,8 +321,8 @@ static int nandmtd1_TestPrerequists(struct mtd_info *mtd)
int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
yaffs_BlockState *pState, __u32 *pSequenceNumber)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
int chunkNo = blockNo * dev->param.nChunksPerBlock;
struct mtd_info *mtd = dev->genericDevice;
int chunkNo = blockNo * dev->nChunksPerBlock;
loff_t addr = (loff_t)chunkNo * dev->nDataBytesPerChunk;
yaffs_ExtendedTags etags;
int state = YAFFS_BLOCK_STATE_DEAD;
@ -338,8 +338,8 @@ int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags);
etags.blockBad = (mtd->block_isbad)(mtd, addr);
if (etags.blockBad) {
T(YAFFS_TRACE_BAD_BLOCKS,
(TSTR("block %d is marked bad"TENDSTR), blockNo));
yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
"block %d is marked bad\n", blockNo);
state = YAFFS_BLOCK_STATE_DEAD;
} else if (etags.eccResult != YAFFS_ECC_RESULT_NO_ERROR) {
/* bad tags, need to look more closely */

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* This program is free software; you can redistribute it and/or modify

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -13,8 +13,11 @@
/* mtd interface for YAFFS2 */
const char *yaffs_mtdif2_c_version =
"$Id$";
#include "yportenv.h"
#include "yaffs_trace.h"
#include "yaffs_mtdif2.h"
@ -24,7 +27,11 @@
#include "yaffs_packedtags2.h"
#include "yaffs_linux.h"
#ifdef CONFIG_YAFFS_DOES_ECC
#define OOB_TAGS_SIZE sizeof(yaffs_PackedTags2)
#else
#define OOB_TAGS_SIZE sizeof(yaffs_PackedTags2TagsPart)
#endif
/* NB For use with inband tags....
* We assume that the data buffer is of size totalBytersPerChunk so that we can also
@ -34,7 +41,7 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
const __u8 *data,
const yaffs_ExtendedTags *tags)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
struct mtd_oob_ops ops;
#else
@ -46,16 +53,12 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
yaffs_PackedTags2 pt;
int packed_tags_size = dev->param.noTagsECC ? sizeof(pt.t) : sizeof(pt);
void * packed_tags_ptr = dev->param.noTagsECC ? (void *) &pt.t : (void *)&pt;
T(YAFFS_TRACE_MTD,
(TSTR
("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
TENDSTR), chunkInNAND, data, tags));
addr = ((loff_t) chunkInNAND) * dev->param.totalBytesPerChunk;
addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
/* For yaffs2 writing there must be both data and tags.
* If we're using inband tags, then the tags are stuffed into
@ -63,30 +66,30 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
*/
if (!data || !tags)
BUG();
else if (dev->param.inbandTags) {
else if (dev->inbandTags) {
yaffs_PackedTags2TagsPart *pt2tp;
pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
yaffs_PackTags2TagsPart(pt2tp, tags);
} else
yaffs_PackTags2(&pt, tags, !dev->param.noTagsECC);
yaffs_PackTags2(&pt, tags);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
ops.mode = MTD_OOB_AUTO;
ops.ooblen = (dev->param.inbandTags) ? 0 : packed_tags_size;
ops.len = dev->param.totalBytesPerChunk;
ops.ooblen = (dev->inbandTags) ? 0 : OOB_TAGS_SIZE;
ops.len = dev->totalBytesPerChunk;
ops.ooboffs = 0;
ops.datbuf = (__u8 *)data;
ops.oobbuf = (dev->param.inbandTags) ? NULL : packed_tags_ptr;
ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt;
retval = mtd->write_oob(mtd, addr, &ops);
#else
if (!dev->param.inbandTags) {
if (!dev->inbandTags) {
retval =
mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
&dummy, data, (__u8 *) packed_tags_ptr, NULL);
&dummy, data, (__u8 *) &pt, NULL);
} else {
retval =
mtd->write(mtd, addr, dev->param.totalBytesPerChunk, &dummy,
mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy,
data);
}
#endif
@ -100,7 +103,7 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
__u8 *data, yaffs_ExtendedTags *tags)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
struct mtd_oob_ops ops;
#endif
@ -108,19 +111,16 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
int retval = 0;
int localData = 0;
loff_t addr = ((loff_t) chunkInNAND) * dev->param.totalBytesPerChunk;
loff_t addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
yaffs_PackedTags2 pt;
int packed_tags_size = dev->param.noTagsECC ? sizeof(pt.t) : sizeof(pt);
void * packed_tags_ptr = dev->param.noTagsECC ? (void *) &pt.t: (void *)&pt;
T(YAFFS_TRACE_MTD,
(TSTR
("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
TENDSTR), chunkInNAND, data, tags));
if (dev->param.inbandTags) {
if (dev->inbandTags) {
if (!data) {
localData = 1;
@ -132,20 +132,20 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
if (dev->param.inbandTags || (data && !tags))
retval = mtd->read(mtd, addr, dev->param.totalBytesPerChunk,
if (dev->inbandTags || (data && !tags))
retval = mtd->read(mtd, addr, dev->totalBytesPerChunk,
&dummy, data);
else if (tags) {
ops.mode = MTD_OOB_AUTO;
ops.ooblen = packed_tags_size;
ops.len = data ? dev->nDataBytesPerChunk : packed_tags_size;
ops.ooblen = OOB_TAGS_SIZE;
ops.len = data ? dev->nDataBytesPerChunk : OOB_TAGS_SIZE;
ops.ooboffs = 0;
ops.datbuf = data;
ops.oobbuf = yaffs_DeviceToLC(dev)->spareBuffer;
ops.oobbuf = dev->spareBuffer;
retval = mtd->read_oob(mtd, addr, &ops);
}
#else
if (!dev->param.inbandTags && data && tags) {
if (!dev->inbandTags && data && tags) {
retval = mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
&dummy, data, dev->spareBuffer,
@ -155,7 +155,7 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
retval =
mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
data);
if (!dev->param.inbandTags && tags)
if (!dev->inbandTags && tags)
retval =
mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
dev->spareBuffer);
@ -163,7 +163,7 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
#endif
if (dev->param.inbandTags) {
if (dev->inbandTags) {
if (tags) {
yaffs_PackedTags2TagsPart *pt2tp;
pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];
@ -171,8 +171,8 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
}
} else {
if (tags) {
memcpy(packed_tags_ptr, yaffs_DeviceToLC(dev)->spareBuffer, packed_tags_size);
yaffs_UnpackTags2(tags, &pt, !dev->param.noTagsECC);
memcpy(&pt, dev->spareBuffer, OOB_TAGS_SIZE);
yaffs_UnpackTags2(tags, &pt);
}
}
@ -183,7 +183,7 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
dev->eccUnfixed++;
}
if(tags && retval == -EUCLEAN && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) {
if (tags && retval == -EUCLEAN && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) {
tags->eccResult = YAFFS_ECC_RESULT_FIXED;
dev->eccFixed++;
}
@ -195,15 +195,15 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
int retval;
T(YAFFS_TRACE_MTD,
(TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo));
retval =
mtd->block_markbad(mtd,
blockNo * dev->param.nChunksPerBlock *
dev->param.totalBytesPerChunk);
blockNo * dev->nChunksPerBlock *
dev->totalBytesPerChunk);
if (retval == 0)
return YAFFS_OK;
@ -215,15 +215,15 @@ int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
yaffs_BlockState *state, __u32 *sequenceNumber)
{
struct mtd_info *mtd = yaffs_DeviceToMtd(dev);
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
int retval;
T(YAFFS_TRACE_MTD,
(TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo));
retval =
mtd->block_isbad(mtd,
blockNo * dev->param.nChunksPerBlock *
dev->param.totalBytesPerChunk);
blockNo * dev->nChunksPerBlock *
dev->totalBytesPerChunk);
if (retval) {
T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
@ -234,7 +234,7 @@ int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
yaffs_ExtendedTags t;
nandmtd2_ReadChunkWithTagsFromNAND(dev,
blockNo *
dev->param.nChunksPerBlock, NULL,
dev->nChunksPerBlock, NULL,
&t);
if (t.chunkUsed) {

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>

View File

@ -1,197 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* This simple implementation of a name-value store assumes a small number of values and fits
* into a small finite buffer.
*
* Each attribute is stored as a record:
* sizeof(int) bytes record size.
* strnlen+1 bytes name null terminated.
* nbytes value.
* ----------
* total size stored in record size
*
* This code has not been tested with unicode yet.
*/
#include "yaffs_nameval.h"
#include "yportenv.h"
static int nval_find(const char *xb, int xb_size, const YCHAR *name,
int *exist_size)
{
int pos=0;
int size;
memcpy(&size,xb,sizeof(int));
while(size > 0 && (size < xb_size) && (pos + size < xb_size)){
if(yaffs_strncmp((YCHAR *)(xb+pos+sizeof(int)),name,size) == 0){
if(exist_size)
*exist_size = size;
return pos;
}
pos += size;
if(pos < xb_size -sizeof(int))
memcpy(&size,xb + pos,sizeof(int));
else
size = 0;
}
if(exist_size)
*exist_size = 0;
return -1;
}
static int nval_used(const char *xb, int xb_size)
{
int pos=0;
int size;
memcpy(&size,xb + pos,sizeof(int));
while(size > 0 && (size < xb_size) && (pos + size < xb_size)){
pos += size;
if(pos < xb_size -sizeof(int))
memcpy(&size,xb + pos,sizeof(int));
else
size = 0;
}
return pos;
}
int nval_del(char *xb, int xb_size, const YCHAR *name)
{
int pos = nval_find(xb, xb_size, name, NULL);
int size;
if(pos >= 0 && pos < xb_size){
/* Find size, shift rest over this record, then zero out the rest of buffer */
memcpy(&size,xb+pos,sizeof(int));
memcpy(xb + pos, xb + pos + size, xb_size - (pos + size));
memset(xb + (xb_size - size),0,size);
return 0;
} else
return -ENODATA;
}
int nval_set(char *xb, int xb_size, const YCHAR *name, const char *buf, int bsize, int flags)
{
int pos;
int namelen = yaffs_strnlen(name,xb_size);
int reclen;
int size_exist = 0;
int space;
int start;
pos = nval_find(xb,xb_size,name, &size_exist);
if(flags & XATTR_CREATE && pos >= 0)
return -EEXIST;
if(flags & XATTR_REPLACE && pos < 0)
return -ENODATA;
start = nval_used(xb,xb_size);
space = xb_size - start + size_exist;
reclen = (sizeof(int) + namelen + 1 + bsize);
if(reclen > space)
return -ENOSPC;
if(pos >= 0){
nval_del(xb,xb_size,name);
start = nval_used(xb, xb_size);
}
pos = start;
memcpy(xb + pos,&reclen,sizeof(int));
pos +=sizeof(int);
yaffs_strncpy((YCHAR *)(xb + pos), name, reclen);
pos+= (namelen+1);
memcpy(xb + pos,buf,bsize);
return 0;
}
int nval_get(const char *xb, int xb_size, const YCHAR *name, char *buf, int bsize)
{
int pos = nval_find(xb,xb_size,name,NULL);
int size;
if(pos >= 0 && pos< xb_size){
memcpy(&size,xb +pos,sizeof(int));
pos+=sizeof(int); /* advance past record length */
size -= sizeof(int);
/* Advance over name string */
while(xb[pos] && size > 0 && pos < xb_size){
pos++;
size--;
}
/*Advance over NUL */
pos++;
size--;
if(size <= bsize){
memcpy(buf,xb + pos,size);
return size;
}
}
if(pos >= 0)
return -ERANGE;
else
return -ENODATA;
}
int nval_list(const char *xb, int xb_size, char *buf, int bsize)
{
int pos = 0;
int size;
int name_len;
int ncopied = 0;
int filled = 0;
memcpy(&size,xb + pos,sizeof(int));
while(size > sizeof(int) && size <= xb_size && (pos + size) < xb_size && !filled){
pos+= sizeof(int);
size-=sizeof(int);
name_len = yaffs_strnlen((YCHAR *)(xb + pos), size);
if(ncopied + name_len + 1 < bsize){
memcpy(buf,xb+pos,name_len * sizeof(YCHAR));
buf+= name_len;
*buf = '\0';
buf++;
if(sizeof(YCHAR) > 1){
*buf = '\0';
buf++;
}
ncopied += (name_len+1);
} else
filled = 1;
pos+=size;
if(pos < xb_size -sizeof(int))
memcpy(&size,xb + pos,sizeof(int));
else
size = 0;
}
return ncopied;
}
int nval_hasvalues(const char *xb, int xb_size)
{
return nval_used(xb, xb_size) > 0;
}

View File

@ -1,25 +0,0 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1 as
* published by the Free Software Foundation.
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*/
#ifndef __NAMEVAL_H__
#define __NAMEVAL_H__
#include "yportenv.h"
int nval_del(char *xb, int xb_size, const YCHAR *name);
int nval_set(char *xb, int xb_size, const YCHAR *name, const char *buf, int bsize, int flags);
int nval_get(const char *xb, int xb_size, const YCHAR *name, char *buf, int bsize);
int nval_list(const char *xb, int xb_size, char *buf, int bsize);
int nval_hasvalues(const char *xb, int xb_size);
#endif

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -11,6 +11,9 @@
* published by the Free Software Foundation.
*/
const char *yaffs_nand_c_version =
"$Id$";
#include "yaffs_nand.h"
#include "yaffs_tagscompat.h"
#include "yaffs_tagsvalidity.h"
@ -32,8 +35,8 @@ int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
if (!tags)
tags = &localTags;
if (dev->param.readChunkWithTagsFromNAND)
result = dev->param.readChunkWithTagsFromNAND(dev, realignedChunkInNAND, buffer,
if (dev->readChunkWithTagsFromNAND)
result = dev->readChunkWithTagsFromNAND(dev, realignedChunkInNAND, buffer,
tags);
else
result = yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev,
@ -43,8 +46,7 @@ int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
if (tags &&
tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR) {
yaffs_BlockInfo *bi;
bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->param.nChunksPerBlock);
yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock);
yaffs_HandleChunkError(dev, bi);
}
@ -78,8 +80,8 @@ int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,
YBUG();
}
if (dev->param.writeChunkWithTagsToNAND)
return dev->param.writeChunkWithTagsToNAND(dev, chunkInNAND, buffer,
if (dev->writeChunkWithTagsToNAND)
return dev->writeChunkWithTagsToNAND(dev, chunkInNAND, buffer,
tags);
else
return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev,
@ -93,8 +95,8 @@ int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo)
blockNo -= dev->blockOffset;
if (dev->param.markNANDBlockBad)
return dev->param.markNANDBlockBad(dev, blockNo);
if (dev->markNANDBlockBad)
return dev->markNANDBlockBad(dev, blockNo);
else
return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo);
}
@ -106,8 +108,8 @@ int yaffs_QueryInitialBlockState(yaffs_Device *dev,
{
blockNo -= dev->blockOffset;
if (dev->param.queryNANDBlock)
return dev->param.queryNANDBlock(dev, blockNo, state, sequenceNumber);
if (dev->queryNANDBlock)
return dev->queryNANDBlock(dev, blockNo, state, sequenceNumber);
else
return yaffs_TagsCompatabilityQueryNANDBlock(dev, blockNo,
state,
@ -124,16 +126,14 @@ int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
dev->nBlockErasures++;
result = dev->param.eraseBlockInNAND(dev, blockInNAND);
result = dev->eraseBlockInNAND(dev, blockInNAND);
return result;
}
int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
{
if(dev->param.initialiseNAND)
return dev->param.initialiseNAND(dev);
return YAFFS_OK;
return dev->initialiseNAND(dev);
}

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -13,7 +13,6 @@
#include "yaffs_packedtags2.h"
#include "yportenv.h"
#include "yaffs_trace.h"
#include "yaffs_tagsvalidity.h"
/* This code packs a set of extended tags into a binary structure for
@ -38,6 +37,9 @@
#define EXTRA_OBJECT_TYPE_SHIFT (28)
#define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
#ifndef CONFIG_YAFFS_DOES_ECC
#define YAFFS_IGNORE_TAGS_ECC 1
#endif
static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart *ptt)
{
@ -97,14 +99,17 @@ void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *ptt,
}
void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t, int tagsECC)
void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t)
{
yaffs_PackTags2TagsPart(&pt->t, t);
if(tagsECC)
#ifndef YAFFS_IGNORE_TAGS_ECC
{
yaffs_ECCCalculateOther((unsigned char *)&pt->t,
sizeof(yaffs_PackedTags2TagsPart),
&pt->ecc);
}
#endif
}
@ -156,24 +161,27 @@ void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags *t,
}
void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt, int tagsECC)
void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt)
{
yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;
if (pt->t.sequenceNumber != 0xFFFFFFFF &&
tagsECC){
/* Chunk is in use and we need to do ECC */
yaffs_ECCOther ecc;
int result;
yaffs_ECCCalculateOther((unsigned char *)&pt->t,
sizeof(yaffs_PackedTags2TagsPart),
&ecc);
result = yaffs_ECCCorrectOther((unsigned char *)&pt->t,
sizeof(yaffs_PackedTags2TagsPart),
&pt->ecc, &ecc);
switch (result) {
if (pt->t.sequenceNumber != 0xFFFFFFFF) {
/* Page is in use */
#ifndef YAFFS_IGNORE_TAGS_ECC
{
yaffs_ECCOther ecc;
int result;
yaffs_ECCCalculateOther((unsigned char *)&pt->t,
sizeof
(yaffs_PackedTags2TagsPart),
&ecc);
result =
yaffs_ECCCorrectOther((unsigned char *)&pt->t,
sizeof
(yaffs_PackedTags2TagsPart),
&pt->ecc, &ecc);
switch (result) {
case 0:
eccResult = YAFFS_ECC_RESULT_NO_ERROR;
break;
@ -185,7 +193,9 @@ void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt, int tagsECC
break;
default:
eccResult = YAFFS_ECC_RESULT_UNKNOWN;
}
}
#endif
}
yaffs_UnpackTags2TagsPart(t, &pt->t);
@ -194,5 +204,6 @@ void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt, int tagsECC
yaffs_DumpPackedTags2(pt);
yaffs_DumpTags2(t);
}

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -34,8 +34,8 @@ typedef struct {
} yaffs_PackedTags2;
/* Full packed tags with ECC, used for oob tags */
void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t, int tagsECC);
void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt, int tagsECC);
void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t);
void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt);
/* Only the tags part (no ECC for use with inband tags */
void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *pt, const yaffs_ExtendedTags *t);

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -17,18 +17,7 @@
#ifndef __YAFFS_QSORT_H__
#define __YAFFS_QSORT_H__
#ifdef __KERNEL__
#include <linux/sort.h>
extern void yaffs_qsort(void *const base, size_t total_elems, size_t size,
int (*cmp)(const void *, const void *)){
sort(base, total_elems, size, cmp, NULL);
}
#else
extern void yaffs_qsort(void *const base, size_t total_elems, size_t size,
int (*cmp)(const void *, const void *));
#endif
#endif

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -15,7 +15,6 @@
#include "yaffs_tagscompat.h"
#include "yaffs_ecc.h"
#include "yaffs_getblockinfo.h"
#include "yaffs_trace.h"
static void yaffs_HandleReadDataError(yaffs_Device *dev, int chunkInNAND);
#ifdef NOTYET
@ -164,14 +163,14 @@ static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,
int chunkInNAND, const __u8 *data,
yaffs_Spare *spare)
{
if (chunkInNAND < dev->param.startBlock * dev->param.nChunksPerBlock) {
if (chunkInNAND < dev->startBlock * dev->nChunksPerBlock) {
T(YAFFS_TRACE_ERROR,
(TSTR("**>> yaffs chunk %d is not valid" TENDSTR),
chunkInNAND));
return YAFFS_FAIL;
}
return dev->param.writeChunkToNAND(dev, chunkInNAND, data, spare);
return dev->writeChunkToNAND(dev, chunkInNAND, data, spare);
}
static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
@ -190,8 +189,8 @@ static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
spare = &localSpare;
}
if (!dev->param.useNANDECC) {
retVal = dev->param.readChunkFromNAND(dev, chunkInNAND, data, spare);
if (!dev->useNANDECC) {
retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, spare);
if (data && doErrorCorrection) {
/* Do ECC correction */
/* Todo handle any errors */
@ -252,7 +251,7 @@ static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
memset(&nspare, 0, sizeof(nspare));
retVal = dev->param.readChunkFromNAND(dev, chunkInNAND, data,
retVal = dev->readChunkFromNAND(dev, chunkInNAND, data,
(yaffs_Spare *) &nspare);
memcpy(spare, &nspare, sizeof(yaffs_Spare));
if (data && doErrorCorrection) {
@ -305,10 +304,10 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
static __u8 cmpbuf[YAFFS_BYTES_PER_CHUNK];
static __u8 data[YAFFS_BYTES_PER_CHUNK];
/* Might as well always allocate the larger size for */
/* dev->param.useNANDECC == true; */
/* dev->useNANDECC == true; */
static __u8 spare[sizeof(struct yaffs_NANDSpare)];
dev->param.readChunkFromNAND(dev, chunkInNAND, data, (yaffs_Spare *) spare);
dev->readChunkFromNAND(dev, chunkInNAND, data, (yaffs_Spare *) spare);
if (!init) {
memset(cmpbuf, 0xff, YAFFS_BYTES_PER_CHUNK);
@ -331,7 +330,7 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
static void yaffs_HandleReadDataError(yaffs_Device *dev, int chunkInNAND)
{
int blockInNAND = chunkInNAND / dev->param.nChunksPerBlock;
int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
/* Mark the block for retirement */
yaffs_GetBlockInfo(dev, blockInNAND + dev->blockOffset)->needsRetiring = 1;
@ -363,7 +362,7 @@ static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND,
static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND)
{
int blockInNAND = chunkInNAND / dev->param.nChunksPerBlock;
int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
/* Mark the block for retirement */
yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
@ -422,7 +421,7 @@ int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device *dev,
tags.serialNumber = eTags->serialNumber;
if (!dev->param.useNANDECC && data)
if (!dev->useNANDECC && data)
yaffs_CalcECC(data, &spare);
yaffs_LoadTagsIntoSpare(&spare, &tags);
@ -496,9 +495,9 @@ int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
spare.blockStatus = 'Y';
yaffs_WriteChunkToNAND(dev, blockInNAND * dev->param.nChunksPerBlock, NULL,
yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock, NULL,
&spare);
yaffs_WriteChunkToNAND(dev, blockInNAND * dev->param.nChunksPerBlock + 1,
yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock + 1,
NULL, &spare);
return YAFFS_OK;
@ -523,9 +522,9 @@ int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
*sequenceNumber = 0;
yaffs_ReadChunkFromNAND(dev, blockNo * dev->param.nChunksPerBlock, NULL,
yaffs_ReadChunkFromNAND(dev, blockNo * dev->nChunksPerBlock, NULL,
&spare0, &dummy, 1);
yaffs_ReadChunkFromNAND(dev, blockNo * dev->param.nChunksPerBlock + 1, NULL,
yaffs_ReadChunkFromNAND(dev, blockNo * dev->nChunksPerBlock + 1, NULL,
&spare1, &dummy, 1);
if (yaffs_CountBits(spare0.blockStatus & spare1.blockStatus) < 7)

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>

View File

@ -1,60 +0,0 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1 as
* published by the Free Software Foundation.
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*/
#ifndef __YTRACE_H__
#define __YTRACE_H__
extern unsigned int yaffs_traceMask;
extern unsigned int yaffs_wr_attempts;
/*
* Tracing flags.
* The flags masked in YAFFS_TRACE_ALWAYS are always traced.
*/
#define YAFFS_TRACE_OS 0x00000002
#define YAFFS_TRACE_ALLOCATE 0x00000004
#define YAFFS_TRACE_SCAN 0x00000008
#define YAFFS_TRACE_BAD_BLOCKS 0x00000010
#define YAFFS_TRACE_ERASE 0x00000020
#define YAFFS_TRACE_GC 0x00000040
#define YAFFS_TRACE_WRITE 0x00000080
#define YAFFS_TRACE_TRACING 0x00000100
#define YAFFS_TRACE_DELETION 0x00000200
#define YAFFS_TRACE_BUFFERS 0x00000400
#define YAFFS_TRACE_NANDACCESS 0x00000800
#define YAFFS_TRACE_GC_DETAIL 0x00001000
#define YAFFS_TRACE_SCAN_DEBUG 0x00002000
#define YAFFS_TRACE_MTD 0x00004000
#define YAFFS_TRACE_CHECKPOINT 0x00008000
#define YAFFS_TRACE_VERIFY 0x00010000
#define YAFFS_TRACE_VERIFY_NAND 0x00020000
#define YAFFS_TRACE_VERIFY_FULL 0x00040000
#define YAFFS_TRACE_VERIFY_ALL 0x000F0000
#define YAFFS_TRACE_SYNC 0x00100000
#define YAFFS_TRACE_BACKGROUND 0x00200000
#define YAFFS_TRACE_LOCK 0x00400000
#define YAFFS_TRACE_ERROR 0x40000000
#define YAFFS_TRACE_BUG 0x80000000
#define YAFFS_TRACE_ALWAYS 0xF0000000
#define T(mask, p) do { if ((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p); } while (0)
#endif

View File

@ -1,626 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "yaffs_verify.h"
#include "yaffs_trace.h"
#include "yaffs_bitmap.h"
#include "yaffs_getblockinfo.h"
#include "yaffs_nand.h"
int yaffs_SkipVerification(yaffs_Device *dev)
{
dev=dev;
return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
}
static int yaffs_SkipFullVerification(yaffs_Device *dev)
{
dev=dev;
return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_FULL));
}
static int yaffs_SkipNANDVerification(yaffs_Device *dev)
{
dev=dev;
return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND));
}
static const char *blockStateName[] = {
"Unknown",
"Needs scanning",
"Scanning",
"Empty",
"Allocating",
"Full",
"Dirty",
"Checkpoint",
"Collecting",
"Dead"
};
void yaffs_VerifyBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n)
{
int actuallyUsed;
int inUse;
if (yaffs_SkipVerification(dev))
return;
/* Report illegal runtime states */
if (bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES)
T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has undefined state %d"TENDSTR), n, bi->blockState));
switch (bi->blockState) {
case YAFFS_BLOCK_STATE_UNKNOWN:
case YAFFS_BLOCK_STATE_SCANNING:
case YAFFS_BLOCK_STATE_NEEDS_SCANNING:
T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has bad run-state %s"TENDSTR),
n, blockStateName[bi->blockState]));
}
/* Check pages in use and soft deletions are legal */
actuallyUsed = bi->pagesInUse - bi->softDeletions;
if (bi->pagesInUse < 0 || bi->pagesInUse > dev->param.nChunksPerBlock ||
bi->softDeletions < 0 || bi->softDeletions > dev->param.nChunksPerBlock ||
actuallyUsed < 0 || actuallyUsed > dev->param.nChunksPerBlock)
T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has illegal values pagesInUsed %d softDeletions %d"TENDSTR),
n, bi->pagesInUse, bi->softDeletions));
/* Check chunk bitmap legal */
inUse = yaffs_CountChunkBits(dev, n);
if (inUse != bi->pagesInUse)
T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has inconsistent values pagesInUse %d counted chunk bits %d"TENDSTR),
n, bi->pagesInUse, inUse));
}
void yaffs_VerifyCollectedBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n)
{
yaffs_VerifyBlock(dev, bi, n);
/* After collection the block should be in the erased state */
if (bi->blockState != YAFFS_BLOCK_STATE_COLLECTING &&
bi->blockState != YAFFS_BLOCK_STATE_EMPTY) {
T(YAFFS_TRACE_ERROR, (TSTR("Block %d is in state %d after gc, should be erased"TENDSTR),
n, bi->blockState));
}
}
void yaffs_VerifyBlocks(yaffs_Device *dev)
{
int i;
int nBlocksPerState[YAFFS_NUMBER_OF_BLOCK_STATES];
int nIllegalBlockStates = 0;
if (yaffs_SkipVerification(dev))
return;
memset(nBlocksPerState, 0, sizeof(nBlocksPerState));
for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i);
yaffs_VerifyBlock(dev, bi, i);
if (bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES)
nBlocksPerState[bi->blockState]++;
else
nIllegalBlockStates++;
}
T(YAFFS_TRACE_VERIFY, (TSTR(""TENDSTR)));
T(YAFFS_TRACE_VERIFY, (TSTR("Block summary"TENDSTR)));
T(YAFFS_TRACE_VERIFY, (TSTR("%d blocks have illegal states"TENDSTR), nIllegalBlockStates));
if (nBlocksPerState[YAFFS_BLOCK_STATE_ALLOCATING] > 1)
T(YAFFS_TRACE_VERIFY, (TSTR("Too many allocating blocks"TENDSTR)));
for (i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++)
T(YAFFS_TRACE_VERIFY,
(TSTR("%s %d blocks"TENDSTR),
blockStateName[i], nBlocksPerState[i]));
if (dev->blocksInCheckpoint != nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT])
T(YAFFS_TRACE_VERIFY,
(TSTR("Checkpoint block count wrong dev %d count %d"TENDSTR),
dev->blocksInCheckpoint, nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT]));
if (dev->nErasedBlocks != nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY])
T(YAFFS_TRACE_VERIFY,
(TSTR("Erased block count wrong dev %d count %d"TENDSTR),
dev->nErasedBlocks, nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY]));
if (nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING] > 1)
T(YAFFS_TRACE_VERIFY,
(TSTR("Too many collecting blocks %d (max is 1)"TENDSTR),
nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING]));
T(YAFFS_TRACE_VERIFY, (TSTR(""TENDSTR)));
}
/*
* Verify the object header. oh must be valid, but obj and tags may be NULL in which
* case those tests will not be performed.
*/
void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck)
{
if (obj && yaffs_SkipVerification(obj->myDev))
return;
if (!(tags && obj && oh)) {
T(YAFFS_TRACE_VERIFY,
(TSTR("Verifying object header tags %p obj %p oh %p"TENDSTR),
tags, obj, oh));
return;
}
if (oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN ||
oh->type > YAFFS_OBJECT_TYPE_MAX)
T(YAFFS_TRACE_VERIFY,
(TSTR("Obj %d header type is illegal value 0x%x"TENDSTR),
tags->objectId, oh->type));
if (tags->objectId != obj->objectId)
T(YAFFS_TRACE_VERIFY,
(TSTR("Obj %d header mismatch objectId %d"TENDSTR),
tags->objectId, obj->objectId));
/*
* Check that the object's parent ids match if parentCheck requested.
*
* Tests do not apply to the root object.
*/
if (parentCheck && tags->objectId > 1 && !obj->parent)
T(YAFFS_TRACE_VERIFY,
(TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR),
tags->objectId, oh->parentObjectId));
if (parentCheck && obj->parent &&
oh->parentObjectId != obj->parent->objectId &&
(oh->parentObjectId != YAFFS_OBJECTID_UNLINKED ||
obj->parent->objectId != YAFFS_OBJECTID_DELETED))
T(YAFFS_TRACE_VERIFY,
(TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR),
tags->objectId, oh->parentObjectId, obj->parent->objectId));
if (tags->objectId > 1 && oh->name[0] == 0) /* Null name */
T(YAFFS_TRACE_VERIFY,
(TSTR("Obj %d header name is NULL"TENDSTR),
obj->objectId));
if (tags->objectId > 1 && ((__u8)(oh->name[0])) == 0xff) /* Trashed name */
T(YAFFS_TRACE_VERIFY,
(TSTR("Obj %d header name is 0xFF"TENDSTR),
obj->objectId));
}
#if 0
/* Not being used, but don't want to throw away yet */
int yaffs_VerifyTnodeWorker(yaffs_Object *obj, yaffs_Tnode *tn,
__u32 level, int chunkOffset)
{
int i;
yaffs_Device *dev = obj->myDev;
int ok = 1;
if (tn) {
if (level > 0) {
for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) {
if (tn->internal[i]) {
ok = yaffs_VerifyTnodeWorker(obj,
tn->internal[i],
level - 1,
(chunkOffset<<YAFFS_TNODES_INTERNAL_BITS) + i);
}
}
} else if (level == 0) {
yaffs_ExtendedTags tags;
__u32 objectId = obj->objectId;
chunkOffset <<= YAFFS_TNODES_LEVEL0_BITS;
for (i = 0; i < YAFFS_NTNODES_LEVEL0; i++) {
__u32 theChunk = yaffs_GetChunkGroupBase(dev, tn, i);
if (theChunk > 0) {
/* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),tags.objectId,tags.chunkId,theChunk)); */
yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL, &tags);
if (tags.objectId != objectId || tags.chunkId != chunkOffset) {
T(~0, (TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR),
objectId, chunkOffset, theChunk,
tags.objectId, tags.chunkId));
}
}
chunkOffset++;
}
}
}
return ok;
}
#endif
void yaffs_VerifyFile(yaffs_Object *obj)
{
int requiredTallness;
int actualTallness;
__u32 lastChunk;
__u32 x;
__u32 i;
yaffs_Device *dev;
yaffs_ExtendedTags tags;
yaffs_Tnode *tn;
__u32 objectId;
if (!obj)
return;
if (yaffs_SkipVerification(obj->myDev))
return;
dev = obj->myDev;
objectId = obj->objectId;
/* Check file size is consistent with tnode depth */
lastChunk = obj->variant.fileVariant.fileSize / dev->nDataBytesPerChunk + 1;
x = lastChunk >> YAFFS_TNODES_LEVEL0_BITS;
requiredTallness = 0;
while (x > 0) {
x >>= YAFFS_TNODES_INTERNAL_BITS;
requiredTallness++;
}
actualTallness = obj->variant.fileVariant.topLevel;
/* Check that the chunks in the tnode tree are all correct.
* We do this by scanning through the tnode tree and
* checking the tags for every chunk match.
*/
if (yaffs_SkipNANDVerification(dev))
return;
for (i = 1; i <= lastChunk; i++) {
tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant, i);
if (tn) {
__u32 theChunk = yaffs_GetChunkGroupBase(dev, tn, i);
if (theChunk > 0) {
/* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),objectId,i,theChunk)); */
yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL, &tags);
if (tags.objectId != objectId || tags.chunkId != i) {
T(~0, (TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR),
objectId, i, theChunk,
tags.objectId, tags.chunkId));
}
}
}
}
}
void yaffs_VerifyHardLink(yaffs_Object *obj)
{
if (obj && yaffs_SkipVerification(obj->myDev))
return;
/* Verify sane equivalent object */
}
void yaffs_VerifySymlink(yaffs_Object *obj)
{
if (obj && yaffs_SkipVerification(obj->myDev))
return;
/* Verify symlink string */
}
void yaffs_VerifySpecial(yaffs_Object *obj)
{
if (obj && yaffs_SkipVerification(obj->myDev))
return;
}
void yaffs_VerifyObject(yaffs_Object *obj)
{
yaffs_Device *dev;
__u32 chunkMin;
__u32 chunkMax;
__u32 chunkIdOk;
__u32 chunkInRange;
__u32 chunkShouldNotBeDeleted;
__u32 chunkValid;
if (!obj)
return;
if (obj->beingCreated)
return;
dev = obj->myDev;
if (yaffs_SkipVerification(dev))
return;
/* Check sane object header chunk */
chunkMin = dev->internalStartBlock * dev->param.nChunksPerBlock;
chunkMax = (dev->internalEndBlock+1) * dev->param.nChunksPerBlock - 1;
chunkInRange = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax);
chunkIdOk = chunkInRange || (obj->hdrChunk == 0);
chunkValid = chunkInRange &&
yaffs_CheckChunkBit(dev,
obj->hdrChunk / dev->param.nChunksPerBlock,
obj->hdrChunk % dev->param.nChunksPerBlock);
chunkShouldNotBeDeleted = chunkInRange && !chunkValid;
if (!obj->fake &&
(!chunkIdOk || chunkShouldNotBeDeleted)) {
T(YAFFS_TRACE_VERIFY,
(TSTR("Obj %d has chunkId %d %s %s"TENDSTR),
obj->objectId, obj->hdrChunk,
chunkIdOk ? "" : ",out of range",
chunkShouldNotBeDeleted ? ",marked as deleted" : ""));
}
if (chunkValid && !yaffs_SkipNANDVerification(dev)) {
yaffs_ExtendedTags tags;
yaffs_ObjectHeader *oh;
__u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);
oh = (yaffs_ObjectHeader *)buffer;
yaffs_ReadChunkWithTagsFromNAND(dev, obj->hdrChunk, buffer,
&tags);
yaffs_VerifyObjectHeader(obj, oh, &tags, 1);
yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
}
/* Verify it has a parent */
if (obj && !obj->fake &&
(!obj->parent || obj->parent->myDev != dev)) {
T(YAFFS_TRACE_VERIFY,
(TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR),
obj->objectId, obj->parent));
}
/* Verify parent is a directory */
if (obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
T(YAFFS_TRACE_VERIFY,
(TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR),
obj->objectId, obj->parent->variantType));
}
switch (obj->variantType) {
case YAFFS_OBJECT_TYPE_FILE:
yaffs_VerifyFile(obj);
break;
case YAFFS_OBJECT_TYPE_SYMLINK:
yaffs_VerifySymlink(obj);
break;
case YAFFS_OBJECT_TYPE_DIRECTORY:
yaffs_VerifyDirectory(obj);
break;
case YAFFS_OBJECT_TYPE_HARDLINK:
yaffs_VerifyHardLink(obj);
break;
case YAFFS_OBJECT_TYPE_SPECIAL:
yaffs_VerifySpecial(obj);
break;
case YAFFS_OBJECT_TYPE_UNKNOWN:
default:
T(YAFFS_TRACE_VERIFY,
(TSTR("Obj %d has illegaltype %d"TENDSTR),
obj->objectId, obj->variantType));
break;
}
}
void yaffs_VerifyObjects(yaffs_Device *dev)
{
yaffs_Object *obj;
int i;
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++) {
ylist_for_each(lh, &dev->objectBucket[i].list) {
if (lh) {
obj = ylist_entry(lh, yaffs_Object, hashLink);
yaffs_VerifyObject(obj);
}
}
}
}
void yaffs_VerifyObjectInDirectory(yaffs_Object *obj)
{
struct ylist_head *lh;
yaffs_Object *listObj;
int count = 0;
if (!obj) {
T(YAFFS_TRACE_ALWAYS, (TSTR("No object to verify" TENDSTR)));
YBUG();
return;
}
if (yaffs_SkipVerification(obj->myDev))
return;
if (!obj->parent) {
T(YAFFS_TRACE_ALWAYS, (TSTR("Object does not have parent" TENDSTR)));
YBUG();
return;
}
if (obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
T(YAFFS_TRACE_ALWAYS, (TSTR("Parent is not directory" TENDSTR)));
YBUG();
}
/* Iterate through the objects in each hash entry */
ylist_for_each(lh, &obj->parent->variant.directoryVariant.children) {
if (lh) {
listObj = ylist_entry(lh, yaffs_Object, siblings);
yaffs_VerifyObject(listObj);
if (obj == listObj)
count++;
}
}
if (count != 1) {
T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory %d times" TENDSTR), count));
YBUG();
}
}
void yaffs_VerifyDirectory(yaffs_Object *directory)
{
struct ylist_head *lh;
yaffs_Object *listObj;
if (!directory) {
YBUG();
return;
}
if (yaffs_SkipFullVerification(directory->myDev))
return;
if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
T(YAFFS_TRACE_ALWAYS, (TSTR("Directory has wrong type: %d" TENDSTR), directory->variantType));
YBUG();
}
/* Iterate through the objects in each hash entry */
ylist_for_each(lh, &directory->variant.directoryVariant.children) {
if (lh) {
listObj = ylist_entry(lh, yaffs_Object, siblings);
if (listObj->parent != directory) {
T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory list has wrong parent %p" TENDSTR), listObj->parent));
YBUG();
}
yaffs_VerifyObjectInDirectory(listObj);
}
}
}
static int yaffs_freeVerificationFailures;
void yaffs_VerifyFreeChunks(yaffs_Device *dev)
{
int counted;
int difference;
if (yaffs_SkipVerification(dev))
return;
counted = yaffs_CountFreeChunks(dev);
difference = dev->nFreeChunks - counted;
if (difference) {
T(YAFFS_TRACE_ALWAYS,
(TSTR("Freechunks verification failure %d %d %d" TENDSTR),
dev->nFreeChunks, counted, difference));
yaffs_freeVerificationFailures++;
}
}
int yaffs_VerifyFileSanity(yaffs_Object *in)
{
#if 0
int chunk;
int nChunks;
int fSize;
int failed = 0;
int objId;
yaffs_Tnode *tn;
yaffs_Tags localTags;
yaffs_Tags *tags = &localTags;
int theChunk;
int chunkDeleted;
if (in->variantType != YAFFS_OBJECT_TYPE_FILE)
return YAFFS_FAIL;
objId = in->objectId;
fSize = in->variant.fileVariant.fileSize;
nChunks =
(fSize + in->myDev->nDataBytesPerChunk - 1) / in->myDev->nDataBytesPerChunk;
for (chunk = 1; chunk <= nChunks; chunk++) {
tn = yaffs_FindLevel0Tnode(in->myDev, &in->variant.fileVariant,
chunk);
if (tn) {
theChunk = yaffs_GetChunkGroupBase(dev, tn, chunk);
if (yaffs_CheckChunkBits
(dev, theChunk / dev->param.nChunksPerBlock,
theChunk % dev->param.nChunksPerBlock)) {
yaffs_ReadChunkTagsFromNAND(in->myDev, theChunk,
tags,
&chunkDeleted);
if (yaffs_TagsMatch
(tags, in->objectId, chunk, chunkDeleted)) {
/* found it; */
}
} else {
failed = 1;
}
} else {
/* T(("No level 0 found for %d\n", chunk)); */
}
}
return failed ? YAFFS_FAIL : YAFFS_OK;
#else
in=in;
return YAFFS_OK;
#endif
}

View File

@ -1,39 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __YAFFS_VERIFY_H__
#define __YAFFS_VERIFY_H__
#include "yaffs_guts.h"
void yaffs_VerifyBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n);
void yaffs_VerifyCollectedBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n);
void yaffs_VerifyBlocks(yaffs_Device *dev);
void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck);
void yaffs_VerifyFile(yaffs_Object *obj);
void yaffs_VerifyHardLink(yaffs_Object *obj);
void yaffs_VerifySymlink(yaffs_Object *obj);
void yaffs_VerifySpecial(yaffs_Object *obj);
void yaffs_VerifyObject(yaffs_Object *obj);
void yaffs_VerifyObjects(yaffs_Device *dev);
void yaffs_VerifyObjectInDirectory(yaffs_Object *obj);
void yaffs_VerifyDirectory(yaffs_Object *directory);
void yaffs_VerifyFreeChunks(yaffs_Device *dev);
int yaffs_VerifyFileSanity(yaffs_Object *obj);
int yaffs_SkipVerification(yaffs_Device *dev);
#endif

View File

@ -1,465 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "yaffs_yaffs1.h"
#include "yportenv.h"
#include "yaffs_trace.h"
#include "yaffs_bitmap.h"
#include "yaffs_getblockinfo.h"
#include "yaffs_nand.h"
int yaffs1_Scan(yaffs_Device *dev)
{
yaffs_ExtendedTags tags;
int blk;
int blockIterator;
int startIterator;
int endIterator;
int result;
int chunk;
int c;
int deleted;
yaffs_BlockState state;
yaffs_Object *hardList = NULL;
yaffs_BlockInfo *bi;
__u32 sequenceNumber;
yaffs_ObjectHeader *oh;
yaffs_Object *in;
yaffs_Object *parent;
int alloc_failed = 0;
struct yaffs_ShadowFixerStruct *shadowFixerList = NULL;
__u8 *chunkData;
T(YAFFS_TRACE_SCAN,
(TSTR("yaffs1_Scan starts intstartblk %d intendblk %d..." TENDSTR),
dev->internalStartBlock, dev->internalEndBlock));
chunkData = yaffs_GetTempBuffer(dev, __LINE__);
dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
/* Scan all the blocks to determine their state */
bi = dev->blockInfo;
for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
yaffs_ClearChunkBits(dev, blk);
bi->pagesInUse = 0;
bi->softDeletions = 0;
yaffs_QueryInitialBlockState(dev, blk, &state, &sequenceNumber);
bi->blockState = state;
bi->sequenceNumber = sequenceNumber;
if (bi->sequenceNumber == YAFFS_SEQUENCE_BAD_BLOCK)
bi->blockState = state = YAFFS_BLOCK_STATE_DEAD;
T(YAFFS_TRACE_SCAN_DEBUG,
(TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
state, sequenceNumber));
if (state == YAFFS_BLOCK_STATE_DEAD) {
T(YAFFS_TRACE_BAD_BLOCKS,
(TSTR("block %d is bad" TENDSTR), blk));
} else if (state == YAFFS_BLOCK_STATE_EMPTY) {
T(YAFFS_TRACE_SCAN_DEBUG,
(TSTR("Block empty " TENDSTR)));
dev->nErasedBlocks++;
dev->nFreeChunks += dev->param.nChunksPerBlock;
}
bi++;
}
startIterator = dev->internalStartBlock;
endIterator = dev->internalEndBlock;
/* For each block.... */
for (blockIterator = startIterator; !alloc_failed && blockIterator <= endIterator;
blockIterator++) {
YYIELD();
YYIELD();
blk = blockIterator;
bi = yaffs_GetBlockInfo(dev, blk);
state = bi->blockState;
deleted = 0;
/* For each chunk in each block that needs scanning....*/
for (c = 0; !alloc_failed && c < dev->param.nChunksPerBlock &&
state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) {
/* Read the tags and decide what to do */
chunk = blk * dev->param.nChunksPerBlock + c;
result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
&tags);
/* Let's have a good look at this chunk... */
if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED || tags.chunkDeleted) {
/* YAFFS1 only...
* A deleted chunk
*/
deleted++;
dev->nFreeChunks++;
/*T((" %d %d deleted\n",blk,c)); */
} else if (!tags.chunkUsed) {
/* An unassigned chunk in the block
* This means that either the block is empty or
* this is the one being allocated from
*/
if (c == 0) {
/* We're looking at the first chunk in the block so the block is unused */
state = YAFFS_BLOCK_STATE_EMPTY;
dev->nErasedBlocks++;
} else {
/* this is the block being allocated from */
T(YAFFS_TRACE_SCAN,
(TSTR
(" Allocating from %d %d" TENDSTR),
blk, c));
state = YAFFS_BLOCK_STATE_ALLOCATING;
dev->allocationBlock = blk;
dev->allocationPage = c;
dev->allocationBlockFinder = blk;
/* Set block finder here to encourage the allocator to go forth from here. */
}
dev->nFreeChunks += (dev->param.nChunksPerBlock - c);
} else if (tags.chunkId > 0) {
/* chunkId > 0 so it is a data chunk... */
unsigned int endpos;
yaffs_SetChunkBit(dev, blk, c);
bi->pagesInUse++;
in = yaffs_FindOrCreateObjectByNumber(dev,
tags.
objectId,
YAFFS_OBJECT_TYPE_FILE);
/* PutChunkIntoFile checks for a clash (two data chunks with
* the same chunkId).
*/
if (!in)
alloc_failed = 1;
if (in) {
if (!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk, 1))
alloc_failed = 1;
}
endpos =
(tags.chunkId - 1) * dev->nDataBytesPerChunk +
tags.byteCount;
if (in &&
in->variantType == YAFFS_OBJECT_TYPE_FILE
&& in->variant.fileVariant.scannedFileSize <
endpos) {
in->variant.fileVariant.
scannedFileSize = endpos;
if (!dev->param.useHeaderFileSize) {
in->variant.fileVariant.
fileSize =
in->variant.fileVariant.
scannedFileSize;
}
}
/* T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId)); */
} else {
/* chunkId == 0, so it is an ObjectHeader.
* Thus, we read in the object header and make the object
*/
yaffs_SetChunkBit(dev, blk, c);
bi->pagesInUse++;
result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk,
chunkData,
NULL);
oh = (yaffs_ObjectHeader *) chunkData;
in = yaffs_FindObjectByNumber(dev,
tags.objectId);
if (in && in->variantType != oh->type) {
/* This should not happen, but somehow
* Wev'e ended up with an objectId that has been reused but not yet
* deleted, and worse still it has changed type. Delete the old object.
*/
yaffs_DeleteObject(in);
in = 0;
}
in = yaffs_FindOrCreateObjectByNumber(dev,
tags.
objectId,
oh->type);
if (!in)
alloc_failed = 1;
if (in && oh->shadowsObject > 0) {
struct yaffs_ShadowFixerStruct *fixer;
fixer = YMALLOC(sizeof(struct yaffs_ShadowFixerStruct));
if (fixer) {
fixer->next = shadowFixerList;
shadowFixerList = fixer;
fixer->objectId = tags.objectId;
fixer->shadowedId = oh->shadowsObject;
T(YAFFS_TRACE_SCAN,
(TSTR
(" Shadow fixer: %d shadows %d" TENDSTR),
fixer->objectId, fixer->shadowedId));
}
}
if (in && in->valid) {
/* We have already filled this one. We have a duplicate and need to resolve it. */
unsigned existingSerial = in->serial;
unsigned newSerial = tags.serialNumber;
if (((existingSerial + 1) & 3) == newSerial) {
/* Use new one - destroy the exisiting one */
yaffs_DeleteChunk(dev,
in->hdrChunk,
1, __LINE__);
in->valid = 0;
} else {
/* Use existing - destroy this one. */
yaffs_DeleteChunk(dev, chunk, 1,
__LINE__);
}
}
if (in && !in->valid &&
(tags.objectId == YAFFS_OBJECTID_ROOT ||
tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) {
/* We only load some info, don't fiddle with directory structure */
in->valid = 1;
in->variantType = oh->type;
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
in->hdrChunk = chunk;
in->serial = tags.serialNumber;
} else if (in && !in->valid) {
/* we need to load this info */
in->valid = 1;
in->variantType = oh->type;
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
in->hdrChunk = chunk;
in->serial = tags.serialNumber;
yaffs_SetObjectNameFromOH(in, oh);
in->dirty = 0;
/* directory stuff...
* hook up to parent
*/
parent =
yaffs_FindOrCreateObjectByNumber
(dev, oh->parentObjectId,
YAFFS_OBJECT_TYPE_DIRECTORY);
if (!parent)
alloc_failed = 1;
if (parent && parent->variantType ==
YAFFS_OBJECT_TYPE_UNKNOWN) {
/* Set up as a directory */
parent->variantType =
YAFFS_OBJECT_TYPE_DIRECTORY;
YINIT_LIST_HEAD(&parent->variant.
directoryVariant.
children);
} else if (!parent || parent->variantType !=
YAFFS_OBJECT_TYPE_DIRECTORY) {
/* Hoosterman, another problem....
* We're trying to use a non-directory as a directory
*/
T(YAFFS_TRACE_ERROR,
(TSTR
("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
TENDSTR)));
parent = dev->lostNFoundDir;
}
yaffs_AddObjectToDirectory(parent, in);
if (0 && (parent == dev->deletedDir ||
parent == dev->unlinkedDir)) {
in->deleted = 1; /* If it is unlinked at start up then it wants deleting */
dev->nDeletedFiles++;
}
/* Note re hardlinks.
* Since we might scan a hardlink before its equivalent object is scanned
* we put them all in a list.
* After scanning is complete, we should have all the objects, so we run through this
* list and fix up all the chains.
*/
switch (in->variantType) {
case YAFFS_OBJECT_TYPE_UNKNOWN:
/* Todo got a problem */
break;
case YAFFS_OBJECT_TYPE_FILE:
if (dev->param.useHeaderFileSize)
in->variant.fileVariant.
fileSize =
oh->fileSize;
break;
case YAFFS_OBJECT_TYPE_HARDLINK:
in->variant.hardLinkVariant.
equivalentObjectId =
oh->equivalentObjectId;
in->hardLinks.next =
(struct ylist_head *)
hardList;
hardList = in;
break;
case YAFFS_OBJECT_TYPE_DIRECTORY:
/* Do nothing */
break;
case YAFFS_OBJECT_TYPE_SPECIAL:
/* Do nothing */
break;
case YAFFS_OBJECT_TYPE_SYMLINK:
in->variant.symLinkVariant.alias =
yaffs_CloneString(oh->alias);
if (!in->variant.symLinkVariant.alias)
alloc_failed = 1;
break;
}
}
}
}
if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
/* If we got this far while scanning, then the block is fully allocated.*/
state = YAFFS_BLOCK_STATE_FULL;
}
if (state == YAFFS_BLOCK_STATE_ALLOCATING) {
/* If the block was partially allocated then treat it as fully allocated.*/
state = YAFFS_BLOCK_STATE_FULL;
dev->allocationBlock = -1;
}
bi->blockState = state;
/* Now let's see if it was dirty */
if (bi->pagesInUse == 0 &&
!bi->hasShrinkHeader &&
bi->blockState == YAFFS_BLOCK_STATE_FULL) {
yaffs_BlockBecameDirty(dev, blk);
}
}
/* Ok, we've done all the scanning.
* Fix up the hard link chains.
* We should now have scanned all the objects, now it's time to add these
* hardlinks.
*/
yaffs_HardlinkFixup(dev, hardList);
/* Fix up any shadowed objects */
{
struct yaffs_ShadowFixerStruct *fixer;
yaffs_Object *obj;
while (shadowFixerList) {
fixer = shadowFixerList;
shadowFixerList = fixer->next;
/* Complete the rename transaction by deleting the shadowed object
* then setting the object header to unshadowed.
*/
obj = yaffs_FindObjectByNumber(dev, fixer->shadowedId);
if (obj)
yaffs_DeleteObject(obj);
obj = yaffs_FindObjectByNumber(dev, fixer->objectId);
if (obj)
yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0, NULL);
YFREE(fixer);
}
}
yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
if (alloc_failed)
return YAFFS_FAIL;
T(YAFFS_TRACE_SCAN, (TSTR("yaffs1_Scan ends" TENDSTR)));
return YAFFS_OK;
}

View File

@ -1,22 +0,0 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1 as
* published by the Free Software Foundation.
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*/
#ifndef __YAFFS_YAFFS1_H__
#define __YAFFS_YAFFS1_H__
#include "yaffs_guts.h"
int yaffs1_Scan(yaffs_Device *dev);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,36 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __YAFFS_YAFFS2_H__
#define __YAFFS_YAFFS2_H__
#include "yaffs_guts.h"
void yaffs2_CalcOldestDirtySequence(yaffs_Device *dev);
void yaffs2_FindOldestDirtySequence(yaffs_Device *dev);
void yaffs2_ClearOldestDirtySequence(yaffs_Device *dev, yaffs_BlockInfo *bi);
void yaffs2_UpdateOldestDirtySequence(yaffs_Device *dev, unsigned blockNo, yaffs_BlockInfo *bi);
int yaffs2_BlockNotDisqualifiedFromGC(yaffs_Device *dev, yaffs_BlockInfo *bi);
__u32 yaffs2_FindRefreshBlock(yaffs_Device *dev);
int yaffs2_CheckpointRequired(yaffs_Device *dev);
int yaffs2_CalcCheckpointBlocksRequired(yaffs_Device *dev);
void yaffs2_InvalidateCheckpoint(yaffs_Device *dev);
int yaffs2_CheckpointSave(yaffs_Device *dev);
int yaffs2_CheckpointRestore(yaffs_Device *dev);
int yaffs2_HandleHole(yaffs_Object *obj, loff_t newSize);
int yaffs2_ScanBackwards(yaffs_Device *dev);
#endif

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>

View File

@ -1,7 +1,7 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2010 Aleph One Ltd.
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
@ -41,14 +41,12 @@
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
#include <linux/config.h>
#endif
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/xattr.h>
#define YCHAR char
#define YUCHAR unsigned char
@ -57,11 +55,11 @@
#define yaffs_strcpy(a, b) strcpy(a, b)
#define yaffs_strncpy(a, b, c) strncpy(a, b, c)
#define yaffs_strncmp(a, b, c) strncmp(a, b, c)
#define yaffs_strnlen(s,m) strnlen(s,m)
#define yaffs_strlen(s) strlen(s)
#define yaffs_sprintf sprintf
#define yaffs_toupper(a) toupper(a)
#define Y_INLINE __inline__
#define Y_INLINE inline
#define YAFFS_LOSTNFOUND_NAME "lost+found"
#define YAFFS_LOSTNFOUND_PREFIX "obj"
@ -73,11 +71,11 @@
#define YFREE_ALT(x) vfree(x)
#define YMALLOC_DMA(x) YMALLOC(x)
/* KR - added for use in scan so processes aren't blocked indefinitely. */
#define YYIELD() schedule()
#define Y_DUMP_STACK() dump_stack()
#define YAFFS_ROOT_MODE 0755
#define YAFFS_LOSTNFOUND_MODE 0700
#define YAFFS_ROOT_MODE 0666
#define YAFFS_LOSTNFOUND_MODE 0666
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
#define Y_CURRENT_TIME CURRENT_TIME.tv_sec
@ -91,10 +89,15 @@
#define yaffs_strcmp(a, b) strcmp(a, b)
#define TENDSTR "\n"
#define TSTR(x) KERN_DEBUG x
#define TSTR(x) KERN_WARNING x
#define TCONT(x) x
#define TOUT(p) printk p
#define yaffs_trace(mask, fmt, args...) \
do { if ((mask) & (yaffs_traceMask|YAFFS_TRACE_ERROR)) \
printk(KERN_WARNING "yaffs: " fmt, ## args); \
} while (0)
#define compile_time_assertion(assertion) \
({ int x = __builtin_choose_expr(assertion, 0, (void)0); (void) x; })
@ -113,6 +116,7 @@
#include "stdio.h"
#include "string.h"
#include "devextras.h"
#define YMALLOC(x) malloc(x)
#define YFREE(x) free(x)
@ -125,7 +129,7 @@
#define yaffs_strcat(a, b) strcat(a, b)
#define yaffs_strcpy(a, b) strcpy(a, b)
#define yaffs_strncpy(a, b, c) strncpy(a, b, c)
#define yaffs_strnlen(s,m) strnlen(s,m)
#define yaffs_strlen(s) strlen(s)
#define yaffs_sprintf sprintf
#define yaffs_toupper(a) toupper(a)
@ -142,8 +146,8 @@
#define YAFFS_LOSTNFOUND_PREFIX "obj"
/* #define YPRINTF(x) printf x */
#define YAFFS_ROOT_MODE 0755
#define YAFFS_LOSTNFOUND_MODE 0700
#define YAFFS_ROOT_MODE 0666
#define YAFFS_LOSTNFOUND_MODE 0666
#define yaffs_SumCompare(x, y) ((x) == (y))
#define yaffs_strcmp(a, b) strcmp(a, b)
@ -154,180 +158,46 @@
#endif
#if defined(CONFIG_YAFFS_DIRECT) || defined(CONFIG_YAFFS_WINCE)
/* see yaffs_fs.c */
extern unsigned int yaffs_traceMask;
extern unsigned int yaffs_wr_attempts;
#ifdef CONFIG_YAFFSFS_PROVIDE_VALUES
/*
* Tracing flags.
* The flags masked in YAFFS_TRACE_ALWAYS are always traced.
*/
#ifndef O_RDONLY
#define O_RDONLY 00
#endif
#define YAFFS_TRACE_OS 0x00000002
#define YAFFS_TRACE_ALLOCATE 0x00000004
#define YAFFS_TRACE_SCAN 0x00000008
#define YAFFS_TRACE_BAD_BLOCKS 0x00000010
#define YAFFS_TRACE_ERASE 0x00000020
#define YAFFS_TRACE_GC 0x00000040
#define YAFFS_TRACE_WRITE 0x00000080
#define YAFFS_TRACE_TRACING 0x00000100
#define YAFFS_TRACE_DELETION 0x00000200
#define YAFFS_TRACE_BUFFERS 0x00000400
#define YAFFS_TRACE_NANDACCESS 0x00000800
#define YAFFS_TRACE_GC_DETAIL 0x00001000
#define YAFFS_TRACE_SCAN_DEBUG 0x00002000
#define YAFFS_TRACE_MTD 0x00004000
#define YAFFS_TRACE_CHECKPOINT 0x00008000
#ifndef O_WRONLY
#define O_WRONLY 01
#endif
#define YAFFS_TRACE_VERIFY 0x00010000
#define YAFFS_TRACE_VERIFY_NAND 0x00020000
#define YAFFS_TRACE_VERIFY_FULL 0x00040000
#define YAFFS_TRACE_VERIFY_ALL 0x000F0000
#define YAFFS_TRACE_HTC_DEBUG 0x00100000
#ifndef O_RDWR
#define O_RDWR 02
#endif
#ifndef O_CREAT
#define O_CREAT 0100
#endif
#ifndef O_EXCL
#define O_EXCL 0200
#endif
#ifndef O_TRUNC
#define O_TRUNC 01000
#endif
#ifndef O_APPEND
#define O_APPEND 02000
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef SEEK_END
#define SEEK_END 2
#endif
#ifndef EBUSY
#define EBUSY 16
#endif
#ifndef ENODEV
#define ENODEV 19
#endif
#ifndef EINVAL
#define EINVAL 22
#endif
#ifndef EBADF
#define EBADF 9
#endif
#ifndef EACCES
#define EACCES 13
#endif
#ifndef EXDEV
#define EXDEV 18
#endif
#ifndef ENOENT
#define ENOENT 2
#endif
#ifndef ENOSPC
#define ENOSPC 28
#endif
#ifndef ERANGE
#define ERANGE 34
#endif
#ifndef ENODATA
#define ENODATA 61
#endif
#ifndef ENOTEMPTY
#define ENOTEMPTY 39
#endif
#ifndef ENAMETOOLONG
#define ENAMETOOLONG 36
#endif
#ifndef ENOMEM
#define ENOMEM 12
#endif
#ifndef EEXIST
#define EEXIST 17
#endif
#ifndef ENOTDIR
#define ENOTDIR 20
#endif
#ifndef EISDIR
#define EISDIR 21
#endif
#define YAFFS_TRACE_ERROR 0x40000000
#define YAFFS_TRACE_BUG 0x80000000
#define YAFFS_TRACE_ALWAYS 0xF0000000
// Mode flags
#ifndef S_IFMT
#define S_IFMT 0170000
#endif
#ifndef S_IFLNK
#define S_IFLNK 0120000
#endif
#ifndef S_IFDIR
#define S_IFDIR 0040000
#endif
#ifndef S_IFREG
#define S_IFREG 0100000
#endif
#ifndef S_IREAD
#define S_IREAD 0000400
#endif
#ifndef S_IWRITE
#define S_IWRITE 0000200
#endif
#ifndef S_IEXEC
#define S_IEXEC 0000100
#endif
#ifndef XATTR_CREATE
#define XATTR_CREATE 1
#endif
#ifndef XATTR_REPLACE
#define XATTR_REPLACE 2
#endif
#ifndef R_OK
#define R_OK 4
#define W_OK 2
#define X_OK 1
#define F_OK 0
#endif
#else
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
#endif
#ifndef Y_DUMP_STACK
#define Y_DUMP_STACK() do { } while (0)
#endif
#define T(mask, p) do { if ((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p); } while (0)
#ifndef YBUG
#define YBUG() do {\
T(YAFFS_TRACE_BUG,\
(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),\
__LINE__));\
Y_DUMP_STACK();\
} while (0)
#define YBUG() do {T(YAFFS_TRACE_BUG, (TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR), __LINE__)); } while (0)
#endif
#endif