*** empty log message ***
authorcharles <charles>
Sun, 9 Jun 2002 07:36:54 +0000 (07:36 +0000)
committercharles <charles>
Sun, 9 Jun 2002 07:36:54 +0000 (07:36 +0000)
Documentation/taffs-todo.html [deleted file]
Documentation/yaffs-todo.html [new file with mode: 0644]
snMakefile
yaffs_fs.c
yaffs_guts.c
yaffs_guts.h
yaffsdev
yaffsdev.c
yaffsdev.proj

diff --git a/Documentation/taffs-todo.html b/Documentation/taffs-todo.html
deleted file mode 100644 (file)
index 1a81f4c..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
-<HTML>
-<HEAD>
-       <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
-       <TITLE></TITLE>
-       <META NAME="GENERATOR" CONTENT="StarOffice/5.2 (Linux)">
-       <META NAME="AUTHOR" CONTENT=" ">
-       <META NAME="CREATED" CONTENT="20020501;19062800">
-       <META NAME="CHANGEDBY" CONTENT=" ">
-       <META NAME="CHANGED" CONTENT="20020513;21165500">
-</HEAD>
-<BODY>
-<P>YAFFS Todo</P>
-<OL>
-       <LI><P>Locking</P>
-       <LI><P>Fix statfs. df does not give correct results.</P>
-       <LI><P>Fix disk full condition. 
-       </P>
-       <LI><P>ECC and write failure handling.</P>
-       <LI><P>Add symlinks and links to VFS interface.</P>
-       <LI><P>Add memory mapping (to allow file execution).</P>
-       <LI><P>Test with nandemul mtd.</P>
-       <LI><P>Discuss improved NAND page interface with mtd group.</P>
-</OL>
-<P>NANDEmul MTD</P>
-<OL>
-       <LI><P>Complete and test.</P>
-       <LI><P></P>
-       <P></P>
-</OL>
-<P><BR><BR>
-</P>
-</BODY>
-</HTML>
\ No newline at end of file
diff --git a/Documentation/yaffs-todo.html b/Documentation/yaffs-todo.html
new file mode 100644 (file)
index 0000000..8489d72
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+<HEAD>
+       <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
+       <TITLE></TITLE>
+       <META NAME="GENERATOR" CONTENT="StarOffice/5.2 (Linux)">
+       <META NAME="AUTHOR" CONTENT=" ">
+       <META NAME="CREATED" CONTENT="20020501;19062800">
+       <META NAME="CHANGEDBY" CONTENT=" ">
+       <META NAME="CHANGED" CONTENT="20020608;9570900">
+</HEAD>
+<BODY>
+<H1>YAFFS Todo as at <SDFIELD TYPE=DATETIME SDNUM="5129;2057;DD/MM/YYYY">08/06/2002</SDFIELD></H1>
+<H3>Stuff not yet done</H3>
+<OL>
+       <LI><P>Directory locking during directory walk.</P>
+       <LI><P>Other locking....</P>
+       <LI><P>Test disk full condition. Might not be being handled
+       correctly.</P>
+       <LI><P>Add write memory mapping.  We probably need this to support
+       loop mounting.</P>
+</OL>
+<H3>Recently done with no known problems (ie. probably needs
+significant testing)</H3>
+<OL>
+       <LI><P>ECC and write failure handling.</P>
+       <LI><P>Added symlinks and hard links to VFS interface.</P>
+       <LI><P>Fixed problem with persistence. Object header was not being
+       updated at end of write and the file size was getting corrupted.</P>
+       <LI><P>Fixed problem where obsoleted object headers were not being
+       deleted on NAND. This caused multiple file entries. Looks like it is
+       working properly now.</P>
+       <LI><P>Read memory mapping. Can now execute a file from yaffs.</P>
+       <LI><P>We now mark a chunk as deleted by marking the OOB data
+       validity flag. Before this we just stomped on the tags, which was
+       mot such a good thing to do with newer NANDs which do not like this
+       sort of thing.</P>
+</OL>
+<H3>Done, but currently known to be broken</H3>
+<OL>
+       <P>nothing.</P>
+</OL>
+<H3>Longer term stuff to do</H3>
+<OL>
+       <LI><P>Discuss improved NAND page interface with mtd group. This has
+       actually started.</P>
+       <LI><P>Pull out all YAFFS_OK and YAFFS_FAIL style errors  and return
+       with -ENOMEM style error messages.</P>
+</OL>
+<P><BR><BR>
+</P>
+</BODY>
+</HTML>
\ No newline at end of file
index d7f5966a3e543810268fcad265a8961d02697785..0872820f8741a1eb258fbd558e718fe7792b8fb4 100644 (file)
@@ -1,6 +1,6 @@
 #########################################################
 # Makefile auto generated by Cygnus Source Navigator.
 #########################################################
 # Makefile auto generated by Cygnus Source Navigator.
-# Target: yaffsdev_disk Date: May 29 2002 Time: 08:12:41 PM
+# Target: yaffsdev_disk Date: Jun 05 2002 Time: 02:41:55 PM
 #
 
 
 #
 
 
