? cvs.diff Index: fs/jffs2/background.c =================================================================== RCS file: /home/cvs/mtd/fs/jffs2/background.c,v retrieving revision 1.30 diff -u -r1.30 background.c --- fs/jffs2/background.c 5 Aug 2002 14:46:47 -0000 1.30 +++ fs/jffs2/background.c 19 Aug 2002 22:30:39 -0000 @@ -155,18 +155,11 @@ static int thread_should_wake(struct jffs2_sb_info *c) { uint32_t gcnodeofs = 0; - int ret; + int ret = 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); - - if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER && - (c->dirty_size - gcnodeofs) > c->sector_size) + if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER && + !jffs2_gc_checkspace (c, JFFS2_RESERVED_BLOCKS_BASE)) ret = 1; - else - ret = 0; D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x (mod 0x%x): %s\n", c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, Index: fs/jffs2/build.c =================================================================== RCS file: /home/cvs/mtd/fs/jffs2/build.c,v retrieving revision 1.36 diff -u -r1.36 build.c --- fs/jffs2/build.c 7 Aug 2002 18:37:32 -0000 1.36 +++ fs/jffs2/build.c 19 Aug 2002 22:30:40 -0000 @@ -43,6 +43,7 @@ return ret; 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. */ for_each_inode(i, c, ic) { @@ -54,7 +55,8 @@ } } 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 @@ -75,6 +77,7 @@ and furthermore that it had children and their nlink has now gone to zero too. So we have to restart the scan. */ } + D1(jffs2_dump_block_lists(c)); } while(ret == -EAGAIN); D1(printk(KERN_DEBUG "Pass 2 complete\n")); @@ -99,6 +102,7 @@ kfree(scan); } D1(printk(KERN_DEBUG "Pass 3 complete\n")); + D1(jffs2_dump_block_lists(c)); /* Rotate the lists by some number to ensure wear levelling */ jffs2_rotate_lists(c); Index: fs/jffs2/gc.c =================================================================== RCS file: /home/cvs/mtd/fs/jffs2/gc.c,v retrieving revision 1.78 diff -u -r1.78 gc.c --- fs/jffs2/gc.c 7 Aug 2002 11:01:14 -0000 1.78 +++ fs/jffs2/gc.c 19 Aug 2002 22:30:42 -0000 @@ -33,6 +33,40 @@ struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, uint32_t start, uint32_t end); +/* Check, if we have enough dirty space for GC */ +int jffs2_gc_checkspace (struct jffs2_sb_info *c, int blocksneeded) +{ + + if (c->dirty_size < blocksneeded * c->sector_size) { + + uint32_t dirty = 0; + struct list_head *this; + + if (!list_empty(&c->very_dirty_list)) { + list_for_each(this, &c->very_dirty_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + dirty += jeb->dirty_size; + } + } + if (!list_empty(&c->dirty_list)) { + list_for_each(this, &c->dirty_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + dirty += jeb->dirty_size; + } + } + /* Add dirty size of current gc-block */ + if (c->gcblock) + dirty += c->gcblock->dirty_size; + + if (dirty < c->sector_size) { + D1(printk(KERN_DEBUG "dirty size in dirty_lists 0x%08x < sector size 0x%08x\n", dirty, c->sector_size)); + return 1; + } + } + /* yep, we can GC */ + return 0; +} + /* Called with erase_completion_lock held */ static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c) { Index: fs/jffs2/nodelist.h =================================================================== RCS file: /home/cvs/mtd/fs/jffs2/nodelist.h,v retrieving revision 1.75 diff -u -r1.75 nodelist.h --- fs/jffs2/nodelist.h 17 Aug 2002 22:28:04 -0000 1.75 +++ fs/jffs2/nodelist.h 19 Aug 2002 22:30:43 -0000 @@ -220,8 +220,9 @@ /* How much dirty space before it goes on the very_dirty_list */ #define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2)) -/* check if unused space is more than sector - 2 * sizeof(struct jffs2_raw_inode) */ -#define ISDIRTY(c, size) ((size) < c->sector_size - (2 * sizeof(struct jffs2_raw_inode))) +/* check if unused space is more than 256 Byte */ +#define ISDIRTY(c, size) ((size) < c->sector_size - 255) +#define MNTISDIRTY(c, size) ((size) < c->sector_size - 4) #define PAD(x) (((x)+3)&~3) @@ -299,6 +300,7 @@ /* gc.c */ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c); +int jffs2_gc_checkspace (struct jffs2_sb_info *c, int blocksneeded); /* read.c */ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsigned char *buf, int ofs, int len); Index: fs/jffs2/nodemgmt.c =================================================================== RCS file: /home/cvs/mtd/fs/jffs2/nodemgmt.c,v retrieving revision 1.71 diff -u -r1.71 nodemgmt.c --- fs/jffs2/nodemgmt.c 17 Aug 2002 22:32:11 -0000 1.71 +++ fs/jffs2/nodemgmt.c 19 Aug 2002 22:30:44 -0000 @@ -62,32 +62,13 @@ int ret; up(&c->alloc_sem); - if (c->dirty_size < c->sector_size) { - D1(printk(KERN_DEBUG "Short on space, but total dirty size 0x%08x < sector size 0x%08x, so -ENOSPC\n", c->dirty_size, c->sector_size)); + + if (jffs2_gc_checkspace(c, blocksneeded)) { + D1(printk (KERN_DEBUG "Too little dirty_space for GC, returning -ENOSPC\n")); spin_unlock_bh(&c->erase_completion_lock); return -ENOSPC; } - if (c->dirty_size < blocksneeded * c->sector_size) { - uint32_t dirty = 0; - struct list_head *this; - if (!list_empty(&c->very_dirty_list)) { - list_for_each(this, &c->very_dirty_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - dirty += jeb->dirty_size; - } - } - if (!list_empty(&c->dirty_list)) { - list_for_each(this, &c->dirty_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - dirty += jeb->dirty_size; - } - } - if (dirty < c->sector_size) { - D1(printk(KERN_DEBUG "Short on space, but dirty size in dirty_lists 0x%08x < sector size 0x%08x, so -ENOSPC\n", dirty, c->sector_size)); - spin_unlock_bh(&c->erase_completion_lock); - return -ENOSPC; - } - } + D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n", c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->free_size + c->dirty_size + c->used_size + c->erasing_size + c->bad_size, c->flash_size)); @@ -498,6 +479,8 @@ #if CONFIG_JFFS2_FS_DEBUG > 0 void jffs2_dump_block_lists(struct jffs2_sb_info *c) { + + printk(KERN_DEBUG "jffs2_dump_block_lists:\n"); printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size); printk(KERN_DEBUG "used_size: %08x\n", c->used_size); @@ -522,31 +505,46 @@ printk(KERN_DEBUG "clean_list: empty\n"); } else { struct list_head *this; + int numblocks = 0; + uint32_t dirty = 0; list_for_each(this, &c->clean_list) { struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + numblocks ++; + dirty += jeb->dirty_size; printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); } + printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", numblocks, dirty, dirty / numblocks); } if (list_empty(&c->very_dirty_list)) { printk(KERN_DEBUG "very_dirty_list: empty\n"); } else { struct list_head *this; + int numblocks = 0; + uint32_t dirty = 0; list_for_each(this, &c->very_dirty_list) { 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, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); } + 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"); } else { struct list_head *this; + int numblocks = 0; + uint32_t dirty = 0; list_for_each(this, &c->dirty_list) { 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, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size); } + 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"); Index: fs/jffs2/scan.c =================================================================== RCS file: /home/cvs/mtd/fs/jffs2/scan.c,v retrieving revision 1.80 diff -u -r1.80 scan.c --- fs/jffs2/scan.c 17 Aug 2002 22:29:28 -0000 1.80 +++ fs/jffs2/scan.c 19 Aug 2002 22:30:47 -0000 @@ -420,7 +420,7 @@ if (jeb->used_size == PAD(sizeof(struct jffs2_unknown_node)) && !jeb->first_node->next_in_ino && !jeb->dirty_size) return BLK_STATE_CLEANMARKER; - else if (!ISDIRTY(c, jeb->used_size)) + else if (!MNTISDIRTY(c, jeb->used_size)) return BLK_STATE_CLEAN; else if (jeb->used_size) return BLK_STATE_PARTDIRTY;