[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: What on Earth is JFFS2 GC doing?




dwmw2@xxxxxxx.org said:
>  There's one optimisation I'm tempted to try before doing that - at
> least we  don't have to walk any given per-inode list more than once,
> if we're being  sensible about it. Currently we go round it once for
> every node we want to  delete. If there's more than one node to delete
> from a given inode, that's  silly. 

Try something like this...

Index: erase.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/erase.c,v
retrieving revision 1.19
diff -u -r1.19 erase.c
--- erase.c	2001/03/25 22:36:12	1.19
+++ erase.c	2001/06/22 23:35:14
@@ -164,48 +164,71 @@
 
 /* Hmmm. Maybe we should accept the extra space it takes and make
    this a standard doubly-linked list? */
-static inline void jffs2_remove_node_ref_from_ino_list(struct jffs2_sb_info *sbinfo, struct jffs2_raw_node_ref *ref)
+static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
+			struct jffs2_raw_node_ref *ref, struct jffs2_eraseblock *jeb)
 {
-	struct jffs2_inode_cache *ic;
-	struct jffs2_raw_node_ref **prev, *this;
-	D2(int c=0);
+	struct jffs2_inode_cache *ic = NULL;
+	struct jffs2_raw_node_ref **prev;
 
-	this = ref;
-	while(this->next_in_ino)
-		 this = this->next_in_ino;
+	prev = &ref->next_in_ino;
 
-	ic = (struct jffs2_inode_cache *)this;
+	/* Walk the inode's list once, removing any nodes from this eraseblock */
+	while (1) {
+		if (!(*prev)->next_in_ino) {
+			/* We're looking at the jffs2_inode_cache, which is 
+			   at the end of the linked list. Stash it and continue
+			   from the beginning of the list */
+			ic = (struct jffs2_inode_cache *)(*prev);
+			prev = &ic->nodes;
+			continue;
+		} 
 
-	D1(printk(KERN_DEBUG "Removing node at phys 0x%08x from ino #%u\n", ref->flash_offset &~3, ic->ino));
+		if (((*prev)->flash_offset & ~(c->sector_size -1)) == jeb->offset) {
+			/* It's in the block we're erasing */
+			struct jffs2_raw_node_ref *this;
 
-	prev = &ic->nodes;
-	if (!*prev) {
-		printk(KERN_WARNING "Eep. ic->nodes == NULL.\n");
-		return;
-	}
-	while (*prev != ref) {
-		if (!(*prev)->next_in_ino) {
-		        printk(KERN_WARNING "Eep. node at phys 0x%08x, mem %p. next_in_ino is NULL.\n", (*prev)->flash_offset &~3, 
-			       *prev);
-			return;
+			this = *prev;
+			*prev = this->next_in_ino;
+			this->next_in_ino = NULL;
+
+			if (this == ref)
+				break;
+
+			continue;
 		}
-		prev = &(*prev)->next_in_ino;
+		/* Not to be deleted. Skip */
+		prev = &((*prev)->next_in_ino);
 	}
-	*prev = ref->next_in_ino;
-	this = ic->nodes;
-	D2(printk(KERN_DEBUG "After remove_node_ref_from_ino_list: \n" KERN_DEBUG);
-	while(this) {
-		printk( "0x%08x(%d)->", this->flash_offset & ~3, this->flash_offset &3);
-		if (++c == 5) {
-			printk("\n" KERN_DEBUG);
-			c=0;
-		}
-		this = this->next_in_ino;
+
+	/* PARANOIA */
+	if (!ic) {
+		printk(KERN_WARNING "inode_cache not found in remove_node_refs()!!\n");
+		return;
 	}
-	printk("\n"););
+
+	D1(printk(KERN_DEBUG "Removed nodes in range 0x%08x-0x%08x from ino #%u\n",
+		  jeb->offset, jeb->offset + c->sector_size, ic->ino));
+
+	D2({
+		int i=0;
+		printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n" KERN_DEBUG);
+
+		this = ic->nodes;
+	   
+		while(this) {
+			printk( "0x%08x(%d)->", this->flash_offset & ~3, this->flash_offset &3);
+			if (++i == 5) {
+				printk("\n" KERN_DEBUG);
+				i=0;
+			}
+			this = this->next_in_ino;
+		}
+		printk("\n");
+	});
+
 	if (ic->nodes == (void *)ic) {
 		D1(printk(KERN_DEBUG "inocache for ino #%u is all gone now. Freeing\n", ic->ino));
-		jffs2_del_ino_cache(sbinfo, ic);
+		jffs2_del_ino_cache(c, ic);
 		jffs2_free_inode_cache(ic);
 	}
 }
@@ -220,8 +243,8 @@
 		
 		/* Remove from the inode-list */
 		if (ref->next_in_ino)
-			jffs2_remove_node_ref_from_ino_list(c, ref);
-		/* else it was a non-inode node so don't bother */
+			jffs2_remove_node_refs_from_ino_list(c, ref, jeb);
+		/* else it was a non-inode node or already removed, so don't bother */
 
 		jffs2_free_raw_node_ref(ref);
 	}


--
dwmw2



To unsubscribe from this list: send the line "unsubscribe jffs-dev" in
the body of a message to majordomo@xxxxxxx.com