index c3f57d7723bc2757030bdd3ef993fc47e9fd37b7..6a2ddb3833f3c1ac20e80377a4cab92cc0ed7271 100644 (file)
@@ -83,11 +83,18 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
 static void yaffs_read_inode (struct inode *inode);
 static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent);
 static void yaffs_put_inode (struct inode *inode);
 static void yaffs_read_inode (struct inode *inode);
 static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent);
 static void yaffs_put_inode (struct inode *inode);
+static int yaffs_readpage(struct file *file, struct page * page);
 
 
-//static int yaffs_readpage(struct file*,struct page *
 
 
-static struct address_space_operations yaffs_address_ops = {
-//     readpage:               yaffs_readpage,
+static int yaffs_readlink(struct dentry *dentry, char *buffer, int buflen);
+static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);
+
+
+
+
+
+static struct address_space_operations yaffs_file_address_operations = {
+       readpage:               yaffs_readpage,
 //     prepare_write:  yaffs_prepare_write,
 //     commit_write:   yaffs_commit_write
 };
 //     prepare_write:  yaffs_prepare_write,
 //     commit_write:   yaffs_commit_write
 };
@@ -96,7 +103,7 @@ static struct address_space_operations yaffs_address_ops = {
 static struct file_operations yaffs_file_operations = {
        read:           yaffs_file_read,
        write:          yaffs_file_write,
 static struct file_operations yaffs_file_operations = {
        read:           yaffs_file_read,
        write:          yaffs_file_write,
-//     mmap:           generic_file_mmap,
+       mmap:           generic_file_mmap,
        fsync:          yaffs_sync_object,
 };
 
        fsync:          yaffs_sync_object,
 };
 
@@ -106,11 +113,11 @@ static struct inode_operations yaffs_file_inode_operations = {
 };
 
 
 };
 
 
-
-static struct file_operations yaffs_dir_operations = {
-       read:           generic_read_dir,
-       readdir:        yaffs_readdir,
-       fsync:          yaffs_sync_object,
+struct inode_operations yaffs_symlink_inode_operations =
+{      
+       readlink:       yaffs_readlink,
+       follow_link:    yaffs_follow_link,
+       setattr:        yaffs_setattr
 };
 
 static struct inode_operations yaffs_dir_inode_operations = {
 };
 
 static struct inode_operations yaffs_dir_inode_operations = {
@@ -126,6 +133,13 @@ static struct inode_operations yaffs_dir_inode_operations = {
        setattr:        yaffs_setattr,
 };
 
        setattr:        yaffs_setattr,
 };
 
+static struct file_operations yaffs_dir_operations = {
+       read:           generic_read_dir,
+       readdir:        yaffs_readdir,
+       fsync:          yaffs_sync_object,
+};
+
+
 static struct super_operations yaffs_super_ops = {
        statfs:                 yaffs_statfs,
        read_inode:             yaffs_read_inode,
 static struct super_operations yaffs_super_ops = {
        statfs:                 yaffs_statfs,
        read_inode:             yaffs_read_inode,
@@ -137,6 +151,39 @@ static struct super_operations yaffs_super_ops = {
 };
 
 
 };
 
 
+
+
+
+static int yaffs_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+       unsigned char *alias;
+       int ret;
+
+       alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
+       
+       if(!alias)
+               return -ENOMEM;
+
+       ret = vfs_readlink(dentry, buffer, buflen, alias);
+       kfree(alias);
+       return ret;
+}
+
+static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+       unsigned char *alias;
+       int ret;
+       alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
+       
+       if(!alias)
+               return -ENOMEM;
+
+       ret = vfs_follow_link(nd,alias);
+       kfree(alias);
+       return ret;
+}
+
+
 struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj);
 
 /*
 struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj);
 
 /*
@@ -152,6 +199,8 @@ static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry)
        
        obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir),dentry->d_name.name);
        
        
        obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir),dentry->d_name.name);
        
+       obj = yaffs_GetEquivalentObject(obj); // in case it was a hardlink
+       
        if(obj)
        {
                T((KERN_DEBUG"yaffs_lookup found %d\n",obj->objectId));
        if(obj)
        {
                T((KERN_DEBUG"yaffs_lookup found %d\n",obj->objectId));
@@ -185,15 +234,52 @@ static void yaffs_put_inode(struct inode *inode)
        
 }
 
        
 }
 
-#ifdef YAFFS_ADDRESS_OPS
-static int yaffs_readpage(struct file *file, struct page * page)
+
+
+static int yaffs_readpage(struct file *f, struct page * pg)
 {
 {
-       T((KERN_DEBUG"yaffs_readpage\n"));
+       struct yaffs_Object *obj;
+       unsigned char *pg_buf;  
+       int ret;
+       
+       T((KERN_DEBUG"yaffs_readpage at %08x, size %08x\n", 
+                     pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE));
 
 
-       // TODO
-       return 0;
+       obj  = yaffs_DentryToObject(f->f_dentry);
+
+       //down(obj->sem);
+       
+       if (!PageLocked(pg))
+                PAGE_BUG(pg);
+
+       pg_buf = kmap(pg);
+       /* FIXME: Can kmap fail? */
+
+       ret = yaffs_ReadDataFromFile(obj,pg_buf, pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE);
+
+       if(ret >= 0) ret = 0;
+
+       if (ret) {
+               ClearPageUptodate(pg);
+               SetPageError(pg);
+       } else {
+               SetPageUptodate(pg);
+               ClearPageError(pg);
+       }
+
+       flush_dcache_page(pg);
+       kunmap(pg);
+
+       UnlockPage(pg);
+
+       //up(&obj->sem);
+
+       T((KERN_DEBUG"yaffs_readpage done\n"));
+       return ret;
 }
 
 }
 
