mtd/fs/jffs2 background.c,1.30,1.31 build.c,1.36,1.37 erase.c,1.39,1.40 gc.c,1.78,1.79 nodelist.h,1.75,1.76 nodemgmt.c,1.71,1.72 scan.c,1.80,1.81 wbuf.c,1.14,1.15
gleixner at infradead.org
gleixner at infradead.org
Tue Aug 20 11:41:31 EDT 2002
Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv27023/fs/jffs2
Modified Files:
background.c build.c erase.c gc.c nodelist.h nodemgmt.c scan.c
wbuf.c
Log Message:
changed GC calculation, introduced wasted space to prevent crashing of 100full filesystems and endless GC loops
Index: background.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/background.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- background.c 5 Aug 2002 14:46:47 -0000 1.30
+++ background.c 20 Aug 2002 15:41:28 -0000 1.31
@@ -154,23 +154,14 @@
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 &&
+ (c->dirty_size > c->sector_size))
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,
- c->dirty_size - gcnodeofs, ret?"yes":"no"));
+ D1(printk(KERN_DEBUG "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"));
return ret;
}
Index: build.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/build.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- build.c 7 Aug 2002 18:37:32 -0000 1.36
+++ build.c 20 Aug 2002 15:41:28 -0000 1.37
@@ -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);
@@ -284,6 +288,7 @@
c->blocks[i].offset = i * c->sector_size;
c->blocks[i].free_size = c->sector_size;
c->blocks[i].dirty_size = 0;
+ c->blocks[i].wasted_size = 0;
c->blocks[i].used_size = 0;
c->blocks[i].first_node = NULL;
c->blocks[i].last_node = NULL;
Index: erase.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/erase.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- erase.c 23 Jul 2002 17:00:45 -0000 1.39
+++ erase.c 20 Aug 2002 15:41:28 -0000 1.40
@@ -344,6 +344,7 @@
jeb->free_size = c->sector_size;
jeb->used_size = 0;
jeb->dirty_size = 0;
+ jeb->wasted_size = 0;
} else {
struct jffs2_unknown_node marker = {
.magic = JFFS2_MAGIC_BITMASK,
@@ -375,6 +376,7 @@
jeb->free_size = c->sector_size - marker_ref->totlen;
jeb->used_size = marker_ref->totlen;
jeb->dirty_size = 0;
+ jeb->wasted_size = 0;
}
spin_lock_bh(&c->erase_completion_lock);
Index: gc.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/gc.c,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -r1.78 -r1.79
--- gc.c 7 Aug 2002 11:01:14 -0000 1.78
+++ gc.c 20 Aug 2002 15:41:28 -0000 1.79
@@ -87,6 +87,15 @@
printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset);
BUG();
}
+
+ /* Have we accidentally picked a clean block with wasted space ? */
+ if (ret->wasted_size) {
+ D1(printk(KERN_DEBUG "Converting wasted_size %08x to dirty_size\n", ret->wasted_size));
+ ret->dirty_size += ret->wasted_size;
+ c->wasted_size -= ret->wasted_size;
+ c->dirty_size += ret->wasted_size;
+ ret->wasted_size = 0;
+ }
D1(jffs2_dump_block_lists(c));
return ret;
@@ -129,7 +138,7 @@
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));
+ printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_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.75
retrieving revision 1.76
diff -u -r1.75 -r1.76
--- nodelist.h 17 Aug 2002 22:28:04 -0000 1.75
+++ nodelist.h 20 Aug 2002 15:41:28 -0000 1.76
@@ -160,6 +160,7 @@
uint32_t used_size;
uint32_t dirty_size;
+ uint32_t wasted_size;
uint32_t free_size; /* Note that sector_size - free_size
is the address of the first free space */
struct jffs2_raw_node_ref *first_node;
@@ -177,16 +178,16 @@
};
#define ACCT_SANITY_CHECK(c, jeb) do { \
- if (jeb->used_size + jeb->dirty_size + jeb->free_size != c->sector_size) { \
+ if (jeb->used_size + jeb->dirty_size + jeb->free_size +jeb->wasted_size != c->sector_size) { \
printk(KERN_NOTICE "Eeep. Space accounting for block at 0x%08x is screwed\n", jeb->offset); \
- printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x != total %08x\n", \
- jeb->free_size, jeb->dirty_size, jeb->used_size, c->sector_size); \
+ printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + wasted %08x != total %08x\n", \
+ jeb->free_size, jeb->dirty_size, jeb->used_size, jeb->wasted_size, c->sector_size); \
BUG(); \
} \
- if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size != c->flash_size) { \
+ if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + c->wasted_size != c->flash_size) { \
printk(KERN_NOTICE "Eeep. Space accounting superblock info is screwed\n"); \
- printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x != total %08x\n", \
- c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->flash_size); \
+ printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x + wasted %08x != total %08x\n", \
+ c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->wasted_size, c->flash_size); \
BUG(); \
} \
} while(0)
@@ -220,8 +221,8 @@
/* 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 dirty space is more than 255 Byte */
+#define ISDIRTY(size) ((size) > sizeof (struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN)
#define PAD(x) (((x)+3)&~3)
Index: nodemgmt.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodemgmt.c,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -r1.71 -r1.72
--- nodemgmt.c 17 Aug 2002 22:32:11 -0000 1.71
+++ nodemgmt.c 20 Aug 2002 15:41:28 -0000 1.72
@@ -62,35 +62,16 @@
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));
+ D1(printk(KERN_DEBUG "dirty size 0x%08x < sector size 0x%08x, returning -ENOSPC\n", c->dirty_size, c->sector_size));
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));
+
+ D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_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->wasted_size, c->used_size, c->erasing_size, c->bad_size,
+ c->free_size + c->dirty_size + c->wasted_size + c->used_size + c->erasing_size + c->bad_size, c->flash_size));
spin_unlock_bh(&c->erase_completion_lock);
ret = jffs2_garbage_collect_pass(c);
@@ -151,22 +132,30 @@
spin_lock_bh(&c->erase_completion_lock);
/* We know nobody's going to have changed nextblock. Just continue */
}
- c->dirty_size += jeb->free_size;
+ c->wasted_size += jeb->free_size;
c->free_size -= jeb->free_size;
- jeb->dirty_size += jeb->free_size;
+ jeb->wasted_size += jeb->free_size;
jeb->free_size = 0;
- if (!ISDIRTY(c, jeb->used_size)) {
+
+ /* Check, if we have a dirty block now, or if it was dirty already */
+ if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) {
+ c->dirty_size += jeb->wasted_size;
+ c->wasted_size -= jeb->wasted_size;
+ jeb->dirty_size += jeb->wasted_size;
+ jeb->wasted_size = 0;
+ 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->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);
+ }
+ } else {
D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_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->clean_list);
- } else 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->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;
}
@@ -373,9 +362,17 @@
spin_lock_bh(&c->erase_completion_lock);
jeb->used_size -= ref->totlen;
- jeb->dirty_size += ref->totlen;
c->used_size -= ref->totlen;
- c->dirty_size += ref->totlen;
+
+ if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref->totlen)) && jeb != c->nextblock) {
+ jeb->dirty_size += ref->totlen + jeb->wasted_size;
+ c->dirty_size += ref->totlen + jeb->wasted_size;
+ c->wasted_size -= jeb->wasted_size;
+ jeb->wasted_size = 0;
+ } else {
+ jeb->wasted_size += ref->totlen;
+ c->wasted_size += ref->totlen;
+ }
ref->flash_offset |= 1;
ACCT_SANITY_CHECK(c, jeb);
@@ -442,7 +439,7 @@
D1(printk(KERN_DEBUG "Done OK\n"));
} else if (jeb == c->gcblock) {
D2(printk(KERN_DEBUG "Not moving gcblock 0x%08x to dirty_list\n", jeb->offset));
- } else if (ISDIRTY(c, jeb->used_size) && !ISDIRTY(c, jeb->used_size + ref->totlen)) {
+ } else if (ISDIRTY(jeb->dirty_size) && !ISDIRTY(jeb->dirty_size - ref->totlen)) {
D1(printk(KERN_DEBUG "Eraseblock at 0x%08x is freshly dirtied. Removing from clean list...\n", jeb->offset));
list_del(&jeb->list);
D1(printk(KERN_DEBUG "...and adding to dirty_list\n"));
@@ -498,10 +495,13 @@
#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);
printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size);
+ printk(KERN_DEBUG "wasted_size: %08x\n", c->wasted_size);
printk(KERN_DEBUG "free_size: %08x\n", c->free_size);
printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size);
printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size);
@@ -509,12 +509,12 @@
printk(KERN_DEBUG "jffs2_reserved_blocks size: %08x\n",c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE);
if (c->nextblock) {
- printk(KERN_DEBUG "nextblock: %08x (used %08x, dirty %08x, free %08x)\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->free_size);
+ printk(KERN_DEBUG "nextblock: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size);
} else {
printk(KERN_DEBUG "nextblock: NULL\n");
}
if (c->gcblock) {
- printk(KERN_DEBUG "gcblock: %08x (used %08x, dirty %08x, free %08x)\n", c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->gcblock->free_size);
+ printk(KERN_DEBUG "gcblock: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->nextblock->wasted_size, c->gcblock->free_size);
} else {
printk(KERN_DEBUG "gcblock: NULL\n");
}
@@ -522,31 +522,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);
- printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+ numblocks ++;
+ dirty += jeb->wasted_size;
+ printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
}
+ printk (KERN_DEBUG "Contains %d blocks with total wasted size %u, average wasted 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);
- 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);
+ numblocks ++;
+ dirty += jeb->dirty_size;
+ printk(KERN_DEBUG "very_dirty_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_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);
- printk(KERN_DEBUG "dirty_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+ numblocks ++;
+ dirty += jeb->dirty_size;
+ printk(KERN_DEBUG "dirty_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_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");
@@ -555,7 +570,7 @@
list_for_each(this, &c->erasable_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
- printk(KERN_DEBUG "erasable_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+ printk(KERN_DEBUG "erasable_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
}
}
if (list_empty(&c->erasing_list)) {
@@ -565,7 +580,7 @@
list_for_each(this, &c->erasing_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
- printk(KERN_DEBUG "erasing_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+ printk(KERN_DEBUG "erasing_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
}
}
if (list_empty(&c->erase_pending_list)) {
@@ -575,7 +590,7 @@
list_for_each(this, &c->erase_pending_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
- printk(KERN_DEBUG "erase_pending_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+ printk(KERN_DEBUG "erase_pending_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
}
}
if (list_empty(&c->erasable_pending_wbuf_list)) {
@@ -585,7 +600,7 @@
list_for_each(this, &c->erasable_pending_wbuf_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
- printk(KERN_DEBUG "erase_pending_wbuf_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+ printk(KERN_DEBUG "erase_pending_wbuf_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
}
}
if (list_empty(&c->free_list)) {
@@ -595,7 +610,7 @@
list_for_each(this, &c->free_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
- printk(KERN_DEBUG "free_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+ printk(KERN_DEBUG "free_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
}
}
if (list_empty(&c->bad_list)) {
@@ -605,7 +620,7 @@
list_for_each(this, &c->bad_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
- printk(KERN_DEBUG "bad_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+ printk(KERN_DEBUG "bad_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
}
}
if (list_empty(&c->bad_used_list)) {
@@ -615,7 +630,7 @@
list_for_each(this, &c->bad_used_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
- printk(KERN_DEBUG "bad_used_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+ printk(KERN_DEBUG "bad_used_list: %08x (used %08x, dirty %08x, wasted %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->free_size);
}
}
}
Index: scan.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/scan.c,v
retrieving revision 1.80
retrieving revision 1.81
diff -u -r1.80 -r1.81
--- scan.c 17 Aug 2002 22:29:28 -0000 1.80
+++ scan.c 20 Aug 2002 15:41:28 -0000 1.81
@@ -120,6 +120,11 @@
(!c->nextblock || c->nextblock->free_size < jeb->free_size)) {
/* Better candidate for the next writes to go to */
if (c->nextblock) {
+ c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size;
+ c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size;
+ c->free_size -= c->nextblock->free_size;
+ c->wasted_size -= c->nextblock->wasted_size;
+ c->nextblock->free_size = c->nextblock->wasted_size = 0;
if (VERYDIRTY(c, c->nextblock->dirty_size)) {
list_add(&c->nextblock->list, &c->very_dirty_list);
} else {
@@ -128,6 +133,11 @@
}
c->nextblock = jeb;
} else {
+ jeb->dirty_size += jeb->free_size + jeb->wasted_size;
+ c->dirty_size += jeb->free_size + jeb->wasted_size;
+ c->free_size -= jeb->free_size;
+ c->wasted_size -= jeb->wasted_size;
+ jeb->free_size = jeb->wasted_size = 0;
if (VERYDIRTY(c, jeb->dirty_size)) {
list_add(&jeb->list, &c->very_dirty_list);
} else {
@@ -156,6 +166,14 @@
BUG();
}
}
+
+ /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */
+ if (c->nextblock && (c->nextblock->dirty_size)) {
+ c->nextblock->wasted_size += c->nextblock->dirty_size;
+ c->wasted_size += c->nextblock->dirty_size;
+ c->dirty_size -= c->nextblock->dirty_size;
+ c->nextblock->dirty_size = 0;
+ }
if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) {
/* If we're going to start writing into a block which already
@@ -166,8 +184,8 @@
D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n",
skip));
- c->nextblock->dirty_size += skip;
- c->dirty_size += skip;
+ c->nextblock->wasted_size += skip;
+ c->wasted_size += skip;
c->nextblock->free_size -= skip;
c->free_size -= skip;
@@ -420,9 +438,14 @@
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))
+ /* move blocks with max 4 byte dirty space to cleanlist */
+ else if (jeb->used_size >= (c->sector_size - 4)) {
+ c->dirty_size -= jeb->dirty_size;
+ c->wasted_size += jeb->dirty_size;
+ jeb->wasted_size = jeb->dirty_size;
+ jeb->dirty_size = 0;
return BLK_STATE_CLEAN;
- else if (jeb->used_size)
+ } else if (jeb->used_size)
return BLK_STATE_PARTDIRTY;
else
return BLK_STATE_ALLDIRTY;
Index: wbuf.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/wbuf.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- wbuf.c 19 Aug 2002 14:33:27 -0000 1.14
+++ wbuf.c 20 Aug 2002 15:41:28 -0000 1.15
@@ -199,7 +199,9 @@
BUG();
}
c->nextblock->free_size -= (c->wbuf_pagesize - c->wbuf_len);
- c->nextblock->dirty_size += (c->wbuf_pagesize - c->wbuf_len);
+ c->free_size -= (c->wbuf_pagesize - c->wbuf_len);
+ c->nextblock->wasted_size += (c->wbuf_pagesize - c->wbuf_len);
+ c->wasted_size += (c->wbuf_pagesize - c->wbuf_len);
spin_unlock_bh(&c->erase_completion_lock);
}
More information about the linux-mtd-cvs
mailing list