/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
- * Copyright (C) 2002-2007 Aleph One Ltd.
+ * Copyright (C) 2002-2010 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
#ifndef __YAFFS_GUTS_H__
#define __YAFFS_GUTS_H__
-#include "devextras.h"
#include "yportenv.h"
+#include "devextras.h"
+#include "yaffs_list.h"
#define YAFFS_OK 1
#define YAFFS_FAIL 0
#define YAFFS_MAX_CHUNK_ID 0x000FFFFF
-#define YAFFS_UNUSED_OBJECT_ID 0x0003FFFF
#define YAFFS_ALLOCATION_NOBJECTS 100
#define YAFFS_ALLOCATION_NTNODES 100
#define YAFFS_OBJECT_SPACE 0x40000
+#define YAFFS_MAX_OBJECT_ID (YAFFS_OBJECT_SPACE -1)
-#define YAFFS_CHECKPOINT_VERSION 3
+#define YAFFS_CHECKPOINT_VERSION 4
#ifdef CONFIG_YAFFS_UNICODE
#define YAFFS_MAX_NAME_LENGTH 127
#define YAFFS_OBJECTID_UNLINKED 3
#define YAFFS_OBJECTID_DELETED 4
-/* Sseudo object ids for checkpointing */
+/* Pseudo 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
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;
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.
/* 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
+ * allocation. Should never be more than one of these.
+ * If a block is only partially allocated at mount it is treated as full.
*/
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,
- /* All pages have been allocated and deleted.
+ /* The block was full and now all chunks have been 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 */
/*--------------------------- 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:
typedef struct {
struct ylist_head children; /* list of child links */
+ struct ylist_head dirty; /* Entry for list of dirty directories */
} yaffs_DirectoryStructure;
typedef struct {
__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 serial; /* serial number of chunk in NAND. Cached here */
__u16 sum; /* sum of the name to speed searching */
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];
__u32 yst_rdev;
-#ifdef __KERNEL__
- struct inode *myInode;
-
-#endif
+ void *myInode;
yaffs_ObjectType variantType;
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;
/*----------------- 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.*/
- int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
+ /*
+ * 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 */
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 */
/* 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)
+ * the number of short op caches (don't use too many).
+ * 10 to 20 is a good bet.
*/
-
- int useHeaderFileSize; /* Flag to determine if we should use file sizes from the header */
-
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 disableLazyLoad; /* Disable lazy loading on this device */
- void *genericDevice; /* Pointer to device context
- * On an mtd this holds the mtd pointer.
- */
- void *superBlock;
+ int isYaffs2; /* Use yaffs2 mode on this device */
+
+ int emptyLostAndFound; /* Auto-empty lost+found directory on mount */
+
+ int refreshPeriod; /* How often we should check to do a block refresh */
+
+ /* Checkpoint control. Can be set before or after initialisation */
+ __u8 skipCheckpointRead;
+ __u8 skipCheckpointWrite;
+
+ int enableXattr; /* Enable xattribs */
/* NAND access functions (Must be set before calling YAFFS)*/
yaffs_BlockState *state, __u32 *sequenceNumber);
#endif
- int isYaffs2;
-
/* The removeObjectCallback function must be supplied by OS flavours that
- * need it. The Linux kernel does not use this, but yaffs direct does use
- * it to implement the faster readdir
+ * need it.
+ * yaffs direct uses it to implement the faster readdir.
+ * Linux uses it to protect the directory during unlocking.
*/
void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj);
- /* Callback to mark the superblock dirsty */
- void (*markSuperBlockDirty)(void *superblock);
+ /* Callback to mark the superblock dirty */
+ void (*markSuperBlockDirty)(struct yaffs_DeviceStruct *dev);
+
+ /* Callback to control garbage collection. */
+ unsigned (*gcControl)(struct yaffs_DeviceStruct *dev);
+ /* 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 */
- YCHAR *pathDividers; /* String of legal path dividers */
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+ int autoUnicode;
+#endif
+ int alwaysCheckErased; /* Force chunk erased check always on */
+};
+typedef struct yaffs_DeviceParamStruct yaffs_DeviceParam;
- /* End of stuff that must be set before initialisation. */
+struct yaffs_DeviceStruct {
+ struct yaffs_DeviceParamStruct param;
- /* Checkpoint control. Can be set before or after initialisation */
- __u8 skipCheckpointRead;
- __u8 skipCheckpointWrite;
+ /* Context storage. Holds extra OS specific data for this device */
+
+ void *osContext;
+ void *driverContext;
+
+ struct ylist_head devList;
/* Runtime parameters. Set up by YAFFS. */
+ int nDataBytesPerChunk;
- __u16 chunkGroupBits; /* 0 for devices <= 32MB. else log2(nchunks) - 16 */
+ /* Non-wide tnode stuff */
+ __u16 chunkGroupBits; /* Number of bits that need to be resolved if
+ * the tnodes are not wide enough.
+ */
__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 */
- __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);
-#endif
int isMounted;
-
+ int readOnly;
int isCheckpointed;
__u32 allocationPage;
int allocationBlockFinder; /* Used to search for next allocation block */
- /* 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;
+ /* Object and Tnode memory management */
+ void *allocator;
+ int nObjects;
+ int nTnodes;
int nHardLinks;
- yaffs_ObjectList *allocatedObjectList;
-
yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS];
+ __u32 bucketFinder;
int nFreeChunks;
- int currentDirtyChecker; /* Used to find current dirtiest block */
-
+ /* Garbage collection control */
__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 */
+ __u32 nCleanups;
+
+ 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;
/* Special directories */
yaffs_Object *rootDir;
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. */
int nUnlinkedFiles; /* Count of unlinked files. */
int nBackgroundDeletions; /* Count of background deletions. */
-
/* Temporary buffer management */
yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];
int maxTemp;
/* yaffs2 runtime stuff */
unsigned sequenceNumber; /* Sequence number of currently allocating block */
unsigned oldestDirtySequence;
-
- /* Auto empty lost and found directory on mount */
- int emptyLostAndFound;
+ 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;
+
};
typedef struct yaffs_DeviceStruct yaffs_Device;
/* yaffs2 runtime stuff */
unsigned sequenceNumber; /* Sequence number of currently allocating block */
- unsigned oldestDirtySequence;
} yaffs_CheckpointDevice;
} 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);
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);
void yfsd_WinFileTimeNow(__u32 target[2]);
#endif
-#ifdef __KERNEL__
-
void yaffs_HandleDeferedFree(yaffs_Object *obj);
-#endif
+
+void yaffs_UpdateDirtyDirectories(yaffs_Device *dev);
+
+int yaffs_BackgroundGarbageCollect(yaffs_Device *dev, unsigned urgency);
/* Debug dump */
int yaffs_DumpObject(yaffs_Object *obj);
void yaffs_GutsTest(yaffs_Device *dev);
-/* A few useful functions */
-void yaffs_InitialiseTags(yaffs_ExtendedTags *tags);
+/* A few useful functions to be used within the core files*/
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);
__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