Re: [PATCH 1/3] btrfs: init devices always
On Fri, Mar 12, 2021 at 01:57:32PM +0800, Anand Jain wrote: > > > On 12/3/21 1:52 pm, Anand Jain wrote: > > On 12/3/21 12:23 am, Josef Bacik wrote: > >> Neal reported a panic trying to use -o rescue=all > >> > >> BUG: kernel NULL pointer dereference, address: 0030 > >> PGD 0 P4D 0 > >> Oops: [#1] SMP NOPTI > >> CPU: 0 PID: 696 Comm: mount Tainted: G W 5.12.0-rc2+ #296 > >> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 > >> 04/01/2014 > >> RIP: 0010:btrfs_device_init_dev_stats+0x1d/0x200 > >> RSP: 0018:afaec1483bb8 EFLAGS: 00010286 > >> RAX: RBX: 9a5715bcb298 RCX: 0070 > >> RDX: 9a5703248000 RSI: 9a57052ea150 RDI: 9a5715bca400 > >> RBP: 9a57052ea150 R08: 0070 R09: 9a57052ea150 > >> R10: 000130faf0741c10 R11: R12: 9a570370 > >> R13: R14: 9a5715bcb278 R15: 9a57052ea150 > >> FS: 7f600d122c40() GS:9a577bc0() > >> knlGS: > >> CS: 0010 DS: ES: CR0: 80050033 > >> CR2: 0030 CR3: 000112a46005 CR4: 00370ef0 > >> Call Trace: > >> ? btrfs_init_dev_stats+0x1f/0xf0 > >> ? kmem_cache_alloc+0xef/0x1f0 > >> btrfs_init_dev_stats+0x5f/0xf0 > >> open_ctree+0x10cb/0x1720 > >> btrfs_mount_root.cold+0x12/0xea > >> legacy_get_tree+0x27/0x40 > >> vfs_get_tree+0x25/0xb0 > >> vfs_kern_mount.part.0+0x71/0xb0 > >> btrfs_mount+0x10d/0x380 > >> legacy_get_tree+0x27/0x40 > >> vfs_get_tree+0x25/0xb0 > >> path_mount+0x433/0xa00 > >> __x64_sys_mount+0xe3/0x120 > >> do_syscall_64+0x33/0x40 > >> entry_SYSCALL_64_after_hwframe+0x44/0xae > >> > >> This happens because when we call btrfs_init_dev_stats we do > >> device->fs_info->dev_root. However device->fs_info isn't init'ed > >> because we were only calling btrfs_init_devices_late() if we properly > >> read the device root. > > > > > >> However we don't actually need the device root to > >> init the devices, this function simply assigns the devices their > >> ->fs_info pointer properly, so this needs to be done unconditionally > >> always so that we can properly deref device->fs_info in rescue cases. > > > > btrfs_device_init_dev_stats() calls btrfs_search_slot() leading > > to btrfs_search_slot_get_root(), and does de-reference root (dev_root) > > to get fs_info. > > Never mind. patch 2/3 handles it. Spoke too early. > Maybe can reorder the patches during integration. I think swapping the order makes sense, though all the patches fix some sort of crash, the number should be decreasing.
Re: [PATCH 1/3] btrfs: init devices always
On 12/3/21 12:23 am, Josef Bacik wrote: Neal reported a panic trying to use -o rescue=all BUG: kernel NULL pointer dereference, address: 0030 PGD 0 P4D 0 Oops: [#1] SMP NOPTI CPU: 0 PID: 696 Comm: mount Tainted: GW 5.12.0-rc2+ #296 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014 RIP: 0010:btrfs_device_init_dev_stats+0x1d/0x200 RSP: 0018:afaec1483bb8 EFLAGS: 00010286 RAX: RBX: 9a5715bcb298 RCX: 0070 RDX: 9a5703248000 RSI: 9a57052ea150 RDI: 9a5715bca400 RBP: 9a57052ea150 R08: 0070 R09: 9a57052ea150 R10: 000130faf0741c10 R11: R12: 9a570370 R13: R14: 9a5715bcb278 R15: 9a57052ea150 FS: 7f600d122c40() GS:9a577bc0() knlGS: CS: 0010 DS: ES: CR0: 80050033 CR2: 0030 CR3: 000112a46005 CR4: 00370ef0 Call Trace: ? btrfs_init_dev_stats+0x1f/0xf0 ? kmem_cache_alloc+0xef/0x1f0 btrfs_init_dev_stats+0x5f/0xf0 open_ctree+0x10cb/0x1720 btrfs_mount_root.cold+0x12/0xea legacy_get_tree+0x27/0x40 vfs_get_tree+0x25/0xb0 vfs_kern_mount.part.0+0x71/0xb0 btrfs_mount+0x10d/0x380 legacy_get_tree+0x27/0x40 vfs_get_tree+0x25/0xb0 path_mount+0x433/0xa00 __x64_sys_mount+0xe3/0x120 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae This happens because when we call btrfs_init_dev_stats we do device->fs_info->dev_root. However device->fs_info isn't init'ed because we were only calling btrfs_init_devices_late() if we properly read the device root. However we don't actually need the device root to init the devices, this function simply assigns the devices their ->fs_info pointer properly, so this needs to be done unconditionally always so that we can properly deref device->fs_info in rescue cases. Reported-by: Neal Gompa Signed-off-by: Josef Bacik Reviewed-by: Anand Jain
Re: [PATCH 1/3] btrfs: init devices always
On 12/3/21 1:52 pm, Anand Jain wrote: On 12/3/21 12:23 am, Josef Bacik wrote: Neal reported a panic trying to use -o rescue=all BUG: kernel NULL pointer dereference, address: 0030 PGD 0 P4D 0 Oops: [#1] SMP NOPTI CPU: 0 PID: 696 Comm: mount Tainted: G W 5.12.0-rc2+ #296 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014 RIP: 0010:btrfs_device_init_dev_stats+0x1d/0x200 RSP: 0018:afaec1483bb8 EFLAGS: 00010286 RAX: RBX: 9a5715bcb298 RCX: 0070 RDX: 9a5703248000 RSI: 9a57052ea150 RDI: 9a5715bca400 RBP: 9a57052ea150 R08: 0070 R09: 9a57052ea150 R10: 000130faf0741c10 R11: R12: 9a570370 R13: R14: 9a5715bcb278 R15: 9a57052ea150 FS: 7f600d122c40() GS:9a577bc0() knlGS: CS: 0010 DS: ES: CR0: 80050033 CR2: 0030 CR3: 000112a46005 CR4: 00370ef0 Call Trace: ? btrfs_init_dev_stats+0x1f/0xf0 ? kmem_cache_alloc+0xef/0x1f0 btrfs_init_dev_stats+0x5f/0xf0 open_ctree+0x10cb/0x1720 btrfs_mount_root.cold+0x12/0xea legacy_get_tree+0x27/0x40 vfs_get_tree+0x25/0xb0 vfs_kern_mount.part.0+0x71/0xb0 btrfs_mount+0x10d/0x380 legacy_get_tree+0x27/0x40 vfs_get_tree+0x25/0xb0 path_mount+0x433/0xa00 __x64_sys_mount+0xe3/0x120 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae This happens because when we call btrfs_init_dev_stats we do device->fs_info->dev_root. However device->fs_info isn't init'ed because we were only calling btrfs_init_devices_late() if we properly read the device root. However we don't actually need the device root to init the devices, this function simply assigns the devices their ->fs_info pointer properly, so this needs to be done unconditionally always so that we can properly deref device->fs_info in rescue cases. btrfs_device_init_dev_stats() calls btrfs_search_slot() leading to btrfs_search_slot_get_root(), and does de-reference root (dev_root) to get fs_info. Never mind. patch 2/3 handles it. Spoke too early. Maybe can reorder the patches during integration. -Anand - static int btrfs_device_init_dev_stats(struct btrfs_device *device, struct btrfs_path *path) :: ret = btrfs_search_slot(NULL, device->fs_info->dev_root, &key, path, 0, 0); int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, ...) :: b = btrfs_search_slot_get_root(root, p, write_lock_level); static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root, ...) { struct btrfs_fs_info *fs_info = root->fs_info; -- Can we allocate a dummy dev_root and set its dev_root::fs_info? Thanks, Anand Reported-by: Neal Gompa Signed-off-by: Josef Bacik --- fs/btrfs/disk-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 41b718cfea40..63656bf23ff2 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2387,8 +2387,8 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info) } else { set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state); fs_info->dev_root = root; - btrfs_init_devices_late(fs_info); } + btrfs_init_devices_late(fs_info); /* If IGNOREDATACSUMS is set don't bother reading the csum root. */ if (!btrfs_test_opt(fs_info, IGNOREDATACSUMS)) {
Re: [PATCH 1/3] btrfs: init devices always
On 12/3/21 12:23 am, Josef Bacik wrote: Neal reported a panic trying to use -o rescue=all BUG: kernel NULL pointer dereference, address: 0030 PGD 0 P4D 0 Oops: [#1] SMP NOPTI CPU: 0 PID: 696 Comm: mount Tainted: GW 5.12.0-rc2+ #296 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014 RIP: 0010:btrfs_device_init_dev_stats+0x1d/0x200 RSP: 0018:afaec1483bb8 EFLAGS: 00010286 RAX: RBX: 9a5715bcb298 RCX: 0070 RDX: 9a5703248000 RSI: 9a57052ea150 RDI: 9a5715bca400 RBP: 9a57052ea150 R08: 0070 R09: 9a57052ea150 R10: 000130faf0741c10 R11: R12: 9a570370 R13: R14: 9a5715bcb278 R15: 9a57052ea150 FS: 7f600d122c40() GS:9a577bc0() knlGS: CS: 0010 DS: ES: CR0: 80050033 CR2: 0030 CR3: 000112a46005 CR4: 00370ef0 Call Trace: ? btrfs_init_dev_stats+0x1f/0xf0 ? kmem_cache_alloc+0xef/0x1f0 btrfs_init_dev_stats+0x5f/0xf0 open_ctree+0x10cb/0x1720 btrfs_mount_root.cold+0x12/0xea legacy_get_tree+0x27/0x40 vfs_get_tree+0x25/0xb0 vfs_kern_mount.part.0+0x71/0xb0 btrfs_mount+0x10d/0x380 legacy_get_tree+0x27/0x40 vfs_get_tree+0x25/0xb0 path_mount+0x433/0xa00 __x64_sys_mount+0xe3/0x120 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae This happens because when we call btrfs_init_dev_stats we do device->fs_info->dev_root. However device->fs_info isn't init'ed because we were only calling btrfs_init_devices_late() if we properly read the device root. However we don't actually need the device root to init the devices, this function simply assigns the devices their ->fs_info pointer properly, so this needs to be done unconditionally always so that we can properly deref device->fs_info in rescue cases. btrfs_device_init_dev_stats() calls btrfs_search_slot() leading to btrfs_search_slot_get_root(), and does de-reference root (dev_root) to get fs_info. - static int btrfs_device_init_dev_stats(struct btrfs_device *device, struct btrfs_path *path) :: ret = btrfs_search_slot(NULL, device->fs_info->dev_root, &key, path, 0, 0); int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, ...) :: b = btrfs_search_slot_get_root(root, p, write_lock_level); static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root, ...) { struct btrfs_fs_info *fs_info = root->fs_info; -- Can we allocate a dummy dev_root and set its dev_root::fs_info? Thanks, Anand Reported-by: Neal Gompa Signed-off-by: Josef Bacik --- fs/btrfs/disk-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 41b718cfea40..63656bf23ff2 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2387,8 +2387,8 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info) } else { set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state); fs_info->dev_root = root; - btrfs_init_devices_late(fs_info); } + btrfs_init_devices_late(fs_info); /* If IGNOREDATACSUMS is set don't bother reading the csum root. */ if (!btrfs_test_opt(fs_info, IGNOREDATACSUMS)) {