+#ifdef YAFFS_ADDRESS_OPS
+
 static int yaffs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
        T((KERN_DEBUG"yaffs_prepare_write\n"));
 static int yaffs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
        T((KERN_DEBUG"yaffs_prepare_write\n"));
@@ -227,7 +313,6 @@ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj)
                inode->i_blksize = YAFFS_BYTES_PER_CHUNK;
                inode->i_blocks = 0;
                inode->i_rdev = NODEV;
                inode->i_blksize = YAFFS_BYTES_PER_CHUNK;
                inode->i_blocks = 0;
                inode->i_rdev = NODEV;
-               inode->i_mapping->a_ops = &yaffs_address_ops;
                inode->i_atime = obj->st_atime;
                inode->i_mtime = obj->st_mtime;
                inode->i_ctime = obj->st_ctime;
                inode->i_atime = obj->st_atime;
                inode->i_mtime = obj->st_mtime;
                inode->i_ctime = obj->st_ctime;
@@ -240,18 +325,19 @@ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj)
                switch (obj->st_mode & S_IFMT) 
                {
                        default:
                switch (obj->st_mode & S_IFMT) 
                {
                        default:
-                       //      init_special_inode(inode, mode, dev);
+                               //      init_special_inode(inode, mode, dev);
                                break;
                        case S_IFREG:   // file         
                                inode->i_op = &yaffs_file_inode_operations;
                                inode->i_fop = &yaffs_file_operations;
                                break;
                        case S_IFREG:   // file         
                                inode->i_op = &yaffs_file_inode_operations;
                                inode->i_fop = &yaffs_file_operations;
+                               inode->i_mapping->a_ops = &yaffs_file_address_operations;
                                break;
                        case S_IFDIR:   // directory
                                inode->i_op = &yaffs_dir_inode_operations;
                                inode->i_fop = &yaffs_dir_operations;
                                break;
                        case S_IFLNK:   // symlink
                                break;
                        case S_IFDIR:   // directory
                                inode->i_op = &yaffs_dir_inode_operations;
                                inode->i_fop = &yaffs_dir_operations;
                                break;
                        case S_IFLNK:   // symlink
-                               inode->i_op = &page_symlink_inode_operations;
+                               inode->i_op = &yaffs_symlink_inode_operations;
                                break;
                }
                
                                break;
                }
                
@@ -458,16 +544,13 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int d
                        break;
                case S_IFLNK:   // symlink
                        T((KERN_DEBUG"yaffs_mknod: making file\n"));
                        break;
                case S_IFLNK:   // symlink
                        T((KERN_DEBUG"yaffs_mknod: making file\n"));
-                       obj = NULL; // Todo
+                       obj = NULL; // Do we ever get here?
                        break;
        }
        
        if(obj)
        {
                inode = yaffs_get_inode(dir->i_sb, mode, dev, obj);
                        break;
        }
        
        if(obj)
        {
                inode = yaffs_get_inode(dir->i_sb, mode, dev, obj);
-
-// did not fix dir bug         if((mode & S_IFMT) == S_IFDIR)  atomic_inc(&inode->i_count);
-
                d_instantiate(dentry, inode);
                T((KERN_DEBUG"yaffs_mknod created object %d count = %d\n",obj->objectId,atomic_read(&inode->i_count)));
                error = 0;
                d_instantiate(dentry, inode);
                T((KERN_DEBUG"yaffs_mknod created object %d count = %d\n",obj->objectId,atomic_read(&inode->i_count)));
                error = 0;
@@ -521,36 +604,52 @@ static int yaffs_unlink(struct inode * dir, struct dentry *dentry)
 
 
 /*
 
 
 /*
- * Link a file..
+ * Create a link...
  */
 static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry)
 {
        struct inode *inode = old_dentry->d_inode;
  */
 static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry)
 {
        struct inode *inode = old_dentry->d_inode;
+       yaffs_Object *obj = NULL;
+       yaffs_Object *link=NULL;
        
        T((KERN_DEBUG"yaffs_link\n"));
        
        
        T((KERN_DEBUG"yaffs_link\n"));
        
-       return -EPERM; //Todo
+       obj = yaffs_InodeToObject(inode);
        
        
-
-       if (S_ISDIR(inode->i_mode))
-               return -EPERM;
-
-
-       return 0;
+       link = yaffs_Link(yaffs_InodeToObject(dir),dentry->d_name.name,obj);
+       
+       if(link)
+       {
+               return 0;
+       }
+       
+       
+       return -EPERM; 
 }
 
 
 static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
 {
 }
 
 
 static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
 {
-       int error;
+       yaffs_Object *obj;
        
        T((KERN_DEBUG"yaffs_symlink\n"));
        
        T((KERN_DEBUG"yaffs_symlink\n"));
-
        
        
-       return -ENOMEM; //Todo
+       obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name, 
+                                                        S_IFLNK | S_IRWXUGO, current->uid, current->gid,
+                                                        symname);
 
 
-       error = yaffs_mknod(dir, dentry, S_IFLNK | S_IRWXUGO, 0);
-       return error;
+       if(obj)
+       {
+               T((KERN_DEBUG"symlink created OK\n"));
+               return 0;
+       }
+       else
+       {
+               T((KERN_DEBUG"symlink not created\n"));
+
+       }
+       
+       return -ENOMEM;
 }
 
 static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync)
 }
 
 static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync)
