public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] exofs: Double page_unlock BUG in write_begin/write_end
@ 2010-10-08 13:20 Boaz Harrosh
  2010-10-08 13:53 ` [PATCH 1/2] exofs: Fix double page_unlock BUG in write_begin/end Boaz Harrosh
  2010-10-08 14:04 ` [PATCH 2/2] exofs: Cleaup read path in regard with read_for_write Boaz Harrosh
  0 siblings, 2 replies; 3+ messages in thread
From: Boaz Harrosh @ 2010-10-08 13:20 UTC (permalink / raw)
  To: linux-fsdevel, linux-kernel, open-osd, Benny Halevy


Testing at Bakeathon, I got a page_unlock BUG_ON triggered.
I've found a very old bug, back from the days of the empire.
It is time related and it only triggers since couple of
rc-releases.

The first patch is the bug fix and I'd want to push it to Linus
for this version. If it's already to late I'll get it to the
merge window with a CC for stable.

The second patch is a cleanup that opened up do to the new
variable introduced in the bugfix above. Which I'll push for
the next release.

[PATCH 1/2] exofs: Fix double page_unlock BUG in write_begin/end
[PATCH 2/2] exofs: Cleaup read path in regard with read_for_write

Thanks
Boaz


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 1/2] exofs: Fix double page_unlock BUG in write_begin/end
  2010-10-08 13:20 [PATCH 0/2] exofs: Double page_unlock BUG in write_begin/write_end Boaz Harrosh
@ 2010-10-08 13:53 ` Boaz Harrosh
  2010-10-08 14:04 ` [PATCH 2/2] exofs: Cleaup read path in regard with read_for_write Boaz Harrosh
  1 sibling, 0 replies; 3+ messages in thread
From: Boaz Harrosh @ 2010-10-08 13:53 UTC (permalink / raw)
  To: linux-fsdevel, linux-kernel, open-osd, Benny Halevy


This BUG is there since the first submit of the code, but only triggered
in last Kernel. It's timing related do to the asynchronous object-creation
behaviour of exofs. (Which should be investigated farther)

The bug is obvious hence the fixed.

Signed-off-by: Boaz Harrosh <Boaz Harrosh bharrosh@panasas.com>
---
 fs/exofs/inode.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index 2f623ac..1cf2286 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -54,6 +54,9 @@ struct page_collect {
 	unsigned nr_pages;
 	unsigned long length;
 	loff_t pg_first; /* keep 64bit also in 32-arches */
+	bool read_4_write; /* This means two things: that the read is sync
+			    * And the pages should not be unlocked.
+			    */
 };
 
 static void _pcol_init(struct page_collect *pcol, unsigned expected_pages,
@@ -71,6 +74,7 @@ static void _pcol_init(struct page_collect *pcol, unsigned expected_pages,
 	pcol->nr_pages = 0;
 	pcol->length = 0;
 	pcol->pg_first = -1;
+	pcol->read_4_write = false;
 }
 
 static void _pcol_reset(struct page_collect *pcol)
@@ -347,7 +351,8 @@ static int readpage_strip(void *data, struct page *page)
 		if (PageError(page))
 			ClearPageError(page);
 
-		unlock_page(page);
+		if (!pcol->read_4_write)
+			unlock_page(page);
 		EXOFS_DBGMSG("readpage_strip(0x%lx, 0x%lx) empty page,"
 			     " splitting\n", inode->i_ino, page->index);
 
@@ -428,6 +433,7 @@ static int _readpage(struct page *page, bool is_sync)
 	/* readpage_strip might call read_exec(,is_sync==false) at several
 	 * places but not if we have a single page.
 	 */
+	pcol.read_4_write = is_sync;
 	ret = readpage_strip(&pcol, page);
 	if (ret) {
 		EXOFS_ERR("_readpage => %d\n", ret);
-- 
1.7.2


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] exofs: Cleaup read path in regard with read_for_write
  2010-10-08 13:20 [PATCH 0/2] exofs: Double page_unlock BUG in write_begin/write_end Boaz Harrosh
  2010-10-08 13:53 ` [PATCH 1/2] exofs: Fix double page_unlock BUG in write_begin/end Boaz Harrosh
@ 2010-10-08 14:04 ` Boaz Harrosh
  1 sibling, 0 replies; 3+ messages in thread
From: Boaz Harrosh @ 2010-10-08 14:04 UTC (permalink / raw)
  To: linux-fsdevel, linux-kernel, open-osd, Benny Halevy


Last BUG fix added a flag to the the page_collect structure
to communicate with readpage_strip. This calls for a clean up
removing that flag's reincarnations in the read functions
parameters.

Signed-off-by: Boaz Harrosh <Boaz Harrosh bharrosh@panasas.com>
---
 fs/exofs/inode.c |   34 ++++++++++++++--------------------
 1 files changed, 14 insertions(+), 20 deletions(-)

diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index 1cf2286..d339921 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -185,7 +185,7 @@ static void update_write_page(struct page *page, int ret)
 /* Called at the end of reads, to optionally unlock pages and update their
  * status.
  */
-static int __readpages_done(struct page_collect *pcol, bool do_unlock)
+static int __readpages_done(struct page_collect *pcol)
 {
 	int i;
 	u64 resid;
@@ -221,7 +221,7 @@ static int __readpages_done(struct page_collect *pcol, bool do_unlock)
 			  page_stat ? "bad_bytes" : "good_bytes");
 
 		ret = update_read_page(page, page_stat);
-		if (do_unlock)
+		if (!pcol->read_4_write)
 			unlock_page(page);
 		length += PAGE_SIZE;
 	}
