We weren't doing any of the accounting cleanup when we aborted
transactions. Fix this by making cleanup_ref_head_accounting global and
calling it from the abort code, this fixes the issue where our
accounting was all wrong after the fs aborts.
The test generic/475 on a 2G VM can trigger the problems eg.:
[ 8502.136957] WARNING: CPU: 0 PID: 11064 at fs/btrfs/extent-tree.c:5986 btrfs_free_block_grou +ps+0x3dc/0x410 [btrfs]
[ 8502.148372] CPU: 0 PID: 11064 Comm: umount Not tainted 5.0.0-rc1-default+ #394
[ 8502.150807] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.11.2-0-gf9626 +cc-prebuilt.qemu-project.org 04/01/2014
[ 8502.154317] RIP: 0010:btrfs_free_block_groups+0x3dc/0x410 [btrfs]
[ 8502.160623] RSP: 0018:
ffffb1ab84b93de8 EFLAGS:
00010206
[ 8502.161906] RAX:
0000000001000000 RBX:
ffff9f34b1756400 RCX:
0000000000000000
[ 8502.163448] RDX:
0000000000000002 RSI:
0000000000000001 RDI:
ffff9f34b1755400
[ 8502.164906] RBP:
ffff9f34b7e8c000 R08:
0000000000000001 R09:
0000000000000000
[ 8502.166716] R10:
0000000000000000 R11:
0000000000000001 R12:
ffff9f34b7e8c108
[ 8502.168498] R13:
ffff9f34b7e8c158 R14:
0000000000000000 R15:
dead000000000100
[ 8502.170296] FS:
00007fb1cf15ffc0(0000) GS:
ffff9f34bd400000(0000) knlGS:
0000000000000000
[ 8502.172439] CS: 0010 DS: 0000 ES: 0000 CR0:
0000000080050033
[ 8502.173669] CR2:
00007fb1ced507b0 CR3:
000000002f7a6000 CR4:
00000000000006f0
[ 8502.175094] Call Trace:
[ 8502.175759] close_ctree+0x17f/0x350 [btrfs]
[ 8502.176721] generic_shutdown_super+0x64/0x100
[ 8502.177702] kill_anon_super+0x14/0x30
[ 8502.178607] btrfs_kill_super+0x12/0xa0 [btrfs]
[ 8502.179602] deactivate_locked_super+0x29/0x60
[ 8502.180595] cleanup_mnt+0x3b/0x70
[ 8502.181406] task_work_run+0x98/0xc0
[ 8502.182255] exit_to_usermode_loop+0x83/0x90
[ 8502.183113] do_syscall_64+0x15b/0x180
[ 8502.183919] entry_SYSCALL_64_after_hwframe+0x49/0xbe
Corresponding to
release_global_block_rsv() {
...
WARN_ON(fs_info->delayed_refs_rsv.reserved > 0);
CC: stable@vger.kernel.org
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
[ add log dump ]
Signed-off-by: David Sterba <dsterba@suse.com>
struct btrfs_trans_handle;
struct btrfs_transaction;
struct btrfs_pending_snapshot;
+struct btrfs_delayed_ref_root;
extern struct kmem_cache *btrfs_trans_handle_cachep;
extern struct kmem_cache *btrfs_bit_radix_cachep;
extern struct kmem_cache *btrfs_path_cachep;
unsigned long count);
int btrfs_async_run_delayed_refs(struct btrfs_fs_info *fs_info,
unsigned long count, u64 transid, int wait);
+void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_root *delayed_refs,
+ struct btrfs_delayed_ref_head *head);
int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len);
int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 bytenr,
if (pin_bytes)
btrfs_pin_extent(fs_info, head->bytenr,
head->num_bytes, 1);
+ btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
btrfs_put_delayed_ref_head(head);
cond_resched();
spin_lock(&delayed_refs->lock);
return ret ? ret : 1;
}
-static void cleanup_ref_head_accounting(struct btrfs_trans_handle *trans,
- struct btrfs_delayed_ref_head *head)
+void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_root *delayed_refs,
+ struct btrfs_delayed_ref_head *head)
{
- struct btrfs_fs_info *fs_info = trans->fs_info;
- struct btrfs_delayed_ref_root *delayed_refs =
- &trans->transaction->delayed_refs;
int nr_items = 1; /* Dropping this ref head update. */
if (head->total_ref_mod < 0) {
}
}
- cleanup_ref_head_accounting(trans, head);
+ btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
trace_run_delayed_ref_head(fs_info, head, 0);
btrfs_delayed_ref_unlock(head);
if (head->must_insert_reserved)
ret = 1;
- cleanup_ref_head_accounting(trans, head);
+ btrfs_cleanup_ref_head_accounting(trans->fs_info, delayed_refs, head);
mutex_unlock(&head->mutex);
btrfs_put_delayed_ref_head(head);
return ret;