All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: David Woodhouse <dwmw2@infradead.org>
Cc: linux-mtd@lists.infradead.org
Subject: Re: No free space left for GC
Date: Tue, 20 Aug 2002 00:34:31 +0200	[thread overview]
Message-ID: <1029796472.22781.136.camel@thomas.tec.linutronix.de> (raw)
In-Reply-To: <1029793649.22781.129.camel@thomas.tec.linutronix.de>

[-- Attachment #1: Type: text/plain, Size: 302 bytes --]

Forgot to attach a diff :)

Last try brought average dirty_space 11 bytes in 492 Blocks in
clean_list. I think we can live with that

-- 
Thomas 
____________________________________________________
linutronix - competence in embedded & realtime linux
http://www.linutronix.de
mail: tglx@linutronix.de

[-- Attachment #2: cvs.diff --]
[-- Type: text/plain, Size: 10031 bytes --]

? 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;

  reply	other threads:[~2002-08-19 22:35 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-08-17 22:35 No free space left for GC Thomas Gleixner
2002-08-19  9:37 ` Massive file corruption Joakim Tjernlund
2002-08-19 21:47 ` No free space left for GC Thomas Gleixner
2002-08-19 22:34   ` Thomas Gleixner [this message]
2002-08-20 10:03     ` David Woodhouse
     [not found]   ` <015501c247f3$d13176a0$b30210ac@gv.com.tw>
2002-08-20  7:59     ` Thomas Gleixner
2002-08-20 15:47       ` Thomas Gleixner
2002-08-21  6:44         ` can i use the cvs code directly in kernel 2.2.19 ? 小明
2002-08-21  7:56           ` Thomas Gleixner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1029796472.22781.136.camel@thomas.tec.linutronix.de \
    --to=tglx@linutronix.de \
    --cc=dwmw2@infradead.org \
    --cc=linux-mtd@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.