From: Tsutomu Itoh <t-itoh@jp.fujitsu.com>
To: Chris Mason <chris.mason@oracle.com>
Cc: miaox <miaox@cn.fujitsu.com>, David Sterba <dave@jikos.cz>,
linux-btrfs <linux-btrfs@vger.kernel.org>
Subject: Re: please review snapshot corruption path with delayed metadata insertion
Date: Fri, 08 Jul 2011 13:50:01 +0900 [thread overview]
Message-ID: <4E168C79.2070903@jp.fujitsu.com> (raw)
In-Reply-To: <1310070350-sup-5716@shiny>
Hi, Chris,
(2011/07/08 5:26), Chris Mason wrote:
> Excerpts from Tsutomu Itoh's message of 2011-07-01 04:11:28 -0400:
>> Hi, Miao,
>>
>> (2011/06/30 15:32), Miao Xie wrote:
>>> Hi, Itoh-san
>>>
>>> Could you test the following patch to check whether it can fix the bug or not?
>>> I have tested it on my x86_64 machine by your test script for two days, it worked well.
>>
>> I ran my test script about a day, I was not able to reproduce this BUG.
>
> Can you please try this patch with the inode_cache option (in addition
> to Miao's code).
Unfortunately, I encountered following panic.
=============================================================================
btrfs: relocating block group 17746100224 flags 20
btrfs: relocating block group 12377391104 flags 9
btrfs: found 4181 extents
------------[ cut here ]------------
kernel BUG at fs/btrfs/relocation.c:2502!
invalid opcode: 0000 [#1] SMP
last sysfs file: /sys/kernel/mm/ksm/run
CPU 0
Modules linked in: btrfs zlib_deflate crc32c libcrc32c autofs4 sunrpc 8021q garp stp llc cpufreq_ondemand acpi_cpufreq freq_table mperf ipv6 ext3 jbd dm_mirror dm_region_hash dm_log dm_mod kvm uinput ppdev parport_pc parport sg pcspkr i2c_i801 i2c_core iTCO_wdt iTCO_vendor_support tg3 shpchp pci_hotplug i3000_edac edac_core ext4 mbcache jbd2 crc16 sd_mod crc_t10dif sr_mod cdrom megaraid_sas pata_acpi ata_generic ata_piix libata scsi_mod floppy [last unloaded: microcode]
Pid: 26214, comm: btrfs Not tainted 2.6.39btrfs-test5+ #2 FUJITSU-SV PRIMERGY /D2399
RIP: 0010:[<ffffffffa04a98f2>] [<ffffffffa04a98f2>] do_relocation+0x562/0x590 [btrfs]
RSP: 0018:ffff8801622519a8 EFLAGS: 00010202
RAX: 0000000000000001 RBX: ffff8800d2754140 RCX: 0000000000000001
RDX: 0000000000000000 RSI: ffff880000000000 RDI: 0000000000000000
RBP: ffff880162251a78 R08: 0000000000000000 R09: 00000000000002e9
R10: 0000000000000000 R11: 0000000000000026 R12: ffff880161f2fb40
R13: ffff8800cd81eac0 R14: ffff880080038000 R15: 0000000000000000
FS: 00007f4081d05740(0000) GS:ffff88019fc00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 00000033cfea6a60 CR3: 000000015d345000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process btrfs (pid: 26214, threadinfo ffff880162250000, task ffff880161c3eab0)
Stack:
ffff880191f006d0 ffff8800cd81eac0 ffff880191f005b0 ffff8800cd81eb00
ffff88016225b000 ffff8800777779e0 0000000162251a48 ffff880162250000
ffff880162251a78 ffff880193a26930 0000000100251a78 ffff880193a26930
Call Trace:
[<ffffffffa044abeb>] ? block_rsv_add_bytes+0x2b/0x70 [btrfs]
[<ffffffffa04ab1ab>] relocate_tree_blocks+0x62b/0x6e0 [btrfs]
[<ffffffffa0484928>] ? read_extent_buffer+0xd8/0x1d0 [btrfs]
[<ffffffffa04ac3d3>] ? add_data_references+0x263/0x280 [btrfs]
[<ffffffffa04ac662>] relocate_block_group+0x272/0x620 [btrfs]
[<ffffffffa04acbc3>] btrfs_relocate_block_group+0x1b3/0x2e0 [btrfs]
[<ffffffffa0496000>] ? btrfs_tree_unlock+0x50/0x50 [btrfs]
[<ffffffffa048b4eb>] btrfs_relocate_chunk+0x8b/0x670 [btrfs]
[<ffffffffa04400ed>] ? btrfs_set_path_blocking+0x3d/0x50 [btrfs]
[<ffffffffa0484928>] ? read_extent_buffer+0xd8/0x1d0 [btrfs]
[<ffffffffa0448f51>] ? btrfs_previous_item+0xb1/0x150 [btrfs]
[<ffffffffa0484928>] ? read_extent_buffer+0xd8/0x1d0 [btrfs]
[<ffffffffa048c6fa>] btrfs_balance+0x21a/0x2a0 [btrfs]
[<ffffffff8115dc41>] ? path_openat+0x101/0x3d0
[<ffffffffa04959d8>] btrfs_ioctl+0x798/0xd20 [btrfs]
[<ffffffff8111e358>] ? handle_mm_fault+0x148/0x270
[<ffffffff814809e8>] ? do_page_fault+0x1d8/0x4b0
[<ffffffff81160d6a>] do_vfs_ioctl+0x9a/0x540
[<ffffffff811612b1>] sys_ioctl+0xa1/0xb0
[<ffffffff81484ec2>] system_call_fastpath+0x16/0x1b
Code: 0f 0b 0f 1f 80 00 00 00 00 eb f7 0f 0b eb fe 0f 0b 0f 1f 84 00 00 00 00 00 eb f6 0f 0b eb fe 0f 0b 0f 1f 84 00 00 00 00 00 eb f6 <0f> 0b eb fe 48 83 7a 68 00 0f 1f 44 00 00 0f 84 d2 fa ff ff 0f
RIP [<ffffffffa04a98f2>] do_relocation+0x562/0x590 [btrfs]
RSP <ffff8801622519a8>
(gdb) l *do_relocation+0x562
0x6f922 is in do_relocation (fs/btrfs/relocation.c:2502).
2497 ret = btrfs_search_slot(trans, root, key, path, 0, 1);
2498 if (ret < 0) {
2499 err = ret;
2500 break;
2501 }
2502 BUG_ON(ret > 0);
2503
2504 if (!upper->eb) {
2505 upper->eb = path->nodes[upper->level];
2506 path->nodes[upper->level] = NULL;
(gdb)
>
> commit d0243d46f7a1e4cd57c74fa14556be65b454687d
> Author: Chris Mason <chris.mason@oracle.com>
> Date: Thu Jul 7 15:53:12 2011 -0400
>
> Btrfs: write out free inode cache before taking snapshots
>
> The btrfs snapshotting code requires that once a root has been
> snapshotted, we don't change it during a commit
>
> But the free inode cache was changing the roots when it root the cache,
> which lead to corruptions.
>
> This fixes things by making sure we write the cache while we are taking
> the snapshot, and that we don't write it again later.
>
> Signed-off-by: Chris Mason <chris.mason@oracle.com>
>
> diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> index bf0d615..d594cf7 100644
> --- a/fs/btrfs/free-space-cache.c
> +++ b/fs/btrfs/free-space-cache.c
> @@ -1651,6 +1651,7 @@ int __btrfs_add_free_space(struct btrfs_free_space_ctl *ctl,
> info->bytes = bytes;
>
> spin_lock(&ctl->tree_lock);
> + ctl->dirty = 1;
>
> if (try_merge_free_space(ctl, info, true))
> goto link;
> @@ -1691,6 +1692,7 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
> int ret = 0;
>
> spin_lock(&ctl->tree_lock);
> + ctl->dirty = 1;
>
> again:
> info = tree_search_offset(ctl, offset, 0, 0);
> @@ -2589,6 +2591,7 @@ u64 btrfs_find_ino_for_alloc(struct btrfs_root *fs_root)
> if (entry->bytes == 0)
> free_bitmap(ctl, entry);
> }
> + ctl->dirty = 1;
> out:
> spin_unlock(&ctl->tree_lock);
>
> @@ -2688,6 +2691,10 @@ int btrfs_write_out_ino_cache(struct btrfs_root *root,
> printk(KERN_ERR "btrfs: failed to write free ino cache "
> "for root %llu\n", root->root_key.objectid);
>
> + /* we write out at transaction commit time, there's no racing. */
> + if (ret == 0)
> + ctl->dirty = 0;
> +
> iput(inode);
> return ret;
> }
> diff --git a/fs/btrfs/free-space-cache.h b/fs/btrfs/free-space-cache.h
> index 8f2613f..1e92c93 100644
> --- a/fs/btrfs/free-space-cache.h
> +++ b/fs/btrfs/free-space-cache.h
> @@ -35,6 +35,11 @@ struct btrfs_free_space_ctl {
> int free_extents;
> int total_bitmaps;
> int unit;
> + /*
> + * record if we've changed since written. This can turn
> + * into a bit field if we need more flags
> + */
> + unsigned long dirty;
> u64 start;
> struct btrfs_free_space_op *op;
> void *private;
> diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c
> index b4087e0..e7c1493 100644
> --- a/fs/btrfs/inode-map.c
> +++ b/fs/btrfs/inode-map.c
> @@ -376,6 +376,7 @@ void btrfs_init_free_ino_ctl(struct btrfs_root *root)
> ctl->start = 0;
> ctl->private = NULL;
> ctl->op = &free_ino_op;
> + ctl->dirty = 1;
>
> /*
> * Initially we allow to use 16K of ram to cache chunks of
> @@ -417,6 +418,9 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
> if (!btrfs_test_opt(root, INODE_MAP_CACHE))
> return 0;
>
> + if (!ctl->dirty)
> + return 0;
> +
> path = btrfs_alloc_path();
> if (!path)
> return -ENOMEM;
> @@ -485,6 +489,24 @@ out:
> return ret;
> }
>
> +/*
> + * this tries to save the cache, but if it fails for any reason we clear
> + * the dirty flag so that it won't be saved again during this commit.
> + *
> + * This is used by the snapshotting code to make sure we don't corrupt the
> + * FS by saving the inode cache after the snapshot is taken.
> + */
> +int btrfs_force_save_ino_cache(struct btrfs_root *root,
> + struct btrfs_trans_handle *trans)
> +{
> + struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
> + int ret;
> + ret = btrfs_save_ino_cache(root, trans);
> +
> + ctl->dirty = 0;
> + return ret;
> +}
> +
> static int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid)
> {
> struct btrfs_path *path;
> diff --git a/fs/btrfs/inode-map.h b/fs/btrfs/inode-map.h
> index ddb347b..2be060e 100644
> --- a/fs/btrfs/inode-map.h
> +++ b/fs/btrfs/inode-map.h
> @@ -7,7 +7,8 @@ void btrfs_return_ino(struct btrfs_root *root, u64 objectid);
> int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid);
> int btrfs_save_ino_cache(struct btrfs_root *root,
> struct btrfs_trans_handle *trans);
> -
> +int btrfs_force_save_ino_cache(struct btrfs_root *root,
> + struct btrfs_trans_handle *trans);
> int btrfs_find_free_objectid(struct btrfs_root *root, u64 *objectid);
>
> #endif
> diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
> index 51dcec8..e34827c 100644
> --- a/fs/btrfs/transaction.c
> +++ b/fs/btrfs/transaction.c
> @@ -966,6 +966,15 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
> ret = btrfs_run_delayed_items(trans, root);
> BUG_ON(ret);
>
> + /*
> + * there are a few transient reasons the free inode cache writeback can fail.
> + * and if it does, we'll try again later in the commit. This forces the
> + * clean bit, tossing the cache. Tossing the cache isn't really good, but
> + * if we try to write it again later in the commit we'll corrupt things.
> + */
> + btrfs_force_save_ino_cache(parent_root, trans);
> +
> +
> record_root_in_trans(trans, root);
> btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
> memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
>
next prev parent reply other threads:[~2011-07-08 4:50 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-17 21:12 please review snapshot corruption path with delayed metadata insertion Chris Mason
2011-06-19 4:34 ` Tsutomu Itoh
2011-06-19 23:41 ` Tsutomu Itoh
2011-06-21 0:24 ` David Sterba
2011-06-21 0:40 ` Chris Mason
2011-06-21 1:15 ` Tsutomu Itoh
2011-06-23 8:52 ` Miao Xie
2011-06-30 6:32 ` Miao Xie
2011-06-30 6:52 ` Tsutomu Itoh
2011-07-01 8:11 ` Tsutomu Itoh
2011-07-07 20:26 ` Chris Mason
2011-07-07 23:51 ` Tsutomu Itoh
2011-07-08 1:59 ` Chris Mason
2011-07-08 4:50 ` Tsutomu Itoh [this message]
2011-06-30 8:03 ` Miao Xie
2011-06-30 8:51 ` Miao Xie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4E168C79.2070903@jp.fujitsu.com \
--to=t-itoh@jp.fujitsu.com \
--cc=chris.mason@oracle.com \
--cc=dave@jikos.cz \
--cc=linux-btrfs@vger.kernel.org \
--cc=miaox@cn.fujitsu.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.