public inbox for linux-btrfs@vger.kernel.org
 help / color / mirror / Atom feed
From: David Woodhouse <dwmw2@infradead.org>
To: Chris Mason <chris.mason@oracle.com>
Cc: Jens Axboe <jens.axboe@oracle.com>,
	Sven Wegener <sven.wegener@stealer.net>,
	linux-btrfs@vger.kernel.org
Subject: Re: [PATCH] Add compability for kernels >=2.6.27-rc1
Date: Tue, 19 Aug 2008 15:51:40 +0100	[thread overview]
Message-ID: <1219157500.3184.484.camel@pmac.infradead.org> (raw)
In-Reply-To: <1217533058.20239.62.camel@think.oraclecorp.com>

On Thu, 2008-07-31 at 15:37 -0400, Chris Mason wrote:
> > BUG: unable to handle kernel paging request at ffff880107c2aa00
> > IP: [<ffffffffa03e73bc>] end_bio_extent_writepage+0x1f4/0x29c
> [btrfs]
> 
> If you can reliably reproduce this, please try with the spin locks
> instead of rcu read locks.  What were you doing at the time?

Just using CONFIG_DEBUG_PAGEALLOC and dirtying a bunch of pages from
different inodes seems enough. Another patch to add to my collection at
git.infradead.org/users/dwmw2/btrfs-kernel-unstable.git ...

From: David Woodhouse <David.Woodhouse@intel.com>
Date: Tue, 19 Aug 2008 15:45:16 +0100
Subject: [PATCH] Remove broken optimisations in end_bio functions.

These ended up freeing objects while they were still using them. Under
guidance from Chris, just rip out the 'clever' bits and do things the
simple way.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
---
 extent_io.c |  159 ++++++++---------------------------------------------------
 1 files changed, 21 insertions(+), 138 deletions(-)

diff --git a/extent_io.c b/extent_io.c
index f46f886..83ba0c3 100644
--- a/extent_io.c
+++ b/extent_io.c
@@ -15,6 +15,8 @@
 #include "extent_io.h"
 #include "extent_map.h"
 #include "compat.h"
+#include "ctree.h"
+#include "btrfs_inode.h"
 
 /* temporary define until extent_map moves out of btrfs */
 struct kmem_cache *btrfs_cache_create(const char *name, size_t size,
@@ -1394,15 +1396,11 @@ static int end_bio_extent_writepage(struct bio *bio,
 {
 	int uptodate = err == 0;
 	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
-	struct extent_state *state = bio->bi_private;
-	struct extent_io_tree *tree = state->tree;
-	struct rb_node *node;
+	struct extent_io_tree *tree;
 	u64 start;
 	u64 end;
-	u64 cur;
 	int whole_page;
 	int ret;
-	unsigned long flags;
 
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
 	if (bio->bi_size)
@@ -1410,6 +1408,8 @@ static int end_bio_extent_writepage(struct bio *bio,
 #endif
 	do {
 		struct page *page = bvec->bv_page;
+		tree = &BTRFS_I(page->mapping->host)->io_tree;
+
 		start = ((u64)page->index << PAGE_CACHE_SHIFT) +
 			 bvec->bv_offset;
 		end = start + bvec->bv_len - 1;
@@ -1423,7 +1423,7 @@ static int end_bio_extent_writepage(struct bio *bio,
 			prefetchw(&bvec->bv_page->flags);
 		if (tree->ops && tree->ops->writepage_end_io_hook) {
 			ret = tree->ops->writepage_end_io_hook(page, start,
-						       end, state, uptodate);
+						       end, NULL, uptodate);
 			if (ret)
 				uptodate = 0;
 		}
@@ -1431,9 +1431,8 @@ static int end_bio_extent_writepage(struct bio *bio,
 		if (!uptodate && tree->ops &&
 		    tree->ops->writepage_io_failed_hook) {
 			ret = tree->ops->writepage_io_failed_hook(bio, page,
-							 start, end, state);
+							 start, end, NULL);
 			if (ret == 0) {
-				state = NULL;
 				uptodate = (err == 0);
 				continue;
 			}
@@ -1445,68 +1444,7 @@ static int end_bio_extent_writepage(struct bio *bio,
 			SetPageError(page);
 		}
 
-		/*
-		 * bios can get merged in funny ways, and so we need to
-		 * be careful with the state variable.  We know the
-		 * state won't be merged with others because it has
-		 * WRITEBACK set, but we can't be sure each biovec is
-		 * sequential in the file.  So, if our cached state
-		 * doesn't match the expected end, search the tree
-		 * for the correct one.
-		 */
-
-		spin_lock_irqsave(&tree->lock, flags);
-		if (!state || state->end != end) {
-			state = NULL;
-			node = __etree_search(tree, start, NULL, NULL);
-			if (node) {
-				state = rb_entry(node, struct extent_state,
-						 rb_node);
-				if (state->end != end ||
-				    !(state->state & EXTENT_WRITEBACK))
-					state = NULL;
-			}
-			if (!state) {
-				spin_unlock_irqrestore(&tree->lock, flags);
-				clear_extent_writeback(tree, start,
-						       end, GFP_ATOMIC);
-				goto next_io;
-			}
-		}
-		cur = end;
-		while(1) {
-			struct extent_state *clear = state;
-			cur = state->start;
-			node = rb_prev(&state->rb_node);
-			if (node) {
-				state = rb_entry(node,
-						 struct extent_state,
-						 rb_node);
-			} else {
-				state = NULL;
-			}
-
-			clear_state_bit(tree, clear, EXTENT_WRITEBACK,
-					1, 0);
-			if (cur == start)
-				break;
-			if (cur < start) {
-				WARN_ON(1);
-				break;
-			}
-			if (!node)
-				break;
-		}
-		/* before releasing the lock, make sure the next state
-		 * variable has the expected bits set and corresponds
-		 * to the correct offsets in the file
-		 */
-		if (state && (state->end + 1 != start ||
-		    !(state->state & EXTENT_WRITEBACK))) {
-			state = NULL;
-		}
-		spin_unlock_irqrestore(&tree->lock, flags);
-next_io:
+		clear_extent_writeback(tree, start, end, GFP_ATOMIC);
 
 		if (whole_page)
 			end_page_writeback(page);
@@ -1539,13 +1477,9 @@ static int end_bio_extent_readpage(struct bio *bio,
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
-	struct extent_state *state = bio->bi_private;
-	struct extent_io_tree *tree = state->tree;
-	struct rb_node *node;
+	struct extent_io_tree *tree;
 	u64 start;
 	u64 end;
-	u64 cur;
-	unsigned long flags;
 	int whole_page;
 	int ret;
 
@@ -1556,6 +1490,8 @@ static int end_bio_extent_readpage(struct bio *bio,
 
 	do {
 		struct page *page = bvec->bv_page;
+		tree = &BTRFS_I(page->mapping->host)->io_tree;
+
 		start = ((u64)page->index << PAGE_CACHE_SHIFT) +
 			bvec->bv_offset;
 		end = start + bvec->bv_len - 1;
@@ -1570,80 +1506,26 @@ static int end_bio_extent_readpage(struct bio *bio,
 
 		if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) {
 			ret = tree->ops->readpage_end_io_hook(page, start, end,
-							      state);
+							      NULL);
 			if (ret)
 				uptodate = 0;
 		}
 		if (!uptodate && tree->ops &&
 		    tree->ops->readpage_io_failed_hook) {
 			ret = tree->ops->readpage_io_failed_hook(bio, page,
-							 start, end, state);
+							 start, end, NULL);
 			if (ret == 0) {
-				state = NULL;
 				uptodate =
 					test_bit(BIO_UPTODATE, &bio->bi_flags);
 				continue;
 			}
 		}
 
-		spin_lock_irqsave(&tree->lock, flags);
-		if (!state || state->end != end) {
-			state = NULL;
-			node = __etree_search(tree, start, NULL, NULL);
-			if (node) {
-				state = rb_entry(node, struct extent_state,
-						 rb_node);
-				if (state->end != end ||
-				    !(state->state & EXTENT_LOCKED))
-					state = NULL;
-			}
-			if (!state) {
-				spin_unlock_irqrestore(&tree->lock, flags);
-				if (uptodate)
-					set_extent_uptodate(tree, start, end,
-							    GFP_ATOMIC);
-				unlock_extent(tree, start, end, GFP_ATOMIC);
-				goto next_io;
-			}
-		}
+		if (uptodate)
+			set_extent_uptodate(tree, start, end,
+					    GFP_ATOMIC);
+		unlock_extent(tree, start, end, GFP_ATOMIC);
 
-		cur = end;
-		while(1) {
-			struct extent_state *clear = state;
-			cur = state->start;
-			node = rb_prev(&state->rb_node);
-			if (node) {
-				state = rb_entry(node,
-					 struct extent_state,
-					 rb_node);
-			} else {
-				state = NULL;
-			}
-			if (uptodate) {
-				set_state_cb(tree, clear, EXTENT_UPTODATE);
-				clear->state |= EXTENT_UPTODATE;
-			}
-			clear_state_bit(tree, clear, EXTENT_LOCKED,
-					1, 0);
-			if (cur == start)
-				break;
-			if (cur < start) {
-				WARN_ON(1);
-				break;
-			}
-			if (!node)
-				break;
-		}
-		/* before releasing the lock, make sure the next state
-		 * variable has the expected bits set and corresponds
-		 * to the correct offsets in the file
-		 */
-		if (state && (state->end + 1 != start ||
-		    !(state->state & EXTENT_LOCKED))) {
-			state = NULL;
-		}
-		spin_unlock_irqrestore(&tree->lock, flags);
-next_io:
 		if (whole_page) {
 			if (uptodate) {
 				SetPageUptodate(page);
@@ -1683,8 +1565,7 @@ static int end_bio_extent_preparewrite(struct bio *bio,
 {
 	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
-	struct extent_state *state = bio->bi_private;
-	struct extent_io_tree *tree = state->tree;
+	struct extent_io_tree *tree;
 	u64 start;
 	u64 end;
 
@@ -1695,6 +1576,8 @@ static int end_bio_extent_preparewrite(struct bio *bio,
 
 	do {
 		struct page *page = bvec->bv_page;
+		tree = &BTRFS_I(page->mapping->host)->io_tree;
+
 		start = ((u64)page->index << PAGE_CACHE_SHIFT) +
 			bvec->bv_offset;
 		end = start + bvec->bv_len - 1;
@@ -1765,7 +1648,7 @@ static int submit_one_bio(int rw, struct bio *bio, int mirror_num)
 	BUG_ON(state->end != end);
 	spin_unlock_irq(&tree->lock);
 
-	bio->bi_private = state;
+	bio->bi_private = NULL;
 
 	bio_get(bio);
 
-- 
1.5.5.1




-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation




  parent reply	other threads:[~2008-08-19 14:51 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-30 19:11 [PATCH] Add compability for kernels >=2.6.27-rc1 Sven Wegener
2008-07-30 19:56 ` Jens Axboe
2008-07-30 20:11   ` Chris Mason
2008-07-30 20:13     ` Jens Axboe
2008-07-30 20:43       ` Chris Mason
2008-07-31 19:27         ` David Woodhouse
2008-07-31 19:37           ` Chris Mason
2008-07-31 19:52             ` David Woodhouse
2008-08-19 14:51             ` David Woodhouse [this message]
2008-08-19 16:30               ` Chris Mason

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1219157500.3184.484.camel@pmac.infradead.org \
    --to=dwmw2@infradead.org \
    --cc=chris.mason@oracle.com \
    --cc=jens.axboe@oracle.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=sven.wegener@stealer.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox