mtd/fs/jffs2 README.Locking,1.8,1.9 wbuf.c,1.79,1.80

David Woodhouse dwmw2 at infradead.org
Sat Nov 20 05:35:44 EST 2004


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

Modified Files:
	README.Locking wbuf.c 
Log Message:
Clean up wbuf_sem a bit, document it.


Index: README.Locking
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/README.Locking,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- README.Locking	14 Nov 2004 11:43:41 -0000	1.8
+++ README.Locking	20 Nov 2004 10:35:40 -0000	1.9
@@ -133,3 +133,16 @@
 collection code is looking at them.
 
 Suggestions for alternative solutions to this problem would be welcomed.
+
+
+	wbuf_sem
+	--------
+
+This read/write semaphore protects against concurrent access to the
+write-behind buffer ('wbuf') used for flash chips where we must write
+in blocks. It protects both the contents of the wbuf and the metadata
+which indicates which flash region (if any) is currently covered by 
+the buffer.
+
+Ordering constraints:
+	Lock wbuf_sem last, after the alloc_sem or and f->sem.

Index: wbuf.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/wbuf.c,v
retrieving revision 1.79
retrieving revision 1.80
diff -u -r1.79 -r1.80
--- wbuf.c	20 Nov 2004 10:21:40 -0000	1.79
+++ wbuf.c	20 Nov 2004 10:35:40 -0000	1.80
@@ -399,7 +399,11 @@
    1: Pad, do not adjust nextblock free_size
    2: Pad, adjust nextblock free_size
 */
-static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad, int alloc_wbuf_sem)
+#define NOPAD		0
+#define PAD_NOACCOUNT	1
+#define PAD_ACCOUNTING	2
+
+static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
 {
 	int ret;
 	size_t retlen;
@@ -415,11 +419,8 @@
 		BUG();
 	}
 
-	if (alloc_wbuf_sem)
-		down_write(&c->wbuf_sem);
-
 	if(!c->wbuf || !c->wbuf_len)
-		goto exit;
+		return 0;
 
 	/* claim remaining space on the page
 	   this happens, if we have a change to a new block,
@@ -472,7 +473,7 @@
 
 		jffs2_wbuf_recover(c);
 
-		goto exit;
+		return ret;
 	}
 
 	spin_lock(&c->erase_completion_lock);
@@ -511,9 +512,6 @@
 	/* adjust write buffer offset, else we get a non contiguous write bug */
 	c->wbuf_ofs += c->wbuf_pagesize;
 	c->wbuf_len = 0;
-exit:
-	if (alloc_wbuf_sem)
-		up_write(&c->wbuf_sem);
 	return 0;
 }
 
@@ -542,7 +540,9 @@
 	if (c->unchecked_size) {
 		/* GC won't make any progress for a while */
 		D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() padding. Not finished checking\n"));
-		ret = __jffs2_flush_wbuf(c, 2, 1);
+		down_write(&c->wbuf_sem);
+		ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
+		up_write(&c->wbuf_sem);
 	} else while (old_wbuf_len &&
 		      old_wbuf_ofs == c->wbuf_ofs) {
 
@@ -554,7 +554,9 @@
 		if (ret) {
 			/* GC failed. Flush it with padding instead */
 			down(&c->alloc_sem);
-			ret = __jffs2_flush_wbuf(c, 2, 1);
+			down_write(&c->wbuf_sem);
+			ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
+			up_write(&c->wbuf_sem);
 			break;
 		}
 		down(&c->alloc_sem);
@@ -569,7 +571,13 @@
 /* Pad write-buffer to end and write it, wasting space. */
 int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c)
 {
-	return __jffs2_flush_wbuf(c, 1, 1);
+	int ret;
+
+	down_write(&c->wbuf_sem);
+	ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT);
+	up_write(&c->wbuf_sem);
+
+	return ret;
 }
 
 #define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) )
@@ -621,7 +629,7 @@
 		/* It's a write to a new block */
 		if (c->wbuf_len) {
 			D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx causes flush of wbuf at 0x%08x\n", (unsigned long)to, c->wbuf_ofs));
-			ret = __jffs2_flush_wbuf(c, 1, 0);
+			ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT);
 			if (ret) {
 				/* the underlying layer has to check wbuf_len to do the cleanup */
 				D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret));
@@ -686,7 +694,7 @@
 		}			
 		
 		/* write buffer is full, flush buffer */
-		ret = __jffs2_flush_wbuf(c, 0, 0);
+		ret = __jffs2_flush_wbuf(c, NOPAD);
 		if (ret) {
 			/* the underlying layer has to check wbuf_len to do the cleanup */
 			D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret));





More information about the linux-mtd-cvs mailing list