Merge branch 'integrity-check-patch-v2' of git://btrfs.giantdisaster.de/git/btrfs into integration
Conflicts: fs/btrfs/ctree.h fs/btrfs/super.c Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
commit
c126dea771
10 changed files with 3201 additions and 10 deletions
|
@ -31,3 +31,22 @@ config BTRFS_FS_POSIX_ACL
|
|||
Linux website <http://acl.bestbits.at/>.
|
||||
|
||||
If you don't know what Access Control Lists are, say N
|
||||
|
||||
config BTRFS_FS_CHECK_INTEGRITY
|
||||
bool "Btrfs with integrity check tool compiled in (DANGEROUS)"
|
||||
depends on BTRFS_FS
|
||||
help
|
||||
Adds code that examines all block write requests (including
|
||||
writes of the super block). The goal is to verify that the
|
||||
state of the filesystem on disk is always consistent, i.e.,
|
||||
after a power-loss or kernel panic event the filesystem is
|
||||
in a consistent state.
|
||||
|
||||
If the integrity check tool is included and activated in
|
||||
the mount options, plenty of kernel memory is used, and
|
||||
plenty of additional CPU cycles are spent. Enabling this
|
||||
functionality is not intended for normal use.
|
||||
|
||||
In most cases, unless you are a btrfs developer who needs
|
||||
to verify the integrity of (super)-block write requests
|
||||
during the run of a regression test, say N
|
||||
|
|
|
@ -11,3 +11,4 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
|
|||
reada.o backref.o ulist.o
|
||||
|
||||
btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o
|
||||
btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o
|
||||
|
|
3068
fs/btrfs/check-integrity.c
Normal file
3068
fs/btrfs/check-integrity.c
Normal file
File diff suppressed because it is too large
Load diff
36
fs/btrfs/check-integrity.h
Normal file
36
fs/btrfs/check-integrity.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) STRATO AG 2011. 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.
|
||||
*/
|
||||
|
||||
#if !defined(__BTRFS_CHECK_INTEGRITY__)
|
||||
#define __BTRFS_CHECK_INTEGRITY__
|
||||
|
||||
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
|
||||
int btrfsic_submit_bh(int rw, struct buffer_head *bh);
|
||||
void btrfsic_submit_bio(int rw, struct bio *bio);
|
||||
#else
|
||||
#define btrfsic_submit_bh submit_bh
|
||||
#define btrfsic_submit_bio submit_bio
|
||||
#endif
|
||||
|
||||
int btrfsic_mount(struct btrfs_root *root,
|
||||
struct btrfs_fs_devices *fs_devices,
|
||||
int including_extent_data, u32 print_mask);
|
||||
void btrfsic_unmount(struct btrfs_root *root,
|
||||
struct btrfs_fs_devices *fs_devices);
|
||||
|
||||
#endif
|
|
@ -1041,7 +1041,7 @@ struct btrfs_fs_info {
|
|||
* is required instead of the faster short fsync log commits
|
||||
*/
|
||||
u64 last_trans_log_full_commit;
|
||||
unsigned long mount_opt:20;
|
||||
unsigned long mount_opt:21;
|
||||
unsigned long compress_type:4;
|
||||
u64 max_inline;
|
||||
u64 alloc_start;
|
||||
|
@ -1236,6 +1236,10 @@ struct btrfs_fs_info {
|
|||
int scrub_workers_refcnt;
|
||||
struct btrfs_workers scrub_workers;
|
||||
|
||||
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
|
||||
u32 check_integrity_print_mask;
|
||||
#endif
|
||||
|
||||
/* filesystem state */
|
||||
u64 fs_state;
|
||||
|
||||
|
@ -1497,6 +1501,8 @@ struct btrfs_ioctl_defrag_range_args {
|
|||
#define BTRFS_MOUNT_INODE_MAP_CACHE (1 << 17)
|
||||
#define BTRFS_MOUNT_RECOVERY (1 << 18)
|
||||
#define BTRFS_MOUNT_SKIP_BALANCE (1 << 19)
|
||||
#define BTRFS_MOUNT_CHECK_INTEGRITY (1 << 20)
|
||||
#define BTRFS_MOUNT_CHECK_INTEGRITY_INCLUDING_EXTENT_DATA (1 << 21)
|
||||
|
||||
#define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt)
|
||||
#define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt)
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "tree-log.h"
|
||||
#include "free-space-cache.h"
|
||||
#include "inode-map.h"
|
||||
#include "check-integrity.h"
|
||||
|
||||
static struct extent_io_ops btree_extent_io_ops;
|
||||
static void end_workqueue_fn(struct btrfs_work *work);
|
||||
|
@ -2002,6 +2003,9 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
|||
init_waitqueue_head(&fs_info->scrub_pause_wait);
|
||||
init_rwsem(&fs_info->scrub_super_lock);
|
||||
fs_info->scrub_workers_refcnt = 0;
|
||||
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
|
||||
fs_info->check_integrity_print_mask = 0;
|
||||
#endif
|
||||
|
||||
spin_lock_init(&fs_info->balance_lock);
|
||||
mutex_init(&fs_info->balance_mutex);
|
||||
|
@ -2360,6 +2364,19 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
|||
btrfs_set_opt(fs_info->mount_opt, SSD);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
|
||||
if (btrfs_test_opt(tree_root, CHECK_INTEGRITY)) {
|
||||
ret = btrfsic_mount(tree_root, fs_devices,
|
||||
btrfs_test_opt(tree_root,
|
||||
CHECK_INTEGRITY_INCLUDING_EXTENT_DATA) ?
|
||||
1 : 0,
|
||||
fs_info->check_integrity_print_mask);
|
||||
if (ret)
|
||||
printk(KERN_WARNING "btrfs: failed to initialize"
|
||||
" integrity check module %s\n", sb->s_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* do not make disk changes in broken FS */
|
||||
if (btrfs_super_log_root(disk_super) != 0 &&
|
||||
!(fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)) {
|
||||
|
@ -2642,7 +2659,7 @@ static int write_dev_supers(struct btrfs_device *device,
|
|||
* we fua the first super. The others we allow
|
||||
* to go down lazy.
|
||||
*/
|
||||
ret = submit_bh(WRITE_FUA, bh);
|
||||
ret = btrfsic_submit_bh(WRITE_FUA, bh);
|
||||
if (ret)
|
||||
errors++;
|
||||
}
|
||||
|
@ -2719,7 +2736,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait)
|
|||
device->flush_bio = bio;
|
||||
|
||||
bio_get(bio);
|
||||
submit_bio(WRITE_FLUSH, bio);
|
||||
btrfsic_submit_bio(WRITE_FLUSH, bio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3068,6 +3085,11 @@ int close_ctree(struct btrfs_root *root)
|
|||
btrfs_stop_workers(&fs_info->caching_workers);
|
||||
btrfs_stop_workers(&fs_info->readahead_workers);
|
||||
|
||||
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
|
||||
if (btrfs_test_opt(root, CHECK_INTEGRITY))
|
||||
btrfsic_unmount(root, fs_info->fs_devices);
|
||||
#endif
|
||||
|
||||
btrfs_close_devices(fs_info->fs_devices);
|
||||
btrfs_mapping_tree_free(&fs_info->mapping_tree);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "ctree.h"
|
||||
#include "btrfs_inode.h"
|
||||
#include "volumes.h"
|
||||
#include "check-integrity.h"
|
||||
|
||||
static struct kmem_cache *extent_state_cache;
|
||||
static struct kmem_cache *extent_buffer_cache;
|
||||
|
@ -1895,7 +1896,7 @@ int repair_io_failure(struct btrfs_mapping_tree *map_tree, u64 start,
|
|||
}
|
||||
bio->bi_bdev = dev->bdev;
|
||||
bio_add_page(bio, page, length, start-page_offset(page));
|
||||
submit_bio(WRITE_SYNC, bio);
|
||||
btrfsic_submit_bio(WRITE_SYNC, bio);
|
||||
wait_for_completion(&compl);
|
||||
|
||||
if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
|
||||
|
@ -2393,7 +2394,7 @@ static int submit_one_bio(int rw, struct bio *bio, int mirror_num,
|
|||
ret = tree->ops->submit_bio_hook(page->mapping->host, rw, bio,
|
||||
mirror_num, bio_flags, start);
|
||||
else
|
||||
submit_bio(rw, bio);
|
||||
btrfsic_submit_bio(rw, bio);
|
||||
|
||||
if (bio_flagged(bio, BIO_EOPNOTSUPP))
|
||||
ret = -EOPNOTSUPP;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "transaction.h"
|
||||
#include "backref.h"
|
||||
#include "extent_io.h"
|
||||
#include "check-integrity.h"
|
||||
|
||||
/*
|
||||
* This is only the first step towards a full-features scrub. It reads all
|
||||
|
@ -733,7 +734,7 @@ static int scrub_fixup_io(int rw, struct block_device *bdev, sector_t sector,
|
|||
bio_add_page(bio, page, PAGE_SIZE, 0);
|
||||
bio->bi_end_io = scrub_fixup_end_io;
|
||||
bio->bi_private = &complete;
|
||||
submit_bio(rw, bio);
|
||||
btrfsic_submit_bio(rw, bio);
|
||||
|
||||
/* this will also unplug the queue */
|
||||
wait_for_completion(&complete);
|
||||
|
@ -959,7 +960,7 @@ static int scrub_submit(struct scrub_dev *sdev)
|
|||
sdev->curr = -1;
|
||||
atomic_inc(&sdev->in_flight);
|
||||
|
||||
submit_bio(READ, sbio->bio);
|
||||
btrfsic_submit_bio(READ, sbio->bio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -166,6 +166,8 @@ enum {
|
|||
Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed,
|
||||
Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_inode_cache,
|
||||
Opt_no_space_cache, Opt_recovery, Opt_skip_balance,
|
||||
Opt_check_integrity, Opt_check_integrity_including_extent_data,
|
||||
Opt_check_integrity_print_mask,
|
||||
Opt_err,
|
||||
};
|
||||
|
||||
|
@ -202,6 +204,9 @@ static match_table_t tokens = {
|
|||
{Opt_no_space_cache, "nospace_cache"},
|
||||
{Opt_recovery, "recovery"},
|
||||
{Opt_skip_balance, "skip_balance"},
|
||||
{Opt_check_integrity, "check_int"},
|
||||
{Opt_check_integrity_including_extent_data, "check_int_data"},
|
||||
{Opt_check_integrity_print_mask, "check_int_print_mask=%d"},
|
||||
{Opt_err, NULL},
|
||||
};
|
||||
|
||||
|
@ -403,6 +408,37 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
|
|||
case Opt_skip_balance:
|
||||
btrfs_set_opt(info->mount_opt, SKIP_BALANCE);
|
||||
break;
|
||||
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
|
||||
case Opt_check_integrity_including_extent_data:
|
||||
printk(KERN_INFO "btrfs: enabling check integrity"
|
||||
" including extent data\n");
|
||||
btrfs_set_opt(info->mount_opt,
|
||||
CHECK_INTEGRITY_INCLUDING_EXTENT_DATA);
|
||||
btrfs_set_opt(info->mount_opt, CHECK_INTEGRITY);
|
||||
break;
|
||||
case Opt_check_integrity:
|
||||
printk(KERN_INFO "btrfs: enabling check integrity\n");
|
||||
btrfs_set_opt(info->mount_opt, CHECK_INTEGRITY);
|
||||
break;
|
||||
case Opt_check_integrity_print_mask:
|
||||
intarg = 0;
|
||||
match_int(&args[0], &intarg);
|
||||
if (intarg) {
|
||||
info->check_integrity_print_mask = intarg;
|
||||
printk(KERN_INFO "btrfs:"
|
||||
" check_integrity_print_mask 0x%x\n",
|
||||
info->check_integrity_print_mask);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case Opt_check_integrity_including_extent_data:
|
||||
case Opt_check_integrity:
|
||||
case Opt_check_integrity_print_mask:
|
||||
printk(KERN_ERR "btrfs: support for check_integrity*"
|
||||
" not compiled in!\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
#endif
|
||||
case Opt_err:
|
||||
printk(KERN_INFO "btrfs: unrecognized mount option "
|
||||
"'%s'\n", p);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "print-tree.h"
|
||||
#include "volumes.h"
|
||||
#include "async-thread.h"
|
||||
#include "check-integrity.h"
|
||||
|
||||
static int init_first_rw_device(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
|
@ -247,7 +248,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
|
|||
sync_pending = 0;
|
||||
}
|
||||
|
||||
submit_bio(cur->bi_rw, cur);
|
||||
btrfsic_submit_bio(cur->bi_rw, cur);
|
||||
num_run++;
|
||||
batch_run++;
|
||||
if (need_resched())
|
||||
|
@ -3962,7 +3963,7 @@ static noinline int schedule_bio(struct btrfs_root *root,
|
|||
/* don't bother with additional async steps for reads, right now */
|
||||
if (!(rw & REQ_WRITE)) {
|
||||
bio_get(bio);
|
||||
submit_bio(rw, bio);
|
||||
btrfsic_submit_bio(rw, bio);
|
||||
bio_put(bio);
|
||||
return 0;
|
||||
}
|
||||
|
@ -4057,7 +4058,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
|
|||
if (async_submit)
|
||||
schedule_bio(root, dev, rw, bio);
|
||||
else
|
||||
submit_bio(rw, bio);
|
||||
btrfsic_submit_bio(rw, bio);
|
||||
} else {
|
||||
bio->bi_bdev = root->fs_info->fs_devices->latest_bdev;
|
||||
bio->bi_sector = logical >> 9;
|
||||
|
|
Loading…
Reference in a new issue