@@ -236,7 +236,7 @@ static void readpages_done(struct exofs_io_state *ios, void *p)
 {
 	struct page_collect *pcol = p;
 
-	__readpages_done(pcol, true);
+	__readpages_done(pcol);
 	atomic_dec(&pcol->sbi->s_curr_pending);
 	kfree(pcol);
 }
@@ -257,7 +257,7 @@ static void _unlock_pcol_pages(struct page_collect *pcol, int ret, int rw)
 	}
 }
 
-static int read_exec(struct page_collect *pcol, bool is_sync)
+static int read_exec(struct page_collect *pcol)
 {
 	struct exofs_i_info *oi = exofs_i(pcol->inode);
 	struct exofs_io_state *ios = pcol->ios;
@@ -267,17 +267,14 @@ static int read_exec(struct page_collect *pcol, bool is_sync)
 	if (!pcol->pages)
 		return 0;
 
-	/* see comment in _readpage() about sync reads */
-	WARN_ON(is_sync && (pcol->nr_pages != 1));
-
 	ios->pages = pcol->pages;
 	ios->nr_pages = pcol->nr_pages;
 	ios->length = pcol->length;
 	ios->offset = pcol->pg_first << PAGE_CACHE_SHIFT;
 
-	if (is_sync) {
+	if (pcol->read_4_write) {
 		exofs_oi_read(oi, pcol->ios);
-		return __readpages_done(pcol, false);
+		return __readpages_done(pcol);
 	}
 
 	pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL);
@@ -303,7 +300,7 @@ static int read_exec(struct page_collect *pcol, bool is_sync)
 	return 0;
 
 err:
-	if (!is_sync)
+	if (!pcol->read_4_write)
 		_unlock_pcol_pages(pcol, ret, READ);
 
 	pcol_free(pcol);
@@ -356,7 +353,7 @@ static int readpage_strip(void *data, struct page *page)
 		EXOFS_DBGMSG("readpage_strip(0x%lx, 0x%lx) empty page,"
 			     " splitting\n", inode->i_ino, page->index);
 
-		return read_exec(pcol, false);
+		return read_exec(pcol);
 	}
 
 try_again:
@@ -366,7 +363,7 @@ try_again:
 	} else if (unlikely((pcol->pg_first + pcol->nr_pages) !=
 		   page->index)) {
 		/* Discontinuity detected, split the request */
-		ret = read_exec(pcol, false);
+		ret = read_exec(pcol);
 		if (unlikely(ret))
 			goto fail;
 		goto try_again;
@@ -391,7 +388,7 @@ try_again:
 			  page, len, pcol->nr_pages, pcol->length);
 
 		/* split the request, and start again with current page */
-		ret = read_exec(pcol, false);
+		ret = read_exec(pcol);
 		if (unlikely(ret))
 			goto fail;
 
@@ -420,27 +417,24 @@ static int exofs_readpages(struct file *file, struct address_space *mapping,
 		return ret;
 	}
 
-	return read_exec(&pcol, false);
+	return read_exec(&pcol);
 }
 
-static int _readpage(struct page *page, bool is_sync)
+static int _readpage(struct page *page, bool read_4_write)
 {
 	struct page_collect pcol;
 	int ret;
 
 	_pcol_init(&pcol, 1, page->mapping->host);
 
-	/* readpage_strip might call read_exec(,is_sync==false) at several
-	 * places but not if we have a single page.
-	 */
-	pcol.read_4_write = is_sync;
+	pcol.read_4_write = read_4_write;
 	ret = readpage_strip(&pcol, page);
 	if (ret) {
 		EXOFS_ERR("_readpage => %d\n", ret);
 		return ret;
 	}
 
-	return read_exec(&pcol, is_sync);
+	return read_exec(&pcol);
 }
 
 /*
-- 
1.7.2



^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-10-08 14:04 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-08 13:20 [PATCH 0/2] exofs: Double page_unlock BUG in write_begin/write_end Boaz Harrosh
2010-10-08 13:53 ` [PATCH 1/2] exofs: Fix double page_unlock BUG in write_begin/end Boaz Harrosh
2010-10-08 14:04 ` [PATCH 2/2] exofs: Cleaup read path in regard with read_for_write Boaz Harrosh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox