mtd/fs/jffs2 gc.c,1.83,1.84 nodelist.c,1.60,1.61 nodelist.h,1.82,1.83 nodemgmt.c,1.76,1.77 readinode.c,1.89,1.90 scan.c,1.88,1.89 write.c,1.58,1.59

David Woodhouse dwmw2 at infradead.org
Fri Sep 6 12:46:32 EDT 2002


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

Modified Files:
	gc.c nodelist.c nodelist.h nodemgmt.c readinode.c scan.c 
	write.c 
Log Message:
Start of distinguishing between REF_NORMAL and REF_PRISTINE state, which
we'll eventually use for garbage collection, so we know when we have to do
a read_inode and when we don't. I suspect we don't quite mark _enough_ 
nodes REF_PRISTINE at the moment, especially where holes and end-of-file 
are concerned. But false positives are nastier than false negatives. I 
think.



Index: gc.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/gc.c,v
retrieving revision 1.83
retrieving revision 1.84
diff -u -r1.83 -r1.84
--- gc.c	6 Sep 2002 14:12:44 -0000	1.83
+++ gc.c	6 Sep 2002 16:46:29 -0000	1.84
@@ -206,6 +206,20 @@
 		if (frag->node && frag->node->raw == raw) {
 			fn = frag->node;
 			end = frag->ofs + frag->size;
+#if 1 /* Temporary debugging sanity checks, till we're ready to _trust_ the REF_PRISTINE flag stuff */ 
+			if (!nrfrags && ref_flags(fn->raw) == REF_PRISTINE) {
+				if (fn->frags > 1)
+					printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2\n", ref_offset(raw), fn->frags);
+
+				if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag) && frag_prev(frag)->node)
+					printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2\n",
+					       ref_offset(raw));
+
+				if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag) && frag_next(frag)->node)
+					printk(KERN_WARNING "REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2\n",
+					       ref_offset(raw), frag->ofs, frag->ofs+frag->size);
+			}
+#endif
 			if (!nrfrags++)
 				start = frag->ofs;
 			if (nrfrags == frag->node->frags)
@@ -670,7 +684,6 @@
 		  f->inocache->ino, start, end));
 
 	orig_end = end;
-
 
 	/* If we're looking at the last node in the block we're
 	   garbage-collecting, we allow ourselves to merge as if the

Index: nodelist.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodelist.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -r1.60 -r1.61
--- nodelist.c	6 Sep 2002 14:12:44 -0000	1.60
+++ nodelist.c	6 Sep 2002 16:46:29 -0000	1.61
@@ -519,6 +519,20 @@
 	return node->rb_parent;
 }
 
+rb_node_t *rb_prev(rb_node_t *node)
+{
+	if (node->rb_left) {
+		node = node->rb_left; 
+		while (node->rb_right)
+			node=node->rb_right;
+		return node;
+	}
+	while (node->rb_parent && node == node->rb_parent->rb_left)
+		node = node->rb_parent;
+
+	return node->rb_parent;
+}
+
 void rb_replace_node(rb_node_t *victim, rb_node_t *new, rb_root_t *root)
 {
 	rb_node_t *parent = victim->rb_parent;

Index: nodelist.h
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodelist.h,v
retrieving revision 1.82
retrieving revision 1.83
diff -u -r1.82 -r1.83
--- nodelist.h	6 Sep 2002 14:12:44 -0000	1.82
+++ nodelist.h	6 Sep 2002 16:46:29 -0000	1.83
@@ -64,10 +64,11 @@
 #define REF_UNCHECKED	0	/* We haven't yet checked the CRC or built its inode */
 #define REF_OBSOLETE	1	/* Obsolete, can be completely ignored */
 #define REF_PRISTINE	2	/* Completely clean. GC without looking */
-#define REF_OVERLAPPED	3	/* Partly clean. Read the page and write again on GC */
+#define REF_NORMAL	3	/* Possibly overlapped. Read the page and write again on GC */
 #define ref_flags(ref)		((ref)->flash_offset & 3)
 #define ref_offset(ref)		((ref)->flash_offset & ~3)
 #define ref_obsolete(ref)	(((ref)->flash_offset & 3) == REF_OBSOLETE)
