Merge branch 'for-linus-min' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull the minimal btrfs branch from Chris Mason: "We have a use-after-free in there, along with errors when mount -o discard is enabled, and a BUG_ON(we should compile with UP more often)." * 'for-linus-min' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: Btrfs: use commit root when loading free space cache Btrfs: fix use-after-free in __btrfs_end_transaction Btrfs: check return value of bio_alloc() properly Btrfs: remove lock assert from get_restripe_target() Btrfs: fix eof while discarding extents Btrfs: fix uninit variable in repair_eb_io_failure Revert "Btrfs: increase the global block reserve estimates"
This commit is contained in:
commit
659e45d8a0
|
@ -405,6 +405,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
|
||||||
bio_put(bio);
|
bio_put(bio);
|
||||||
|
|
||||||
bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS);
|
bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS);
|
||||||
|
BUG_ON(!bio);
|
||||||
bio->bi_private = cb;
|
bio->bi_private = cb;
|
||||||
bio->bi_end_io = end_compressed_bio_write;
|
bio->bi_end_io = end_compressed_bio_write;
|
||||||
bio_add_page(bio, page, PAGE_CACHE_SIZE, 0);
|
bio_add_page(bio, page, PAGE_CACHE_SIZE, 0);
|
||||||
|
@ -687,6 +688,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
|
||||||
|
|
||||||
comp_bio = compressed_bio_alloc(bdev, cur_disk_byte,
|
comp_bio = compressed_bio_alloc(bdev, cur_disk_byte,
|
||||||
GFP_NOFS);
|
GFP_NOFS);
|
||||||
|
BUG_ON(!comp_bio);
|
||||||
comp_bio->bi_private = cb;
|
comp_bio->bi_private = cb;
|
||||||
comp_bio->bi_end_io = end_compressed_bio_read;
|
comp_bio->bi_end_io = end_compressed_bio_read;
|
||||||
|
|
||||||
|
|
|
@ -529,9 +529,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
|
||||||
* allocate blocks for the tree root we can't do the fast caching since
|
* allocate blocks for the tree root we can't do the fast caching since
|
||||||
* we likely hold important locks.
|
* we likely hold important locks.
|
||||||
*/
|
*/
|
||||||
if (trans && (!trans->transaction->in_commit) &&
|
if (fs_info->mount_opt & BTRFS_MOUNT_SPACE_CACHE) {
|
||||||
(root && root != root->fs_info->tree_root) &&
|
|
||||||
btrfs_test_opt(root, SPACE_CACHE)) {
|
|
||||||
ret = load_free_space_cache(fs_info, cache);
|
ret = load_free_space_cache(fs_info, cache);
|
||||||
|
|
||||||
spin_lock(&cache->lock);
|
spin_lock(&cache->lock);
|
||||||
|
@ -3152,15 +3150,14 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
|
||||||
/*
|
/*
|
||||||
* returns target flags in extended format or 0 if restripe for this
|
* returns target flags in extended format or 0 if restripe for this
|
||||||
* chunk_type is not in progress
|
* chunk_type is not in progress
|
||||||
|
*
|
||||||
|
* should be called with either volume_mutex or balance_lock held
|
||||||
*/
|
*/
|
||||||
static u64 get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags)
|
static u64 get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags)
|
||||||
{
|
{
|
||||||
struct btrfs_balance_control *bctl = fs_info->balance_ctl;
|
struct btrfs_balance_control *bctl = fs_info->balance_ctl;
|
||||||
u64 target = 0;
|
u64 target = 0;
|
||||||
|
|
||||||
BUG_ON(!mutex_is_locked(&fs_info->volume_mutex) &&
|
|
||||||
!spin_is_locked(&fs_info->balance_lock));
|
|
||||||
|
|
||||||
if (!bctl)
|
if (!bctl)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -4205,7 +4202,7 @@ static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info)
|
||||||
num_bytes += div64_u64(data_used + meta_used, 50);
|
num_bytes += div64_u64(data_used + meta_used, 50);
|
||||||
|
|
||||||
if (num_bytes * 3 > meta_used)
|
if (num_bytes * 3 > meta_used)
|
||||||
num_bytes = div64_u64(meta_used, 3) * 2;
|
num_bytes = div64_u64(meta_used, 3);
|
||||||
|
|
||||||
return ALIGN(num_bytes, fs_info->extent_root->leafsize << 10);
|
return ALIGN(num_bytes, fs_info->extent_root->leafsize << 10);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1937,7 +1937,7 @@ int repair_eb_io_failure(struct btrfs_root *root, struct extent_buffer *eb,
|
||||||
struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
|
struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
|
||||||
u64 start = eb->start;
|
u64 start = eb->start;
|
||||||
unsigned long i, num_pages = num_extent_pages(eb->start, eb->len);
|
unsigned long i, num_pages = num_extent_pages(eb->start, eb->len);
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
for (i = 0; i < num_pages; i++) {
|
for (i = 0; i < num_pages; i++) {
|
||||||
struct page *p = extent_buffer_page(eb, i);
|
struct page *p = extent_buffer_page(eb, i);
|
||||||
|
@ -2180,6 +2180,10 @@ static int bio_readpage_error(struct bio *failed_bio, struct page *page,
|
||||||
}
|
}
|
||||||
|
|
||||||
bio = bio_alloc(GFP_NOFS, 1);
|
bio = bio_alloc(GFP_NOFS, 1);
|
||||||
|
if (!bio) {
|
||||||
|
free_io_failure(inode, failrec, 0);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
bio->bi_private = state;
|
bio->bi_private = state;
|
||||||
bio->bi_end_io = failed_bio->bi_end_io;
|
bio->bi_end_io = failed_bio->bi_end_io;
|
||||||
bio->bi_sector = failrec->logical >> 9;
|
bio->bi_sector = failrec->logical >> 9;
|
||||||
|
|
|
@ -747,13 +747,6 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
|
||||||
bool matched;
|
bool matched;
|
||||||
u64 used = btrfs_block_group_used(&block_group->item);
|
u64 used = btrfs_block_group_used(&block_group->item);
|
||||||
|
|
||||||
/*
|
|
||||||
* If we're unmounting then just return, since this does a search on the
|
|
||||||
* normal root and not the commit root and we could deadlock.
|
|
||||||
*/
|
|
||||||
if (btrfs_fs_closing(fs_info))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this block group has been marked to be cleared for one reason or
|
* If this block group has been marked to be cleared for one reason or
|
||||||
* another then we can't trust the on disk cache, so just return.
|
* another then we can't trust the on disk cache, so just return.
|
||||||
|
@ -768,6 +761,8 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
|
||||||
path = btrfs_alloc_path();
|
path = btrfs_alloc_path();
|
||||||
if (!path)
|
if (!path)
|
||||||
return 0;
|
return 0;
|
||||||
|
path->search_commit_root = 1;
|
||||||
|
path->skip_locking = 1;
|
||||||
|
|
||||||
inode = lookup_free_space_inode(root, block_group, path);
|
inode = lookup_free_space_inode(root, block_group, path);
|
||||||
if (IS_ERR(inode)) {
|
if (IS_ERR(inode)) {
|
||||||
|
|
|
@ -1044,6 +1044,8 @@ static int scrub_recheck_block(struct btrfs_fs_info *fs_info,
|
||||||
|
|
||||||
BUG_ON(!page->page);
|
BUG_ON(!page->page);
|
||||||
bio = bio_alloc(GFP_NOFS, 1);
|
bio = bio_alloc(GFP_NOFS, 1);
|
||||||
|
if (!bio)
|
||||||
|
return -EIO;
|
||||||
bio->bi_bdev = page->bdev;
|
bio->bi_bdev = page->bdev;
|
||||||
bio->bi_sector = page->physical >> 9;
|
bio->bi_sector = page->physical >> 9;
|
||||||
bio->bi_end_io = scrub_complete_bio_end_io;
|
bio->bi_end_io = scrub_complete_bio_end_io;
|
||||||
|
@ -1171,6 +1173,8 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad,
|
||||||
DECLARE_COMPLETION_ONSTACK(complete);
|
DECLARE_COMPLETION_ONSTACK(complete);
|
||||||
|
|
||||||
bio = bio_alloc(GFP_NOFS, 1);
|
bio = bio_alloc(GFP_NOFS, 1);
|
||||||
|
if (!bio)
|
||||||
|
return -EIO;
|
||||||
bio->bi_bdev = page_bad->bdev;
|
bio->bi_bdev = page_bad->bdev;
|
||||||
bio->bi_sector = page_bad->physical >> 9;
|
bio->bi_sector = page_bad->physical >> 9;
|
||||||
bio->bi_end_io = scrub_complete_bio_end_io;
|
bio->bi_end_io = scrub_complete_bio_end_io;
|
||||||
|
|
|
@ -480,6 +480,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_transaction *cur_trans = trans->transaction;
|
struct btrfs_transaction *cur_trans = trans->transaction;
|
||||||
struct btrfs_fs_info *info = root->fs_info;
|
struct btrfs_fs_info *info = root->fs_info;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
if (--trans->use_count) {
|
if (--trans->use_count) {
|
||||||
trans->block_rsv = trans->orig_rsv;
|
trans->block_rsv = trans->orig_rsv;
|
||||||
|
@ -532,18 +533,18 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
|
||||||
|
|
||||||
if (current->journal_info == trans)
|
if (current->journal_info == trans)
|
||||||
current->journal_info = NULL;
|
current->journal_info = NULL;
|
||||||
memset(trans, 0, sizeof(*trans));
|
|
||||||
kmem_cache_free(btrfs_trans_handle_cachep, trans);
|
|
||||||
|
|
||||||
if (throttle)
|
if (throttle)
|
||||||
btrfs_run_delayed_iputs(root);
|
btrfs_run_delayed_iputs(root);
|
||||||
|
|
||||||
if (trans->aborted ||
|
if (trans->aborted ||
|
||||||
root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
|
root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
|
||||||
return -EIO;
|
err = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
memset(trans, 0, sizeof(*trans));
|
||||||
|
kmem_cache_free(btrfs_trans_handle_cachep, trans);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_end_transaction(struct btrfs_trans_handle *trans,
|
int btrfs_end_transaction(struct btrfs_trans_handle *trans,
|
||||||
|
|
|
@ -3833,6 +3833,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
|
||||||
int sub_stripes = 0;
|
int sub_stripes = 0;
|
||||||
u64 stripes_per_dev = 0;
|
u64 stripes_per_dev = 0;
|
||||||
u32 remaining_stripes = 0;
|
u32 remaining_stripes = 0;
|
||||||
|
u32 last_stripe = 0;
|
||||||
|
|
||||||
if (map->type &
|
if (map->type &
|
||||||
(BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) {
|
(BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) {
|
||||||
|
@ -3846,6 +3847,8 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
|
||||||
stripe_nr_orig,
|
stripe_nr_orig,
|
||||||
factor,
|
factor,
|
||||||
&remaining_stripes);
|
&remaining_stripes);
|
||||||
|
div_u64_rem(stripe_nr_end - 1, factor, &last_stripe);
|
||||||
|
last_stripe *= sub_stripes;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_stripes; i++) {
|
for (i = 0; i < num_stripes; i++) {
|
||||||
|
@ -3858,16 +3861,29 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
|
||||||
BTRFS_BLOCK_GROUP_RAID10)) {
|
BTRFS_BLOCK_GROUP_RAID10)) {
|
||||||
bbio->stripes[i].length = stripes_per_dev *
|
bbio->stripes[i].length = stripes_per_dev *
|
||||||
map->stripe_len;
|
map->stripe_len;
|
||||||
|
|
||||||
if (i / sub_stripes < remaining_stripes)
|
if (i / sub_stripes < remaining_stripes)
|
||||||
bbio->stripes[i].length +=
|
bbio->stripes[i].length +=
|
||||||
map->stripe_len;
|
map->stripe_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Special for the first stripe and
|
||||||
|
* the last stripe:
|
||||||
|
*
|
||||||
|
* |-------|...|-------|
|
||||||
|
* |----------|
|
||||||
|
* off end_off
|
||||||
|
*/
|
||||||
if (i < sub_stripes)
|
if (i < sub_stripes)
|
||||||
bbio->stripes[i].length -=
|
bbio->stripes[i].length -=
|
||||||
stripe_offset;
|
stripe_offset;
|
||||||
if ((i / sub_stripes + 1) %
|
|
||||||
sub_stripes == remaining_stripes)
|
if (stripe_index >= last_stripe &&
|
||||||
|
stripe_index <= (last_stripe +
|
||||||
|
sub_stripes - 1))
|
||||||
bbio->stripes[i].length -=
|
bbio->stripes[i].length -=
|
||||||
stripe_end_offset;
|
stripe_end_offset;
|
||||||
|
|
||||||
if (i == sub_stripes - 1)
|
if (i == sub_stripes - 1)
|
||||||
stripe_offset = 0;
|
stripe_offset = 0;
|
||||||
} else
|
} else
|
||||||
|
|
Loading…
Reference in New Issue