mtd/fs/jffs2 background.c,1.31,1.32 build.c,1.41,1.42 erase.c,1.42,1.43 gc.c,1.84,1.85 nodelist.c,1.61,1.62 nodelist.h,1.83,1.84 nodemgmt.c,1.77,1.78 readinode.c,1.90,1.91 scan.c,1.91,1.92 write.c,1.59,1.60

David Woodhouse dwmw2 at infradead.org
Mon Sep 9 12:29:11 EDT 2002


Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv25358/fs/jffs2

Modified Files:
	background.c build.c erase.c gc.c nodelist.c nodelist.h 
	nodemgmt.c readinode.c scan.c write.c 
Log Message:
Wheee. Late checking of CRC makes the mount time somewhat better. We can improve this
but it's OK as a proof-of-concept.

Some benchmark times on recent code changes with a 14M mtdram device (hence not a great
deal of improvement from point code):

point, list code  0.291s
read,  list code  0.299s
point, tree code  0.282s
read,  tree code  0.292s
point, tree, no data crc 0.123s
point, tree, no inode crc 0.112s
point, tree, scan just-in-time 0.080s
point, tree, scan just-in-time, D1(PARANOIA), 0.050s


Index: background.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/background.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- background.c	20 Aug 2002 15:41:28 -0000	1.31
+++ background.c	9 Sep 2002 16:29:08 -0000	1.32
@@ -156,6 +156,12 @@
 {
 	int ret = 0;
 
+	if (c->unchecked_size) {
+		D1(printk(KERN_DEBUG "thread_should_wake(): unchecked_size %d, checked_ino #%d\n",
+			  c->unchecked_size, c->checked_ino));
+		return 1;
+	}
+
 	if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER && 
 			(c->dirty_size > c->sector_size)) 
 		ret = 1;

Index: build.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/build.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -r1.41 -r1.42
--- build.c	6 Sep 2002 14:12:44 -0000	1.41
+++ build.c	9 Sep 2002 16:29:08 -0000	1.42
@@ -44,8 +44,8 @@
 
 	D1(printk(KERN_DEBUG "Scanned flash completely\n"));
 	D1(jffs2_dump_block_lists(c));
-	/* Now build the data map for each inode, marking obsoleted nodes
-	   as such, and also increase nlink of any children. */
+
+	/* Now scan the directory tree, increasing nlink according to every dirent found. */
 	for_each_inode(i, c, ic) {
 		D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino));
 		ret = jffs2_build_inode_pass1(c, ic);
@@ -57,7 +57,7 @@
 	}
 	D1(printk(KERN_DEBUG "Pass 1 complete\n"));
 	D1(jffs2_dump_block_lists(c));
-	
+
 	/* Next, scan for inodes with nlink == 0 and remove them. If
 	   they were directories, then decrement the nlink of their
 	   children too, and repeat the scan. As that's going to be
@@ -90,22 +90,15 @@
 	
 	/* Finally, we can scan again and free the dirent nodes and scan_info structs */
 	for_each_inode(i, c, ic) {
-		struct jffs2_scan_info *scan = ic->scan;
 		struct jffs2_full_dirent *fd;
 		D1(printk(KERN_DEBUG "Pass 3: ino #%u, ic %p, nodes %p\n", ic->ino, ic, ic->nodes));
-		if (!scan) {
-			if (ic->nlink) {
-				D1(printk(KERN_WARNING "Why no scan struct for ino #%u which has nlink %d?\n", ic->ino, ic->nlink));
-			}
-			continue;
-		}
-		ic->scan = NULL;
-		while(scan->dents) {
-			fd = scan->dents;
-			scan->dents = fd->next;
+
+		while(ic->scan_dents) {
+			fd = ic->scan_dents;
+			ic->scan_dents = fd->next;
 			jffs2_free_full_dirent(fd);
 		}
-		kfree(scan);
+		ic->scan_dents = NULL;
 		cond_resched();
 	}
 	D1(printk(KERN_DEBUG "Pass 3 complete\n"));
@@ -116,73 +109,18 @@
 
 	return ret;
 }