+#define mark_ref_normal(ref)    do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0)
 };
 
 /* 
@@ -252,6 +253,7 @@
 }
 #define rb_parent(rb) ((rb)->rb_parent)
 #define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb)
+#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb)
 #define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb)
 #define frag_left(frag) rb_entry((frag)->rb.rb_left, struct jffs2_node_frag, rb)
 #define frag_right(frag) rb_entry((frag)->rb.rb_right, struct jffs2_node_frag, rb)
@@ -274,12 +276,13 @@
 void jffs2_kill_fragtree(rb_root_t *root, struct jffs2_sb_info *c_delete);
 void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base);
 rb_node_t *rb_next(rb_node_t *);
+rb_node_t *rb_prev(rb_node_t *);
 void rb_replace_node(rb_node_t *victim, rb_node_t *new, rb_root_t *root);
 
 /* nodemgmt.c */
 int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio);
 int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len);
-int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len, int dirty);
+int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new);
 void jffs2_complete_reservation(struct jffs2_sb_info *c);
 void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw);
 void jffs2_dump_block_lists(struct jffs2_sb_info *c);

Index: nodemgmt.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodemgmt.c,v
retrieving revision 1.76
retrieving revision 1.77
diff -u -r1.76 -r1.77
--- nodemgmt.c	6 Sep 2002 14:33:37 -0000	1.76
+++ nodemgmt.c	6 Sep 2002 16:46:29 -0000	1.77
@@ -269,11 +269,11 @@
  *	Must be called with the alloc_sem held.
  */
  
-int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len, int dirty)
+int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new)
 {
 	struct jffs2_eraseblock *jeb;
+	uint32_t len = new->totlen;
 
-	len = PAD(len);
 	jeb = &c->blocks[new->flash_offset / c->sector_size];
 	D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x, size 0x%x\n", ref_offset(new), len));
 #if 1
@@ -293,8 +293,7 @@
 
 	jeb->free_size -= len;
 	c->free_size -= len;
-	if (dirty) {
-		new->flash_offset |= REF_OBSOLETE;
+	if (ref_obsolete(new)) {
 		jeb->dirty_size += len;
 		c->dirty_size += len;
 	} else {

Index: readinode.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/readinode.c,v
retrieving revision 1.89
retrieving revision 1.90
diff -u -r1.89 -r1.90
--- readinode.c	6 Sep 2002 14:12:44 -0000	1.89
+++ readinode.c	6 Sep 2002 16:46:29 -0000	1.90
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/crc32.h>
+#include <linux/pagemap.h>
 #include <linux/mtd/mtd.h>
 #include <linux/interrupt.h>
 #include "nodelist.h"
@@ -77,9 +78,10 @@
 			jffs2_mark_node_obsolete(c, this->node->raw);
 			jffs2_free_full_dnode(this->node);
 		} else {
-			D2(printk(KERN_DEBUG "Not marking old node @0x%08x (0x%04x-0x%04x) obsolete. frags is %d\n",
+			D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n",
 				  ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size,
 				  this->node->frags));
+			mark_ref_normal(this->node->raw);
 		}
 		
 	}
@@ -98,10 +100,12 @@
 		return -ENOMEM;
 	}
 
-	D2(if (fn->raw)
-		printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag);
-	else
-		printk(KERN_DEBUG "adding hole node %04x-%04x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, newfrag));
+	if (!fn->raw) {
+		printk(KERN_WARNING "dwmw2 is stupid. j_a_f_d_t_f should never happen with ->raw == NULL\n");
+		BUG();
+	}
+
+	D2(printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag));
 	
 	if (!fn->size) {
 		jffs2_free_node_frag(newfrag);
@@ -128,6 +132,17 @@
 	/* See if we ran off the end of the list */
 	if (lastend <= newfrag->ofs) {
 		/* We did */
+
+		/* Check if 'this' node was on the same page as the new node.
+		   If so, both 'this' and the new node get marked REF_NORMAL so
+		   the GC can take a look.
+		*/
+		if ((lastend-1) >> PAGE_CACHE_SHIFT == newfrag->ofs >> PAGE_CACHE_SHIFT) {
+			if (this->node)
+				mark_ref_normal(this->node->raw);
+			mark_ref_normal(fn->raw);
+		}
+
 		if (lastend < fn->ofs) {
 			/* ... and we need to put a hole in before the new node */
 			struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag();
@@ -171,6 +186,13 @@
 	 */
 	if (newfrag->ofs > this->ofs) {
 		/* This node isn't completely obsoleted. The start of it remains valid */
+
+		/* Mark the new node and the partially covered node REF_NORMAL -- let 
+		   the GC take a look at them */
+		mark_ref_normal(fn->raw);
+		if (this->node)
+			mark_ref_normal(this->node->raw);
+
 		if (this->ofs + this->size > newfrag->ofs + newfrag->size) {
 			/* The new node splits 'this' frag into two */
 			struct jffs2_node_frag *newfrag2 = jffs2_alloc_node_frag();
@@ -254,6 +276,11 @@
 	/* Still some overlap but we don't need to move it in the tree */
 	this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size);
 	this->ofs = newfrag->ofs + newfrag->size;
+
+	/* And mark them REF_NORMAL so the GC takes a look at them */
+	if (this->node)
+		mark_ref_normal(this->node->raw);
+	mark_ref_normal(fn->raw);
 
 	return 0;
 }

Index: scan.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/scan.c,v
retrieving revision 1.88
retrieving revision 1.89
diff -u -r1.88 -r1.89
--- scan.c	6 Sep 2002 14:33:37 -0000	1.88
+++ scan.c	6 Sep 2002 16:46:29 -0000	1.89
@@ -742,7 +742,11 @@
 	}
 
 	/* Build the data structures and file them for later */
-	raw->flash_offset = ofs | REF_NORMAL;
+	if (dsize == PAGE_CACHE_SIZE)
+		raw->flash_offset = ofs | REF_PRISTINE;
+	else
+		raw->flash_offset = ofs | REF_NORMAL;
+
 	raw->totlen = PAD(je32_to_cpu(ri->totlen));
 	raw->next_phys = NULL;
 	raw->next_in_ino = ic->nodes;
@@ -770,7 +774,7 @@
 		*/
 		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,
-			  (*tn_list)->ref_offset(fn->raw)));
+			  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)));

Index: write.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/write.c,v
retrieving revision 1.58
retrieving revision 1.59
diff -u -r1.58 -r1.59
--- write.c	20 Aug 2002 21:37:28 -0000	1.58
+++ write.c	6 Sep 2002 16:46:30 -0000	1.59
@@ -15,6 +15,7 @@
 #include <linux/fs.h>
 #include <linux/crc32.h>
 #include <linux/slab.h>
+#include <linux/pagemap.h>
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
@@ -117,7 +118,7 @@
 		return ERR_PTR(-ENOMEM);
 	}
 	raw->flash_offset = flash_ofs;
-	raw->totlen = PAD(je32_to_cpu(ri->totlen));
+	raw->totlen = PAD(sizeof(*ri)+datalen);
 	raw->next_phys = NULL;
 
 	fn->ofs = je32_to_cpu(ri->offset);
@@ -144,7 +145,8 @@
 			   seem corrupted, in which case the scan would skip over
 			   any node we write before the original intended end of 
 			   this node */
-			jffs2_add_physical_node_ref(c, raw, sizeof(*ri)+datalen, 1);
+			raw->flash_offset |= REF_OBSOLETE;
+			jffs2_add_physical_node_ref(c, raw);
 			jffs2_mark_node_obsolete(c, raw);
 		} else {
 			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
@@ -158,7 +160,11 @@
 		return ERR_PTR(ret?ret:-EIO);
 	}
 	/* Mark the space used */
-	jffs2_add_physical_node_ref(c, raw, retlen, 0);
+	if (datalen == PAGE_CACHE_SIZE)
+		raw->flash_offset |= REF_PRISTINE;
+	else
+		raw->flash_offset |= REF_NORMAL;
+	jffs2_add_physical_node_ref(c, raw);
 
 	/* Link into per-inode list */
 	raw->next_in_ino = f->inocache->nodes;
@@ -210,7 +216,7 @@
 		return ERR_PTR(-ENOMEM);
 	}
 	raw->flash_offset = flash_ofs;
-	raw->totlen = PAD(je32_to_cpu(rd->totlen));
+	raw->totlen = PAD(sizeof(*rd)+namelen);
 	raw->next_in_ino = f->inocache->nodes;
 	f->inocache->nodes = raw;
 	raw->next_phys = NULL;
@@ -229,7 +235,8 @@
 			       sizeof(*rd)+namelen, flash_ofs, ret, retlen);
 		/* Mark the space as dirtied */
 		if (retlen) {
-			jffs2_add_physical_node_ref(c, raw, sizeof(*rd)+namelen, 1);
+			raw->flash_offset |= REF_OBSOLETE;
+			jffs2_add_physical_node_ref(c, raw);
 			jffs2_mark_node_obsolete(c, raw);
 		} else {
 			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
@@ -243,7 +250,8 @@
 		return ERR_PTR(ret?ret:-EIO);
 	}
 	/* Mark the space used */
-	jffs2_add_physical_node_ref(c, raw, retlen, 0);
+	raw->flash_offset |= REF_PRISTINE;
+	jffs2_add_physical_node_ref(c, raw);
 	if (writelen)
 		*writelen = retlen;
 





More information about the linux-mtd-cvs mailing list