go back to using google's version of yaffs for higher stability
This commit is contained in:
parent
e7a2876f71
commit
e97d7c88a7
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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__)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
@ -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
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
@ -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
|
@ -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>
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user