index 88b02a3659cf7b51da032b6d0bf31ba7d2991dcc..4c7e81af75ef9b1c136ec0a4b464cde7272c3ba5 100644 (file)
@@ -75,7 +75,6 @@ static int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name);
 static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId);
 static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj);
 static int yaffs_CheckStructures(void);
 static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId);
 static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj);
 static int yaffs_CheckStructures(void);
-static yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj);
 
 loff_t yaffs_GetFileSize(yaffs_Object *obj);
 
 
 loff_t yaffs_GetFileSize(yaffs_Object *obj);
 
@@ -1127,6 +1126,12 @@ yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type,
 
        yaffs_Device *dev = parent->myDev;
        
 
        yaffs_Device *dev = parent->myDev;
        
+       // Check if the entry exists. If it does then fail the call since we don't want a dup.
+       if(yaffs_FindObjectByName(parent,name))
+       {
+               return NULL;
+       }
+       
        in = yaffs_CreateNewObject(dev,-1,type);
        
        if(in)
        in = yaffs_CreateNewObject(dev,-1,type);
        
        if(in)
@@ -1221,7 +1226,10 @@ static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const
                obj->dirty = 1;
                yaffs_AddObjectToDirectory(newDir,obj);
                
                obj->dirty = 1;
                yaffs_AddObjectToDirectory(newDir,obj);
                
-               return yaffs_UpdateObjectHeader(obj,newName);   
+               if(yaffs_UpdateObjectHeader(obj,newName) >= 0)
+               {
+                       return YAFFS_OK;
+               }
        }
        
        return YAFFS_FAIL;
        }
        
        return YAFFS_FAIL;
@@ -1631,6 +1639,7 @@ static int yaffs_ReadChunkTagsFromNAND(yaffs_Device *dev,int chunkInNAND, yaffs_
        return YAFFS_OK;
 }
 
        return YAFFS_OK;
 }
 
+#if 0
 static int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND, const __u8 *buffer, yaffs_Tags *tags)
 {
        // NB There must be tags, data is optional
 static int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND, const __u8 *buffer, yaffs_Tags *tags)
 {
        // NB There must be tags, data is optional
@@ -1656,6 +1665,8 @@ static int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND, con
        return yaffs_WriteChunkToNAND(dev,chunkInNAND,buffer,&spare);
        
 }
        return yaffs_WriteChunkToNAND(dev,chunkInNAND,buffer,&spare);
        
 }
