diff options
author | David Woodhouse <dwmw2@infradead.org> | 2007-10-06 21:12:58 +0200 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2007-10-06 21:12:58 +0200 |
commit | 8fb870df5a1f261294b833dd807bcba3bacface6 (patch) | |
tree | 2e6018f0256feca906797b248603202962302fa6 /fs/jffs2/nodemgmt.c | |
parent | [MTD] [NAND] Avoid deadlock in erase callback; release chip lock first. (diff) | |
download | linux-8fb870df5a1f261294b833dd807bcba3bacface6.tar.xz linux-8fb870df5a1f261294b833dd807bcba3bacface6.zip |
[JFFS2] Trigger garbage collection when very_dirty_list size becomes excessive
With huge amounts of free space, we weren't bothering to GC for while a
while, and pathological numbers of obsolete nodes were accumulating,
seriously affecting performance on NAND flash (OLPC trac #3978)
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'fs/jffs2/nodemgmt.c')
-rw-r--r-- | fs/jffs2/nodemgmt.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 5b49bff364b4..1b79534e9d48 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -722,6 +722,8 @@ int jffs2_thread_should_wake(struct jffs2_sb_info *c) { int ret = 0; uint32_t dirty; + int nr_very_dirty = 0; + struct jffs2_eraseblock *jeb; if (c->unchecked_size) { D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): unchecked_size %d, checked_ino #%d\n", @@ -743,8 +745,16 @@ int jffs2_thread_should_wake(struct jffs2_sb_info *c) (dirty > c->nospc_dirty_size)) ret = 1; - D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n", - c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, ret?"yes":"no")); + list_for_each_entry(jeb, &c->very_dirty_list, list) { + nr_very_dirty++; + if (nr_very_dirty == c->vdirty_blocks_gctrigger) { + ret = 1; + D1(break); + } + } + + D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x, vdirty_blocks %d: %s\n", + c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, nr_very_dirty, ret?"yes":"no")); return ret; } |