-	
+
 int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
 {
-	struct jffs2_tmp_dnode_info *tn;
 	struct jffs2_full_dirent *fd;
-	rb_root_t fragtree = RB_ROOT;
-	struct jffs2_tmp_dnode_info *metadata = NULL;
 
 	D1(printk(KERN_DEBUG "jffs2_build_inode building inode #%u\n", ic->ino));
+
 	if (ic->ino > c->highest_ino)
 		c->highest_ino = ic->ino;
 
-	if (!ic->scan->tmpnodes && ic->ino != 1) {
-		D1(printk(KERN_DEBUG "jffs2_build_inode: ino #%u has no data nodes!\n", ic->ino));
-	}
-	/* Build the list to make sure any obsolete nodes are marked as such */
-	while(ic->scan->tmpnodes) {
-		tn = ic->scan->tmpnodes;
-		ic->scan->tmpnodes = tn->next;
-		
-		if (metadata && tn->version > metadata->version) {
-			D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring old metadata at 0x%08x\n",
-				  ref_offset(metadata->fn->raw)));
-			
-			jffs2_mark_node_obsolete(c, metadata->fn->raw);
-			jffs2_free_full_dnode(metadata->fn);
-			jffs2_free_tmp_dnode_info(metadata);
-			metadata = NULL;
-		}
-			
-		if (tn->fn->size) {
-			jffs2_add_full_dnode_to_fraglist (c, &fragtree, tn->fn);
-			jffs2_free_tmp_dnode_info(tn);
-		} else {
-			if (!metadata) {
-				metadata = tn;
-			} else {
-				/* This will only happen if it has the _same_ version
-				   number as the existing metadata node. */
-				D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring new metadata at 0x%08x\n",
-					  ref_offset(tn->fn->raw)));
-				
-				jffs2_mark_node_obsolete(c, tn->fn->raw);
-				jffs2_free_full_dnode(tn->fn);
-				jffs2_free_tmp_dnode_info(tn);
-			}
-		}
-	}
-
-	if (ic->scan->version) {
-		/* It's a regular file, so truncate it to the last known
-		   i_size, if necessary */
-		D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 truncating fraglist to 0x%08x\n", ic->scan->isize));
-		jffs2_truncate_fraglist(c, &fragtree, ic->scan->isize);
-	}
-	
-	/* OK. Now clear up */
-	if (metadata) {
-		jffs2_free_full_dnode(metadata->fn);
-		jffs2_free_tmp_dnode_info(metadata);
-	}
-	metadata = NULL;
-
-	jffs2_kill_fragtree(&fragtree, NULL);
-
-	/* Now for each child, increase nlink */
-	for(fd=ic->scan->dents; fd; fd = fd->next) {
+	/* For each child, increase nlink */
+	for(fd=ic->scan_dents; fd; fd = fd->next) {
 		struct jffs2_inode_cache *child_ic;
 		if (!fd->ino)
 			continue;
@@ -216,11 +154,6 @@
 	struct jffs2_full_dirent *fd;
 	int ret = 0;
 
-	if(!ic->scan) {
-		D1(printk(KERN_DEBUG "ino #%u was already removed\n", ic->ino));
-		return 0;
-	}
-
 	D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino));
 	
 	for (raw = ic->nodes; raw != (void *)ic; raw = raw->next_in_ino) {
@@ -228,15 +161,15 @@
 		jffs2_mark_node_obsolete(c, raw);
 	}
 
-	if (ic->scan->dents) {
+	if (ic->scan_dents) {
 		int whinged = 0;
 		D1(printk(KERN_DEBUG "Inode #%u was a directory which may have children...\n", ic->ino));
 
-		while(ic->scan->dents) {
+		while(ic->scan_dents) {
 			struct jffs2_inode_cache *child_ic;
 
-			fd = ic->scan->dents;
-			ic->scan->dents = fd->next;
+			fd = ic->scan_dents;
+			ic->scan_dents = fd->next;
 
 			if (!fd->ino) {
 				/* It's a deletion dirent. Ignore it */
@@ -263,8 +196,6 @@
 		}
 		ret = -EAGAIN;
 	}
-	kfree(ic->scan);
-	ic->scan = NULL;
 
 	/*
 	   We don't delete the inocache from the hash list and free it yet. 
@@ -289,6 +220,7 @@
 		c->blocks[i].free_size = c->sector_size;
 		c->blocks[i].dirty_size = 0;
 		c->blocks[i].wasted_size = 0;
+		c->blocks[i].unchecked_size = 0;
 		c->blocks[i].used_size = 0;
 		c->blocks[i].first_node = NULL;
 		c->blocks[i].last_node = NULL;

Index: erase.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/erase.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -r1.42 -r1.43
--- erase.c	6 Sep 2002 14:12:44 -0000	1.42
+++ erase.c	9 Sep 2002 16:29:08 -0000	1.43
@@ -368,7 +368,7 @@
 			
 			marker_ref->next_in_ino = NULL;
 			marker_ref->next_phys = NULL;
-			marker_ref->flash_offset = jeb->offset;
+			marker_ref->flash_offset = jeb->offset | REF_NORMAL;
 			marker_ref->totlen = PAD(je32_to_cpu(marker.totlen));
 			
 			jeb->first_node = jeb->last_node = marker_ref;

Index: gc.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/gc.c,v
retrieving revision 1.84
retrieving revision 1.85
diff -u -r1.84 -r1.85
--- gc.c	6 Sep 2002 16:46:29 -0000	1.84
+++ gc.c	9 Sep 2002 16:29:08 -0000	1.85
@@ -123,6 +123,49 @@
 
 	spin_lock_bh(&c->erase_completion_lock);
 
+	while (c->unchecked_size) {
+		/* We can't start doing GC yet. We haven't finished checking
+		   the node CRCs etc. Do it now and wait for it. */
+		struct jffs2_inode_cache *ic;
+
+		if (c->checked_ino > c->highest_ino) {
+			printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n",
+			       c->unchecked_size);
+			jffs2_dump_block_lists(c);
+			BUG();
+		}
+		ic = jffs2_get_ino_cache(c, c->checked_ino++);
+		if (!ic)
+			continue;
+		if (!ic->nlink) {
+			D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n",
+				  ic->ino));
+			continue;
+		}
+		if (ic->state != INO_STATE_UNCHECKED) {
+			D1(printk(KERN_DEBUG "Skipping check of ino #%d already in state %d\n",
+				  ic->ino, ic->state));
+			continue;
+		}
+
+		spin_unlock_bh(&c->erase_completion_lock);
+
+		D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() triggering inode scan of ino#%d\n", ic->ino));
+		
+		{
+			/* XXX: This wants doing more sensibly -- split the core of jffs2_do_read_inode up */
+			struct inode *i = iget(OFNI_BS_2SFFJ(c), ic->ino);
+			if (is_bad_inode(i)) {
+				printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u\n", ic->ino);
+				ret = -EIO;
+			}
+			iput(i);
+		}
+
+		up(&c->alloc_sem);
+		return ret;
+	}
+
 	/* First, work out which block we're garbage-collecting */
 	jeb = c->gcblock;
 

Index: nodelist.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodelist.c,v
retrieving revision 1.61
retrieving revision 1.62
diff -u -r1.61 -r1.62
--- nodelist.c	6 Sep 2002 16:46:29 -0000	1.61
+++ nodelist.c	9 Sep 2002 16:29:08 -0000	1.62
@@ -16,6 +16,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/interrupt.h>
 #include <linux/rbtree.h>
+#include <linux/crc32.h>
+#include <linux/slab.h>
 #include "nodelist.h"
 
 void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list)
@@ -127,6 +129,7 @@
 		   they're in gets erased */
 		spin_unlock_bh(&c->erase_completion_lock);
 
+		/* FIXME: point() */
 		err = jffs2_flash_read(c, (ref_offset(ref)), min(ref->totlen, sizeof(node)), &retlen, (void *)&node);
 		if (err) {
 			printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref));
@@ -143,7 +146,11 @@
 			
 		switch (je16_to_cpu(node.u.nodetype)) {
 		case JFFS2_NODETYPE_DIRENT:
-			D1(printk(KERN_DEBUG "Node at %08x is a dirent node\n", ref_offset(ref)));
+			D1(printk(KERN_DEBUG "Node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref)));
+			if (ref_flags(ref) == REF_UNCHECKED) {
+				printk(KERN_WARNING "BUG: Dirent node at 0x%08x never got checked? How?\n", ref_offset(ref));
+				BUG();
+			}
 			if (retlen < sizeof(node.d)) {
 				printk(KERN_WARNING "short read in get_inode_nodes()\n");
 				err = -EIO;
@@ -184,6 +191,7 @@
 			   from the flash?
 			*/
 			if (node.d.nsize + sizeof(struct jffs2_raw_dirent) > retlen) {
+				/* FIXME: point() */
 				int already = retlen - sizeof(struct jffs2_raw_dirent);
 					
 				err = jffs2_flash_read(c, (ref_offset(ref)) + retlen, 
@@ -207,7 +215,7 @@
 			break;
 
 		case JFFS2_NODETYPE_INODE:
-			D1(printk(KERN_DEBUG "Node at %08x is a data node\n", ref_offset(ref)));
+			D1(printk(KERN_DEBUG "Node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref)));
 			if (retlen < sizeof(node.i)) {
 				printk(KERN_WARNING "read too short for dnode\n");
 				err = -EIO;
@@ -223,6 +231,59 @@
 				       ref_offset(ref));
 				BUG();
 			}
+
+			/* If we've never checked the CRCs on this node, check them now. */
+			if (ref_flags(ref) == REF_UNCHECKED) {
+				uint32_t crc;
+				struct jffs2_eraseblock *jeb;
+
+				crc = crc32(0, &node, sizeof(node.i)-8);
+				if (crc != je32_to_cpu(node.i.node_crc)) {
+					printk(KERN_NOTICE "jffs2_get_inode_nodes(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
+					       ref_offset(ref), je32_to_cpu(node.i.node_crc), crc);
+					jffs2_mark_node_obsolete(c, ref);
+					spin_lock_bh(&c->erase_completion_lock);
+					continue;
+				}
+
+				if (node.i.compr != JFFS2_COMPR_ZERO && je32_to_cpu(node.i.csize)) {
+					/* FIXME: point() */
+					char *buf = kmalloc(je32_to_cpu(node.i.csize), GFP_KERNEL);
+					if (!buf)
+						return -ENOMEM;
+
+					err = jffs2_flash_read(c, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize),
+							       &retlen, buf);
+					if (!err && retlen != je32_to_cpu(node.i.csize))
+						err = -EIO;
+					if (err) {
+						kfree(buf);
+						return err;
+					}
+					
+					crc = crc32(0, buf, je32_to_cpu(node.i.csize));
+					kfree(buf);
+
+					if (crc != je32_to_cpu(node.i.data_crc)) {
+						printk(KERN_NOTICE "jffs2_get_inode_nodes(): Data CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
+						       ref_offset(ref), je32_to_cpu(node.i.data_crc), crc);
+						jffs2_mark_node_obsolete(c, ref);
+						spin_lock_bh(&c->erase_completion_lock);
+						continue;
+					}
+					
+				}
+
+				/* Mark the node as having been checked and fix the accounting accordingly */
+				jeb = &c->blocks[ref->flash_offset / c->sector_size];
+				jeb->used_size += ref->totlen;
+				jeb->unchecked_size -= ref->totlen;
+				c->used_size += ref->totlen;
+				c->unchecked_size -= ref->totlen;
+
+				mark_ref_normal(ref);
+			}
+
 			tn = jffs2_alloc_tmp_dnode_info();
 			if (!tn) {
 				D1(printk(KERN_DEBUG "alloc tn failed\n"));

Index: nodelist.h
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodelist.h,v
retrieving revision 1.83
retrieving revision 1.84
diff -u -r1.83 -r1.84
--- nodelist.h	6 Sep 2002 16:46:29 -0000	1.83
+++ nodelist.h	9 Sep 2002 16:29:08 -0000	1.84
@@ -89,14 +89,20 @@
    a pointer to the first physical node which is part of this inode, too.
 */
 struct jffs2_inode_cache {
-	struct jffs2_scan_info *scan; /* Used during scan to hold
-		temporary lists of nodes, and later must be set to
+	struct jffs2_full_dirent *scan_dents; /* Used during scan to hold
+		temporary lists of dirents, and later must be set to
 		NULL to mark the end of the raw_node_ref->next_in_ino
 		chain. */
 	struct jffs2_inode_cache *next;
 	struct jffs2_raw_node_ref *nodes;
 	uint32_t ino;
 	int nlink;
+	int state;
+#define INO_STATE_UNCHECKED 0
+#define INO_STATE_CHECKING 1
+#define INO_STATE_CHECKEDABSENT 2
+#define INO_STATE_READINGINODE 3
+#define INO_STATE_PRESENT 5
 };
 
 #define INOCACHE_HASHSIZE 128
@@ -164,6 +170,7 @@
 	int bad_count;
 	uint32_t offset;		/* of this block in the MTD */
 
+	uint32_t unchecked_size;
 	uint32_t used_size;
 	uint32_t dirty_size;
 	uint32_t wasted_size;
@@ -184,30 +191,37 @@
 };
 
 #define ACCT_SANITY_CHECK(c, jeb) do { \
-	if (jeb->used_size + jeb->dirty_size + jeb->free_size +jeb->wasted_size != c->sector_size) { \
+	if (jeb->used_size + jeb->dirty_size + jeb->free_size + jeb->wasted_size + jeb->unchecked_size != c->sector_size) { \
 		printk(KERN_NOTICE "Eeep. Space accounting for block at 0x%08x is screwed\n", jeb->offset); \
-		printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + wasted %08x != total %08x\n", \
-		jeb->free_size, jeb->dirty_size, jeb->used_size, jeb->wasted_size, c->sector_size); \
+		printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + wasted %08x + unchecked %08x != total %08x\n", \
+		jeb->free_size, jeb->dirty_size, jeb->used_size, jeb->wasted_size, jeb->unchecked_size, c->sector_size); \
 		BUG(); \
 	} \
-	if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + c->wasted_size != c->flash_size) { \
+	if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + c->wasted_size + c->unchecked_size != c->flash_size) { \
 		printk(KERN_NOTICE "Eeep. Space accounting superblock info is screwed\n"); \
-		printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x + wasted %08x != total %08x\n", \
-		c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->wasted_size, c->flash_size); \
+		printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x + wasted %08x + unchecked %08x != total %08x\n", \
+		c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->wasted_size, c->unchecked_size, c->flash_size); \
 		BUG(); \
 	} \
 } while(0)
 
 #define ACCT_PARANOIA_CHECK(jeb) do { \
 		uint32_t my_used_size = 0; \
+		uint32_t my_unchecked_size = 0; \
 		struct jffs2_raw_node_ref *ref2 = jeb->first_node; \
 		while (ref2) { \
-			if (!ref_obsolete(ref2)) \
+			if (ref_flags(ref2) == REF_UNCHECKED) \
+				my_unchecked_size += ref2->totlen; \
+			else if (!ref_obsolete(ref2)) \
 				my_used_size += ref2->totlen; \
 			ref2 = ref2->next_phys; \
 		} \
 		if (my_used_size != jeb->used_size) { \
 			printk(KERN_NOTICE "Calculated used size %08x != stored used size %08x\n", my_used_size, jeb->used_size); \
+			BUG(); \
+		} \
+		if (my_unchecked_size != jeb->unchecked_size) { \
+			printk(KERN_NOTICE "Calculated unchecked size %08x != stored unchecked size %08x\n", my_unchecked_size, jeb->unchecked_size); \
 			BUG(); \
 		} \
 	} while(0)

Index: nodemgmt.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodemgmt.c,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -r1.77 -r1.78
--- nodemgmt.c	6 Sep 2002 16:46:29 -0000	1.77
+++ nodemgmt.c	9 Sep 2002 16:29:08 -0000	1.78
@@ -63,8 +63,9 @@
 
 			up(&c->alloc_sem);
 			
-			if (c->dirty_size < c->sector_size) {
-				D1(printk(KERN_DEBUG "dirty size 0x%08x < sector size 0x%08x, returning -ENOSPC\n", c->dirty_size, c->sector_size));
+			if (c->dirty_size + c->unchecked_size < c->sector_size) {
+				D1(printk(KERN_DEBUG "dirty size 0x%08x + unchecked_size 0x%08x < sector size 0x%08x, returning -ENOSPC\n",
+					  c->dirty_size, c->unchecked_size, c->sector_size));
 				spin_unlock_bh(&c->erase_completion_lock);
 				return -ENOSPC;
 			}
@@ -316,7 +317,7 @@
 		c->nextblock = NULL;
 	}
 	ACCT_SANITY_CHECK(c,jeb);
-	ACCT_PARANOIA_CHECK(jeb);
+	D1(ACCT_PARANOIA_CHECK(jeb));
 
 	spin_unlock_bh(&c->erase_completion_lock);
 
@@ -360,15 +361,25 @@
 	}
 
 	spin_lock_bh(&c->erase_completion_lock);
-	jeb->used_size -= ref->totlen;
-	c->used_size -= ref->totlen;
+
+	if (ref_flags(ref) == REF_UNCHECKED) {
+		D1(printk("Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), ref->totlen));
+		jeb->unchecked_size -= ref->totlen;
+		c->unchecked_size -= ref->totlen;
+	} else {
+		D1(printk("Obsoleting node at 0x%08x of len %x: ", ref_offset(ref), ref->totlen));
+		jeb->used_size -= ref->totlen;
+		c->used_size -= ref->totlen;
+	}
 
 	if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref->totlen)) && jeb != c->nextblock) {
+		D1(printk("Dirtying\n"));
 		jeb->dirty_size += ref->totlen + jeb->wasted_size;
 		c->dirty_size += ref->totlen + jeb->wasted_size;
 		c->wasted_size -= jeb->wasted_size;
 		jeb->wasted_size = 0;
 	} else {
+		D1(printk("Wasting\n"));
 		jeb->wasted_size += ref->totlen;
 		c->wasted_size += ref->totlen;	
 	}
