Btrfs: add a extent ref verify tool
PATCH 1/1 Btrfs: add a extent ref verify tool
We were having corruption issues that were tied back to problems with the extent tree. In order to track them down I built this tool to try and find the culprit, which was pretty successful. If you compile with this tool on it will live verify every ref update that the fs makes and make sure it is consistent and valid. This should only be used with a clean file system to start with and then have the tests run as it doesn't lookup the actual shared refs on mount, so it will get snapshots and things wrong. This could be fixed in the future easily, I just didn't need it for my particular test. Thanks,
Signed-off-by Josef Bacik <[email protected]>
--- fs/btrfs/Kconfig | 10 + fs/btrfs/Makefile | 1 + fs/btrfs/ctree.c | 2 +- fs/btrfs/ctree.h | 7 + fs/btrfs/disk-io.c | 14 +- fs/btrfs/extent-tree.c | 16 + fs/btrfs/ref-verify.c | 892 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/ref-verify.h | 34 ++ fs/btrfs/relocation.c | 1 + 9 files changed, 975 insertions(+), 2 deletions(-) create mode 100644 fs/btrfs/ref-verify.c create mode 100644 fs/btrfs/ref-verify.h
fs/btrfs/Kconfig +10 -0
@@ -88,3 +88,13 @@ config BTRFS_ASSERT any of the assertions trip. This is meant for btrfs developers only. If unsure, say N. + +config BTRFS_FS_REF_VERIFY + bool "Btrfs with the ref verify tool compiled in" + depends on BTRFS_FS + help + Enable run-time extent reference verification instrumentation. This + is meant to be used by btrfs developers for tracking down extent + reference problems or verifying they didn't break something. + + If unsure, say N.
fs/btrfs/Makefile +1 -0
@@ -13,6 +13,7 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o +btrfs-$(CONFIG_BTRFS_FS_REF_VERIFY) += ref-verify.o btrfs-$(CONFIG_BTRFS_FS_RUN_SANITY_TESTS) += tests/free-space-tests.o \ tests/extent-buffer-tests.o tests/btrfs-tests.o \
fs/btrfs/ctree.c +1 -1
@@ -202,7 +202,7 @@ struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root)* tree until you end up with a lock on the root. A locked buffer * is returned, with a reference held. */ -static struct extent_buffer *btrfs_read_lock_root_node (struct btrfs_root *root) +struct extent_buffer *btrfs_read_lock_root_node (struct btrfs_root *root) {struct extent_buffer *eb;
fs/btrfs/ctree.h +7 -0
@@ -1680,6 +1680,12 @@ struct btrfs_fs_info {struct semaphore uuid_tree_rescan_sem; unsigned int update_uuid_tree_gen:1; + +#ifdef CONFIG_BTRFS_FS_REF_VERIFY +spinlock_t ref_verify_lock; +struct rb_root block_tree; +bool ref_verify_enabled; +#endif };struct btrfs_subvolume_writers {
@@ -3379,6 +3385,7 @@ void btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *new_key);struct extent_buffer *btrfs_root_node (struct btrfs_root *root);struct extent_buffer *btrfs_lock_root_node (struct btrfs_root *root); +struct extent_buffer *btrfs_read_lock_root_node (struct btrfs_root *root);int btrfs_find_next_key (struct btrfs_root *root,struct btrfs_path *path,struct btrfs_key *key,int lowest_level,u64 min_trans);
fs/btrfs/disk-io.c +13 -1
@@ -49,6 +49,7 @@#include "dev-replace.h" #include "raid56.h" #include "sysfs.h" +#include "ref-verify.h" #ifdef CONFIG_X86 #include <asm/cpufeature.h>
@@ -2268,6 +2269,11 @@ int open_ctree(struct super_block *sb,#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY fs_info->check_integrity_print_mask =0 ;#endif +#ifdef CONFIG_BTRFS_FS_REF_VERIFY +spin_lock_init (&fs_info->ref_verify_lock); + fs_info->block_tree =RB_ROOT ; + fs_info->ref_verify_enabled = true; +#endif spin_lock_init (&fs_info->balance_lock);mutex_init (&fs_info->balance_mutex);
@@ -2895,7 +2901,12 @@ retry_root_backup:if (sb->s_flags &MS_RDONLY )return 0 ; - +#ifdef CONFIG_BTRFS_FS_REF_VERIFY +if (btrfs_build_ref_tree (fs_info)) { + fs_info->ref_verify_enabled = false; +printk (KERN_ERR "BTRFS: couldn't build ref tree\n" ); + } +#endif down_read (&fs_info->cleanup_work_sem);if ((ret =btrfs_orphan_cleanup (fs_info->fs_root)) || (ret =btrfs_orphan_cleanup (fs_info->tree_root))) {
@@ -3639,6 +3650,7 @@ int close_ctree(struct btrfs_root *root)cleanup_srcu_struct (&fs_info->subvol_srcu);btrfs_free_stripe_hash_table (fs_info); +btrfs_free_ref_cache (fs_info);btrfs_free_block_rsv (root, root->orphan_block_rsv); root->orphan_block_rsv =NULL ;
fs/btrfs/extent-tree.c +16 -0
@@ -36,6 +36,7 @@#include "free-space-cache.h" #include "math.h" #include "sysfs.h" +#include "ref-verify.h" #undef SCRAMBLE_DELAYED_REFS
@@ -1953,6 +1954,9 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,BUG_ON (owner <BTRFS_FIRST_FREE_OBJECTID && root_objectid ==BTRFS_TREE_LOG_OBJECTID ); +btrfs_ref_tree_mod (root, bytenr, num_bytes, parent, root_objectid, + owner, offset,BTRFS_ADD_DELAYED_REF ); +if (owner <BTRFS_FIRST_FREE_OBJECTID ) { ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr, num_bytes,
@@ -5955,6 +5959,9 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,int ret;if (root->root_key.objectid !=BTRFS_TREE_LOG_OBJECTID ) { +btrfs_ref_tree_mod (root, buf->start, buf->len, parent, + root->objectid,btrfs_header_level (buf), +0 ,BTRFS_DROP_DELAYED_REF ); ret = btrfs_add_delayed_tree_ref(root->fs_info, trans, buf->start, buf->len, parent, root->root_key.objectid,
@@ -6011,6 +6018,9 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root,add_pinned_bytes (root->fs_info, num_bytes, owner, root_objectid); +btrfs_ref_tree_mod (root, bytenr, num_bytes, parent, root_objectid, + owner, offset,BTRFS_DROP_DELAYED_REF ); +/* * tree log blocks never actually go into the extent allocation * tree, just update pinning info and exit early.
@@ -6827,6 +6837,9 @@ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,BUG_ON (root_objectid ==BTRFS_TREE_LOG_OBJECTID ); +btrfs_ref_tree_mod (root, ins->objectid, ins->offset,0 , root_objectid, + owner, offset,BTRFS_ADD_DELAYED_EXTENT ); + ret = btrfs_add_delayed_data_ref(root->fs_info, trans, ins->objectid, ins->offset, 0, root_objectid, owner, offset,
@@ -7029,6 +7042,9 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, extent_op->is_data =0 ; extent_op->level = level; +btrfs_ref_tree_mod (root, ins.objectid, ins.offset, parent, + root_objectid, level,0 , +BTRFS_ADD_DELAYED_EXTENT ); ret = btrfs_add_delayed_tree_ref(root->fs_info, trans, ins.objectid, ins.offset, parent, root_objectid,
fs/btrfs/ref-verify.c new file +892 -0
892 lines not on this page · raw message
fs/btrfs/ref-verify.h new file +34 -0
@@ -0,0 +1,34 @@ +/* +* Copyright (C) 2014 Facebook. All rights reserved. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public +* License v2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., 59 Temple Place - Suite 330, +* Boston, MA 021110-1307, USA. +*/ +#ifndef __REF_VERIFY__ +#define __REF_VERIFY__ + +#ifdef CONFIG_BTRFS_FS_REF_VERIFY +int btrfs_build_ref_tree (struct btrfs_fs_info *fs_info); +void btrfs_free_ref_cache (struct btrfs_fs_info *fs_info); +int btrfs_ref_tree_mod (struct btrfs_root *root,u64 bytenr,u64 num_bytes, +u64 parent,u64 ref_root,u64 owner,u64 offset, +int action); +#else + +#define btrfs_free_ref_cache (fs_info) do { } while (0) +#define btrfs_ref_tree_mod (root, bytenr, num_bytes, parent, ref_root, \ + owner, offset, action) do { } while (0) + +#endif /* CONFIG_BTRFS_FS_REF_VERIFY */ +#endif /* _REF_VERIFY__ */
fs/btrfs/relocation.c +1 -0
@@ -31,6 +31,7 @@#include "async-thread.h" #include "free-space-cache.h" #include "inode-map.h" +#include "ref-verify.h" /* * backref_node, mapping_node and tree_block start with this
Signature · 1 line
1.8.3.1