* published by the Free Software Foundation.
*
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */\r
-\r
-/*\r
+ */
+
+/*
* 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.
- *\r
- */\r
-\r
-#ifndef __EXTRAS_H__\r
-#define __EXTRAS_H__\r
-\r
-\r
-#if !(defined __KERNEL__) \r
-\r
+ *
+ */
+
+#ifndef __EXTRAS_H__
+#define __EXTRAS_H__
+
+
+#if !(defined __KERNEL__)
+
/* Definition of types */
-typedef unsigned char __u8;\r
-typedef unsigned short __u16;\r
-typedef unsigned __u32;\r
-\r
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned __u32;
+
#endif
-\r
-/*\r
- * This is a simple doubly linked list implementation that matches the \r
- * way the Linux kernel doubly linked list implementation works.\r
- */\r
-\r
+
+/*
+ * 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 */
-};\r
-\r
-\r
-/* Initialise a list head to an empty list */\r
+ 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 { \\r
- (p)->next = (p);\\r
+do { \
+ (p)->next = (p);\
(p)->prev = (p); \
-} while(0)\r
-\r
-\r
-/* Add an element to a list */\r
+} while(0)
+
+
+/* Add an element to a list */
static __inline__ void ylist_add(struct ylist_head *newEntry,
struct ylist_head *list)
-{\r
+{
struct ylist_head *listNext = list->next;
- \r
- list->next = newEntry;\r
- newEntry->prev = list;\r
+
+ list->next = newEntry;
+ newEntry->prev = list;
newEntry->next = listNext;
listNext->prev = newEntry;
}
-\r
-/* Take an element out of its current list, with or without\r
- * reinitialising the links.of the entry*/\r
+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)
-{\r
+{
struct ylist_head *listNext = entry->next;
struct ylist_head *listPrev = entry->prev;
- \r
- listNext->prev = listPrev;\r
- listPrev->next = listNext;\r
- \r
-}\r
-\r
+
+ listNext->prev = listPrev;
+ listPrev->next = listNext;
+
+}
+
static __inline__ void ylist_del_init(struct ylist_head *entry)
-{\r
+{
ylist_del(entry);
- entry->next = entry->prev = entry;\r
-}\r
-\r
-\r
-/* Test if the list is empty */\r
+ entry->next = entry->prev = entry;
+}
+
+
+/* Test if the list is empty */
static __inline__ int ylist_empty(struct ylist_head *entry)
-{\r
- return (entry->next == entry);\r
-}\r
-\r
-\r
+{
+ 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.\r
- */\r
- \r
- \r
+ * 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)))\r
-\r
-\r
+ ((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
- */\r
-\r
+ */
+
#define ylist_for_each(itervar, list) \
- for (itervar = (list)->next; itervar != (list); itervar = itervar->next )\r
-\r
+ 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); \\r
- itervar = saveVar, saveVar = saveVar->next)\r
-\r
+ for (itervar = (list)->next, saveVar = (list)->next->next; itervar != (list); \
+ itervar = saveVar, saveVar = saveVar->next)
+
#if !(defined __KERNEL__)
#ifdef CONFIG_YAFFS_PROVIDE_DEFS
-/* File types */\r
-\r
+/* File types */
-#define DT_UNKNOWN 0\r
-#define DT_FIFO 1\r
-#define DT_CHR 2\r
+
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
#define DT_DIR 4
#define DT_BLK 6
-#define DT_REG 8\r
-#define DT_LNK 10\r
-#define DT_SOCK 12\r
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
#define DT_WHT 14
-\r
-\r
-#ifndef WIN32\r
-#include <sys/stat.h>\r
-#endif\r
-\r
-/*\r
- * Attribute flags. These should be or-ed together to figure out what\r
- * has been changed!\r
- */\r
-#define ATTR_MODE 1\r
-#define ATTR_UID 2\r
+
+
+#ifndef WIN32
+#include <sys/stat.h>
+#endif
+
+/*
+ * Attribute flags. These should be or-ed together to figure out what
+ * has been changed!
+ */
+#define ATTR_MODE 1
+#define ATTR_UID 2
#define ATTR_GID 4
#define ATTR_SIZE 8
#define ATTR_ATIME 16
unsigned ia_atime;
unsigned ia_mtime;
unsigned ia_ctime;
- unsigned int ia_attr_flags;\r
-};\r
-\r
+ unsigned int ia_attr_flags;
+};
+
#endif
-#define KERN_DEBUG\r
-\r
-#else\r
-\r
-#include <linux/types.h>\r
-#include <linux/fs.h>\r
-#include <linux/stat.h>\r
-\r
-#endif\r
-\r
-\r
-#endif\r
+#define KERN_DEBUG
+
+#else
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+
+#endif
+
+
+#endif
}
+
int resize_stress_test(const char *path)
{
int a,b,i,j;
}
+int root_perm_remount(const char *path)
+{
+ struct yaffs_stat s;
+
+ yaffs_StartUp();
+
+ yaffs_mount(path);
+
+ yaffs_stat(path,&s);
+ printf("root perms after mount %x\n",s.st_mode);
+
+ yaffs_chmod(path, 0777);
+
+ yaffs_stat(path,&s);
+ printf("root perms after setting to 0777 is %x\n",s.st_mode);
+
+ yaffs_unmount(path);
+
+ return 0;
+
+}
+
int resize_stress_test_no_grow_complex(const char *path,int iters)
{
//return cache_read_test();
- //resize_stress_test_no_grow("/flash/flash",20);
+ // resize_stress_test_no_grow("/flash/flash",20);
+ //root_perm_remount("/flash/flash");
//huge_directory_test_on_path("/ram2k");
#endif
-const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.20 2008-07-02 20:17:41 charles Exp $";
+const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.21 2008-07-03 20:06:05 charles Exp $";
// configurationList is the list of devices that are supported
static yaffsfs_DeviceConfiguration *yaffsfs_configurationList;
return retVal;
}
+int yaffs_inodecount(const YCHAR *path)
+{
+ loff_t retVal= -1;
+ yaffs_Device *dev=NULL;
+ YCHAR *dummy;
+
+ yaffsfs_Lock();
+ dev = yaffsfs_FindDevice(path,&dummy);
+ if(dev && dev->isMounted) {
+ int nObjects = dev->nObjectsCreated - dev->nFreeObjects;
+ if(nObjects > dev->nHardLinks)
+ retVal = nObjects - dev->nHardLinks;
+ }
+
+ if(retVal < 0){
+ yaffsfs_SetError(-EINVAL);
+ }
+
+ yaffsfs_Unlock();
+ return retVal;
+}
+
void yaffs_initialise(yaffsfs_DeviceConfiguration *cfgList)
loff_t yaffs_freespace(const YCHAR *path);
loff_t yaffs_totalspace(const YCHAR *path);
+int yaffs_inodecount(const YCHAR *path);
+
+
void yaffs_initialise(yaffsfs_DeviceConfiguration *configList);
int yaffs_StartUp(void);
## Change or override KERNELDIR to your kernel
## comment out USE_xxxx if you don't want these features.
-KERNELDIR = /usr/src/kernel-headers-2.4.27
+KERNELDIR = /opt/linux-source-2.6.24
+#CFLAGS = -D__KERNEL__ -DMODULE -I$(KERNELDIR)/include -O2 -Wall -g
CFLAGS = -D__KERNEL__ -DMODULE -I$(KERNELDIR)/include -O2 -Wall -g
* This version hacked for emulating 2kpage NAND for YAFFS2 testing.
*/
-#include <linux/config.h>
+//#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
*/
static int nand_read (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
-static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf, u_char *oob_buf, struct nand_oobinfo *dummy);
static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
static int nand_write (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf);
-static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf,
- u_char *oob_buf, struct nand_oobinfo *dummy);
static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,7))
/* Get raw starting column */
- start = from & (mtd->oobblock-1);
+ start = from & (PAGE_DATA_SIZE - 1);
// OK now check for the curveball where the start and end are in
// the same page
- if((start + n) < mtd->oobblock)
+ if((start + n) < PAGE_DATA_SIZE)
{
nToCopy = n;
}
else
{
- nToCopy = mtd->oobblock - start;
+ nToCopy = PAGE_DATA_SIZE - start;
}
nandemul2k_Read(buf, page, start, nToCopy);
page = ((int) from) >> NAND_SHIFT;
/* Mask to get column */
- col = from & 0x0f;
+ col = from & (PAGE_SPARE_SIZE-1)
/* Initialize return length value */
*retlen = 0;
/* Get raw starting column */
- start = to & (mtd->oobblock - 1);
+ start = to & (PAGE_DATA_SIZE - 1);
// OK now check for the curveball where the start and end are in
// the same page
- if((start + n) < mtd->oobblock)
+ if((start + n) < PAGE_DATA_SIZE)
{
nToCopy = n;
}
else
{
- nToCopy = mtd->oobblock - start;
+ nToCopy = PAGE_DATA_SIZE - start;
}
nandemul2k_Program(buf, page, start, nToCopy);
page = ((int) to) >> NAND_SHIFT;
/* Mask to get column */
- col = to & 0x0f;
+ col = to & PAGE_SPARE_SIZE;
/* Initialize return length value */
*retlen = 0;
nandemul2k_DoErase(block);
block++;
}
-
- instr->state = MTD_ERASE_DONE; Â * change state to ERASE_DONE */
-
- instr->callback(instr); Â * wake up */
+
+ instr->state = MTD_ERASE_DONE; /* Changed state to done */
+ instr->callback(instr); /* ... and wake up */
return 0;
*/
static int nandemul2k_scan (struct mtd_info *mtd,int nchips)
{
- mtd->oobblock = PAGE_DATA_SIZE;
- mtd->oobsize = PAGE_SPARE_SIZE;
+ mtd->writesize = PAGE_DATA_SIZE;
+ mtd->oobsize = PAGE_SPARE_SIZE;
+ mtd->oobavail = PAGE_SPARE_SIZE/2; /* Simulate using up some for other uses */
mtd->erasesize = PAGE_DATA_SIZE * PAGES_PER_BLOCK;
mtd->size = sizeInMB * 1024*1024;
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->owner = THIS_MODULE;
- mtd->ecctype = MTD_ECC_NONE;
mtd->erase = nand_erase;
mtd->point = NULL;
mtd->unpoint = NULL;
mtd->read = nand_read;
mtd->write = nand_write;
- mtd->read_ecc = nand_read_ecc;
- mtd->write_ecc = nand_write_ecc;
+ mtd->read_oob = nand_read_oob;
+ mtd->write_oob = nand_write_oob;
mtd->read_oob = nand_read_oob;
mtd->write_oob = nand_write_oob;
mtd->block_isbad = nand_block_isbad;
*/
const char *yaffs_fs_c_version =
- "$Id: yaffs_fs.c,v 1.66 2008-05-05 07:58:58 charles Exp $";
+ "$Id: yaffs_fs.c,v 1.67 2008-07-03 20:06:05 charles Exp $";
extern const char *yaffs_guts_c_version;
#include <linux/version.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
-#include <linux/list.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/smp_lock.h>
MODULE_PARM(yaffs_wr_attempts,"i");
#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
+/* use iget and read_inode */
+#define Y_IGET(sb,inum) iget((sb),(inum))
+static void yaffs_read_inode(struct inode *inode);
+
+#else
+/* Call local equivalent */
+#define YAFFS_USE_OWN_IGET
+#define Y_IGET(sb,inum) yaffs_iget((sb),(inum))
+
+static struct inode * yaffs_iget(struct super_block *sb, unsigned long ino);
+#endif
+
/*#define T(x) printk x */
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
#else
static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
#endif
-static void yaffs_read_inode(struct inode *inode);
static void yaffs_put_inode(struct inode *inode);
static void yaffs_delete_inode(struct inode *);
static struct super_operations yaffs_super_ops = {
.statfs = yaffs_statfs,
+
+#ifndef YAFFS_USE_OWN_IGET
.read_inode = yaffs_read_inode,
+#endif
.put_inode = yaffs_put_inode,
.put_super = yaffs_put_super,
.delete_inode = yaffs_delete_inode,
T(YAFFS_TRACE_OS,
(KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId));
- inode = iget(sb, obj->objectId);
+ inode = Y_IGET(sb, obj->objectId);
+ if(IS_ERR(inode))
+ return NULL;
/* NB Side effect: iget calls back to yaffs_read_inode(). */
/* iget also increments the inode's i_count */
yaffs_Device *dev;
struct inode *inode = f->f_dentry->d_inode;
unsigned long offset, curoffs;
- struct list_head *i;
+ struct ylist_head *i;
yaffs_Object *l;
char name[YAFFS_MAX_NAME_LENGTH + 1];
f->f_version = inode->i_version;
}
- list_for_each(i, &obj->variant.directoryVariant.children) {
+ ylist_for_each(i, &obj->variant.directoryVariant.children) {
curoffs++;
if (curoffs >= offset) {
- l = list_entry(i, yaffs_Object, siblings);
+ l = ylist_entry(i, yaffs_Object, siblings);
yaffs_GetObjectName(l, name,
YAFFS_MAX_NAME_LENGTH + 1);
if (target &&
target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
- !list_empty(&target->variant.directoryVariant.children)) {
+ !ylist_empty(&target->variant.directoryVariant.children)) {
T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n"));
}
-/**
static int yaffs_do_sync_fs(struct super_block *sb)
{
if(sb->s_dirt) {
yaffs_GrossLock(dev);
- if(dev)
+ if(dev){
+ yaffs_FlushEntireDeviceCache(dev);
yaffs_CheckpointSave(dev);
+ }
yaffs_GrossUnlock(dev);
}
return 0;
}
-**/
+
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
static void yaffs_write_super(struct super_block *sb)
{
T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n"));
+ yaffs_do_sync_fs(sb);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
- return 0; /* yaffs_do_sync_fs(sb);*/
+ return 0;
#endif
}
T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n"));
- return 0; /* yaffs_do_sync_fs(sb);*/
+ yaffs_do_sync_fs(sb);
+
+ return 0;
+
+}
+
+#ifdef YAFFS_USE_OWN_IGET
+
+static struct inode * yaffs_iget(struct super_block *sb, unsigned long ino)
+{
+ struct inode *inode;
+ yaffs_Object *obj;
+ yaffs_Device *dev = yaffs_SuperToDevice(sb);
+
+ T(YAFFS_TRACE_OS,
+ (KERN_DEBUG "yaffs_iget for %lu\n", ino));
+
+ inode = iget_locked(sb, ino);
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
+ if (!(inode->i_state & I_NEW))
+ return inode;
+
+ /* NB This is called as a side effect of other functions, but
+ * we had to release the lock to prevent deadlocks, so
+ * need to lock again.
+ */
+
+ yaffs_GrossLock(dev);
+
+ obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
+
+ yaffs_FillInodeFromObject(inode, obj);
+ yaffs_GrossUnlock(dev);
+
+ unlock_new_inode(inode);
+ return inode;
}
+#else
static void yaffs_read_inode(struct inode *inode)
{
yaffs_GrossUnlock(dev);
}
-static LIST_HEAD(yaffs_dev_list);
+#endif
+
+static YLIST_HEAD(yaffs_dev_list);
#if 0 // not used
static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
yaffs_GrossUnlock(dev);
/* we assume this is protected by lock_kernel() in mount/umount */
- list_del(&dev->devList);
+ ylist_del(&dev->devList);
if(dev->spareBuffer){
YFREE(dev->spareBuffer);
dev->skipCheckpointWrite = options.skip_checkpoint_write;
/* we assume this is protected by lock_kernel() in mount/umount */
- list_add_tail(&dev->devList, &yaffs_dev_list);
+ ylist_add_tail(&dev->devList, &yaffs_dev_list);
init_MUTEX(&dev->grossLock);
char **start,
off_t offset, int count, int *eof, void *data)
{
- struct list_head *item;
+ struct ylist_head *item;
char *buf = page;
int step = offset;
int n = 0;
lock_kernel();
/* Locate and print the Nth entry. Order N-squared but N is small. */
- list_for_each(item, &yaffs_dev_list) {
- yaffs_Device *dev = list_entry(item, yaffs_Device, devList);
+ ylist_for_each(item, &yaffs_dev_list) {
+ yaffs_Device *dev = ylist_entry(item, yaffs_Device, devList);
if (n < step) {
n++;
continue;
*/
const char *yaffs_guts_c_version =
- "$Id: yaffs_guts.c,v 1.57 2008-07-02 20:17:41 charles Exp $";
+ "$Id: yaffs_guts.c,v 1.58 2008-07-03 20:06:05 charles Exp $";
#include "yportenv.h"
return;
/* Check sane object header chunk */
-
- chunkMin = dev->internalStartBlock * dev->nChunksPerBlock;
- chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1;
-
- chunkIdOk = (((unsigned)(obj->chunkId)) >= chunkMin && ((unsigned)(obj->chunkId)) <= chunkMax);
- chunkIsLive = chunkIdOk &&
- yaffs_CheckChunkBit(dev,
- obj->chunkId / dev->nChunksPerBlock,
- obj->chunkId % dev->nChunksPerBlock);
- if(!obj->fake &&
+
+ chunkMin = dev->internalStartBlock * dev->nChunksPerBlock;
+ chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1;
+
+ chunkIdOk = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax);
+ chunkIsLive = chunkIdOk &&
+ yaffs_CheckChunkBit(dev,
+ obj->hdrChunk / dev->nChunksPerBlock,
+ obj->hdrChunk % dev->nChunksPerBlock);
+ if(!obj->fake &&
(!chunkIdOk || !chunkIsLive)) {
T(YAFFS_TRACE_VERIFY,
(TSTR("Obj %d has chunkId %d %s %s"TENDSTR),
- obj->objectId,obj->chunkId,
+ obj->objectId,obj->hdrChunk,
chunkIdOk ? "" : ",out of range",
chunkIsLive || !chunkIdOk ? "" : ",marked as deleted"));
}
__u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__);
oh = (yaffs_ObjectHeader *)buffer;
-
- yaffs_ReadChunkWithTagsFromNAND(dev, obj->chunkId,buffer, &tags);
-
+
+ yaffs_ReadChunkWithTagsFromNAND(dev, obj->hdrChunk,buffer, &tags);
+
yaffs_VerifyObjectHeader(obj,oh,&tags,1);
yaffs_ReleaseTempBuffer(dev,buffer,__LINE__);
}
/*
- * Access functions to useful fake objects
+ * Access functions to useful fake objects.
+ * Note that root might have a presence in NAND if permissions are set.
*/
yaffs_Object *yaffs_Root(yaffs_Device * dev)
/* Now sweeten it up... */
memset(tn, 0, sizeof(yaffs_Object));
- tn->myDev = dev;
- tn->chunkId = -1;
- tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
- YINIT_LIST_HEAD(&(tn->hardLinks));
- YINIT_LIST_HEAD(&(tn->hashLink));
- YINIT_LIST_HEAD(&tn->siblings);
+ tn->myDev = dev;
+ tn->hdrChunk = 0;
+ tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
+ YINIT_LIST_HEAD(&(tn->hardLinks));
+ YINIT_LIST_HEAD(&(tn->hashLink));
+ YINIT_LIST_HEAD(&tn->siblings);
/* Add it to the lost and found directory.
* NB Can't put root or lostNFound in lostNFound so
yaffs_Object *obj =
yaffs_CreateNewObject(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
if (obj) {
- obj->fake = 1; /* it is fake so it has no NAND presence... */
+ obj->fake = 1; /* it is fake so it might have no NAND presence... */
obj->renameAllowed = 0; /* ... and we're not allowed to rename it... */
obj->unlinkAllowed = 0; /* ... or unlink it */
obj->deleted = 0;
obj->unlinked = 0;
obj->yst_mode = mode;
obj->myDev = dev;
- obj->chunkId = 0; /* Not a valid chunk. */
+ obj->hdrChunk = 0; /* Not a valid chunk. */
}
return obj;
if (in) {
- in->chunkId = -1;
+ in->hdrChunk = 0;
in->valid = 1;
in->variantType = type;
if(object && !yaffs_SkipVerification(dev)){
if(tags.chunkId == 0)
- matchingChunk = object->chunkId;
+ matchingChunk = object->hdrChunk;
else if(object->softDeleted)
matchingChunk = oldChunk; /* Defeat the test */
else
/* Deleted object header with no data chunks.
* Can be discarded and the file deleted.
*/
- object->chunkId = 0;
+ object->hdrChunk = 0;
yaffs_FreeTnode(object->myDev,
object->variant.
fileVariant.top);
if (tags.chunkId == 0) {
/* It's a header */
- object->chunkId = newChunk;
+ object->hdrChunk = newChunk;
object->serial = tags.serialNumber;
} else {
/* It's a data chunk */
* Update: For backward scanning we don't need to re-read tags so this is quite cheap.
*/
- if (existingChunk != 0) {
+ if (existingChunk > 0) {
/* NB Right now existing chunk will not be real chunkId if the device >= 32MB
* thus we have to do a FindChunkInFile to get the real chunk id.
*
yaffs_strcpy(oldName,_Y("silly old name"));
- if (!in->fake || force) {
+
+ if (!in->fake ||
+ in == dev->rootDir || /* The rootDir should also be saved */
+ force) {
yaffs_CheckGarbageCollection(dev);
yaffs_CheckObjectDetailsLoaded(in);
buffer = yaffs_GetTempBuffer(in->myDev, __LINE__);
oh = (yaffs_ObjectHeader *) buffer;
- prevChunkId = in->chunkId;
+ prevChunkId = in->hdrChunk;
- if (prevChunkId >= 0) {
+ if (prevChunkId > 0) {
result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId,
buffer, &oldTags);
if (newChunkId >= 0) {
- in->chunkId = newChunkId;
+ in->hdrChunk = newChunkId;
if (prevChunkId >= 0) {
yaffs_DeleteChunk(dev, prevChunkId, 1,
cp->objectId = obj->objectId;
cp->parentId = (obj->parent) ? obj->parent->objectId : 0;
- cp->chunkId = obj->chunkId;
- cp->variantType = obj->variantType;
+ cp->hdrChunk = obj->hdrChunk;
+ cp->variantType = obj->variantType;
cp->deleted = obj->deleted;
cp->softDeleted = obj->softDeleted;
cp->unlinked = obj->unlinked;
if(parent)
yaffs_AddObjectToDirectory(parent, obj);
-
- obj->chunkId = cp->chunkId;
- obj->variantType = cp->variantType;
+
+ obj->hdrChunk = cp->hdrChunk;
+ obj->variantType = cp->variantType;
obj->deleted = cp->deleted;
obj->softDeleted = cp->softDeleted;
obj->unlinked = cp->unlinked;
obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId;
else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId;
-
- if(obj->objectId >= YAFFS_NOBJECT_BUCKETS)
+
+ if(obj->hdrChunk > 0)
obj->lazyLoaded = 1;
}
T(YAFFS_TRACE_CHECKPOINT,(
TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR),
- cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj));
-
+ cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk,(unsigned) obj));
+
ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){
}
T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR),
- cp.objectId,cp.parentId,cp.variantType,cp.chunkId));
-
+ cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk));
+
if(ok && cp.objectId == ~0)
done = 1;
else if(ok){
}
yaffs_RemoveObjectFromDirectory(in);
- yaffs_DeleteChunk(in->myDev, in->chunkId, 1, __LINE__);
- in->chunkId = -1;
+ yaffs_DeleteChunk(in->myDev, in->hdrChunk, 1, __LINE__);
+ in->hdrChunk = 0;
yaffs_FreeObject(in);
return YAFFS_OK;
newSerial) {
/* Use new one - destroy the exisiting one */
yaffs_DeleteChunk(dev,
- in->chunkId,
+ in->hdrChunk,
1, __LINE__);
in->valid = 0;
} else {
in->yst_ctime = oh->yst_ctime;
in->yst_rdev = oh->yst_rdev;
#endif
- in->chunkId = chunk;
+ in->hdrChunk = chunk;
} else if (in && !in->valid) {
/* we need to load this info */
in->yst_ctime = oh->yst_ctime;
in->yst_rdev = oh->yst_rdev;
#endif
- in->chunkId = chunk;
+ in->hdrChunk = chunk;
yaffs_SetObjectName(in, oh->name);
in->dirty = 0;
in->lazyLoaded ? "not yet" : "already"));
#endif
- if(in->lazyLoaded){
+ if(in->lazyLoaded && in->hdrChunk > 0){
in->lazyLoaded = 0;
chunkData = yaffs_GetTempBuffer(dev, __LINE__);
- result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags);
- oh = (yaffs_ObjectHeader *) chunkData;
+ result = yaffs_ReadChunkWithTagsFromNAND(dev,in->hdrChunk,chunkData,&tags);
+ oh = (yaffs_ObjectHeader *) chunkData;
in->yst_mode = oh->yst_mode;
#ifdef CONFIG_YAFFS_WINCE
in->variantType = tags.extraObjectType;
in->lazyLoaded = 1;
}
-
- in->chunkId = chunk;
+
+ in->hdrChunk = chunk;
} else if (!in->valid) {
/* we need to load this info */
in->valid = 1;
- in->chunkId = chunk;
-
+ in->hdrChunk = chunk;
+
if(oh) {
in->variantType = oh->type;
if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) {
return l;
}
- } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0)
- {
- /* LostnFound cunk called Objxxx
+ } else if (yaffs_SumCompare(l->sum, sum) || l->hdrChunk <= 0){
+ /* LostnFound chunk called Objxxx
* Do a real check
*/
yaffs_GetObjectName(l, buffer,
if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1);
- } else if (obj->chunkId <= 0) {
+ } else if (obj->hdrChunk <= 0) {
YCHAR locName[20];
/* make up a name */
yaffs_sprintf(locName, _Y("%s%d"), YAFFS_LOSTNFOUND_PREFIX,
memset(buffer, 0, obj->myDev->nDataBytesPerChunk);
- if (obj->chunkId >= 0) {
+ if (obj->hdrChunk > 0) {
result = yaffs_ReadChunkWithTagsFromNAND(obj->myDev,
- obj->chunkId, buffer,
+ obj->hdrChunk, buffer,
NULL);
}
yaffs_strncpy(name, oh->name, buffSize - 1);
("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d"
" chunk %d type %d size %d\n"
TENDSTR), obj->objectId, yaffs_GetObjectInode(obj), name,
- obj->dirty, obj->valid, obj->serial, obj->sum, obj->chunkId,
+ obj->dirty, obj->valid, obj->serial, obj->sum, obj->hdrChunk,
yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj)));
return YAFFS_OK;
/* Now scan the flash. */
if (dev->isYaffs2) {
if(yaffs_CheckpointRestore(dev)) {
+ yaffs_CheckObjectDetailsLoaded(dev->rootDir);
T(YAFFS_TRACE_ALWAYS,
(TSTR("yaffs: restored from checkpoint" TENDSTR)));
} else {
struct yaffs_ObjectStruct *parent;
struct ylist_head siblings;
- /* Where's my object header in NAND? */
- int chunkId;
+ /* Where's my object header in NAND? */
+ int hdrChunk;
int nDataChunks; /* Number of data chunks attached to the file. */
int structType;
__u32 objectId;
__u32 parentId;
- int chunkId;
-
+ int hdrChunk;
yaffs_ObjectType variantType:3;
__u8 deleted:1;
__u8 softDeleted:1;
int nObjectsCreated;
yaffs_Object *freeObjects;
int nFreeObjects;
+
+ int nHardLinks;
yaffs_ObjectList *allocatedObjectList;