@@ -376,7 +387,7 @@
 	
 	ACCT_SANITY_CHECK(c, jeb);
 
-	ACCT_PARANOIA_CHECK(jeb);
+	D1(ACCT_PARANOIA_CHECK(jeb));
 
 	if (c->flags & JFFS2_SB_FLAG_MOUNTING) {
 		/* Mount in progress. Don't muck about with the block
@@ -492,7 +503,7 @@
 	}
 }
 
-#if CONFIG_JFFS2_FS_DEBUG > 0
+#if 1 || CONFIG_JFFS2_FS_DEBUG > 0
 void jffs2_dump_block_lists(struct jffs2_sb_info *c)
 {
 
@@ -502,6 +513,7 @@
 	printk(KERN_DEBUG "used_size: %08x\n", c->used_size);
 	printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size);
 	printk(KERN_DEBUG "wasted_size: %08x\n", c->wasted_size);
+	printk(KERN_DEBUG "unchecked_size: %08x\n", c->unchecked_size);
 	printk(KERN_DEBUG "free_size: %08x\n", c->free_size);
 	printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size);
 	printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size);
@@ -509,12 +521,14 @@
 	printk(KERN_DEBUG "jffs2_reserved_blocks size: %08x\n",c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE);
 
 	if (c->nextblock) {
-		printk(KERN_DEBUG "nextblock: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size);
+		printk(KERN_DEBUG "nextblock: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n",
+		       c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->unchecked_size, c->nextblock->free_size);
 	} else {
 		printk(KERN_DEBUG "nextblock: NULL\n");
 	}
 	if (c->gcblock) {
-		printk(KERN_DEBUG "gcblock: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->gcblock->wasted_size, c->gcblock->free_size);
+		printk(KERN_DEBUG "gcblock: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n",
+		       c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
 	} else {
 		printk(KERN_DEBUG "gcblock: NULL\n");
 	}
@@ -529,7 +543,7 @@
 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
 			numblocks ++;
 			dirty += jeb->wasted_size;
-			printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
+			printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size);
 		}
 		printk (KERN_DEBUG "Contains %d blocks with total wasted size %u, average wasted size: %u\n", numblocks, dirty, dirty / numblocks);
 	}
@@ -544,9 +558,11 @@
 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
 			numblocks ++;
 			dirty += jeb->dirty_size;
-			printk(KERN_DEBUG "very_dirty_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
+			printk(KERN_DEBUG "very_dirty_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n",
+			       jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size);
 		}
-		printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", numblocks, dirty, dirty / numblocks);
+		printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
+			numblocks, dirty, dirty / numblocks);
 	}
 	if (list_empty(&c->dirty_list)) {
 		printk(KERN_DEBUG "dirty_list: empty\n");
@@ -559,9 +575,11 @@
 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
 			numblocks ++;
 			dirty += jeb->dirty_size;
-			printk(KERN_DEBUG "dirty_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
+			printk(KERN_DEBUG "dirty_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n",
+			       jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size);
 		}
-		printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", numblocks, dirty, dirty / numblocks);
+		printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
+			numblocks, dirty, dirty / numblocks);
 	}
 	if (list_empty(&c->erasable_list)) {
 		printk(KERN_DEBUG "erasable_list: empty\n");
@@ -570,7 +588,8 @@
 
 		list_for_each(this, &c->erasable_list) {
 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "erasable_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
+			printk(KERN_DEBUG "erasable_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n",
+			       jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size);
 		}
 	}
 	if (list_empty(&c->erasing_list)) {
@@ -580,7 +599,8 @@
 
 		list_for_each(this, &c->erasing_list) {
 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "erasing_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
+			printk(KERN_DEBUG "erasing_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n",
+			       jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size);
 		}
 	}
 	if (list_empty(&c->erase_pending_list)) {
@@ -590,7 +610,8 @@
 
 		list_for_each(this, &c->erase_pending_list) {
 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "erase_pending_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
+			printk(KERN_DEBUG "erase_pending_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n",
+			       jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size);
 		}
 	}
 	if (list_empty(&c->erasable_pending_wbuf_list)) {
@@ -600,7 +621,8 @@
 
 		list_for_each(this, &c->erasable_pending_wbuf_list) {
 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "erase_pending_wbuf_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
+			printk(KERN_DEBUG "erase_pending_wbuf_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n",
+			       jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size);
 		}
 	}
 	if (list_empty(&c->free_list)) {
@@ -610,7 +632,8 @@
 
 		list_for_each(this, &c->free_list) {
 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "free_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
+			printk(KERN_DEBUG "free_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n",
+			       jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size);
 		}
 	}
 	if (list_empty(&c->bad_list)) {
@@ -620,7 +643,8 @@
 
 		list_for_each(this, &c->bad_list) {
 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "bad_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
+			printk(KERN_DEBUG "bad_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n",
+			       jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size);
 		}
 	}
 	if (list_empty(&c->bad_used_list)) {
@@ -630,7 +654,8 @@
 
 		list_for_each(this, &c->bad_used_list) {
 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "bad_used_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
+			printk(KERN_DEBUG "bad_used_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n",
+			       jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size);
 		}
 	}
 }

Index: readinode.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/readinode.c,v
retrieving revision 1.90
retrieving revision 1.91
diff -u -r1.90 -r1.91
--- readinode.c	6 Sep 2002 16:46:29 -0000	1.90
+++ readinode.c	9 Sep 2002 16:29:08 -0000	1.91
@@ -472,6 +472,7 @@
 		f->fragtree = RB_ROOT;
 		break;
 	}
+	f->inocache->state = INO_STATE_PRESENT;
 
 	return 0;
 }
@@ -507,8 +508,12 @@
 		jffs2_free_full_dirent(fd);
 	}
 
+	if (f->inocache)
+		f->inocache->state = INO_STATE_CHECKEDABSENT;
+
 	up(&f->sem);
 
 	if(deleted)
 		up(&c->alloc_sem);
+
 }

Index: scan.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/scan.c,v
retrieving revision 1.91
retrieving revision 1.92
diff -u -r1.91 -r1.92
--- scan.c	9 Sep 2002 07:47:53 -0000	1.91
+++ scan.c	9 Sep 2002 16:29:08 -0000	1.92
@@ -28,6 +28,10 @@
 		c->free_size -= _x; c->used_size += _x; \
 		jeb->free_size -= _x ; jeb->used_size += _x; \
 		}while(0)
+#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \
+		c->free_size -= _x; c->unchecked_size += _x; \
+		jeb->free_size -= _x ; jeb->unchecked_size += _x; \
+		}while(0)
 
 #define noisy_printk(noise, args...) do { \
 	if (*(noise)) { \
@@ -344,7 +348,7 @@
 
 	while(ofs < jeb->offset + c->sector_size) {
 
-		ACCT_PARANOIA_CHECK(jeb);
+		D1(ACCT_PARANOIA_CHECK(jeb));
 
 		cond_resched();
 
@@ -536,7 +540,7 @@
 				}
 				marker_ref->next_in_ino = NULL;
 				marker_ref->next_phys = NULL;
-				marker_ref->flash_offset = ofs;
+				marker_ref->flash_offset = ofs | REF_NORMAL;
 				marker_ref->totlen = c->cleanmarker_size;
 				jeb->first_node = jeb->last_node = marker_ref;
 			     
@@ -592,17 +596,17 @@
 		jeb->wasted_size = 0;
 	}
 
-	if (jeb->used_size == PAD(c->cleanmarker_size) && 
+	if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && 
 	    !jeb->first_node->next_in_ino && !jeb->dirty_size)
 		return BLK_STATE_CLEANMARKER;
 	/* move blocks with max 4 byte dirty space to cleanlist */	
-	else if (!ISDIRTY(c->sector_size - jeb->used_size)) {
+	else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) {
 		c->dirty_size -= jeb->dirty_size;
 		c->wasted_size += jeb->dirty_size; 
 		jeb->wasted_size += jeb->dirty_size;
 		jeb->dirty_size = 0;
 		return BLK_STATE_CLEAN;
-	} else if (jeb->used_size)
+	} else if (jeb->used_size || jeb->unchecked_size)
 		return BLK_STATE_PARTDIRTY;
 	else
 		return BLK_STATE_ALLDIRTY;
