From 92ee023b9d7144e178a050eff898aaae4415096b Mon Sep 17 00:00:00 2001 From: charles Date: Thu, 3 Jul 2008 20:06:05 +0000 Subject: [PATCH] Some cleanups, Linux 2.6.25 handling, fix handing of root permissions --- devextras.h | 234 +++++++++++++++++++++++-------------------- direct/dtest.c | 26 ++++- direct/yaffsfs.c | 24 ++++- direct/yaffsfs.h | 3 + mtdemul/Makefile | 3 +- mtdemul/nandemul2k.c | 40 ++++---- yaffs_fs.c | 95 ++++++++++++++---- yaffs_guts.c | 130 ++++++++++++------------ yaffs_guts.h | 9 +- 9 files changed, 344 insertions(+), 220 deletions(-) diff --git a/devextras.h b/devextras.h index d2abbd5..a9366fd 100644 --- a/devextras.h +++ b/devextras.h @@ -11,107 +11,125 @@ * 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 __EXTRAS_H__ -#define __EXTRAS_H__ - - -#if !(defined __KERNEL__) - + * + */ + +#ifndef __EXTRAS_H__ +#define __EXTRAS_H__ + + +#if !(defined __KERNEL__) + /* Definition of types */ -typedef unsigned char __u8; -typedef unsigned short __u16; -typedef unsigned __u32; - +typedef unsigned char __u8; +typedef unsigned short __u16; +typedef unsigned __u32; + #endif - -/* - * This is a simple doubly linked list implementation that matches the - * way the Linux kernel doubly linked list implementation works. - */ - + +/* + * 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 list head to an empty list */ + 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);\ +do { \ + (p)->next = (p);\ (p)->prev = (p); \ -} while(0) - - -/* Add an element to a list */ +} 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; + + list->next = newEntry; + newEntry->prev = list; newEntry->next = listNext; listNext->prev = newEntry; } - -/* Take an element out of its current list, with or without - * reinitialising the links.of the entry*/ +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; - -} - + + 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 */ + entry->next = entry->prev = entry; +} + + +/* Test if the list is empty */ static __inline__ int ylist_empty(struct ylist_head *entry) -{ - return (entry->next == 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. - */ - - + * 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))) - - + ((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 ) - + 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) - + for (itervar = (list)->next, saveVar = (list)->next->next; itervar != (list); \ + itervar = saveVar, saveVar = saveVar->next) + #if !(defined __KERNEL__) @@ -122,30 +140,30 @@ static __inline__ int ylist_empty(struct ylist_head *entry) #ifdef CONFIG_YAFFS_PROVIDE_DEFS -/* File types */ - +/* File types */ -#define DT_UNKNOWN 0 -#define DT_FIFO 1 -#define DT_CHR 2 + +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 #define DT_DIR 4 #define DT_BLK 6 -#define DT_REG 8 -#define DT_LNK 10 -#define DT_SOCK 12 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 #define DT_WHT 14 - - -#ifndef WIN32 -#include -#endif - -/* - * Attribute flags. These should be or-ed together to figure out what - * has been changed! - */ -#define ATTR_MODE 1 -#define ATTR_UID 2 + + +#ifndef WIN32 +#include +#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 @@ -161,21 +179,21 @@ struct iattr { unsigned ia_atime; unsigned ia_mtime; unsigned ia_ctime; - unsigned int ia_attr_flags; -}; - + unsigned int ia_attr_flags; +}; + #endif -#define KERN_DEBUG - -#else - -#include -#include -#include - -#endif - - -#endif +#define KERN_DEBUG + +#else + +#include +#include +#include + +#endif + + +#endif diff --git a/direct/dtest.c b/direct/dtest.c index 5b038c4..792c67e 100644 --- a/direct/dtest.c +++ b/direct/dtest.c @@ -966,6 +966,7 @@ void rename_over_test(const char *mountpt) } + int resize_stress_test(const char *path) { int a,b,i,j; @@ -1029,6 +1030,28 @@ int resize_stress_test(const char *path) } +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) { @@ -2259,7 +2282,8 @@ int main(int argc, char *argv[]) //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"); diff --git a/direct/yaffsfs.c b/direct/yaffsfs.c index 6206ed4..1197518 100644 --- a/direct/yaffsfs.c +++ b/direct/yaffsfs.c @@ -24,7 +24,7 @@ #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; @@ -1602,6 +1602,28 @@ loff_t yaffs_totalspace(const YCHAR *path) 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) diff --git a/direct/yaffsfs.h b/direct/yaffsfs.h index 1c0d316..c05e02a 100644 --- a/direct/yaffsfs.h +++ b/direct/yaffsfs.h @@ -272,6 +272,9 @@ int yaffs_mknod(const YCHAR *pathname, mode_t mode, dev_t dev); 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); diff --git a/mtdemul/Makefile b/mtdemul/Makefile index fe03b47..eeac54e 100644 --- a/mtdemul/Makefile +++ b/mtdemul/Makefile @@ -15,8 +15,9 @@ ## 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 diff --git a/mtdemul/nandemul2k.c b/mtdemul/nandemul2k.c index bcbf16a..7efa8d4 100644 --- a/mtdemul/nandemul2k.c +++ b/mtdemul/nandemul2k.c @@ -15,7 +15,7 @@ * This version hacked for emulating 2kpage NAND for YAFFS2 testing. */ -#include +//#include #include #include #include @@ -280,15 +280,10 @@ static int nandemul2k_ReadStatus(__u8 *status) */ 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)) @@ -343,17 +338,17 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, /* 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); @@ -386,7 +381,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, page = ((int) from) >> NAND_SHIFT; /* Mask to get column */ - col = from & 0x0f; + col = from & (PAGE_SPARE_SIZE-1) /* Initialize return length value */ *retlen = 0; @@ -447,17 +442,17 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, /* 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); @@ -492,7 +487,7 @@ static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, page = ((int) to) >> NAND_SHIFT; /* Mask to get column */ - col = to & 0x0f; + col = to & PAGE_SPARE_SIZE; /* Initialize return length value */ *retlen = 0; @@ -567,10 +562,9 @@ static int nand_erase (struct mtd_info *mtd, struct erase_info *instr) 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; @@ -603,8 +597,9 @@ static void nand_sync (struct mtd_info *mtd) */ 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; @@ -614,14 +609,13 @@ static int nandemul2k_scan (struct mtd_info *mtd,int nchips) 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; diff --git a/yaffs_fs.c b/yaffs_fs.c index ab6a3a7..b8f2575 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -32,7 +32,7 @@ */ 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 @@ -43,7 +43,6 @@ extern const char *yaffs_guts_c_version; #include #include #include -#include #include #include #include @@ -108,6 +107,19 @@ MODULE_PARM(yaffs_traceMask,"i"); 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)) @@ -183,7 +195,6 @@ static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf); #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 *); @@ -286,7 +297,10 @@ static struct file_operations yaffs_dir_operations = { 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, @@ -848,7 +862,9 @@ struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, 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 */ @@ -920,7 +936,7 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir) 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]; @@ -969,10 +985,10 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir) 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); @@ -1273,7 +1289,7 @@ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, 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")); @@ -1404,7 +1420,6 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf) } -/** static int yaffs_do_sync_fs(struct super_block *sb) { @@ -1414,8 +1429,10 @@ 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); @@ -1423,7 +1440,7 @@ static int yaffs_do_sync_fs(struct super_block *sb) } return 0; } -**/ + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) static void yaffs_write_super(struct super_block *sb) @@ -1433,8 +1450,9 @@ static int 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 } @@ -1448,10 +1466,47 @@ static int yaffs_sync_fs(struct super_block *sb) 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) { @@ -1475,7 +1530,9 @@ 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) @@ -1529,7 +1586,7 @@ static void yaffs_put_super(struct super_block *sb) 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); @@ -1864,7 +1921,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, 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); @@ -2049,7 +2106,7 @@ static int yaffs_proc_read(char *page, 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; @@ -2073,8 +2130,8 @@ static int yaffs_proc_read(char *page, 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; diff --git a/yaffs_guts.c b/yaffs_guts.c index 6e725ac..d4ecda3 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -12,7 +12,7 @@ */ 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" @@ -767,20 +767,20 @@ static void yaffs_VerifyObject(yaffs_Object *obj) 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")); } @@ -791,9 +791,9 @@ static void yaffs_VerifyObject(yaffs_Object *obj) __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__); @@ -875,7 +875,8 @@ static Y_INLINE int yaffs_HashFunction(int n) } /* - * 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) @@ -1922,12 +1923,12 @@ static yaffs_Object *yaffs_AllocateEmptyObject(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 @@ -1950,14 +1951,14 @@ static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device * dev, int number, 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; @@ -2296,7 +2297,7 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, if (in) { - in->chunkId = -1; + in->hdrChunk = 0; in->valid = 1; in->variantType = type; @@ -3035,7 +3036,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) 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 @@ -3079,7 +3080,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) /* 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); @@ -3125,7 +3126,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) if (tags.chunkId == 0) { /* It's a header */ - object->chunkId = newChunk; + object->hdrChunk = newChunk; object->serial = tags.serialNumber; } else { /* It's a data chunk */ @@ -3444,7 +3445,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode, * 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. * @@ -3675,7 +3676,10 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force, 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); @@ -3683,9 +3687,9 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force, 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); @@ -3787,7 +3791,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force, if (newChunkId >= 0) { - in->chunkId = newChunkId; + in->hdrChunk = newChunkId; if (prevChunkId >= 0) { yaffs_DeleteChunk(dev, prevChunkId, 1, @@ -4227,8 +4231,8 @@ static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp, 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; @@ -4261,9 +4265,9 @@ static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointOb 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; @@ -4277,8 +4281,8 @@ static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointOb 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; } @@ -4409,8 +4413,8 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev) 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){ @@ -4448,8 +4452,8 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) } 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){ @@ -5143,8 +5147,8 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object * in) } 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; @@ -5678,7 +5682,7 @@ static int yaffs_Scan(yaffs_Device * dev) newSerial) { /* Use new one - destroy the exisiting one */ yaffs_DeleteChunk(dev, - in->chunkId, + in->hdrChunk, 1, __LINE__); in->valid = 0; } else { @@ -5711,7 +5715,7 @@ static int yaffs_Scan(yaffs_Device * dev) 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 */ @@ -5735,7 +5739,7 @@ static int yaffs_Scan(yaffs_Device * dev) 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; @@ -5934,12 +5938,12 @@ static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in) 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 @@ -6420,15 +6424,15 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) 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; @@ -6745,9 +6749,8 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, 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, @@ -6822,7 +6825,7 @@ int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize) 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, @@ -6843,9 +6846,9 @@ int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize) 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); @@ -7006,7 +7009,7 @@ int yaffs_DumpObject(yaffs_Object * obj) ("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; @@ -7306,6 +7309,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) /* 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 { diff --git a/yaffs_guts.h b/yaffs_guts.h index 4506724..a193625 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -436,8 +436,8 @@ struct yaffs_ObjectStruct { 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. */ @@ -501,8 +501,7 @@ typedef struct { int structType; __u32 objectId; __u32 parentId; - int chunkId; - + int hdrChunk; yaffs_ObjectType variantType:3; __u8 deleted:1; __u8 softDeleted:1; @@ -693,6 +692,8 @@ struct yaffs_DeviceStruct { int nObjectsCreated; yaffs_Object *freeObjects; int nFreeObjects; + + int nHardLinks; yaffs_ObjectList *allocatedObjectList; -- 2.30.2