Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "This has our collection of bug fixes. I missed the last rc because I thought our patches were making NFS crash during my xfs test runs. Turns out it was an NFS client bug fixed by someone else while I tried to bisect it. All of these fixes are small, but some are fairly high impact. The biggest are fixes for our mount -o remount handling, a deadlock due to GFP_KERNEL allocations in readdir, and a RAID10 error handling bug. This was tested against both 3.3 and Linus' master as of this morning." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (26 commits) Btrfs: reduce lock contention during extent insertion Btrfs: avoid deadlocks from GFP_KERNEL allocations during btrfs_real_readdir Btrfs: Fix space checking during fs resize Btrfs: fix block_rsv and space_info lock ordering Btrfs: Prevent root_list corruption Btrfs: fix repair code for RAID10 Btrfs: do not start delalloc inodes during sync Btrfs: fix that check_int_data mount option was ignored Btrfs: don't count CRC or header errors twice while scrubbing Btrfs: fix btrfs_ioctl_dev_info() crash on missing device btrfs: don't return EINTR Btrfs: double unlock bug in error handling Btrfs: always store the mirror we read the eb from fs/btrfs/volumes.c: add missing free_fs_devices btrfs: fix early abort in 'remount' Btrfs: fix max chunk size check in chunk allocator Btrfs: add missing read locks in backref.c Btrfs: don't call free_extent_buffer twice in iterate_irefs Btrfs: Make free_ipath() deal gracefully with NULL pointers Btrfs: avoid possible use-after-free in clear_extent_bit() ...
This commit is contained in:
@@ -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);
|
||||
@@ -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);
|
||||
|
Reference in New Issue
Block a user