mtd/fs/jffs2 build.c,1.53,1.54

David Woodhouse dwmw2 at infradead.org
Fri Oct 24 13:31:13 EDT 2003


Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv13203

Modified Files:
	build.c 
Log Message:
Better optimisation for NAND: Don't restart pass 2 if a child of a zero-nlink
directory ends up with nlink zero, just add it to a list to be cleaned up 
afterwards


Index: build.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/build.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -r1.53 -r1.54
--- build.c	24 Oct 2003 11:32:59 -0000	1.53
+++ build.c	24 Oct 2003 17:31:11 -0000	1.54
@@ -16,8 +16,8 @@
 #include <linux/slab.h>
 #include "nodelist.h"
 
-int jffs2_build_inode_pass1(struct jffs2_sb_info *, struct jffs2_inode_cache *);
-int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *);
+static int jffs2_build_inode_pass1(struct jffs2_sb_info *, struct jffs2_inode_cache *);
+static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *, struct jffs2_full_dirent **);
 
 static inline struct jffs2_inode_cache *
 first_inode_chain(int *i, struct jffs2_sb_info *c)
@@ -54,6 +54,7 @@
 	int ret;
 	int i;
 	struct jffs2_inode_cache *ic;
+	struct jffs2_full_dirent *dead_fds = NULL;
 
 	/* First, scan the medium and build all the inode caches with
 	   lists of physical nodes */
@@ -86,30 +87,35 @@
 	   children too, and repeat the scan. As that's going to be
 	   a fairly uncommon occurrence, it's not so evil to do it this
 	   way. Recursion bad. */
-	do { 
-		D1(printk(KERN_DEBUG "Pass 2 (re)starting\n"));
-		ret = 0;
-		for_each_inode(i, c, ic) {
-			D1(printk(KERN_DEBUG "Pass 2: ino #%u, nlink %d, ic %p, nodes %p\n", ic->ino, ic->nlink, ic, ic->nodes));
-			if (ic->nlink)
-				continue;
+	D1(printk(KERN_DEBUG "Pass 2 starting\n"));
+
+	for_each_inode(i, c, ic) {
+		D1(printk(KERN_DEBUG "Pass 2: ino #%u, nlink %d, ic %p, nodes %p\n", ic->ino, ic->nlink, ic, ic->nodes));
+		if (ic->nlink)
+			continue;
 			
-			/* XXX: Can get high latency here. Move the cond_resched() from the end of the loop? */
+		jffs2_build_remove_unlinked_inode(c, ic, &dead_fds);
+		cond_resched();
+	} 
 
-			ret = jffs2_build_remove_unlinked_inode(c, ic);
-			if (ret)
-				break;
-		/* -EAGAIN means the inode's nlink was zero, so we deleted it,
-		   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));
+	D1(printk(KERN_DEBUG "Pass 2a starting\n"));
 
-		cond_resched();
-	
-	} while(ret == -EAGAIN);
+	while (dead_fds) {
+		struct jffs2_inode_cache *ic;
+		struct jffs2_full_dirent *fd = dead_fds;
+
+		dead_fds = fd->next;
+
+		ic = jffs2_get_ino_cache(c, fd->ino);
+		D1(printk(KERN_DEBUG "Removing dead_fd ino #%u (\"%s\"), ic at %p\n", fd->ino, fd->name, ic));
+
+		if (ic)
+			jffs2_build_remove_unlinked_inode(c, ic, &dead_fds);
+		jffs2_free_full_dirent(fd);
+	}
 
 	D1(printk(KERN_DEBUG "Pass 2 complete\n"));
+	D1(jffs2_dump_block_lists(c));
 	
 	/* Finally, we can scan again and free the dirent nodes and scan_info structs */
 	for_each_inode(i, c, ic) {
@@ -133,7 +139,7 @@
 	return ret;
 }
 
-int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+static int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
 {
 	struct jffs2_full_dirent *fd;
 
@@ -171,11 +177,10 @@
 	return 0;
 }
 
-int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_full_dirent **dead_fds)
 {
 	struct jffs2_raw_node_ref *raw;
 	struct jffs2_full_dirent *fd;
-	int ret = 0;
 
 	D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino));
 	
@@ -214,9 +219,22 @@
 				jffs2_free_full_dirent(fd);
 				continue;
 			}
-			jffs2_free_full_dirent(fd);
+
+			/* Reduce nlink of the child. If it's now zero, stick it on the 
+			   dead_fds list to be cleaned up later. Else just free the fd */
+
 			child_ic->nlink--;
-			ret = -EAGAIN;
+			
+			if (!child_ic->nlink) {
+				D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got zero nlink. Adding to dead_fds list.\n",
+					  fd->ino, fd->name));
+				fd->next = *dead_fds;
+				*dead_fds = fd;
+			} else {
+				D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got nlink %d. Ignoring.\n",
+					  fd->ino, fd->name, child_ic->nlink));
+				jffs2_free_full_dirent(fd);
+			}
 		}
 	}
 
@@ -224,8 +242,6 @@
 	   We don't delete the inocache from the hash list and free it yet. 
 	   The erase code will do that, when all the nodes are completely gone.
 	*/
-
-	return ret;
 }
 
 static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c)




More information about the linux-mtd-cvs mailing list