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