+#endif
+
 
 static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device *dev, const __u8 *buffer, yaffs_Tags *tags, int useReserve)
 {
 
 static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device *dev, const __u8 *buffer, yaffs_Tags *tags, int useReserve)
 {
@@ -1921,18 +1932,18 @@ static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId)
 {
        int block = chunkId / YAFFS_CHUNKS_PER_BLOCK;
        int page = chunkId % YAFFS_CHUNKS_PER_BLOCK;
 {
        int block = chunkId / YAFFS_CHUNKS_PER_BLOCK;
        int page = chunkId % YAFFS_CHUNKS_PER_BLOCK;
-       yaffs_Tags tags;
+       yaffs_Spare spare;
+               
+       yaffs_SpareInitialise(&spare);
        
        
-       // Mark the deleted NAND page as deleted
-       tags.chunkId = 0;
-       tags.objectId = 0;
-       tags.byteCount = 0;
-       tags.ecc = 0;
+       spare.pageStatus = 0; // To mark it as deleted.
+
        
        
-       yaffs_WriteChunkWithTagsToNAND(dev,chunkId,NULL,&tags); 
+       yaffs_WriteChunkToNAND(dev,chunkId,NULL,&spare);
                        
        
        // Pull out of the management area.
                        
        
        // Pull out of the management area.
+       // If the whole block became dirty, this will kick off an erasure.
        if(     dev->blockInfo[block].blockState == YAFFS_BLOCK_STATE_ALLOCATING ||
            dev->blockInfo[block].blockState == YAFFS_BLOCK_STATE_FULL)
        {
        if(     dev->blockInfo[block].blockState == YAFFS_BLOCK_STATE_ALLOCATING ||
            dev->blockInfo[block].blockState == YAFFS_BLOCK_STATE_FULL)
        {
@@ -2573,12 +2584,14 @@ static int yaffs_UnlinkWorker(yaffs_Object *obj)
                char name[YAFFS_MAX_NAME_LENGTH+1];
                
                hl = list_entry(obj->hardLinks.next,yaffs_Object,hardLinks);
                char name[YAFFS_MAX_NAME_LENGTH+1];
                
                hl = list_entry(obj->hardLinks.next,yaffs_Object,hardLinks);
+               
                list_del_init(&hl->hardLinks);
                list_del_init(&hl->siblings);
                
                yaffs_GetObjectName(hl,name,YAFFS_MAX_NAME_LENGTH+1);
                
                retVal = yaffs_ChangeObjectName(obj, hl->parent, name);
                list_del_init(&hl->hardLinks);
                list_del_init(&hl->siblings);
                
                yaffs_GetObjectName(hl,name,YAFFS_MAX_NAME_LENGTH+1);
                
                retVal = yaffs_ChangeObjectName(obj, hl->parent, name);
+               
                if(retVal == YAFFS_OK)
                {
                        retVal = yaffs_DoGenericObjectDeletion(hl);
                if(retVal == YAFFS_OK)
                {
                        retVal = yaffs_DoGenericObjectDeletion(hl);
@@ -2636,12 +2649,12 @@ static int yaffs_Scan(yaffs_Device *dev)
        int chunk;
        int c;
        int deleted;
        int chunk;
        int c;
        int deleted;
-       int inuse;
        yaffs_BlockState state;
        yaffs_Object *hardList = NULL;
        yaffs_Object *hl;
        
        yaffs_BlockState state;
        yaffs_Object *hardList = NULL;
        yaffs_Object *hl;
        
-       __u32 pageBits;
+//     int inuse;
+//     __u32 pageBits;
        
        yaffs_ObjectHeader *oh;
        yaffs_Object *in;
        
        yaffs_ObjectHeader *oh;
        yaffs_Object *in;
@@ -2649,18 +2662,24 @@ static int yaffs_Scan(yaffs_Device *dev)
        
        __u8 chunkData[YAFFS_BYTES_PER_CHUNK];
        
        
        __u8 chunkData[YAFFS_BYTES_PER_CHUNK];
        
+       
+       // Scan all the blocks...
+       
        for(blk = dev->startBlock; blk <= dev->endBlock; blk++)
        {
                deleted = 0;
        for(blk = dev->startBlock; blk <= dev->endBlock; blk++)
        {
                deleted = 0;
-               pageBits = 0;
-               inuse = 0;
-               state = YAFFS_BLOCK_STATE_UNKNOWN;
+               dev->blockInfo[blk].pageBits = 0;
+               dev->blockInfo[blk].pagesInUse = 0;
+               state = YAFFS_BLOCK_STATE_SCANNING;
+               
+               // Read each chunk in the block.
                
                for(c = 0; c < YAFFS_CHUNKS_PER_BLOCK && 
                
                for(c = 0; c < YAFFS_CHUNKS_PER_BLOCK && 
-                                  state == YAFFS_BLOCK_STATE_UNKNOWN; c++)
+                                  state == YAFFS_BLOCK_STATE_SCANNING; c++)
                {
                        // Read the spare area and decide what to do
                        chunk = blk * YAFFS_CHUNKS_PER_BLOCK + c;
                {
                        // Read the spare area and decide what to do
                        chunk = blk * YAFFS_CHUNKS_PER_BLOCK + c;
+                       
                        yaffs_ReadChunkFromNAND(dev,chunk,NULL,&spare);
 
                        
                        yaffs_ReadChunkFromNAND(dev,chunk,NULL,&spare);
 
                        
@@ -2670,7 +2689,14 @@ static int yaffs_Scan(yaffs_Device *dev)
                                // This block looks ok, now what's in this chunk?
                                yaffs_GetTagsFromSpare(&spare,&tags);
                                
                                // This block looks ok, now what's in this chunk?
                                yaffs_GetTagsFromSpare(&spare,&tags);
                                
-                               if(tags.objectId == YAFFS_UNUSED_OBJECT_ID)
+                               if(yaffs_countBits[spare.pageStatus] < 6)
+                               {
+                                       // A deleted chunk
+                                       deleted++;
+                                       dev->nFreeChunks ++;
+                                       T((" %d %d deleted\n",blk,c));
+                               }
+                               else if(tags.objectId == YAFFS_UNUSED_OBJECT_ID)
                                {
                                        // An unassigned chunk in the block
                                        // This means that either the block is empty or 
                                {
                                        // An unassigned chunk in the block
                                        // This means that either the block is empty or 
@@ -2693,20 +2719,14 @@ static int yaffs_Scan(yaffs_Device *dev)
 
                                        dev->nFreeChunks += (YAFFS_CHUNKS_PER_BLOCK - c);
                                }
 
                                        dev->nFreeChunks += (YAFFS_CHUNKS_PER_BLOCK - c);
                                }
-                               else if(tags.objectId == 0)
-                               {
-                                       // A deleted chunk
-                                       deleted++;
-                                       dev->nFreeChunks ++;
-                                       T((" %d %d deleted\n",blk,c));
-                               }
                                else if(tags.chunkId > 0)
                                {
                                        // A data chunk.
                                else if(tags.chunkId > 0)
                                {
                                        // A data chunk.
-                                       inuse++;
-                                       pageBits |= ( 1 <<c);                           
+                                       dev->blockInfo[blk].pageBits |= (1 << c);
+                                       dev->blockInfo[blk].pagesInUse++;
+                                                                       
                                        in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,YAFFS_OBJECT_TYPE_FILE);
                                        in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,YAFFS_OBJECT_TYPE_FILE);
-                                       // PutChuunkIntoFIle checks for a clash (two data chunks with
+                                       // PutChunkIntoFIle checks for a clash (two data chunks with
                                        // the same chunkId).
                                        yaffs_PutChunkIntoFile(in,tags.chunkId,chunk,1);
                                        T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId));    
                                        // the same chunkId).
                                        yaffs_PutChunkIntoFile(in,tags.chunkId,chunk,1);
                                        T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId));    
@@ -2714,78 +2734,99 @@ static int yaffs_Scan(yaffs_Device *dev)
                                else
                                {
                                        // chunkId == 0, so it is an ObjectHeader.
                                else
                                {
                                        // chunkId == 0, so it is an ObjectHeader.
-                                       inuse++;                                
-                                       pageBits |= ( 1 <<c);                           
+                                       // Thus, we read in the object header and make the object
+                                       dev->blockInfo[blk].pageBits |= (1 << c);
+                                       dev->blockInfo[blk].pagesInUse++;
+                                                               
                                        yaffs_ReadChunkFromNAND(dev,chunk,chunkData,NULL);
                                        yaffs_ReadChunkFromNAND(dev,chunk,chunkData,NULL);
+                                       
                                        oh = (yaffs_ObjectHeader *)chunkData;
                                        
                                        in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,oh->type);
                                        oh = (yaffs_ObjectHeader *)chunkData;
                                        
                                        in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,oh->type);
+                                       
                                        if(in->valid)
                                        {
                                        if(in->valid)
                                        {
-                                               // todo we have already filled this one. We have
-                                               // a duplicate. Need to fix
+                                               // 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->chunkId);
+                                                       in->valid = 0;
+                                               }
+                                               else
+                                               {
+                                                       // Use existing - destroy this one.
+                                                       yaffs_DeleteChunk(dev,chunk);
+                                               }
                                        }
                                        
                                        }
                                        
-                                       // we don't have a duplicate...
+                                       if(!in->valid)
+                                       {
+                                               // we need to load this info
                                        
                                        
-                                       in->valid = 1;
-                                       in->variantType = oh->type;
-               
-                                       in->st_mode  = oh->st_mode;
-                                       in->st_uid   = oh->st_uid;
-                                       in->st_gid   = oh->st_gid;
-                                       in->st_atime = oh->st_atime;
-                                       in->st_mtime = oh->st_mtime;
-                                       in->st_ctime = oh->st_ctime;
-                                       in->chunkId  = chunk;
-
-                                       in->sum = oh->sum;
-                                       in->dirty = 0;
+                                               in->valid = 1;
+                                               in->variantType = oh->type;
+               
+                                               in->st_mode  = oh->st_mode;
+                                               in->st_uid   = oh->st_uid;
+                                               in->st_gid   = oh->st_gid;
+                                               in->st_atime = oh->st_atime;
+                                               in->st_mtime = oh->st_mtime;
+                                               in->st_ctime = oh->st_ctime;
+                                               in->chunkId  = chunk;
+
+                                               in->sum = oh->sum;
+                                               in->dirty = 0;
                                                                
                                                                
-                                       // directory stuff...
-                                       // hook up to parent
-               
-                                       parent = yaffs_FindOrCreateObjectByNumber(dev,oh->parentObjectId,YAFFS_OBJECT_TYPE_DIRECTORY);
-                                       if(parent->variantType == YAFFS_OBJECT_TYPE_UNKNOWN)
-                                       {
-                                               // Set up as a directory
-                                               parent->variantType = YAFFS_OBJECT_TYPE_DIRECTORY;
-                                               INIT_LIST_HEAD(&parent->variant.directoryVariant.children);
-                                       }
-                                       else if(parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
-                                       {
-                                               // Hoosterman, another problem....
-                                               // We're trying to use a non-directory as a directory
-                                               // Todo ... handle
-                                       }
+                                               // directory stuff...
+                                               // hook up to parent
+               
+                                               parent = yaffs_FindOrCreateObjectByNumber(dev,oh->parentObjectId,YAFFS_OBJECT_TYPE_DIRECTORY);
+                                               if(parent->variantType == YAFFS_OBJECT_TYPE_UNKNOWN)
+                                               {
+                                                       // Set up as a directory
+                                                       parent->variantType = YAFFS_OBJECT_TYPE_DIRECTORY;
+                                                       INIT_LIST_HEAD(&parent->variant.directoryVariant.children);
+                                               }
+                                               else if(parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
+                                               {
+                                                       // Hoosterman, another problem....
+                                                       // We're trying to use a non-directory as a directory
+                                                       // Todo ... handle
+                                               }
                                        
                                        
-                                       yaffs_AddObjectToDirectory(parent,in);  
+                                               yaffs_AddObjectToDirectory(parent,in);  
                                        
                                        
-                                       // 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:
-                                                       in->variant.fileVariant.fileSize = oh->fileSize;
-                                                       break;
-                                               case YAFFS_OBJECT_TYPE_HARDLINK:
-                                                       in->variant.hardLinkVariant.equivalentObjectId = oh->equivalentObjectId;
-                                                       (yaffs_Object *)(in->hardLinks.next) = hardList;
-                                                       hardList = in;
-                                                       break;
-                                               case YAFFS_OBJECT_TYPE_DIRECTORY:       // Do nothing
-                                                       break;
-                                               case YAFFS_OBJECT_TYPE_SYMLINK:         // Do nothing
-                                                       in->variant.symLinkVariant.alias = yaffs_CloneString(oh->alias);
-                                                       break;
+                                               // 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:
+                                                               in->variant.fileVariant.fileSize = oh->fileSize;
+                                                               break;
+                                                       case YAFFS_OBJECT_TYPE_HARDLINK:
+                                                               in->variant.hardLinkVariant.equivalentObjectId = oh->equivalentObjectId;
+                                                               (yaffs_Object *)(in->hardLinks.next) = hardList;
+                                                               hardList = in;
+                                                               break;
+                                                       case YAFFS_OBJECT_TYPE_DIRECTORY:       // Do nothing
+                                                               break;
+                                                       case YAFFS_OBJECT_TYPE_SYMLINK:         // Do nothing
+                                                               in->variant.symLinkVariant.alias = yaffs_CloneString(oh->alias);
+                                                               break;
+                                               }
+                                               T((" %d %d header %d \"%s\" type %d\n",blk,c,tags.objectId,oh->name,in->variantType));  
                                        }
                                        }
-                                       T((" %d %d header %d \"%s\" type %d\n",blk,c,tags.objectId,oh->name,in->variantType));  
                                }
                        }
                        else
                                }
                        }
                        else
@@ -2795,21 +2836,26 @@ static int yaffs_Scan(yaffs_Device *dev)
                        }                       
                }
                
                        }                       
                }
                
-               if(state == YAFFS_BLOCK_STATE_UNKNOWN)
+               if(state == YAFFS_BLOCK_STATE_SCANNING)
                {
                {
-                       // If we got this far, then the block is fully allocated.
-                       // ie. Full or Dirty
-                       state = (inuse) ? YAFFS_BLOCK_STATE_FULL : YAFFS_BLOCK_STATE_DIRTY;
-       
+                       // If we got this far while scanning, then the block is fully allocated.
+                       state = YAFFS_BLOCK_STATE_FULL; 
                }
                
                }
                
-               dev->blockInfo[blk].pageBits = pageBits;
-               dev->blockInfo[blk].pagesInUse = inuse;
                dev->blockInfo[blk].blockState = state;
                
                dev->blockInfo[blk].blockState = state;
                
+               // Now let's see if it was dirty
+               if(     dev->blockInfo[blk].pagesInUse == 0 &&
+               dev->blockInfo[blk].blockState == YAFFS_BLOCK_STATE_FULL)
+           {
+               yaffs_BlockBecameDirty(dev,blk);
+           }
+
        }
        
        }
        
-       // Todo fix up the hard link chains
+       // Fix up the hard link chains.
+       // We should now have scanned all the objects, now it's time to add these 
+       // hardlinks.
        while(hardList)
        {
                hl = hardList;
        while(hardList)
        {
                hl = hardList;
@@ -2819,12 +2865,14 @@ static int yaffs_Scan(yaffs_Device *dev)
                
                if(in)
                {
                
                if(in)
                {
+                       // Add the hardlink pointers
                        hl->variant.hardLinkVariant.equivalentObject=in;
                        list_add(&hl->hardLinks,&in->hardLinks);
                }
                else
                {
                        hl->variant.hardLinkVariant.equivalentObject=in;
                        list_add(&hl->hardLinks,&in->hardLinks);
                }
                else
                {
-                       //Todo Need to report this better.
+                       //Todo Need to report/handle this better.
+                       // Got a problem... hardlink to a non-existant object
                        hl->variant.hardLinkVariant.equivalentObject=NULL;
                        INIT_LIST_HEAD(&hl->hardLinks);
                        
                        hl->variant.hardLinkVariant.equivalentObject=NULL;
                        INIT_LIST_HEAD(&hl->hardLinks);
                        
@@ -2930,7 +2978,7 @@ int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir,int (*fn)(yaffs_Object *
 // GetEquivalentObject dereferences any hard links to get to the
 // actual object.
 
 // GetEquivalentObject dereferences any hard links to get to the
 // actual object.
 
-static yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj)
+yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj)
 {
        if(obj && obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
        {
 {
        if(obj && obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
        {
@@ -3092,8 +3140,8 @@ int yaffs_DumpObject(yaffs_Object *obj)
        
        yaffs_GetObjectName(obj,name,256);
        
        
        yaffs_GetObjectName(obj,name,256);
        
-       YPRINTF(("Object %d \"%s\"\n dirty %d valid %d serial %d sum %d chunk %d type %d size %d\n",
-                       yaffs_GetObjectInode(obj), name, obj->dirty, obj->valid, obj->serial, 
+       YPRINTF(("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d chunk %d type %d size %d\n",
+                       obj->objectId,yaffs_GetObjectInode(obj), name, obj->dirty, obj->valid, obj->serial, 
                        obj->sum, obj->chunkId, yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj)));
 
 #if 0
                        obj->sum, obj->chunkId, yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj)));
 
 #if 0
index 7b059aacd6be6d03d8685147e05bb704c16c1d99..3ae36e7214d16dc622d16b52678546925e63e460 100644 (file)
@@ -108,7 +108,9 @@ typedef struct
 // Block data in RAM
 
 typedef enum {
 // Block data in RAM
 
 typedef enum {
-       YAFFS_BLOCK_STATE_UNKNOWN       = 0,
+       YAFFS_BLOCK_STATE_UddNKNOWN     = 0,
+       YAFFS_BLOCK_STATE_SCANNING,             // Used while the block is being scanned.
+                                                                       // NB Don't erase blocks while they're being scanned
        
        YAFFS_BLOCK_STATE_EMPTY,                // This block is empty
        
        
        YAFFS_BLOCK_STATE_EMPTY,                // This block is empty
        
@@ -420,6 +422,8 @@ yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev,int number);
 // Link operations
 yaffs_Object *yaffs_Link(yaffs_Object *parent, const char *name, yaffs_Object *equivalentObject);
 
 // Link operations
 yaffs_Object *yaffs_Link(yaffs_Object *parent, const char *name, yaffs_Object *equivalentObject);
 
+yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj);
+
 // Symlink operations
 yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const char *name, __u32 mode,  __u32 uid, __u32 gid, const char *alias);
 char *yaffs_GetSymlinkAlias(yaffs_Object *obj);
 // Symlink operations
 yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const char *name, __u32 mode,  __u32 uid, __u32 gid, const char *alias);
 char *yaffs_GetSymlinkAlias(yaffs_Object *obj);
index 70d4cc2136bc2f54eedded57b3a4a67290d7ee49..14777893ae8c047ed075a43b3ff7bbfad91a2087 100755 (executable)
Binary files a/yaffsdev and b/yaffsdev differ
index e38a98330a5f04b2f4139ea86a3a431dd71e8be1..9675dabfd7b04c46f038de1f0e76b3630be5903a 100644 (file)
@@ -155,8 +155,16 @@ void TestTime(yaffs_Device *dev)
        int written;
        
        
        int written;
        
        
+       printf("Exisiting objects\n");
+       yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
+       printf("Exisiting objects in lost+found\n");
+       lnf = yaffs_FindObjectByName(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME);
+       yaffs_ApplyToDirectoryChildren(lnf,yaffs_DumpObject);
+
        printf("Start\n");
        
        printf("Start\n");
        
+       
+       
 
        f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
        if(f)
 
        f = yaffs_FindObjectByName(yaffs_Root(dev),"Name1");
        if(f)
@@ -285,6 +293,10 @@ void TestTime(yaffs_Device *dev)
        x = yaffs_RenameObject(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME,NULL,"Renamed");
        yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
 
        x = yaffs_RenameObject(yaffs_Root(dev),YAFFS_LOSTNFOUND_NAME,NULL,"Renamed");
        yaffs_ApplyToDirectoryChildren(yaffs_Root(dev),yaffs_DumpObject);
 
+       f = yaffs_MknodFile(yaffs_Root(dev),"pfile",0,0,0);
+       yaffs_WriteDataToFile(f,testStr,0,strlen(testStr));
+
+       yaffs_Link(yaffs_Root(dev),"phl4",f);
 }
 
 int main(int argc,char *argv[])
 }
 
 int main(int argc,char *argv[])
index fc2bac33a6995411fcd1a8d65cf58e8f071abf2c..e3e07f414dd3e0e9d25092f5de900db17f85a5be 100644 (file)
Binary files a/yaffsdev.proj and b/yaffsdev.proj differ