Merge branch 'for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "The most user visible change here is a fix for our recent superblock validation checks that were causing problems on non-4k pagesized systems" * 'for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: Btrfs: btrfs_check_super_valid: Allow 4096 as stripesize btrfs: remove build fixup for qgroup_account_snapshot btrfs: use new error message helper in qgroup_account_snapshot btrfs: avoid blocking open_ctree from cleaner_kthread Btrfs: don't BUG_ON() in btrfs_orphan_add btrfs: account for non-CoW'd blocks in btrfs_abort_transaction Btrfs: check if extent buffer is aligned to sectorsize btrfs: Use correct format specifier
This commit is contained in:
commit
4c6459f945
11 changed files with 61 additions and 43 deletions
|
@ -2645,7 +2645,7 @@ static void btrfsic_dump_tree_sub(const struct btrfsic_state *state,
|
|||
* This algorithm is recursive because the amount of used stack space
|
||||
* is very small and the max recursion depth is limited.
|
||||
*/
|
||||
indent_add = sprintf(buf, "%c-%llu(%s/%llu/%d)",
|
||||
indent_add = sprintf(buf, "%c-%llu(%s/%llu/%u)",
|
||||
btrfsic_get_block_type(state, block),
|
||||
block->logical_bytenr, block->dev_state->name,
|
||||
block->dev_bytenr, block->mirror_num);
|
||||
|
|
|
@ -1554,6 +1554,7 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
|
|||
trans->transid, root->fs_info->generation);
|
||||
|
||||
if (!should_cow_block(trans, root, buf)) {
|
||||
trans->dirty = true;
|
||||
*cow_ret = buf;
|
||||
return 0;
|
||||
}
|
||||
|
@ -2512,6 +2513,8 @@ read_block_for_search(struct btrfs_trans_handle *trans,
|
|||
if (!btrfs_buffer_uptodate(tmp, 0, 0))
|
||||
ret = -EIO;
|
||||
free_extent_buffer(tmp);
|
||||
} else {
|
||||
ret = PTR_ERR(tmp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -2775,8 +2778,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
|
|||
* then we don't want to set the path blocking,
|
||||
* so we test it here
|
||||
*/
|
||||
if (!should_cow_block(trans, root, b))
|
||||
if (!should_cow_block(trans, root, b)) {
|
||||
trans->dirty = true;
|
||||
goto cow_done;
|
||||
}
|
||||
|
||||
/*
|
||||
* must have write locks on this node and the
|
||||
|
|
|
@ -1098,7 +1098,7 @@ void readahead_tree_block(struct btrfs_root *root, u64 bytenr)
|
|||
struct inode *btree_inode = root->fs_info->btree_inode;
|
||||
|
||||
buf = btrfs_find_create_tree_block(root, bytenr);
|
||||
if (!buf)
|
||||
if (IS_ERR(buf))
|
||||
return;
|
||||
read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree,
|
||||
buf, 0, WAIT_NONE, btree_get_extent, 0);
|
||||
|
@ -1114,7 +1114,7 @@ int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr,
|
|||
int ret;
|
||||
|
||||
buf = btrfs_find_create_tree_block(root, bytenr);
|
||||
if (!buf)
|
||||
if (IS_ERR(buf))
|
||||
return 0;
|
||||
|
||||
set_bit(EXTENT_BUFFER_READAHEAD, &buf->bflags);
|
||||
|
@ -1172,8 +1172,8 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
|
|||
int ret;
|
||||
|
||||
buf = btrfs_find_create_tree_block(root, bytenr);
|
||||
if (!buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
if (IS_ERR(buf))
|
||||
return buf;
|
||||
|
||||
ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
|
||||
if (ret) {
|
||||
|
@ -1806,6 +1806,13 @@ static int cleaner_kthread(void *arg)
|
|||
if (btrfs_need_cleaner_sleep(root))
|
||||
goto sleep;
|
||||
|
||||
/*
|
||||
* Do not do anything if we might cause open_ctree() to block
|
||||
* before we have finished mounting the filesystem.
|
||||
*/
|
||||
if (!root->fs_info->open)
|
||||
goto sleep;
|
||||
|
||||
if (!mutex_trylock(&root->fs_info->cleaner_mutex))
|
||||
goto sleep;
|
||||
|
||||
|
@ -2520,7 +2527,6 @@ int open_ctree(struct super_block *sb,
|
|||
int num_backups_tried = 0;
|
||||
int backup_index = 0;
|
||||
int max_active;
|
||||
bool cleaner_mutex_locked = false;
|
||||
|
||||
tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
|
||||
chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
|
||||
|
@ -2999,13 +3005,6 @@ int open_ctree(struct super_block *sb,
|
|||
goto fail_sysfs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hold the cleaner_mutex thread here so that we don't block
|
||||
* for a long time on btrfs_recover_relocation. cleaner_kthread
|
||||
* will wait for us to finish mounting the filesystem.
|
||||
*/
|
||||
mutex_lock(&fs_info->cleaner_mutex);
|
||||
cleaner_mutex_locked = true;
|
||||
fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
|
||||
"btrfs-cleaner");
|
||||
if (IS_ERR(fs_info->cleaner_kthread))
|
||||
|
@ -3065,8 +3064,10 @@ int open_ctree(struct super_block *sb,
|
|||
ret = btrfs_cleanup_fs_roots(fs_info);
|
||||
if (ret)
|
||||
goto fail_qgroup;
|
||||
/* We locked cleaner_mutex before creating cleaner_kthread. */
|
||||
|
||||
mutex_lock(&fs_info->cleaner_mutex);
|
||||
ret = btrfs_recover_relocation(tree_root);
|
||||
mutex_unlock(&fs_info->cleaner_mutex);
|
||||
if (ret < 0) {
|
||||
btrfs_warn(fs_info, "failed to recover relocation: %d",
|
||||
ret);
|
||||
|
@ -3074,8 +3075,6 @@ int open_ctree(struct super_block *sb,
|
|||
goto fail_qgroup;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&fs_info->cleaner_mutex);
|
||||
cleaner_mutex_locked = false;
|
||||
|
||||
location.objectid = BTRFS_FS_TREE_OBJECTID;
|
||||
location.type = BTRFS_ROOT_ITEM_KEY;
|
||||
|
@ -3189,10 +3188,6 @@ int open_ctree(struct super_block *sb,
|
|||
filemap_write_and_wait(fs_info->btree_inode->i_mapping);
|
||||
|
||||
fail_sysfs:
|
||||
if (cleaner_mutex_locked) {
|
||||
mutex_unlock(&fs_info->cleaner_mutex);
|
||||
cleaner_mutex_locked = false;
|
||||
}
|
||||
btrfs_sysfs_remove_mounted(fs_info);
|
||||
|
||||
fail_fsdev_sysfs:
|
||||
|
@ -4139,7 +4134,8 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
|
|||
ret = -EINVAL;
|
||||
}
|
||||
if (!is_power_of_2(btrfs_super_stripesize(sb)) ||
|
||||
btrfs_super_stripesize(sb) != sectorsize) {
|
||||
((btrfs_super_stripesize(sb) != sectorsize) &&
|
||||
(btrfs_super_stripesize(sb) != 4096))) {
|
||||
btrfs_err(fs_info, "invalid stripesize %u",
|
||||
btrfs_super_stripesize(sb));
|
||||
ret = -EINVAL;
|
||||
|
|
|
@ -8016,8 +8016,9 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
|||
struct extent_buffer *buf;
|
||||
|
||||
buf = btrfs_find_create_tree_block(root, bytenr);
|
||||
if (!buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
if (IS_ERR(buf))
|
||||
return buf;
|
||||
|
||||
btrfs_set_header_generation(buf, trans->transid);
|
||||
btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level);
|
||||
btrfs_tree_lock(buf);
|
||||
|
@ -8044,7 +8045,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
|||
set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
|
||||
buf->start + buf->len - 1, GFP_NOFS);
|
||||
}
|
||||
trans->blocks_used++;
|
||||
trans->dirty = true;
|
||||
/* this returns a buffer locked for blocking */
|
||||
return buf;
|
||||
}
|
||||
|
@ -8659,8 +8660,9 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
|
|||
next = btrfs_find_tree_block(root->fs_info, bytenr);
|
||||
if (!next) {
|
||||
next = btrfs_find_create_tree_block(root, bytenr);
|
||||
if (!next)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(next))
|
||||
return PTR_ERR(next);
|
||||
|
||||
btrfs_set_buffer_lockdep_class(root->root_key.objectid, next,
|
||||
level - 1);
|
||||
reada = 1;
|
||||
|
|
|
@ -4892,18 +4892,25 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
|
|||
int uptodate = 1;
|
||||
int ret;
|
||||
|
||||
if (!IS_ALIGNED(start, fs_info->tree_root->sectorsize)) {
|
||||
btrfs_err(fs_info, "bad tree block start %llu", start);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
eb = find_extent_buffer(fs_info, start);
|
||||
if (eb)
|
||||
return eb;
|
||||
|
||||
eb = __alloc_extent_buffer(fs_info, start, len);
|
||||
if (!eb)
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
for (i = 0; i < num_pages; i++, index++) {
|
||||
p = find_or_create_page(mapping, index, GFP_NOFS|__GFP_NOFAIL);
|
||||
if (!p)
|
||||
if (!p) {
|
||||
exists = ERR_PTR(-ENOMEM);
|
||||
goto free_eb;
|
||||
}
|
||||
|
||||
spin_lock(&mapping->private_lock);
|
||||
if (PagePrivate(p)) {
|
||||
|
@ -4948,8 +4955,10 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
|
|||
set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
|
||||
again:
|
||||
ret = radix_tree_preload(GFP_NOFS);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
exists = ERR_PTR(ret);
|
||||
goto free_eb;
|
||||
}
|
||||
|
||||
spin_lock(&fs_info->buffer_lock);
|
||||
ret = radix_tree_insert(&fs_info->buffer_radix,
|
||||
|
|
|
@ -3271,7 +3271,16 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode)
|
|||
/* grab metadata reservation from transaction handle */
|
||||
if (reserve) {
|
||||
ret = btrfs_orphan_reserve_metadata(trans, inode);
|
||||
BUG_ON(ret); /* -ENOSPC in reservation; Logic error? JDM */
|
||||
ASSERT(!ret);
|
||||
if (ret) {
|
||||
atomic_dec(&root->orphan_inodes);
|
||||
clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED,
|
||||
&BTRFS_I(inode)->runtime_flags);
|
||||
if (insert)
|
||||
clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
|
||||
&BTRFS_I(inode)->runtime_flags);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* insert an orphan item to track this unlinked/truncated file */
|
||||
|
|
|
@ -235,7 +235,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
|
|||
trans->aborted = errno;
|
||||
/* Nothing used. The other threads that have joined this
|
||||
* transaction may be able to continue. */
|
||||
if (!trans->blocks_used && list_empty(&trans->new_bgs)) {
|
||||
if (!trans->dirty && list_empty(&trans->new_bgs)) {
|
||||
const char *errstr;
|
||||
|
||||
errstr = btrfs_decode_error(errno);
|
||||
|
@ -1807,6 +1807,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
|
|||
}
|
||||
}
|
||||
sb->s_flags &= ~MS_RDONLY;
|
||||
|
||||
fs_info->open = 1;
|
||||
}
|
||||
out:
|
||||
wake_up_process(fs_info->transaction_kthread);
|
||||
|
|
|
@ -1311,11 +1311,6 @@ int btrfs_defrag_root(struct btrfs_root *root)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Bisesctability fixup, remove in 4.8 */
|
||||
#ifndef btrfs_std_error
|
||||
#define btrfs_std_error btrfs_handle_fs_error
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Do all special snapshot related qgroup dirty hack.
|
||||
*
|
||||
|
@ -1385,7 +1380,7 @@ static int qgroup_account_snapshot(struct btrfs_trans_handle *trans,
|
|||
switch_commit_roots(trans->transaction, fs_info);
|
||||
ret = btrfs_write_and_wait_transaction(trans, src);
|
||||
if (ret)
|
||||
btrfs_std_error(fs_info, ret,
|
||||
btrfs_handle_fs_error(fs_info, ret,
|
||||
"Error while writing out transaction for qgroup");
|
||||
|
||||
out:
|
||||
|
|
|
@ -110,7 +110,6 @@ struct btrfs_trans_handle {
|
|||
u64 chunk_bytes_reserved;
|
||||
unsigned long use_count;
|
||||
unsigned long blocks_reserved;
|
||||
unsigned long blocks_used;
|
||||
unsigned long delayed_ref_updates;
|
||||
struct btrfs_transaction *transaction;
|
||||
struct btrfs_block_rsv *block_rsv;
|
||||
|
@ -121,6 +120,7 @@ struct btrfs_trans_handle {
|
|||
bool can_flush_pending_bgs;
|
||||
bool reloc_reserved;
|
||||
bool sync;
|
||||
bool dirty;
|
||||
unsigned int type;
|
||||
/*
|
||||
* this root is only needed to validate that the root passed to
|
||||
|
|
|
@ -2422,8 +2422,8 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
|
|||
root_owner = btrfs_header_owner(parent);
|
||||
|
||||
next = btrfs_find_create_tree_block(root, bytenr);
|
||||
if (!next)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(next))
|
||||
return PTR_ERR(next);
|
||||
|
||||
if (*level == 1) {
|
||||
ret = wc->process_func(root, next, wc, ptr_gen);
|
||||
|
|
|
@ -6607,8 +6607,8 @@ int btrfs_read_sys_array(struct btrfs_root *root)
|
|||
* overallocate but we can keep it as-is, only the first page is used.
|
||||
*/
|
||||
sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET);
|
||||
if (!sb)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(sb))
|
||||
return PTR_ERR(sb);
|
||||
set_extent_buffer_uptodate(sb);
|
||||
btrfs_set_buffer_lockdep_class(root->root_key.objectid, sb, 0);
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue