mtd/fs/jffs2 nodelist.c,1.89,1.90

David Woodhouse dwmw2 at infradead.org
Wed Dec 8 12:59:23 EST 2004


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

Modified Files:
	nodelist.c 
Log Message:
Adjust jffs2_get_inode_nodes() so we don't use node refs after they're obsoleted.


Index: nodelist.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodelist.c,v
retrieving revision 1.89
retrieving revision 1.90
diff -u -r1.89 -r1.90
--- nodelist.c	28 Nov 2004 12:20:35 -0000	1.89
+++ nodelist.c	8 Dec 2004 17:59:20 -0000	1.90
@@ -92,6 +92,17 @@
 	}
 }
 
+/* Returns first valid node after 'ref'. May return 'ref' */
+static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref)
+{
+	while (ref && ref->next_in_ino) {
+		if (!ref_obsolete(ref))
+			return ref;
+		D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)));
+		ref = ref->next_in_ino;
+	}
+	return NULL;
+}
 
 /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
    with this ino, returning the former in order of version */
@@ -101,7 +112,7 @@
 			  uint32_t *highest_version, uint32_t *latest_mctime,
 			  uint32_t *mctime_ver)
 {
-	struct jffs2_raw_node_ref *ref = f->inocache->nodes;
+	struct jffs2_raw_node_ref *ref, *valid_ref;
 	struct jffs2_tmp_dnode_info *tn, *ret_tn = NULL;
 	struct jffs2_full_dirent *fd, *ret_fd = NULL;
 	union jffs2_node_union node;
@@ -111,22 +122,23 @@
 	*mctime_ver = 0;
 	
 	D1(printk(KERN_DEBUG "jffs2_get_inode_nodes(): ino #%u\n", f->inocache->ino));
-	if (!f->inocache->nodes) {
-		printk(KERN_WARNING "Eep. no nodes for ino #%u\n", f->inocache->ino);
-	}
 
 	spin_lock(&c->erase_completion_lock);
 
-	for (ref = f->inocache->nodes; ref && ref->next_in_ino; ref = ref->next_in_ino) {
-		/* Work out whether it's a data node or a dirent node */
-		if (ref_obsolete(ref)) {
-			/* FIXME: On NAND flash we may need to read these */
-			D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)));
-			continue;
-		}
+	valid_ref = jffs2_first_valid_node(f->inocache->nodes);
+
+	if (!valid_ref)
+		printk(KERN_WARNING "Eep. No valid nodes for ino #%u\n", f->inocache->ino);
+
+	while (valid_ref) {
 		/* We can hold a pointer to a non-obsolete node without the spinlock,
 		   but _obsolete_ nodes may disappear at any time, if the block
-		   they're in gets erased */
+		   they're in gets erased. So if we mark 'ref' obsolete while we're
+		   not holding the lock, it can go away immediately. For that reason,
+		   we find the next valid node first, before processing 'ref'.
+		*/
+		ref = valid_ref;
+		valid_ref = jffs2_first_valid_node(ref->next_in_ino);
 		spin_unlock(&c->erase_completion_lock);
 
 		cond_resched();





More information about the linux-mtd-cvs mailing list