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