From 298a8f9cf17d2f2e1ffc41e5e247fa3695a8a76f Mon Sep 17 00:00:00 2001 From: Wang Shilong Date: Thu, 19 Jun 2014 10:42:52 +0800 Subject: Btrfs: fix NULL pointer crash when running balance and scrub concurrently While running balance, scrub, fsstress concurrently we hit the following kernel crash: [56561.448845] BTRFS info (device sde): relocating block group 11005853696 flags 132 [56561.524077] BUG: unable to handle kernel NULL pointer dereference at 0000000000000078 [56561.524237] IP: [] scrub_chunk.isra.12+0xdd/0x130 [btrfs] [56561.524297] PGD 9be28067 PUD 7f3dd067 PMD 0 [56561.524325] Oops: 0000 [#1] SMP [....] [56561.527237] Call Trace: [56561.527309] [] scrub_enumerate_chunks+0x24e/0x490 [btrfs] [56561.527392] [] ? abort_exclusive_wait+0x50/0xb0 [56561.527476] [] btrfs_scrub_dev+0x1a4/0x530 [btrfs] [56561.527561] [] btrfs_ioctl+0x13f7/0x2a90 [btrfs] [56561.527639] [] do_vfs_ioctl+0x2e0/0x4c0 [56561.527712] [] ? vtime_account_user+0x54/0x60 [56561.527788] [] ? __audit_syscall_entry+0x9c/0xf0 [56561.527870] [] SyS_ioctl+0x81/0xa0 [56561.527941] [] tracesys+0xdd/0xe2 [...] [56561.528304] RIP [] scrub_chunk.isra.12+0xdd/0x130 [btrfs] [56561.528395] RSP [56561.528454] CR2: 0000000000000078 This is because in btrfs_relocate_chunk(), we will free @bdev directly while scrub may still hold extent mapping, and may access freed memory. Fix this problem by wrapping freeing @bdev work into free_extent_map() which is based on reference count. Reported-by: Qu Wenruo Signed-off-by: Wang Shilong Signed-off-by: Miao Xie Signed-off-by: Chris Mason --- fs/btrfs/extent_map.h | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/btrfs/extent_map.h') diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index e7fd8a5..b2991fd 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h @@ -15,6 +15,7 @@ #define EXTENT_FLAG_PREALLOC 3 /* pre-allocated extent */ #define EXTENT_FLAG_LOGGING 4 /* Logging this extent */ #define EXTENT_FLAG_FILLING 5 /* Filling in a preallocated extent */ +#define EXTENT_FLAG_FS_MAPPING 6 /* filesystem extent mapping type */ struct extent_map { struct rb_node rb_node; -- cgit v1.1