mtd/fs/jffs2 background.c,1.35,1.36 nodemgmt.c,1.93,1.94
gleixner at infradead.org
gleixner at infradead.org
Wed Feb 19 12:50:28 EST 2003
Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv11951
Modified Files:
background.c nodemgmt.c
Log Message:
fix endless gc looping by including dirty_space in erase_pending_list in gc-trigger and out of space decisions
Index: background.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/background.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- background.c 21 Jan 2003 18:11:28 -0000 1.35
+++ background.c 19 Feb 2003 17:50:26 -0000 1.36
@@ -153,6 +153,7 @@
static int thread_should_wake(struct jffs2_sb_info *c)
{
int ret = 0;
+ uint32_t dirty;
if (c->unchecked_size) {
D1(printk(KERN_DEBUG "thread_should_wake(): unchecked_size %d, checked_ino #%d\n",
@@ -160,8 +161,18 @@
return 1;
}
+ /* dirty_size contains blocks on erase_pending_list
+ * those blocks are counted in c->nr_erasing_blocks.
+ * If one block is actually erased, it is not longer counted as dirty_space
+ * but it is counted in c->nr_erasing_blocks, so we add it and subtract it
+ * with c->nr_erasing_blocks * c->sector_size again.
+ * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks
+ * This helps us to force gc and pick eventually a clean block to spread the load.
+ */
+ dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size;
+
if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER &&
- (c->dirty_size > c->sector_size))
+ (dirty > c->sector_size))
ret = 1;
D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n",
Index: nodemgmt.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodemgmt.c,v
retrieving revision 1.93
retrieving revision 1.94
diff -u -r1.93 -r1.94
--- nodemgmt.c 18 Feb 2003 18:37:41 -0000 1.93
+++ nodemgmt.c 19 Feb 2003 17:50:26 -0000 1.94
@@ -57,16 +57,47 @@
spin_lock(&c->erase_completion_lock);
- /* this needs a little more thought */
+ /* this needs a little more thought (true <tglx> :)) */
while(ret == -EAGAIN) {
while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) {
int ret;
+ uint32_t dirty, avail;
up(&c->alloc_sem);
- if (c->dirty_size + c->unchecked_size < c->sector_size) {
+ /* calculate real dirty size
+ * dirty_size contains blocks on erase_pending_list
+ * those blocks are counted in c->nr_erasing_blocks.
+ * If one block is actually erased, it is not longer counted as dirty_space
+ * but it is counted in c->nr_erasing_blocks, so we add it and subtract it
+ * with c->nr_erasing_blocks * c->sector_size again.
+ * Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks
+ * This helps us to force gc and pick eventually a clean block to spread the load.
+ * We add unchecked_size here, as we hopefully will find some space to use.
+ * This will affect the sum only once, as gc first finishes checking
+ * of nodes.
+ */
+ dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size + c->unchecked_size;
+ if (dirty < c->sector_size) {
D1(printk(KERN_DEBUG "dirty size 0x%08x + unchecked_size 0x%08x < sector size 0x%08x, returning -ENOSPC\n",
- c->dirty_size, c->unchecked_size, c->sector_size));
+ dirty, c->unchecked_size, c->sector_size));
+ spin_unlock(&c->erase_completion_lock);
+ return -ENOSPC;
+ }
+
+ /* Calc possibly available space. Possibly available means that we
+ * don't know, if unchecked size contains obsoleted nodes, which could give us some
+ * more usable space. This will affect the sum only once, as gc first finishes checking
+ * of nodes.
+ + Return -ENOSPC, if the maximum possibly available space is less or equal than
+ * blocksneeded * sector_size.
+ * This blocks endless gc looping on a filesystem, which is nearly full, even if
+ * the check above passes.
+ */
+ avail = c->free_size + c->dirty_size + c->erasing_size + c->unchecked_size;
+ if ( (avail / c->sector_size) <= blocksneeded) {
+ D1(printk(KERN_DEBUG "max. available size 0x%08x < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n",
+ avail, blocksneeded * c->sector_size));
spin_unlock(&c->erase_completion_lock);
return -ENOSPC;
}
More information about the linux-mtd-cvs
mailing list