mtd/fs/jffs2 gc.c,1.124,1.125

David Woodhouse dwmw2 at infradead.org
Mon Nov 3 08:30:33 EST 2003


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

Modified Files:
	gc.c 
Log Message:
Make jffs2_garbage_collect_deletion_dirent() not completely bloody 
stupidly inefficient.


Index: gc.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/gc.c,v
retrieving revision 1.124
retrieving revision 1.125
diff -u -r1.124 -r1.125
--- gc.c	2 Nov 2003 19:28:42 -0000	1.124
+++ gc.c	3 Nov 2003 13:30:29 -0000	1.125
@@ -292,7 +292,7 @@
 		   can happen.
 		*/
 		printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n",
-		       ic->state);
+		       ic->ino, ic->state);
 		up(&c->alloc_sem);
 		spin_unlock(&c->inocache_lock);
 		BUG();
@@ -823,13 +823,17 @@
 	   delete a 'real' dirent with the same name that's still
 	   somewhere else on the flash. */
 	if (!jffs2_can_mark_obsolete(c)) {
-		struct jffs2_raw_dirent rd;
+		struct jffs2_raw_dirent *rd;
 		struct jffs2_raw_node_ref *raw;
 		int ret;
 		size_t retlen;
 		int name_len = strlen(fd->name);
 		uint32_t name_crc = crc32(0, fd->name, name_len);
-		char *namebuf = NULL;
+		uint32_t rawlen = ref_totlen(c, jeb, fd->raw);
+
+		rd = kmalloc(rawlen, GFP_KERNEL);
+		if (!rd)
+			return -ENOMEM;
 
 		/* Prevent the erase code from nicking the obsolete node refs while
 		   we're looking at them. I really don't like this extra lock but
@@ -837,91 +841,66 @@
 		down(&c->erase_free_sem);
 
 		for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) {
+
 			/* We only care about obsolete ones */
 			if (!(ref_obsolete(raw)))
 				continue;
 
+			/* Any dirent with the same name is going to have the same length... */
+			if (ref_totlen(c, NULL, raw) != rawlen)
+				continue;
+
 			/* Doesn't matter if there's one in the same erase block. We're going to 
 			   delete it too at the same time. */
 			if ((raw->flash_offset & ~(c->sector_size-1)) ==
 			    (fd->raw->flash_offset & ~(c->sector_size-1)))
 				continue;
 
-			/* This is an obsolete node belonging to the same directory */
-			ret = jffs2_flash_read(c, ref_offset(raw), sizeof(struct jffs2_unknown_node), &retlen, (char *)&rd);
+			D1(printk(KERN_DEBUG "Check potential deletion dirent at %08x\n", ref_offset(raw)));
+
+			/* This is an obsolete node belonging to the same directory, and it's of the right
+			   length. We need to take a closer look...*/
+			ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)rd);
 			if (ret) {
-				printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading header from obsolete node at %08x\n", ret, ref_offset(raw));
+				printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading obsolete node at %08x\n", ret, ref_offset(raw));
 				/* If we can't read it, we don't need to continue to obsolete it. Continue */
 				continue;
 			}
-			if (retlen != sizeof(struct jffs2_unknown_node)) {
+			if (retlen != rawlen) {
 				printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%zd not %zd) reading header from obsolete node at %08x\n",
-				       retlen, sizeof(struct jffs2_unknown_node), ref_offset(raw));
+				       retlen, rawlen, ref_offset(raw));
 				continue;
 			}
-			if (je16_to_cpu(rd.nodetype) != JFFS2_NODETYPE_DIRENT ||
-			    PAD(je32_to_cpu(rd.totlen)) != PAD(sizeof(rd) + name_len))
-				continue;
 
-			/* OK, it's a dirent node, it's the right length. We have to take a 
-			   closer look at it... */
-			ret = jffs2_flash_read(c, ref_offset(raw), sizeof(rd), &retlen, (char *)&rd);
-			if (ret) {
-				printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading from obsolete node at %08x\n", ret, ref_offset(raw));
-				/* If we can't read it, we don't need to continune to obsolete it. Continue */
-				continue;
-			}
-			if (retlen != sizeof(rd)) {
-				printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%zd not %zd) reading from obsolete node at %08x\n",
-				       retlen, sizeof(rd), ref_offset(raw));
+			if (je16_to_cpu(rd->nodetype) != JFFS2_NODETYPE_DIRENT)
 				continue;
-			}
 
 			/* If the name CRC doesn't match, skip */
-			if (je32_to_cpu(rd.name_crc) != name_crc)
+			if (je32_to_cpu(rd->name_crc) != name_crc)
 				continue;
+
 			/* If the name length doesn't match, or it's another deletion dirent, skip */
-			if (rd.nsize != name_len || !je32_to_cpu(rd.ino))
+			if (rd->nsize != name_len || !je32_to_cpu(rd->ino))
 				continue;
 
 			/* OK, check the actual name now */
-			if (!namebuf) {
-				namebuf = kmalloc(name_len + 1, GFP_KERNEL);
-				if (!namebuf) {
-					up(&c->erase_free_sem);
-					return -ENOMEM;
-				}
-			}
-			/* We read the extra byte before it so it's a word-aligned read */
-			ret = jffs2_flash_read(c, (ref_offset(raw))+sizeof(rd)-1, name_len+1, &retlen, namebuf);
-			if (ret) {
-				printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading name from obsolete node at %08x\n", ret, ref_offset(raw));
-				/* If we can't read it, we don't need to continune to obsolete it. Continue */
-				continue;
-			}
-			if (retlen != name_len+1) {
-				printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%zd not %d) reading name from obsolete node at %08x\n",
-				       retlen, name_len+1, ref_offset(raw));
-				continue;
-			}
-			if (memcmp(namebuf+1, fd->name, name_len))
+			if (memcmp(rd->name, fd->name, name_len))
 				continue;
 
 			/* OK. The name really does match. There really is still an older node on
 			   the flash which our deletion dirent obsoletes. So we have to write out
 			   a new deletion dirent to replace it */
-			
-			if (namebuf)
-				kfree(namebuf);
-
 			up(&c->erase_free_sem);
+
+			D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n",
+				  ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino)));
+			kfree(rd);
+
 			return jffs2_garbage_collect_dirent(c, jeb, f, fd);
 		}
 
 		up(&c->erase_free_sem);
-
-		if (namebuf) 
-			kfree(namebuf);
+		kfree(rd);
 	}
 
 	/* No need for it any more. Just mark it obsolete and remove it from the list */




More information about the linux-mtd-cvs mailing list