diff options
Diffstat (limited to 'fs/btrfs/extent_io.c')
| -rw-r--r-- | fs/btrfs/extent_io.c | 60 | 
1 files changed, 30 insertions, 30 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index cd4b5e40022..c9018a05036 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -402,20 +402,28 @@ static int split_state(struct extent_io_tree *tree, struct extent_state *orig,  	return 0;  } +static struct extent_state *next_state(struct extent_state *state) +{ +	struct rb_node *next = rb_next(&state->rb_node); +	if (next) +		return rb_entry(next, struct extent_state, rb_node); +	else +		return NULL; +} +  /*   * utility function to clear some bits in an extent state struct. - * it will optionally wake up any one waiting on this state (wake == 1), or - * forcibly remove the state from the tree (delete == 1). + * it will optionally wake up any one waiting on this state (wake == 1)   *   * If no bits are set on the state struct after clearing things, the   * struct is freed and removed from the tree   */ -static int clear_state_bit(struct extent_io_tree *tree, -			    struct extent_state *state, -			    int *bits, int wake) +static struct extent_state *clear_state_bit(struct extent_io_tree *tree, +					    struct extent_state *state, +					    int *bits, int wake)  { +	struct extent_state *next;  	int bits_to_clear = *bits & ~EXTENT_CTLBITS; -	int ret = state->state & bits_to_clear;  	if ((bits_to_clear & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) {  		u64 range = state->end - state->start + 1; @@ -427,6 +435,7 @@ static int clear_state_bit(struct extent_io_tree *tree,  	if (wake)  		wake_up(&state->wq);  	if (state->state == 0) { +		next = next_state(state);  		if (state->tree) {  			rb_erase(&state->rb_node, &tree->state);  			state->tree = NULL; @@ -436,8 +445,9 @@ static int clear_state_bit(struct extent_io_tree *tree,  		}  	} else {  		merge_state(tree, state); +		next = next_state(state);  	} -	return ret; +	return next;  }  static struct extent_state * @@ -476,7 +486,6 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,  	struct extent_state *state;  	struct extent_state *cached;  	struct extent_state *prealloc = NULL; -	struct rb_node *next_node;  	struct rb_node *node;  	u64 last_end;  	int err; @@ -528,14 +537,11 @@ hit_next:  	WARN_ON(state->end < start);  	last_end = state->end; -	if (state->end < end && !need_resched()) -		next_node = rb_next(&state->rb_node); -	else -		next_node = NULL; -  	/* the state doesn't have the wanted bits, go ahead */ -	if (!(state->state & bits)) +	if (!(state->state & bits)) { +		state = next_state(state);  		goto next; +	}  	/*  	 *     | ---- desired range ---- | @@ -593,16 +599,13 @@ hit_next:  		goto out;  	} -	clear_state_bit(tree, state, &bits, wake); +	state = clear_state_bit(tree, state, &bits, wake);  next:  	if (last_end == (u64)-1)  		goto out;  	start = last_end + 1; -	if (start <= end && next_node) { -		state = rb_entry(next_node, struct extent_state, -				 rb_node); +	if (start <= end && state && !need_resched())  		goto hit_next; -	}  	goto search_again;  out: @@ -2301,7 +2304,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)  	u64 start;  	u64 end;  	int whole_page; -	int failed_mirror; +	int mirror;  	int ret;  	if (err) @@ -2340,20 +2343,18 @@ static void end_bio_extent_readpage(struct bio *bio, int err)  		}  		spin_unlock(&tree->lock); +		mirror = (int)(unsigned long)bio->bi_bdev;  		if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) {  			ret = tree->ops->readpage_end_io_hook(page, start, end, -							      state); +							      state, mirror);  			if (ret)  				uptodate = 0;  			else  				clean_io_failure(start, page);  		} -		if (!uptodate) -			failed_mirror = (int)(unsigned long)bio->bi_bdev; -  		if (!uptodate && tree->ops && tree->ops->readpage_io_failed_hook) { -			ret = tree->ops->readpage_io_failed_hook(page, failed_mirror); +			ret = tree->ops->readpage_io_failed_hook(page, mirror);  			if (!ret && !err &&  			    test_bit(BIO_UPTODATE, &bio->bi_flags))  				uptodate = 1; @@ -2368,8 +2369,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)  			 * can't handle the error it will return -EIO and we  			 * remain responsible for that page.  			 */ -			ret = bio_readpage_error(bio, page, start, end, -							failed_mirror, NULL); +			ret = bio_readpage_error(bio, page, start, end, mirror, NULL);  			if (ret == 0) {  				uptodate =  					test_bit(BIO_UPTODATE, &bio->bi_flags); @@ -4120,6 +4120,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,  			if (atomic_inc_not_zero(&exists->refs)) {  				spin_unlock(&mapping->private_lock);  				unlock_page(p); +				page_cache_release(p);  				mark_extent_buffer_accessed(exists);  				goto free_eb;  			} @@ -4199,8 +4200,7 @@ free_eb:  			unlock_page(eb->pages[i]);  	} -	if (!atomic_dec_and_test(&eb->refs)) -		return exists; +	WARN_ON(!atomic_dec_and_test(&eb->refs));  	btrfs_release_extent_buffer(eb);  	return exists;  } @@ -4462,7 +4462,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,  	}  	clear_bit(EXTENT_BUFFER_IOERR, &eb->bflags); -	eb->failed_mirror = 0; +	eb->read_mirror = 0;  	atomic_set(&eb->io_pages, num_reads);  	for (i = start_i; i < num_pages; i++) {  		page = extent_buffer_page(eb, i);  |