mtd/fs/jffs2 background.c,1.24,1.25 build.c,1.33,1.34 gc.c,1.70,1.71 nodelist.h,1.70,1.71 nodemgmt.c,1.66,1.67 scan.c,1.73,1.74
David Woodhouse
dwmw2 at infradead.org
Fri May 10 17:09:06 EDT 2002
- Previous message: mtd/fs/jffs2 fs.c,1.9,1.10 gc.c,1.69,1.70 nodelist.h,1.69,1.70 nodemgmt.c,1.65,1.66
- Next message: mtd/fs/jffs2 background.c,1.25,1.26
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv24129
Modified Files:
background.c build.c gc.c nodelist.h nodemgmt.c scan.c
Log Message:
Add new very_dirty_list for blocks with more than 50% dirty space. We favour this
list over the normal dirty_list in picking blocks to GC from. This means GC is
_far_ more likely to actually make progress. We might want to add a
'slightly_dirty_list' too, for blocks with less than 25% or something.
I don't want to sort the node lists because that screws up the randomness that we
want for wear levelling purposes -- we sometimes _do_ pick blocks from all lists
and sorting the lists would make this a pain. Perhaps we could have a single sorted
list but pick a block from <N> items into the list, where N is a pseudo-random number
suitably weighted to favour blocks near the start of the list?
Index: background.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/background.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- background.c 28 Apr 2002 13:43:03 -0000 1.24
+++ background.c 10 May 2002 21:09:03 -0000 1.25
@@ -178,10 +178,18 @@
static int thread_should_wake(struct jffs2_sb_info *c)
{
- D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x\n",
- c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size));
+ uint32_t gcnodeofs = 0;
+
+ /* Don't count any progress we've already made through the gcblock
+ as dirty space, for the purposes of this calculation */
+ if (c->gcblock && c->gcblock->gc_node)
+ gcnodeofs = c->gcblock->gc_node->flash_offset & ~3 & (c->sector_size-1);
+
+ D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x (mod 0x%x\n",
+ c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size,
+ c->dirty_size - gcnodeofs));
if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER &&
- c->dirty_size > c->sector_size)
+ (c->dirty_size - gcnodeofs) > c->sector_size)
return 1;
else
return 0;
Index: build.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/build.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -r1.33 -r1.34
--- build.c 15 Mar 2002 11:00:36 -0000 1.33
+++ build.c 10 May 2002 21:09:03 -0000 1.34
@@ -307,6 +307,7 @@
spin_lock_init(&c->inocache_lock);
INIT_LIST_HEAD(&c->clean_list);
+ INIT_LIST_HEAD(&c->very_dirty_list);
INIT_LIST_HEAD(&c->dirty_list);
INIT_LIST_HEAD(&c->erasable_list);
INIT_LIST_HEAD(&c->erasing_list);
Index: gc.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/gc.c,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -r1.70 -r1.71
--- gc.c 10 May 2002 19:14:46 -0000 1.70
+++ gc.c 10 May 2002 21:09:03 -0000 1.71
@@ -75,8 +75,11 @@
So don't favour the erasable_list _too_ much. */
D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next\n"));
nextlist = &c->erasable_list;
+ } else if (n < 110 && !list_empty(&c->very_dirty_list)) {
+ /* Most of the time, pick one off the very_dirty list */
+ D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next\n"));
+ nextlist = &c->very_dirty_list;
} else if (n < 126 && !list_empty(&c->dirty_list)) {
- /* Most of the time, pick one off the dirty list */
D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next\n"));
nextlist = &c->dirty_list;
} else if (!list_empty(&c->clean_list)) {
@@ -86,12 +89,15 @@
D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next (clean_list was empty)\n"));
nextlist = &c->dirty_list;
+ } else if (!list_empty(&c->very_dirty_list)) {
+ D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next (clean_list and dirty_list were empty)\n"));
+ nextlist = &c->very_dirty_list;
} else if (!list_empty(&c->erasable_list)) {
- D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next (clean_list and dirty_list were empty)\n"));
+ D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next (clean_list and {very_,}dirty_list were empty)\n"));
nextlist = &c->erasable_list;
} else {
- /* Eep. Both were empty */
+ /* Eep. All were empty */
printk(KERN_NOTICE "jffs2: No clean, dirty _or_ erasable blocks to GC from! Where are they all?\n");
return NULL;
}
@@ -104,7 +110,7 @@
printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset);
BUG();
}
- D1(printk("Picked block at %08x, used_size %08x, dirty_size %08x, free_size %08x\n", ret->offset, ret->used_size, ret->dirty_size, ret->free_size));
+
D1(jffs2_dump_block_lists(c));
return ret;
}
@@ -144,7 +150,9 @@
return -EIO;
}
- D1(printk(KERN_DEBUG "garbage collect from block at phys 0x%08x\n", jeb->offset));
+ D1(printk(KERN_DEBUG "GC from block %08x, used_size %08x, dirty_size %08x, free_size %08x\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size));
+ D1(if (c->nextblock)
+ printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->free_size));
if (!jeb->used_size)
goto eraseit;
Index: nodelist.h
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodelist.h,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -r1.70 -r1.71
--- nodelist.h 10 May 2002 19:14:46 -0000 1.70
+++ nodelist.h 10 May 2002 21:09:03 -0000 1.71
@@ -240,6 +240,9 @@
#define JFFS2_RESERVED_BLOCKS_GCMERGE (JFFS2_RESERVED_BLOCKS_BASE) /* ... merge pages when garbage collecting */
+/* How much dirty space before it goes on the very_dirty_list */
+#define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2))
+
#define PAD(x) (((x)+3)&~3)
static inline int jffs2_raw_ref_to_inum(struct jffs2_raw_node_ref *raw)
Index: nodemgmt.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodemgmt.c,v
retrieving revision 1.66
retrieving revision 1.67
diff -u -r1.66 -r1.67
--- nodemgmt.c 10 May 2002 19:14:46 -0000 1.66
+++ nodemgmt.c 10 May 2002 21:09:03 -0000 1.67
@@ -158,9 +158,15 @@
c->free_size -= jeb->free_size;
jeb->dirty_size += jeb->free_size;
jeb->free_size = 0;
- D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
+ if (VERYDIRTY(c, jeb->dirty_size)) {
+ D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size));
- list_add_tail(&jeb->list, &c->dirty_list);
+ list_add_tail(&jeb->list, &c->very_dirty_list);
+ } else {
+ D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
+ jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size));
+ list_add_tail(&jeb->list, &c->dirty_list);
+ }
c->nextblock = jeb = NULL;
}
@@ -442,6 +448,12 @@
list_del(&jeb->list);
D1(printk(KERN_DEBUG "...and adding to dirty_list\n"));
list_add_tail(&jeb->list, &c->dirty_list);
+ } else if (VERYDIRTY(c, jeb->dirty_size) &&
+ !VERYDIRTY(c, jeb->dirty_size - ref->totlen)) {
+ D1(printk(KERN_DEBUG "Eraseblock at 0x%08x is now very dirty. Removing from dirty list...\n", jeb->offset));
+ list_del(&jeb->list);
+ D1(printk(KERN_DEBUG "...and adding to very_dirty_list\n"));
+ list_add_tail(&jeb->list, &c->very_dirty_list);
}
spin_unlock_bh(&c->erase_completion_lock);
@@ -480,6 +492,7 @@
return;
}
}
+
#if CONFIG_JFFS2_FS_DEBUG > 0
void jffs2_dump_block_lists(struct jffs2_sb_info *c)
{
@@ -511,6 +524,16 @@
list_for_each(this, &c->clean_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+ }
+ }
+ if (list_empty(&c->very_dirty_list)) {
+ printk(KERN_DEBUG "very_dirty_list: empty\n");
+ } else {
+ struct list_head *this;
+
+ list_for_each(this, &c->very_dirty_list) {
+ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+ printk(KERN_DEBUG "very_dirty_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
}
}
if (list_empty(&c->dirty_list)) {
Index: scan.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/scan.c,v
retrieving revision 1.73
retrieving revision 1.74
diff -u -r1.73 -r1.74
--- scan.c 28 Mar 2002 09:58:11 -0000 1.73
+++ scan.c 10 May 2002 21:09:03 -0000 1.74
@@ -143,11 +143,20 @@
(jffs2_can_mark_obsolete(c) || jeb->free_size > c->wbuf_pagesize) &&
(!c->nextblock || c->nextblock->free_size < jeb->free_size)) {
/* Better candidate for the next writes to go to */
- if (c->nextblock)
- list_add(&c->nextblock->list, &c->dirty_list);
+ if (c->nextblock) {
+ if (VERYDIRTY(c, c->nextblock->dirty_size)) {
+ list_add(&c->nextblock->list, &c->very_dirty_list);
+ } else {
+ list_add(&c->nextblock->list, &c->dirty_list);
+ }
+ }
c->nextblock = jeb;
} else {
- list_add(&jeb->list, &c->dirty_list);
+ if (VERYDIRTY(c, jeb->dirty_size)) {
+ list_add(&jeb->list, &c->very_dirty_list);
+ } else {
+ list_add(&jeb->list, &c->dirty_list);
+ }
}
break;
@@ -846,6 +855,19 @@
list_entry(c->clean_list.next, struct jffs2_eraseblock, list)->offset));
} else {
D1(printk(KERN_DEBUG "Not rotating empty clean_list\n"));
+ }
+
+ x = count_list(&c->very_dirty_list);
+ if (x) {
+ rotateby = pseudo_random % x;
+ D1(printk(KERN_DEBUG "Rotating very_dirty_list by %d\n", rotateby));
+
+ rotate_list((&c->very_dirty_list), rotateby);
+
+ D1(printk(KERN_DEBUG "Erase block at front of very_dirty_list is at %08x\n",
+ list_entry(c->very_dirty_list.next, struct jffs2_eraseblock, list)->offset));
+ } else {
+ D1(printk(KERN_DEBUG "Not rotating empty very_dirty_list\n"));
}
x = count_list(&c->dirty_list);
- Previous message: mtd/fs/jffs2 fs.c,1.9,1.10 gc.c,1.69,1.70 nodelist.h,1.69,1.70 nodemgmt.c,1.65,1.66
- Next message: mtd/fs/jffs2 background.c,1.25,1.26
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the linux-mtd-cvs
mailing list