From a944442c2b8a420301e7830f976bab8cc86a2b4d Mon Sep 17 00:00:00 2001 From: Allen Pais Date: Tue, 12 Jun 2018 17:18:25 +0530 Subject: btrfs: replace get_seconds with new 64bit time API The get_seconds() function is deprecated as it truncates the timestamp to 32 bits. Change it to or ktime_get_real_seconds(). Signed-off-by: Allen Pais Reviewed-by: David Sterba [ update changelog ] Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 205092dc9390..f3224e23d5fa 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1803,7 +1803,7 @@ static int transaction_kthread(void *arg) struct btrfs_trans_handle *trans; struct btrfs_transaction *cur; u64 transid; - unsigned long now; + time64_t now; unsigned long delay; bool cannot_commit; @@ -1819,7 +1819,7 @@ static int transaction_kthread(void *arg) goto sleep; } - now = get_seconds(); + now = ktime_get_real_seconds(); if (cur->state < TRANS_STATE_BLOCKED && !test_bit(BTRFS_FS_NEED_ASYNC_COMMIT, &fs_info->flags) && (now < cur->start_time || -- cgit v1.2.3 From bc877d285ca3dba24c52406946a4a69847cc7422 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Mon, 18 Jun 2018 14:13:19 +0300 Subject: btrfs: Deduplicate extent_buffer init code When a new extent buffer is allocated there are a few mandatory fields which need to be set in order for the buffer to be sane: level, generation, bytenr, backref_rev, owner and FSID/UUID. Currently this is open coded in the callers of btrfs_alloc_tree_block, meaning it's fairly high in the abstraction hierarchy of operations. This patch solves this by simply moving this init code in btrfs_init_new_buffer, since this is the function which initializes a newly allocated extent buffer. No functional changes. Signed-off-by: Nikolay Borisov Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/ctree.c | 29 +---------------------------- fs/btrfs/disk-io.c | 14 -------------- fs/btrfs/extent-tree.c | 16 ++++++++++++---- fs/btrfs/ioctl.c | 8 -------- 4 files changed, 13 insertions(+), 54 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 18fd80e2f278..18f1ca1c5bd9 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -3358,17 +3358,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, root_add_used(root, fs_info->nodesize); - memzero_extent_buffer(c, 0, sizeof(struct btrfs_header)); btrfs_set_header_nritems(c, 1); - btrfs_set_header_level(c, level); - btrfs_set_header_bytenr(c, c->start); - btrfs_set_header_generation(c, trans->transid); - btrfs_set_header_backref_rev(c, BTRFS_MIXED_BACKREF_REV); - btrfs_set_header_owner(c, root->root_key.objectid); - - write_extent_buffer_fsid(c, fs_info->fsid); - write_extent_buffer_chunk_tree_uuid(c, fs_info->chunk_tree_uuid); - btrfs_set_node_key(c, &lower_key, 0); btrfs_set_node_blockptr(c, 0, lower->start); lower_gen = btrfs_header_generation(lower); @@ -3497,15 +3487,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans, return PTR_ERR(split); root_add_used(root, fs_info->nodesize); - - memzero_extent_buffer(split, 0, sizeof(struct btrfs_header)); - btrfs_set_header_level(split, btrfs_header_level(c)); - btrfs_set_header_bytenr(split, split->start); - btrfs_set_header_generation(split, trans->transid); - btrfs_set_header_backref_rev(split, BTRFS_MIXED_BACKREF_REV); - btrfs_set_header_owner(split, root->root_key.objectid); - write_extent_buffer_fsid(split, fs_info->fsid); - write_extent_buffer_chunk_tree_uuid(split, fs_info->chunk_tree_uuid); + ASSERT(btrfs_header_level(c) == level); ret = tree_mod_log_eb_copy(fs_info, split, c, 0, mid, c_nritems - mid); if (ret) { @@ -4291,15 +4273,6 @@ again: root_add_used(root, fs_info->nodesize); - memzero_extent_buffer(right, 0, sizeof(struct btrfs_header)); - btrfs_set_header_bytenr(right, right->start); - btrfs_set_header_generation(right, trans->transid); - btrfs_set_header_backref_rev(right, BTRFS_MIXED_BACKREF_REV); - btrfs_set_header_owner(right, root->root_key.objectid); - btrfs_set_header_level(right, 0); - write_extent_buffer_fsid(right, fs_info->fsid); - write_extent_buffer_chunk_tree_uuid(right, fs_info->chunk_tree_uuid); - if (split == 0) { if (mid <= slot) { btrfs_set_header_nritems(right, 0); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index f3224e23d5fa..6318ac2539d3 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1292,15 +1292,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, goto fail; } - memzero_extent_buffer(leaf, 0, sizeof(struct btrfs_header)); - btrfs_set_header_bytenr(leaf, leaf->start); - btrfs_set_header_generation(leaf, trans->transid); - btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV); - btrfs_set_header_owner(leaf, objectid); root->node = leaf; - - write_extent_buffer_fsid(leaf, fs_info->fsid); - write_extent_buffer_chunk_tree_uuid(leaf, fs_info->chunk_tree_uuid); btrfs_mark_buffer_dirty(leaf); root->commit_root = btrfs_root_node(root); @@ -1374,14 +1366,8 @@ static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans, return ERR_CAST(leaf); } - memzero_extent_buffer(leaf, 0, sizeof(struct btrfs_header)); - btrfs_set_header_bytenr(leaf, leaf->start); - btrfs_set_header_generation(leaf, trans->transid); - btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV); - btrfs_set_header_owner(leaf, BTRFS_TREE_LOG_OBJECTID); root->node = leaf; - write_extent_buffer_fsid(root->node, fs_info->fsid); btrfs_mark_buffer_dirty(root->node); btrfs_tree_unlock(root->node); return root; diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 472872a6cc27..0ca3999356c7 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -8302,7 +8302,7 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans, static struct extent_buffer * btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, - u64 bytenr, int level) + u64 bytenr, int level, u64 owner) { struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *buf; @@ -8311,7 +8311,6 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, 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); clean_tree_block(fs_info, buf); @@ -8320,6 +8319,14 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, btrfs_set_lock_blocking(buf); set_extent_buffer_uptodate(buf); + memzero_extent_buffer(buf, 0, sizeof(struct btrfs_header)); + btrfs_set_header_level(buf, level); + btrfs_set_header_bytenr(buf, buf->start); + btrfs_set_header_generation(buf, trans->transid); + btrfs_set_header_backref_rev(buf, BTRFS_MIXED_BACKREF_REV); + btrfs_set_header_owner(buf, owner); + write_extent_buffer_fsid(buf, fs_info->fsid); + write_extent_buffer_chunk_tree_uuid(buf, fs_info->chunk_tree_uuid); if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) { buf->log_index = root->log_transid % 2; /* @@ -8428,7 +8435,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS if (btrfs_is_testing(fs_info)) { buf = btrfs_init_new_buffer(trans, root, root->alloc_bytenr, - level); + level, root_objectid); if (!IS_ERR(buf)) root->alloc_bytenr += blocksize; return buf; @@ -8444,7 +8451,8 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, if (ret) goto out_unuse; - buf = btrfs_init_new_buffer(trans, root, ins.objectid, level); + buf = btrfs_init_new_buffer(trans, root, ins.objectid, level, + root_objectid); if (IS_ERR(buf)) { ret = PTR_ERR(buf); goto out_free_reserved; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 0c4b9f364e84..08b8c0b346b3 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -616,14 +616,6 @@ static noinline int create_subvol(struct inode *dir, goto fail; } - memzero_extent_buffer(leaf, 0, sizeof(struct btrfs_header)); - btrfs_set_header_bytenr(leaf, leaf->start); - btrfs_set_header_generation(leaf, trans->transid); - btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV); - btrfs_set_header_owner(leaf, objectid); - - write_extent_buffer_fsid(leaf, fs_info->fsid); - write_extent_buffer_chunk_tree_uuid(leaf, fs_info->chunk_tree_uuid); btrfs_mark_buffer_dirty(leaf); inode_item = &root_item->inode; -- cgit v1.2.3 From afd48513f0019a2048afed0d98904d3fec7e05dd Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 21 Jun 2018 18:04:05 +0200 Subject: btrfs: use monotonic time for transaction handling The transaction times were changed to ktime_get_real_seconds to avoid the y2038 overflow, but they still have a minor problem when they go backwards or jump due to settimeofday() or leap seconds. This changes the transaction handling to instead use ktime_get_seconds(), which returns a CLOCK_MONOTONIC timestamp that has neither of those problems. Signed-off-by: Arnd Bergmann Reviewed-by: Nikolay Borisov Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 2 +- fs/btrfs/transaction.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 6318ac2539d3..2de3da7b7bdc 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1805,7 +1805,7 @@ static int transaction_kthread(void *arg) goto sleep; } - now = ktime_get_real_seconds(); + now = ktime_get_seconds(); if (cur->state < TRANS_STATE_BLOCKED && !test_bit(BTRFS_FS_NEED_ASYNC_COMMIT, &fs_info->flags) && (now < cur->start_time || diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 56c8bab0b816..ebe50dfb8947 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -241,7 +241,7 @@ loop: refcount_set(&cur_trans->use_count, 2); atomic_set(&cur_trans->pending_ordered, 0); cur_trans->flags = 0; - cur_trans->start_time = ktime_get_real_seconds(); + cur_trans->start_time = ktime_get_seconds(); memset(&cur_trans->delayed_refs, 0, sizeof(cur_trans->delayed_refs)); -- cgit v1.2.3 From 893bf4b115c713738df05bb557f8fba14f07c077 Mon Sep 17 00:00:00 2001 From: Su Yue Date: Fri, 22 Jun 2018 09:52:15 +0800 Subject: btrfs: print more details when checking tree block finds a problem For easier debugging, print eb->start if level is invalid. Also make clear if bytenr found is not expected. Signed-off-by: Su Yue Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 2de3da7b7bdc..c77afa9e5d91 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -615,8 +615,8 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio, found_start = btrfs_header_bytenr(eb); if (found_start != eb->start) { - btrfs_err_rl(fs_info, "bad tree block start %llu %llu", - found_start, eb->start); + btrfs_err_rl(fs_info, "bad tree block start, want %llu have %llu", + eb->start, found_start); ret = -EIO; goto err; } @@ -628,8 +628,8 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio, } found_level = btrfs_header_level(eb); if (found_level >= BTRFS_MAX_LEVEL) { - btrfs_err(fs_info, "bad tree block level %d", - (int)btrfs_header_level(eb)); + btrfs_err(fs_info, "bad tree block level %d on %llu", + (int)btrfs_header_level(eb), eb->start); ret = -EIO; goto err; } -- cgit v1.2.3 From 3ffbd68c48320730ef64ebfb5e639220f1f65483 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Fri, 29 Jun 2018 10:56:42 +0200 Subject: btrfs: simplify pointer chasing of local fs_info variables Functions that get btrfs inode can simply reach the fs_info by dereferencing the root and this looks a bit more straightforward compared to the btrfs_sb(...) indirection. If the transaction handle is available and not NULL it's used instead. Signed-off-by: David Sterba --- fs/btrfs/delayed-inode.c | 4 ++-- fs/btrfs/disk-io.c | 2 +- fs/btrfs/extent-tree.c | 6 +++--- fs/btrfs/file-item.c | 2 +- fs/btrfs/file.c | 14 +++++++------- fs/btrfs/free-space-cache.c | 7 ++----- fs/btrfs/inode.c | 6 +++--- fs/btrfs/tree-log.c | 6 +++--- 8 files changed, 22 insertions(+), 25 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index fe6caa7e698b..596d2af0c8aa 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -1222,7 +1222,7 @@ int btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, int btrfs_commit_inode_delayed_inode(struct btrfs_inode *inode) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; struct btrfs_trans_handle *trans; struct btrfs_delayed_node *delayed_node = btrfs_get_delayed_node(inode); struct btrfs_path *path; @@ -1837,7 +1837,7 @@ release_node: int btrfs_delayed_delete_inode_ref(struct btrfs_inode *inode) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; struct btrfs_delayed_node *delayed_node; /* diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c77afa9e5d91..e0baf2f3154d 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -212,7 +212,7 @@ struct extent_map *btree_get_extent(struct btrfs_inode *inode, struct page *page, size_t pg_offset, u64 start, u64 len, int create) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; struct extent_map_tree *em_tree = &inode->extent_tree; struct extent_map *em; int ret; diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 352b7e95f657..6bba288133b8 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -5889,7 +5889,7 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info, int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; unsigned nr_extents; enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_FLUSH_ALL; int ret = 0; @@ -5962,7 +5962,7 @@ out_fail: void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes, bool qgroup_free) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; num_bytes = ALIGN(num_bytes, fs_info->sectorsize); spin_lock(&inode->lock); @@ -5991,7 +5991,7 @@ void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes, void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes, bool qgroup_free) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; unsigned num_extents; spin_lock(&inode->lock); diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 8c3cd7072caf..ba74827beb32 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -922,7 +922,7 @@ void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode, const bool new_inline, struct extent_map *em) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; struct btrfs_root *root = inode->root; struct extent_buffer *leaf = path->nodes[0]; const int slot = path->slots[0]; diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 89c9404fee9a..da53e45705ba 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -83,7 +83,7 @@ static int __compare_inode_defrag(struct inode_defrag *defrag1, static int __btrfs_add_inode_defrag(struct btrfs_inode *inode, struct inode_defrag *defrag) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; struct inode_defrag *entry; struct rb_node **p; struct rb_node *parent = NULL; @@ -135,8 +135,8 @@ static inline int __need_auto_defrag(struct btrfs_fs_info *fs_info) int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, struct btrfs_inode *inode) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); struct btrfs_root *root = inode->root; + struct btrfs_fs_info *fs_info = root->fs_info; struct inode_defrag *defrag; u64 transid; int ret; @@ -185,7 +185,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, static void btrfs_requeue_inode_defrag(struct btrfs_inode *inode, struct inode_defrag *defrag) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; int ret; if (!__need_auto_defrag(fs_info)) @@ -1132,7 +1132,7 @@ static int extent_mergeable(struct extent_buffer *leaf, int slot, int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, struct btrfs_inode *inode, u64 start, u64 end) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_root *root = inode->root; struct extent_buffer *leaf; struct btrfs_path *path; @@ -1469,7 +1469,7 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages, u64 *lockstart, u64 *lockend, struct extent_state **cached_state) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; u64 start_pos; u64 last_pos; int i; @@ -1525,7 +1525,7 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages, static noinline int check_can_nocow(struct btrfs_inode *inode, loff_t pos, size_t *write_bytes) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; struct btrfs_root *root = inode->root; struct btrfs_ordered_extent *ordered; u64 lockstart, lockend; @@ -2227,7 +2227,7 @@ static int fill_holes(struct btrfs_trans_handle *trans, struct btrfs_inode *inode, struct btrfs_path *path, u64 offset, u64 end) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_root *root = inode->root; struct extent_buffer *leaf; struct btrfs_file_extent_item *fi; diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index d2c0bdbd79ec..354d55f22d99 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -655,7 +655,7 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, struct btrfs_free_space_ctl *ctl, struct btrfs_path *path, u64 offset) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_free_space_header *header; struct extent_buffer *leaf; struct btrfs_io_ctl io_ctl; @@ -1123,13 +1123,10 @@ static int __btrfs_wait_cache_io(struct btrfs_root *root, { int ret; struct inode *inode = io_ctl->inode; - struct btrfs_fs_info *fs_info; if (!inode) return 0; - fs_info = btrfs_sb(inode->i_sb); - /* Flush the dirty pages in the cache file. */ ret = flush_dirty_cache(inode); if (ret) @@ -1145,7 +1142,7 @@ out: BTRFS_I(inode)->generation = 0; if (block_group) { #ifdef DEBUG - btrfs_err(fs_info, + btrfs_err(root->fs_info, "failed to write free space cache for block group %llu", block_group->key.objectid); #endif diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 17816c455786..32613dca13c1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1751,7 +1751,7 @@ static void btrfs_add_delalloc_inodes(struct btrfs_root *root, void __btrfs_del_delalloc_inode(struct btrfs_root *root, struct btrfs_inode *inode) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = root->fs_info; if (!list_empty(&inode->delalloc_inodes)) { list_del_init(&inode->delalloc_inodes); @@ -6418,7 +6418,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, struct btrfs_inode *parent_inode, struct btrfs_inode *inode, const char *name, int name_len, int add_backref, u64 index) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = trans->fs_info; int ret = 0; struct btrfs_key key; struct btrfs_root *root = parent_inode->root; @@ -6846,7 +6846,7 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode, size_t pg_offset, u64 start, u64 len, int create) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = inode->root->fs_info; int ret; int err = 0; u64 extent_start = 0; diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 6bca8f88ade0..7b7498f1f641 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -3739,7 +3739,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, int start_slot, int nr, int inode_only, u64 logged_isize) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = trans->fs_info; unsigned long src_offset; unsigned long dst_offset; struct btrfs_root *log = inode->root->log_root; @@ -5436,7 +5436,7 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans, struct btrfs_inode *inode, struct btrfs_log_ctx *ctx) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = trans->fs_info; int ret; struct btrfs_path *path; struct btrfs_key key; @@ -5971,7 +5971,7 @@ int btrfs_log_new_name(struct btrfs_trans_handle *trans, struct btrfs_inode *inode, struct btrfs_inode *old_dir, struct dentry *parent) { - struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); + struct btrfs_fs_info *fs_info = trans->fs_info; /* * this will force the logging code to walk the dentry chain -- cgit v1.2.3 From d7f663fa3ff906247a979c1115bc92cbabfb19ba Mon Sep 17 00:00:00 2001 From: David Sterba Date: Fri, 29 Jun 2018 10:56:47 +0200 Subject: btrfs: prune unused includes Remove includes if none of the interfaces and exports is used in the given source file. Signed-off-by: David Sterba --- fs/btrfs/compression.c | 4 ---- fs/btrfs/dev-replace.c | 5 ----- fs/btrfs/disk-io.c | 2 -- fs/btrfs/file.c | 3 --- fs/btrfs/inode-map.c | 1 - fs/btrfs/inode.c | 4 ---- fs/btrfs/ioctl.c | 5 ----- fs/btrfs/ordered-data.c | 1 - fs/btrfs/raid56.c | 13 ------------- fs/btrfs/reada.c | 1 - fs/btrfs/struct-funcs.c | 1 - fs/btrfs/super.c | 3 --- fs/btrfs/sysfs.c | 2 -- fs/btrfs/volumes.c | 3 --- 14 files changed, 48 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index d3e447b45bf7..f48794a36068 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -14,10 +13,7 @@ #include #include #include -#include -#include #include -#include #include #include #include diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 1b30c38d05c9..059ca3d5ddd3 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -6,14 +6,9 @@ #include #include #include -#include #include -#include -#include -#include #include #include -#include #include "ctree.h" #include "extent_map.h" #include "disk-io.h" diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e0baf2f3154d..6023eed3e805 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -5,8 +5,6 @@ #include #include -#include -#include #include #include #include diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index da53e45705ba..2be00e873e92 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -5,14 +5,11 @@ #include #include -#include #include #include #include #include -#include #include -#include #include #include #include diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index a56f88ea9c73..ffca2abf13d0 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c @@ -3,7 +3,6 @@ * Copyright (C) 2007 Oracle. All rights reserved. */ -#include #include #include diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 32613dca13c1..ada8a698af10 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -14,17 +14,13 @@ #include #include #include -#include -#include #include #include -#include #include #include #include #include #include -#include #include #include #include diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 08b8c0b346b3..802918507cc0 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -5,23 +5,18 @@ #include #include -#include #include #include #include #include #include #include -#include #include #include #include -#include #include -#include #include #include -#include #include #include #include diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index e173b252d795..0c4ef208b8b9 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "ctree.h" #include "transaction.h" #include "btrfs_inode.h" diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index 27ed47a23f26..42631079c492 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c @@ -5,32 +5,19 @@ */ #include -#include #include #include -#include #include -#include -#include -#include -#include -#include #include #include #include #include #include -#include #include "ctree.h" -#include "extent_map.h" #include "disk-io.h" -#include "transaction.h" -#include "print-tree.h" #include "volumes.h" #include "raid56.h" #include "async-thread.h" -#include "check-integrity.h" -#include "rcu-string.h" /* set when additional merges to this rbio are not allowed */ #define RBIO_RMW_LOCKED_BIT 1 diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c index 4be425f70c2d..dec14b739b10 100644 --- a/fs/btrfs/reada.c +++ b/fs/btrfs/reada.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include "ctree.h" diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c index b7b4acb12833..4c13b737f568 100644 --- a/fs/btrfs/struct-funcs.c +++ b/fs/btrfs/struct-funcs.c @@ -3,7 +3,6 @@ * Copyright (C) 2007 Oracle. All rights reserved. */ -#include #include #include "ctree.h" diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 3c5f221b5303..e04bcf0b0ed4 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -15,8 +14,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 4a4e960c7c66..3717c864ba23 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -7,10 +7,8 @@ #include #include #include -#include #include #include -#include #include #include "ctree.h" diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 1ffc49c9c02f..211fb2161487 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -8,15 +8,12 @@ #include #include #include -#include -#include #include #include #include #include #include #include -#include #include "ctree.h" #include "extent_map.h" #include "disk-io.h" -- cgit v1.2.3 From d814a49198eafa6163698bdd93961302f3a877a4 Mon Sep 17 00:00:00 2001 From: Ethan Lien Date: Mon, 2 Jul 2018 15:44:58 +0800 Subject: btrfs: use correct compare function of dirty_metadata_bytes We use customized, nodesize batch value to update dirty_metadata_bytes. We should also use batch version of compare function or we will easily goto fast path and get false result from percpu_counter_compare(). Fixes: e2d845211eda ("Btrfs: use percpu counter for dirty metadata count") CC: stable@vger.kernel.org # 4.4+ Signed-off-by: Ethan Lien Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 6023eed3e805..e3858b2fe014 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -959,8 +959,9 @@ static int btree_writepages(struct address_space *mapping, fs_info = BTRFS_I(mapping->host)->root->fs_info; /* this is a bit racy, but that's ok */ - ret = percpu_counter_compare(&fs_info->dirty_metadata_bytes, - BTRFS_DIRTY_METADATA_THRESH); + ret = __percpu_counter_compare(&fs_info->dirty_metadata_bytes, + BTRFS_DIRTY_METADATA_THRESH, + fs_info->dirty_metadata_batch); if (ret < 0) return 0; } @@ -4134,8 +4135,9 @@ static void __btrfs_btree_balance_dirty(struct btrfs_fs_info *fs_info, if (flush_delayed) btrfs_balance_delayed_items(fs_info); - ret = percpu_counter_compare(&fs_info->dirty_metadata_bytes, - BTRFS_DIRTY_METADATA_THRESH); + ret = __percpu_counter_compare(&fs_info->dirty_metadata_bytes, + BTRFS_DIRTY_METADATA_THRESH, + fs_info->dirty_metadata_batch); if (ret > 0) { balance_dirty_pages_ratelimited(fs_info->btree_inode->i_mapping); } -- cgit v1.2.3 From b0132a3be5daf84116833542717ff5692f51640e Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Wed, 27 Jun 2018 16:38:24 +0300 Subject: btrfs: Rename EXTENT_BUFFER_DUMMY to EXTENT_BUFFER_UNMAPPED EXTENT_BUFFER_DUMMY is an awful name for this flag. Buffers which have this flag set are not in any way dummy. Rather, they are private in the sense that are not mapped and linked to the global buffer tree. This flag has subtle implications to the way free_extent_buffer works for example, as well as controls whether page->mapping->private_lock is held during extent_buffer release. Pages for an unmapped buffer cannot be under io, nor can they be written by a 3rd party so taking the lock is unnecessary. Signed-off-by: Nikolay Borisov Reviewed-by: David Sterba [ EXTENT_BUFFER_UNMAPPED, update changelog ] Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 4 ++-- fs/btrfs/extent_io.c | 10 +++++----- fs/btrfs/extent_io.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e3858b2fe014..a4b713d03a33 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -4089,10 +4089,10 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf) #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS /* * This is a fast path so only do this check if we have sanity tests - * enabled. Normal people shouldn't be marking dummy buffers as dirty + * enabled. Normal people shouldn't be using umapped buffers as dirty * outside of the sanity tests. */ - if (unlikely(test_bit(EXTENT_BUFFER_DUMMY, &buf->bflags))) + if (unlikely(test_bit(EXTENT_BUFFER_UNMAPPED, &buf->bflags))) return; #endif root = BTRFS_I(buf->pages[0]->mapping->host)->root; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 5ab401f79683..3440053f3599 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -4649,7 +4649,7 @@ static void btrfs_release_extent_buffer_pages(struct extent_buffer *eb) { int i; int num_pages; - int mapped = !test_bit(EXTENT_BUFFER_DUMMY, &eb->bflags); + int mapped = !test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags); BUG_ON(extent_buffer_under_io(eb)); @@ -4763,7 +4763,7 @@ struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src) } set_bit(EXTENT_BUFFER_UPTODATE, &new->bflags); - set_bit(EXTENT_BUFFER_DUMMY, &new->bflags); + set_bit(EXTENT_BUFFER_UNMAPPED, &new->bflags); return new; } @@ -4787,7 +4787,7 @@ struct extent_buffer *__alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, } set_extent_buffer_uptodate(eb); btrfs_set_header_nritems(eb, 0); - set_bit(EXTENT_BUFFER_DUMMY, &eb->bflags); + set_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags); return eb; err: @@ -5088,7 +5088,7 @@ static int release_extent_buffer(struct extent_buffer *eb) /* Should be safe to release our pages at this point */ btrfs_release_extent_buffer_pages(eb); #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS - if (unlikely(test_bit(EXTENT_BUFFER_DUMMY, &eb->bflags))) { + if (unlikely(test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags))) { __free_extent_buffer(eb); return 1; } @@ -5119,7 +5119,7 @@ void free_extent_buffer(struct extent_buffer *eb) spin_lock(&eb->refs_lock); if (atomic_read(&eb->refs) == 2 && - test_bit(EXTENT_BUFFER_DUMMY, &eb->bflags)) + test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags)) atomic_dec(&eb->refs); if (atomic_read(&eb->refs) == 2 && diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 48f1ee9ad379..0ecc13b7d6f7 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -46,7 +46,7 @@ #define EXTENT_BUFFER_STALE 6 #define EXTENT_BUFFER_WRITEBACK 7 #define EXTENT_BUFFER_READ_ERR 8 /* read IO error */ -#define EXTENT_BUFFER_DUMMY 9 +#define EXTENT_BUFFER_UNMAPPED 9 #define EXTENT_BUFFER_IN_TREE 10 #define EXTENT_BUFFER_WRITE_ERR 11 /* write IO error */ -- cgit v1.2.3 From d7e8555b1dd493c809e56e359974eecabe7d3fde Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 18 Jul 2018 17:31:19 +0200 Subject: btrfs: remove unused member async_submit_bio::fs_info Introduced by c6100a4b4e3d1 ("Btrfs: replace tree->mapping with tree->private_data") to be used in run_one_async_done where it got unused after 736cd52e0c720103 ("Btrfs: remove nr_async_submits and async_submit_draining"). Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a4b713d03a33..8033289d2189 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -106,7 +106,6 @@ void __cold btrfs_end_io_wq_exit(void) */ struct async_submit_bio { void *private_data; - struct btrfs_fs_info *fs_info; struct bio *bio; extent_submit_bio_start_t *submit_bio_start; extent_submit_bio_done_t *submit_bio_done; @@ -801,7 +800,6 @@ blk_status_t btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio, return BLK_STS_RESOURCE; async->private_data = private_data; - async->fs_info = fs_info; async->bio = bio; async->mirror_num = mirror_num; async->submit_bio_start = submit_bio_start; -- cgit v1.2.3 From d7cbfafc4bc37ed21351cdedbc6f9d979545dbf3 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 18 Jul 2018 17:31:10 +0200 Subject: btrfs: remove unused member async_submit_bio::bio_flags After splitting the start and end hooks in a758781d4b76c3 ("btrfs: separate types for submit_bio_start and submit_bio_done"), some of the function arguments were dropped but not removed from the structure. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 8033289d2189..d82df15af89c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -110,7 +110,6 @@ struct async_submit_bio { extent_submit_bio_start_t *submit_bio_start; extent_submit_bio_done_t *submit_bio_done; int mirror_num; - unsigned long bio_flags; /* * bio_offset is optional, can be used if the pages in the bio * can't tell us where in the file the bio should go @@ -808,7 +807,6 @@ blk_status_t btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio, btrfs_init_work(&async->work, btrfs_worker_helper, run_one_async_start, run_one_async_done, run_one_async_free); - async->bio_flags = bio_flags; async->bio_offset = bio_offset; async->status = 0; -- cgit v1.2.3 From e288c080dddd1fdc3b7e0165cebd7af51a52d016 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 18 Jul 2018 17:36:24 +0200 Subject: btrfs: unify end_io callbacks of async_submit_bio The end_io callbacks passed to btrfs_wq_submit_bio (btrfs_submit_bio_done and btree_submit_bio_done) are effectively the same code, there's no point to do the indirection. Export btrfs_submit_bio_done and call it directly. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 28 +++------------------------- fs/btrfs/disk-io.h | 5 +++-- fs/btrfs/extent_io.h | 3 --- fs/btrfs/inode.c | 8 +++----- 4 files changed, 9 insertions(+), 35 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index d82df15af89c..03a7ed448f38 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -108,7 +108,6 @@ struct async_submit_bio { void *private_data; struct bio *bio; extent_submit_bio_start_t *submit_bio_start; - extent_submit_bio_done_t *submit_bio_done; int mirror_num; /* * bio_offset is optional, can be used if the pages in the bio @@ -775,7 +774,7 @@ static void run_one_async_done(struct btrfs_work *work) return; } - async->submit_bio_done(async->private_data, async->bio, async->mirror_num); + btrfs_submit_bio_done(async->private_data, async->bio, async->mirror_num); } static void run_one_async_free(struct btrfs_work *work) @@ -789,8 +788,7 @@ static void run_one_async_free(struct btrfs_work *work) blk_status_t btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio, int mirror_num, unsigned long bio_flags, u64 bio_offset, void *private_data, - extent_submit_bio_start_t *submit_bio_start, - extent_submit_bio_done_t *submit_bio_done) + extent_submit_bio_start_t *submit_bio_start) { struct async_submit_bio *async; @@ -802,7 +800,6 @@ blk_status_t btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio, async->bio = bio; async->mirror_num = mirror_num; async->submit_bio_start = submit_bio_start; - async->submit_bio_done = submit_bio_done; btrfs_init_work(&async->work, btrfs_worker_helper, run_one_async_start, run_one_async_done, run_one_async_free); @@ -845,24 +842,6 @@ static blk_status_t btree_submit_bio_start(void *private_data, struct bio *bio, return btree_csum_one_bio(bio); } -static blk_status_t btree_submit_bio_done(void *private_data, struct bio *bio, - int mirror_num) -{ - struct inode *inode = private_data; - blk_status_t ret; - - /* - * when we're called for a write, we're already in the async - * submission context. Just jump into btrfs_map_bio - */ - ret = btrfs_map_bio(btrfs_sb(inode->i_sb), bio, mirror_num, 1); - if (ret) { - bio->bi_status = ret; - bio_endio(bio); - } - return ret; -} - static int check_async_write(struct btrfs_inode *bi) { if (atomic_read(&bi->sync_writers)) @@ -905,8 +884,7 @@ static blk_status_t btree_submit_bio_hook(void *private_data, struct bio *bio, */ ret = btrfs_wq_submit_bio(fs_info, bio, mirror_num, 0, bio_offset, private_data, - btree_submit_bio_start, - btree_submit_bio_done); + btree_submit_bio_start); } if (ret) diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 1a3d277b027b..4cccba22640f 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h @@ -120,8 +120,9 @@ blk_status_t btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio, blk_status_t btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio, int mirror_num, unsigned long bio_flags, u64 bio_offset, void *private_data, - extent_submit_bio_start_t *submit_bio_start, - extent_submit_bio_done_t *submit_bio_done); + extent_submit_bio_start_t *submit_bio_start); +blk_status_t btrfs_submit_bio_done(void *private_data, struct bio *bio, + int mirror_num); int btrfs_write_tree_block(struct extent_buffer *buf); void btrfs_wait_tree_block_writeback(struct extent_buffer *buf); int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 0ecc13b7d6f7..4e6d34dd7caf 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -92,9 +92,6 @@ typedef blk_status_t (extent_submit_bio_hook_t)(void *private_data, struct bio * typedef blk_status_t (extent_submit_bio_start_t)(void *private_data, struct bio *bio, u64 bio_offset); -typedef blk_status_t (extent_submit_bio_done_t)(void *private_data, - struct bio *bio, int mirror_num); - struct extent_io_ops { /* * The following callbacks must be allways defined, the function diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 564ec00c765b..6cb42e33fdc3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1957,7 +1957,7 @@ static blk_status_t btrfs_submit_bio_start(void *private_data, struct bio *bio, * At IO completion time the cums attached on the ordered extent record * are inserted into the btree */ -static blk_status_t btrfs_submit_bio_done(void *private_data, struct bio *bio, +blk_status_t btrfs_submit_bio_done(void *private_data, struct bio *bio, int mirror_num) { struct inode *inode = private_data; @@ -2030,8 +2030,7 @@ static blk_status_t btrfs_submit_bio_hook(void *private_data, struct bio *bio, /* we're doing a write, do the async checksumming */ ret = btrfs_wq_submit_bio(fs_info, bio, mirror_num, bio_flags, bio_offset, inode, - btrfs_submit_bio_start, - btrfs_submit_bio_done); + btrfs_submit_bio_start); goto out; } else if (!skip_sum) { ret = btrfs_csum_one_bio(inode, bio, 0, 0); @@ -8295,8 +8294,7 @@ static inline blk_status_t btrfs_submit_dio_bio(struct bio *bio, if (write && async_submit) { ret = btrfs_wq_submit_bio(fs_info, bio, 0, 0, file_offset, inode, - btrfs_submit_bio_start_direct_io, - btrfs_submit_bio_done); + btrfs_submit_bio_start_direct_io); goto err; } else if (write) { /* -- cgit v1.2.3 From 05912a3c04ebca217507b4323b679c60eda4ac11 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 18 Jul 2018 19:23:45 +0200 Subject: btrfs: drop extent_io_ops::tree_fs_info callback All implementations of the callback are trivial and do the same and there's only one user. Merge everything together. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 7 ------- fs/btrfs/extent_io.c | 14 ++++---------- fs/btrfs/extent_io.h | 1 - fs/btrfs/inode.c | 7 ------- 4 files changed, 4 insertions(+), 25 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 03a7ed448f38..126460214512 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -4523,12 +4523,6 @@ static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info) return 0; } -static struct btrfs_fs_info *btree_fs_info(void *private_data) -{ - struct inode *inode = private_data; - return btrfs_sb(inode->i_sb); -} - static const struct extent_io_ops btree_extent_io_ops = { /* mandatory callbacks */ .submit_bio_hook = btree_submit_bio_hook, @@ -4537,7 +4531,6 @@ static const struct extent_io_ops btree_extent_io_ops = { .merge_bio_hook = btrfs_merge_bio_hook, .readpage_io_failed_hook = btree_io_failed_hook, .set_range_writeback = btrfs_set_range_writeback, - .tree_fs_info = btree_fs_info, /* optional callbacks */ }; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 3440053f3599..7a19437c6eda 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -140,14 +140,6 @@ static int add_extent_changeset(struct extent_state *state, unsigned bits, static void flush_write_bio(struct extent_page_data *epd); -static inline struct btrfs_fs_info * -tree_fs_info(struct extent_io_tree *tree) -{ - if (tree->ops) - return tree->ops->tree_fs_info(tree->private_data); - return NULL; -} - int __init extent_io_init(void) { extent_state_cache = kmem_cache_create("btrfs_extent_state", @@ -564,8 +556,10 @@ alloc_extent_state_atomic(struct extent_state *prealloc) static void extent_io_tree_panic(struct extent_io_tree *tree, int err) { - btrfs_panic(tree_fs_info(tree), err, - "Locking error: Extent tree was modified by another thread while locked."); + struct inode *inode = tree->private_data; + + btrfs_panic(btrfs_sb(inode->i_sb), err, + "locking error: extent tree was modified by another thread while locked"); } /* diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 4e6d34dd7caf..004517f3eb35 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -105,7 +105,6 @@ struct extent_io_ops { size_t size, struct bio *bio, unsigned long bio_flags); int (*readpage_io_failed_hook)(struct page *page, int failed_mirror); - struct btrfs_fs_info *(*tree_fs_info)(void *private_data); void (*set_range_writeback)(void *private_data, u64 start, u64 end); /* diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6cb42e33fdc3..f279e380f36e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -10473,12 +10473,6 @@ static int btrfs_readpage_io_failed_hook(struct page *page, int failed_mirror) return -EAGAIN; } -static struct btrfs_fs_info *iotree_fs_info(void *private_data) -{ - struct inode *inode = private_data; - return btrfs_sb(inode->i_sb); -} - static void btrfs_check_extent_io_range(void *private_data, const char *caller, u64 start, u64 end) { @@ -10553,7 +10547,6 @@ static const struct extent_io_ops btrfs_extent_io_ops = { .readpage_end_io_hook = btrfs_readpage_end_io_hook, .merge_bio_hook = btrfs_merge_bio_hook, .readpage_io_failed_hook = btrfs_readpage_io_failed_hook, - .tree_fs_info = iotree_fs_info, .set_range_writeback = btrfs_set_range_writeback, /* optional callbacks */ -- cgit v1.2.3 From 00032d38eaa89c76de7d9c1ae6de8c48c14edd74 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 18 Jul 2018 19:28:09 +0200 Subject: btrfs: drop extent_io_ops::merge_bio_hook callback The data and metadata callback implementation both use the same function. We can remove the call indirection completely. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/compression.c | 10 +++------- fs/btrfs/disk-io.c | 2 -- fs/btrfs/extent_io.c | 4 ++-- fs/btrfs/extent_io.h | 3 --- fs/btrfs/inode.c | 5 ++--- 5 files changed, 7 insertions(+), 17 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 70dace47258b..9bfa66592aa7 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -299,7 +299,6 @@ blk_status_t btrfs_submit_compressed_write(struct inode *inode, u64 start, struct bio *bio = NULL; struct compressed_bio *cb; unsigned long bytes_left; - struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; int pg_index = 0; struct page *page; u64 first_byte = disk_start; @@ -338,9 +337,7 @@ blk_status_t btrfs_submit_compressed_write(struct inode *inode, u64 start, page = compressed_pages[pg_index]; page->mapping = inode->i_mapping; if (bio->bi_iter.bi_size) - submit = io_tree->ops->merge_bio_hook(page, 0, - PAGE_SIZE, - bio, 0); + submit = btrfs_merge_bio_hook(page, 0, PAGE_SIZE, bio, 0); page->mapping = NULL; if (submit || bio_add_page(bio, page, PAGE_SIZE, 0) < @@ -622,9 +619,8 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, page->index = em_start >> PAGE_SHIFT; if (comp_bio->bi_iter.bi_size) - submit = tree->ops->merge_bio_hook(page, 0, - PAGE_SIZE, - comp_bio, 0); + submit = btrfs_merge_bio_hook(page, 0, PAGE_SIZE, + comp_bio, 0); page->mapping = NULL; if (submit || bio_add_page(comp_bio, page, PAGE_SIZE, 0) < diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 126460214512..0c9c029ade72 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -4527,8 +4527,6 @@ static const struct extent_io_ops btree_extent_io_ops = { /* mandatory callbacks */ .submit_bio_hook = btree_submit_bio_hook, .readpage_end_io_hook = btree_readpage_end_io_hook, - /* note we're sharing with inode.c for the merge bio hook */ - .merge_bio_hook = btrfs_merge_bio_hook, .readpage_io_failed_hook = btree_io_failed_hook, .set_range_writeback = btrfs_set_range_writeback, diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 7a19437c6eda..20af0efd7c17 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2784,8 +2784,8 @@ static int submit_extent_page(unsigned int opf, struct extent_io_tree *tree, else contig = bio_end_sector(bio) == sector; - if (tree->ops && tree->ops->merge_bio_hook(page, offset, - page_size, bio, bio_flags)) + if (tree->ops && btrfs_merge_bio_hook(page, offset, page_size, + bio, bio_flags)) can_merge = false; if (prev_bio_flags != bio_flags || !contig || !can_merge || diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 004517f3eb35..5c07f87c2ec9 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -101,9 +101,6 @@ struct extent_io_ops { int (*readpage_end_io_hook)(struct btrfs_io_bio *io_bio, u64 phy_offset, struct page *page, u64 start, u64 end, int mirror); - int (*merge_bio_hook)(struct page *page, unsigned long offset, - size_t size, struct bio *bio, - unsigned long bio_flags); int (*readpage_io_failed_hook)(struct page *page, int failed_mirror); void (*set_range_writeback)(void *private_data, u64 start, u64 end); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f279e380f36e..a72784d5666f 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1898,8 +1898,8 @@ static void btrfs_clear_bit_hook(void *private_data, } /* - * extent_io.c merge_bio_hook, this must check the chunk tree to make sure - * we don't create bios that span stripes or chunks + * Merge bio hook, this must check the chunk tree to make sure we don't create + * bios that span stripes or chunks * * return 1 if page cannot be merged to bio * return 0 if page can be merged to bio @@ -10545,7 +10545,6 @@ static const struct extent_io_ops btrfs_extent_io_ops = { /* mandatory callbacks */ .submit_bio_hook = btrfs_submit_bio_hook, .readpage_end_io_hook = btrfs_readpage_end_io_hook, - .merge_bio_hook = btrfs_merge_bio_hook, .readpage_io_failed_hook = btrfs_readpage_io_failed_hook, .set_range_writeback = btrfs_set_range_writeback, -- cgit v1.2.3 From 5cdc84bfde22dc17b11ee7cb18cebd48f4a09f70 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 18 Jul 2018 20:32:52 +0200 Subject: btrfs: drop extent_io_ops::set_range_writeback callback The data and metadata callback implementation both use the same function. We can remove the call indirection and intermediate helper completely. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 2 +- fs/btrfs/disk-io.c | 1 - fs/btrfs/extent_io.c | 10 +--------- fs/btrfs/extent_io.h | 1 - fs/btrfs/inode.c | 5 ++--- 5 files changed, 4 insertions(+), 15 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index ee1e152cb94b..9c638931b75e 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -3172,7 +3172,7 @@ int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, int btrfs_merge_bio_hook(struct page *page, unsigned long offset, size_t size, struct bio *bio, unsigned long bio_flags); -void btrfs_set_range_writeback(void *private_data, u64 start, u64 end); +void btrfs_set_range_writeback(struct extent_io_tree *tree, u64 start, u64 end); vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf); int btrfs_readpage(struct file *file, struct page *page); void btrfs_evict_inode(struct inode *inode); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 0c9c029ade72..9b208ccf24fe 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -4528,7 +4528,6 @@ static const struct extent_io_ops btree_extent_io_ops = { .submit_bio_hook = btree_submit_bio_hook, .readpage_end_io_hook = btree_readpage_end_io_hook, .readpage_io_failed_hook = btree_io_failed_hook, - .set_range_writeback = btrfs_set_range_writeback, /* optional callbacks */ }; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 20af0efd7c17..628f1aef34b0 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1380,14 +1380,6 @@ void extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end) } } -/* - * helper function to set both pages and extents in the tree writeback - */ -static void set_range_writeback(struct extent_io_tree *tree, u64 start, u64 end) -{ - tree->ops->set_range_writeback(tree->private_data, start, end); -} - /* find the first state struct with 'bits' set after 'start', and * return it. tree->lock must be held. NULL will returned if * nothing was found after 'start' @@ -3416,7 +3408,7 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode, continue; } - set_range_writeback(tree, cur, cur + iosize - 1); + btrfs_set_range_writeback(tree, cur, cur + iosize - 1); if (!PageWriteback(page)) { btrfs_err(BTRFS_I(inode)->root->fs_info, "page %lu not writeback, cur %llu end %llu", diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 5c07f87c2ec9..b4d03e677e1d 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -102,7 +102,6 @@ struct extent_io_ops { struct page *page, u64 start, u64 end, int mirror); int (*readpage_io_failed_hook)(struct page *page, int failed_mirror); - void (*set_range_writeback)(void *private_data, u64 start, u64 end); /* * Optional hooks, called if the pointer is not NULL diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index a72784d5666f..4955e04da4c8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -10487,9 +10487,9 @@ static void btrfs_check_extent_io_range(void *private_data, const char *caller, } } -void btrfs_set_range_writeback(void *private_data, u64 start, u64 end) +void btrfs_set_range_writeback(struct extent_io_tree *tree, u64 start, u64 end) { - struct inode *inode = private_data; + struct inode *inode = tree->private_data; unsigned long index = start >> PAGE_SHIFT; unsigned long end_index = end >> PAGE_SHIFT; struct page *page; @@ -10546,7 +10546,6 @@ static const struct extent_io_ops btrfs_extent_io_ops = { .submit_bio_hook = btrfs_submit_bio_hook, .readpage_end_io_hook = btrfs_readpage_end_io_hook, .readpage_io_failed_hook = btrfs_readpage_io_failed_hook, - .set_range_writeback = btrfs_set_range_writeback, /* optional callbacks */ .fill_delalloc = run_delalloc_range, -- cgit v1.2.3 From e17385ca2960177da402d6f4d80bdc5b53c29bc4 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Fri, 20 Jul 2018 16:30:18 +0200 Subject: btrfs: remove unused member btrfs_root::name Added in 58176a9604c ("Btrfs: Add per-root block accounting and sysfs entries") in 2007, the roots had names exported in sysfs. The code was commented out in 4df27c4d5cc1dda54ed ("Btrfs: change how subvolumes are organized") and cleaned by 182608c8294b5fe9 ("btrfs: remove old unused commented out code"). Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 1 - fs/btrfs/disk-io.c | 2 -- 2 files changed, 3 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 9c638931b75e..4ca6c4e141ea 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1219,7 +1219,6 @@ struct btrfs_root { u64 defrag_trans_start; struct btrfs_key defrag_progress; struct btrfs_key defrag_max; - char *name; /* the dirty list is only used by non-reference counted roots */ struct list_head dirty_list; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 9b208ccf24fe..3830867e0225 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1154,7 +1154,6 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info, root->highest_objectid = 0; root->nr_delalloc_inodes = 0; root->nr_ordered_extents = 0; - root->name = NULL; root->inode_tree = RB_ROOT; INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC); root->block_rsv = NULL; @@ -3849,7 +3848,6 @@ static void free_fs_root(struct btrfs_root *root) free_extent_buffer(root->commit_root); kfree(root->free_ino_ctl); kfree(root->free_ino_pinned); - kfree(root->name); btrfs_put_fs_root(root); } -- cgit v1.2.3 From e9539cff04728e31e150b41000b828745fc0c2b3 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Fri, 20 Jul 2018 16:30:20 +0200 Subject: btrfs: dev-replace: remove unused members of btrfs_dev_replace Lock owner and nesting level have been unused since day 1, probably copy&pasted from the extent_buffer locking scheme without much thinking. The locking of device replace is simpler and does not need any lock nesting. Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 2 -- fs/btrfs/disk-io.c | 2 -- 2 files changed, 4 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 4ca6c4e141ea..5f6ec80d374f 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -365,8 +365,6 @@ struct btrfs_dev_replace { struct btrfs_device *srcdev; struct btrfs_device *tgtdev; - pid_t lock_owner; - atomic_t nesting_level; struct mutex lock_finishing_cancel_unmount; rwlock_t lock; atomic_t read_locks; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3830867e0225..c1d287a766c1 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2154,8 +2154,6 @@ static void btrfs_init_btree_inode(struct btrfs_fs_info *fs_info) static void btrfs_init_dev_replace_locks(struct btrfs_fs_info *fs_info) { - fs_info->dev_replace.lock_owner = 0; - atomic_set(&fs_info->dev_replace.nesting_level, 0); mutex_init(&fs_info->dev_replace.lock_finishing_cancel_unmount); rwlock_init(&fs_info->dev_replace.lock); atomic_set(&fs_info->dev_replace.read_locks, 0); -- cgit v1.2.3 From 84db5ccf4262894852e0d178d250678945d9b0b8 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Fri, 20 Jul 2018 16:30:25 +0200 Subject: btrfs: merge free_fs_root helpers The exported helper just calls the static one. There's no obvious reason to have them separate eg. for performance reasons where the static one could be better optimized in the same unit. There's a slight decrease in code size and stack consumption. Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c1d287a766c1..6a5a3cd12886 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -52,7 +52,6 @@ static const struct extent_io_ops btree_extent_io_ops; static void end_workqueue_fn(struct btrfs_work *work); -static void free_fs_root(struct btrfs_root *root); static void btrfs_destroy_ordered_extents(struct btrfs_root *root); static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, struct btrfs_fs_info *fs_info); @@ -1504,7 +1503,7 @@ int btrfs_init_fs_root(struct btrfs_root *root) return 0; fail: - /* the caller is responsible to call free_fs_root */ + /* The caller is responsible to call btrfs_free_fs_root */ return ret; } @@ -1609,14 +1608,14 @@ again: ret = btrfs_insert_fs_root(fs_info, root); if (ret) { if (ret == -EEXIST) { - free_fs_root(root); + btrfs_free_fs_root(root); goto again; } goto fail; } return root; fail: - free_fs_root(root); + btrfs_free_fs_root(root); return ERR_PTR(ret); } @@ -3831,10 +3830,10 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info, __btrfs_remove_free_space_cache(root->free_ino_pinned); if (root->free_ino_ctl) __btrfs_remove_free_space_cache(root->free_ino_ctl); - free_fs_root(root); + btrfs_free_fs_root(root); } -static void free_fs_root(struct btrfs_root *root) +void btrfs_free_fs_root(struct btrfs_root *root) { iput(root->ino_cache_inode); WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree)); @@ -3849,11 +3848,6 @@ static void free_fs_root(struct btrfs_root *root) btrfs_put_fs_root(root); } -void btrfs_free_fs_root(struct btrfs_root *root) -{ - free_fs_root(root); -} - int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info) { u64 root_objectid = 0; -- cgit v1.2.3 From cf90d884b347c50a1e8c1effc4093e497dd68b4b Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Wed, 1 Aug 2018 10:37:19 +0800 Subject: btrfs: Introduce mount time chunk <-> dev extent mapping check This patch will introduce chunk <-> dev extent mapping check, to protect us against invalid dev extents or chunks. Since chunk mapping is the fundamental infrastructure of btrfs, extra check at mount time could prevent a lot of unexpected behavior (BUG_ON). Reported-by: Xu Wen Link: https://bugzilla.kernel.org/show_bug.cgi?id=200403 Link: https://bugzilla.kernel.org/show_bug.cgi?id=200407 Signed-off-by: Qu Wenruo Reviewed-by: Su Yue Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 7 ++ fs/btrfs/volumes.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/volumes.h | 2 + 3 files changed, 193 insertions(+) (limited to 'fs/btrfs/disk-io.c') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 6a5a3cd12886..5124c15705ce 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3030,6 +3030,13 @@ retry_root_backup: fs_info->generation = generation; fs_info->last_trans_committed = generation; + ret = btrfs_verify_dev_extents(fs_info); + if (ret) { + btrfs_err(fs_info, + "failed to verify dev extents against chunks: %d", + ret); + goto fail_block_groups; + } ret = btrfs_recover_balance(fs_info); if (ret) { btrfs_err(fs_info, "failed to recover balance: %d", ret); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 74977203fc85..96be1e50b027 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6452,6 +6452,7 @@ static int read_one_chunk(struct btrfs_fs_info *fs_info, struct btrfs_key *key, map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk); map->type = btrfs_chunk_type(leaf, chunk); map->sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); + map->verified_stripes = 0; for (i = 0; i < num_stripes; i++) { map->stripes[i].physical = btrfs_stripe_offset_nr(leaf, chunk, i); @@ -7318,3 +7319,186 @@ int btrfs_bg_type_to_factor(u64 flags) return 2; return 1; } + + +static u64 calc_stripe_length(u64 type, u64 chunk_len, int num_stripes) +{ + int index = btrfs_bg_flags_to_raid_index(type); + int ncopies = btrfs_raid_array[index].ncopies; + int data_stripes; + + switch (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) { + case BTRFS_BLOCK_GROUP_RAID5: + data_stripes = num_stripes - 1; + break; + case BTRFS_BLOCK_GROUP_RAID6: + data_stripes = num_stripes - 2; + break; + default: + data_stripes = num_stripes / ncopies; + break; + } + return div_u64(chunk_len, data_stripes); +} + +static int verify_one_dev_extent(struct btrfs_fs_info *fs_info, + u64 chunk_offset, u64 devid, + u64 physical_offset, u64 physical_len) +{ + struct extent_map_tree *em_tree = &fs_info->mapping_tree.map_tree; + struct extent_map *em; + struct map_lookup *map; + u64 stripe_len; + bool found = false; + int ret = 0; + int i; + + read_lock(&em_tree->lock); + em = lookup_extent_mapping(em_tree, chunk_offset, 1); + read_unlock(&em_tree->lock); + + if (!em) { + btrfs_err(fs_info, +"dev extent physical offset %llu on devid %llu doesn't have corresponding chunk", + physical_offset, devid); + ret = -EUCLEAN; + goto out; + } + + map = em->map_lookup; + stripe_len = calc_stripe_length(map->type, em->len, map->num_stripes); + if (physical_len != stripe_len) { + btrfs_err(fs_info, +"dev extent physical offset %llu on devid %llu length doesn't match chunk %llu, have %llu expect %llu", + physical_offset, devid, em->start, physical_len, + stripe_len); + ret = -EUCLEAN; + goto out; + } + + for (i = 0; i < map->num_stripes; i++) { + if (map->stripes[i].dev->devid == devid && + map->stripes[i].physical == physical_offset) { + found = true; + if (map->verified_stripes >= map->num_stripes) { + btrfs_err(fs_info, + "too many dev extents for chunk %llu found", + em->start); + ret = -EUCLEAN; + goto out; + } + map->verified_stripes++; + break; + } + } + if (!found) { + btrfs_err(fs_info, + "dev extent physical offset %llu devid %llu has no corresponding chunk", + physical_offset, devid); + ret = -EUCLEAN; + } +out: + free_extent_map(em); + return ret; +} + +static int verify_chunk_dev_extent_mapping(struct btrfs_fs_info *fs_info) +{ + struct extent_map_tree *em_tree = &fs_info->mapping_tree.map_tree; + struct extent_map *em; + struct rb_node *node; + int ret = 0; + + read_lock(&em_tree->lock); + for (node = rb_first(&em_tree->map); node; node = rb_next(node)) { + em = rb_entry(node, struct extent_map, rb_node); + if (em->map_lookup->num_stripes != + em->map_lookup->verified_stripes) { + btrfs_err(fs_info, + "chunk %llu has missing dev extent, have %d expect %d", + em->start, em->map_lookup->verified_stripes, + em->map_lookup->num_stripes); + ret = -EUCLEAN; + goto out; + } + } +out: + read_unlock(&em_tree->lock); + return ret; +} + +/* + * Ensure that all dev extents are mapped to correct chunk, otherwise + * later chunk allocation/free would cause unexpected behavior. + * + * NOTE: This will iterate through the whole device tree, which should be of + * the same size level as the chunk tree. This slightly increases mount time. + */ +int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info) +{ + struct btrfs_path *path; + struct btrfs_root *root = fs_info->dev_root; + struct btrfs_key key; + int ret = 0; + + key.objectid = 1; + key.type = BTRFS_DEV_EXTENT_KEY; + key.offset = 0; + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + + path->reada = READA_FORWARD; + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret < 0) + goto out; + + if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) { + ret = btrfs_next_item(root, path); + if (ret < 0) + goto out; + /* No dev extents at all? Not good */ + if (ret > 0) { + ret = -EUCLEAN; + goto out; + } + } + while (1) { + struct extent_buffer *leaf = path->nodes[0]; + struct btrfs_dev_extent *dext; + int slot = path->slots[0]; + u64 chunk_offset; + u64 physical_offset; + u64 physical_len; + u64 devid; + + btrfs_item_key_to_cpu(leaf, &key, slot); + if (key.type != BTRFS_DEV_EXTENT_KEY) + break; + devid = key.objectid; + physical_offset = key.offset; + + dext = btrfs_item_ptr(leaf, slot, struct btrfs_dev_extent); + chunk_offset = btrfs_dev_extent_chunk_offset(leaf, dext); + physical_len = btrfs_dev_extent_length(leaf, dext); + + ret = verify_one_dev_extent(fs_info, chunk_offset, devid, + physical_offset, physical_len); + if (ret < 0) + goto out; + ret = btrfs_next_item(root, path); + if (ret < 0) + goto out; + if (ret > 0) { + ret = 0; + break; + } + } + + /* Ensure all chunks have corresponding dev extents */ + ret = verify_chunk_dev_extent_mapping(fs_info); +out: + btrfs_free_path(path); + return ret; +} diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 049619176831..23e9285d88de 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -345,6 +345,7 @@ struct map_lookup { u64 stripe_len; int num_stripes; int sub_stripes; + int verified_stripes; /* For mount time dev extent verification */ struct btrfs_bio_stripe stripes[]; }; @@ -556,5 +557,6 @@ bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info, struct btrfs_device *failing_dev); int btrfs_bg_type_to_factor(u64 flags); +int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info); #endif -- cgit v1.2.3