@@ -622,13 +626,7 @@
 		return NULL;
 	}
 	memset(ic, 0, sizeof(*ic));
-	ic->scan = kmalloc(sizeof(struct jffs2_scan_info), GFP_KERNEL);
-	if (!ic->scan) {
-		printk(KERN_NOTICE "jffs2_scan_make_inode_cache(): allocation of scan info for inode cache failed\n");
-		jffs2_free_inode_cache(ic);
-		return NULL;
-	}
-	memset(ic->scan, 0, sizeof(*ic->scan));
+
 	ic->ino = ino;
 	ic->nodes = (void *)ic;
 	jffs2_add_ino_cache(c, ic);
@@ -641,116 +639,54 @@
 				 struct jffs2_raw_inode *ri, uint32_t ofs)
 {
 	struct jffs2_raw_node_ref *raw;
-	struct jffs2_full_dnode *fn;
-	struct jffs2_tmp_dnode_info *tn, **tn_list;
 	struct jffs2_inode_cache *ic;
-	uint32_t dsize, csize;
-	uint32_t crc;
-	int ret;
+	uint32_t ino = je32_to_cpu(ri->ino);
 
 	D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs));
 
-	/* FIXME: Actually we don't need to do all this here. We can just make a raw_node_ref for it,
-	   and file it against ri->inode. We don't even need to check the CRC. If the CRC is valid,
-	   all was well, if the CRC was _invalid_, we're gonna drop it when we find out anyway, so
-	   it doesn't matter which inode it was filed against. Of course we have to go through and
-	   do the CRC checks for each inode some time later, but we don't have to hold up the mount
-	   for it.
-
-	   Hmm, perhaps we'd want to do the CRC check if there's not already an inocache for the inode
-	   we think it belongs to, to prevent us from ending up creating an inocache for ino #0xFFFFFFFF
-	   if that's what we see on the flash.
-	*/
-	   
-
-	/* We don't get here unless the node is still valid, so we don't have to
-	   mask in the ACCURATE bit any more. */
-	crc = crc32(0, ri, sizeof(*ri)-8);
-
-	if(crc != je32_to_cpu(ri->node_crc)) {
-		printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
-		       ofs, je32_to_cpu(ri->node_crc), crc);
-		/* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
-		DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen)));
-		return 0;
-	}
-	/* There was a bug where we wrote hole nodes out with csize/dsize
-	   swapped. Deal with it */
-	if (unlikely(ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) && je32_to_cpu(ri->csize))) {
-		dsize = je32_to_cpu(ri->csize);
-		csize = 0;
-	} else {
-		csize = je32_to_cpu(ri->csize);
-		dsize = je32_to_cpu(ri->dsize);
-	}
-
-	if (csize) {
-		/* Check data CRC too */
-		unsigned char *dbuf;
-		uint32_t crc;
-		size_t retlen;
-
-		dbuf = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
-		if (!dbuf) {
-			printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of temporary data buffer for CRC check failed\n");
-			return -ENOMEM;
-		}
-		ret = jffs2_flash_read(c, ofs+sizeof(*ri), csize, &retlen, dbuf);
-		if (ret) {
-			printk(KERN_NOTICE "jffs2_scan_inode_node(): Read error at 0x%08x: %d\n", ofs+sizeof(*ri), ret);
-			kfree(dbuf);
-			return ret;
-		}
-		if (retlen != csize) {
-			printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", 
-			       retlen, ofs+sizeof(*ri), csize);
-			kfree(dbuf);
-			return -EIO;
-		}
-		crc = crc32(0, dbuf, csize);
-		kfree(dbuf);
-		if (crc != je32_to_cpu(ri->data_crc)) {
-			printk(KERN_NOTICE "jffs2_scan_inode_node(): Data CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
-			       ofs, je32_to_cpu(ri->data_crc), crc);
-			DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen)));
-			return 0;
-		}
-	}
+	/* We do very little here now. Just check the ino# to which we should attribute
+	   this node; we can do all the CRC checking etc. later. There's a tradeoff here -- 
+	   we used to scan the flash once only, reading everything we want from it into
+	   memory, then building all our in-core data structures and freeing the extra
+	   information. Now we allow the first part of the mount to complete a lot quicker,
+	   but we have to go _back_ to the flash in order to finish the CRC checking, etc. 
+	   Which means that the _full_ amount of time to get to proper write mode with GC
+	   operational may actually be _longer_ than before. Sucks to be me. */
 
-	/* Wheee. It worked */
 	raw = jffs2_alloc_raw_node_ref();
 	if (!raw) {
 		printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n");
 		return -ENOMEM;
 	}
-	tn = jffs2_alloc_tmp_dnode_info();
-	if (!tn) {
-		jffs2_free_raw_node_ref(raw);
-		return -ENOMEM;
-	}
-	fn = jffs2_alloc_full_dnode();
-	if (!fn) {
-		jffs2_free_tmp_dnode_info(tn);
-		jffs2_free_raw_node_ref(raw);
-		return -ENOMEM;
-	}
-	ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(ri->ino));
+
+	ic = jffs2_get_ino_cache(c, ino);
 	if (!ic) {
-		jffs2_free_full_dnode(fn);
-		jffs2_free_tmp_dnode_info(tn);
-		jffs2_free_raw_node_ref(raw);
-		return -ENOMEM;
+		/* Inocache get failed. Either we read a bogus ino# or it's just genuinely the
+		   first node we found for this inode. Do a CRC check to protect against the former
+		   case */
+		uint32_t crc = crc32(0, ri, sizeof(*ri)-8);
+
+		if (crc != je32_to_cpu(ri->node_crc)) {
+			printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
+			       ofs, je32_to_cpu(ri->node_crc), crc);
+			/* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
+			DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen)));
+			return 0;
+		}
+		ic = jffs2_scan_make_ino_cache(c, ino);
+		if (!ic) {
+			jffs2_free_raw_node_ref(raw);
+			return -ENOMEM;
+		}
 	}
 
-	/* Build the data structures and file them for later */
-	if (dsize == PAGE_CACHE_SIZE)
-		raw->flash_offset = ofs | REF_PRISTINE;
-	else
-		raw->flash_offset = ofs | REF_NORMAL;
+	/* Wheee. It worked */
 
+	raw->flash_offset = ofs | REF_UNCHECKED;
 	raw->totlen = PAD(je32_to_cpu(ri->totlen));
 	raw->next_phys = NULL;
 	raw->next_in_ino = ic->nodes;
+
 	ic->nodes = raw;
 	if (!jeb->first_node)
 		jeb->first_node = raw;
@@ -761,73 +697,11 @@
 	D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", 
 		  je32_to_cpu(ri->ino), je32_to_cpu(ri->version),
 		  je32_to_cpu(ri->offset),
-		  je32_to_cpu(ri->offset)+dsize));
+		  je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize)));
 
 	pseudo_random += je32_to_cpu(ri->version);
 
-	for (tn_list = &ic->scan->tmpnodes; *tn_list; tn_list = &((*tn_list)->next)) {
-		if ((*tn_list)->version < je32_to_cpu(ri->version))
-			continue;
-		if ((*tn_list)->version > je32_to_cpu(ri->version)) 
-			break;
-		/* Wheee. We've found another instance of the same version number.
-		   We should obsolete one of them. 
-		*/
-		D1(printk(KERN_DEBUG "Duplicate version %d found in ino #%u. Previous one is at 0x%08x\n",
-			  je32_to_cpu(ri->version), ic->ino,
-			  ref_offset((*tn_list)->fn->raw)));
-		if (!jeb->used_size) {
-			D1(printk(KERN_DEBUG "No valid nodes yet found in this eraseblock 0x%08x, so obsoleting the new instance at 0x%08x\n", 
-				  jeb->offset, ref_offset(raw)));
-			jffs2_free_full_dnode(fn);
-			jffs2_free_tmp_dnode_info(tn);
-			raw->flash_offset |= REF_OBSOLETE;
-			DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen)));
-			/* Perhaps we could also mark it as such on the medium. Maybe later */
-			return 0;
-		}
-		break;
-	}
-
-	/* Only do fraglist truncation in pass1 for S_IFREG inodes */
-	if (S_ISREG(je32_to_cpu(ri->mode)) && ic->scan->version < je32_to_cpu(ri->version)) {
-		ic->scan->version = je32_to_cpu(ri->version);
-		ic->scan->isize = je32_to_cpu(ri->isize);
-	}
-
-	memset(fn,0,sizeof(*fn));
-
-	fn->ofs = je32_to_cpu(ri->offset);
-	fn->size = dsize;
-	fn->frags = 0;
-	fn->raw = raw;
-
-	tn->next = NULL;
-	tn->fn = fn;
-	tn->version = je32_to_cpu(ri->version);
-
-	USED_SPACE(PAD(je32_to_cpu(ri->totlen)));
-
-	/* No need to scan from the beginning of the list again. 
-	   We can start from tn_list instead (Thanks Jocke) */
-	jffs2_add_tn_to_list(tn, tn_list);
-
-	/* Make sure the one we just added is the _last_ in the list
-	   with this version number, so the older ones get obsoleted */
-	while (tn->next && tn->next->version == tn->version) {
-
-		D1(printk(KERN_DEBUG "Shifting new node at 0x%08x after other node at 0x%08x for version %d in list\n",
-			  ref_offset(fn->raw), 
-			  ref_offset(tn->next->fn->raw),
-			  je32_to_cpu(ri->version)));
-
-		if(tn->fn != fn)
-			BUG();
-		tn->fn = tn->next->fn;
-		tn->next->fn = fn;
-		tn = tn->next;
-	}
-
+	UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen)));
 	return 0;
 }
 
@@ -887,7 +761,7 @@
 	}
 	
 	raw->totlen = PAD(je32_to_cpu(rd->totlen));
-	raw->flash_offset = ofs;
+	raw->flash_offset = ofs | REF_PRISTINE;
 	raw->next_phys = NULL;
 	raw->next_in_ino = ic->nodes;
 	ic->nodes = raw;
@@ -904,7 +778,7 @@
 	fd->nhash = full_name_hash(fd->name, rd->nsize);
 	fd->type = rd->type;
 	USED_SPACE(PAD(je32_to_cpu(rd->totlen)));
-	jffs2_add_fd_to_list(c, fd, &ic->scan->dents);
+	jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
 
 	return 0;
 }

Index: write.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/write.c,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -r1.59 -r1.60
--- write.c	6 Sep 2002 16:46:30 -0000	1.59
+++ write.c	9 Sep 2002 16:29:08 -0000	1.60
@@ -36,6 +36,8 @@
 	f->inocache->nlink = 1;
 	f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
 	f->inocache->ino = ++c->highest_ino;
+	f->inocache->state = INO_STATE_PRESENT;
+
 	ri->ino = cpu_to_je32(f->inocache->ino);
 
 	D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino));





More information about the linux-mtd-cvs mailing list