mtd/fs/jffs2 wbuf.c,1.42,1.43

David Woodhouse dwmw2 at infradead.org
Fri Oct 3 10:58:55 EDT 2003


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

Modified Files:
	wbuf.c 
Log Message:
Fixed and tested wbuf recovery


Index: wbuf.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/wbuf.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -r1.42 -r1.43
--- wbuf.c	2 Oct 2003 16:31:48 -0000	1.42
+++ wbuf.c	3 Oct 2003 14:58:52 -0000	1.43
@@ -139,8 +139,8 @@
 	/* File the existing block on the bad_used_list.... */
 	if (c->nextblock == jeb)
 		c->nextblock = NULL;
-	/* else BUG() I think but I need more coffee. */
-	list_del(&jeb->list);
+	else /* Not sure this should ever happen... need more coffee */
+		list_del(&jeb->list);
 	list_add(&jeb->list, &c->bad_used_list);
 
 	/* Adjust its size counts accordingly */
@@ -166,7 +166,7 @@
 
 	/* Find the last node to be recovered */
 	raw = first_raw;
-	while ((*raw)->next_phys) {
+	while ((*raw)) {
 		if (!ref_obsolete(*raw))
 			end = ref_offset(*raw) + (*raw)->totlen;
 
@@ -229,6 +229,12 @@
 		 there? :) */
 		ret = c->mtd->write_ecc(c->mtd, ofs, (end-start)%c->wbuf_pagesize,
 					&retlen, buf, NULL, c->oobinfo);
+#ifdef BREAKME
+		if (static int breakme++ == 40) {
+			breakme = 0;
+			ret = -EIO;
+		}
+#endif
 		if (!ret || retlen != (end-start)%c->wbuf_pagesize) {
 			/* Argh. We tried. Really we did. */
 			printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
@@ -257,7 +263,6 @@
 		memcpy(c->wbuf, buf + retlen, c->wbuf_len);
 		/* Don't muck about with c->wbuf_inodes. False positives are harmless. */
 
-		spin_lock(&c->erase_completion_lock);
 	} else {
 		/* OK, now we're left with the dregs in the wbuf */
 		memmove(c->wbuf, c->wbuf + (start - c->wbuf_ofs), end - start);
@@ -267,9 +272,6 @@
 	/* Now sort out the jffs2_raw_node_refs, moving them from the old to the next block */
 	new_jeb = &c->blocks[ofs / c->sector_size];
 
-	/* Yeah right, we just started using it... */
-	BUG_ON(new_jeb->first_node);
-	
 	spin_lock(&c->erase_completion_lock);
 	if (new_jeb->first_node) {
 		/* Odd, but possible with ST flash later maybe */
@@ -277,21 +279,30 @@
 	} else {
 		new_jeb->first_node = *first_raw;
 	}
+
 	raw = first_raw;
 	while (*raw) {
+		D1(printk(KERN_DEBUG "Refiling block of %08x at %08x(%d) to %08x\n",
+			  (*raw)->totlen, ref_offset(*raw), ref_flags(*raw), ofs));
+
 		if (ref_obsolete(*raw)) {
 			/* Shouldn't really happen much */
 			new_jeb->dirty_size += (*raw)->totlen;
+			new_jeb->free_size -= (*raw)->totlen;
 			c->dirty_size += (*raw)->totlen;
 		} else {
 			new_jeb->used_size += (*raw)->totlen;
-			jeb->used_size  -= (*raw)->totlen;
+			new_jeb->free_size -= (*raw)->totlen;
 			jeb->dirty_size += (*raw)->totlen;
+			jeb->used_size  -= (*raw)->totlen;
 			c->dirty_size += (*raw)->totlen;
 		}
 		c->free_size -= (*raw)->totlen;
 		(*raw)->flash_offset = ofs | ref_flags(*raw);
+		ofs += (*raw)->totlen;
 		new_jeb->last_node = *raw;
+
+		raw = &(*raw)->next_phys;
 	}
 
 	/* Fix up the original jeb now it's on the bad_list */
@@ -357,7 +368,14 @@
 	   buffer for us, and will deal with the node refs etc. later. */
 	
 	ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo);
-	
+
+#ifdef BREAKME
+	if (static int breakme++ == 40) {
+		breakme = 0;
+		ret = -EIO;
+	}
+#endif
+
 	if (ret || retlen != c->wbuf_pagesize) {
 		if (ret)
 			printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n",ret);
@@ -680,7 +698,7 @@
 
 	vecs[0].iov_base = (unsigned char *) buf;
 	vecs[0].iov_len = len;
-	return jffs2_flash_writev(c, vecs, 1, ofs, retlen, NOT_GC);
+	return jffs2_flash_writev(c, vecs, 1, ofs, retlen, 0);
 }
 
 /*




More information about the linux-mtd-cvs mailing list