NVSL / linux-nova

NOVA is a log-structured file system designed for byte-addressable non-volatile memories, developed at the University of California, San Diego.
http://nvsl.ucsd.edu/index.php?path=projects/nova
Other
422 stars 117 forks source link

General protection fault with metadata_csum mode #115

Closed hayley-leblanc closed 2 years ago

hayley-leblanc commented 2 years ago

Hi,

I'm working with NOVA in metadata_csum mode on a QEMU/KVM virtual machine. Unmounting and remounting an instance of NOVA with this configuration is consistently leading to a general protection fault. The following is a trace obtained by mounting a fresh NOVA instance, immediately unmounting it, and then re-mounting it.

[   31.439366] ------------[ cut here ]------------
[   31.440266] General protection fault in user access. Non-canonical address?
[   31.440303] WARNING: CPU: 0 PID: 326 at arch/x86/mm/extable.c:125 ex_handler_uaccess+0x6a/0x70
[   31.442344] Modules linked in: nova(E)
[   31.442733] CPU: 0 PID: 326 Comm: mount Tainted: G            E     5.1.0+ #433
[   31.443504] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
[   31.444414] RIP: 0010:ex_handler_uaccess+0x6a/0x70
[   31.444910] Code: 41 5d 5d c3 e8 b7 4a 12 00 80 3d aa cc 76 01 00 75 d0 e8 a9 4a 12 00 48 c7 c7 b0 07 49 82 c6 05 95 cc 76 01 01 e8 56 58 02 00 <0f> 0b eb8
[   31.446750] RSP: 0018:ffffc90001d3f908 EFLAGS: 00010282
[   31.447273] RAX: 0000000000000000 RBX: ffffffff8200287c RCX: ffffffff8112b323
[   31.447983] RDX: 0000000000000000 RSI: ffffffff82b5f99f RDI: 0000000000000293
[   31.448696] RBP: ffffc90001d3f920 R08: 0000000a4e32c4ad R09: 000000000000003f
[   31.449402] R10: 0000000000000000 R11: 0000000000000000 R12: ffffc90001d3f998
[   31.450107] R13: 000000000000000d R14: 0000000000000000 R15: 0000000000000000
[   31.450813] FS:  00007f7ba9929e40(0000) GS:ffff888237e00000(0000) knlGS:0000000000000000
[   31.451612] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   31.452193] CR2: 00007ff7436db000 CR3: 00000002353da000 CR4: 00000000000006b0
[   31.452919] Call Trace:
[   31.453177]  fixup_exception+0x5a/0x80
[   31.453557]  do_general_protection+0x50/0x160
[   31.454002]  general_protection+0x1e/0x30
[   31.454411] RIP: 0010:__copy_user_nocache+0x41/0xf0
[   31.454903] Code: d9 29 ca 8a 06 88 07 48 ff c6 48 ff c7 ff c9 75 f2 89 d1 83 e2 3f c1 e9 06 74 52 4c 8b 06 4c 8b 4e 08 4c 8b 56 10 4c 8b 5e 18 <4c> 0f c36
[   31.456761] RSP: 0018:ffffc90001d3fa48 EFLAGS: 00010203
[   31.457323] RAX: ffff8882367dc140 RBX: ffff518101d3fb88 RCX: 0000000000000001
[   31.458029] RDX: 0000000000000038 RSI: ffff888100001180 RDI: ffff518101d3fb88
[   31.458736] RBP: ffffc90001d3fa68 R08: 0000000000000000 R09: 0000000000000000
[   31.459442] R10: 0000000000000000 R11: 0000000000000000 R12: ffff888100001180
[   31.460149] R13: 0000000000000078 R14: ffff8882352d7000 R15: ffff888233443000
[   31.460921]  ? memcpy_to_pmem_nocache+0x2f/0x36 [nova]
[   31.461439]  nova_free_inode_log+0x16d/0x338 [nova]
[   31.461931]  ? nova_insert_range_node+0x10d/0x11e [nova]
[   31.462466]  nova_init_blockmap_from_inode+0xd4/0x3da [nova]
[   31.463041]  ? crc32c+0x67/0xb0
[   31.463362]  ? xas_find_marked+0x18d/0x3e0
[   31.463778]  ? __switch_to_asm+0x34/0x70
[   31.464177]  ? __switch_to_asm+0x40/0x70
[   31.464583]  ? find_first_zero_bit+0x5e/0x90
[   31.465011]  ? find_first_zero_bit+0x5e/0x90
[   31.465443]  nova_recovery+0x47d/0xadd [nova]
[   31.465882]  ? nova_recovery+0x47d/0xadd [nova]
[   31.466337]  ? _cond_resched+0x19/0x40
[   31.466719]  ? __kmalloc+0x1fe/0x210
[   31.467083]  ? nova_lite_journal_soft_init+0x4e3/0x5a3 [nova]
[   31.467660]  nova_fill_super+0xcf9/0xf4b [nova]
[   31.468147]  mount_bdev+0x1cc/0x210
[   31.468564]  ? nova_init+0x81c/0x81c [nova]
[   31.468975]  nova_mount+0x39/0x42 [nova]
[   31.469365]  legacy_get_tree+0x2f/0x80
[   31.469732]  vfs_get_tree+0x35/0x140
[   31.470086]  do_mount+0x9a9/0x1150
[   31.470459]  ? memdup_user+0x63/0x90
[   31.470926]  ? copy_mount_options+0x192/0x2b0
[   31.471388]  ksys_mount+0xb0/0x120
[   31.471733]  __x64_sys_mount+0x2b/0x30
[   31.472111]  do_syscall_64+0x67/0x160
[   31.472496]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[   31.473004] RIP: 0033:0x7f7ba8fe748a
[   31.473369] Code: 48 8b 0d 11 fa 2a 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 018
[   31.475216] RSP: 002b:00007ffdede8e4b8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a5
[   31.475972] RAX: ffffffffffffffda RBX: 000055d3f9b76060 RCX: 00007f7ba8fe748a
[   31.476686] RDX: 000055d3f9b76240 RSI: 000055d3f9b76280 RDI: 000055d3f9b76260
[   31.477390] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000020
[   31.478094] R10: 00000000c0ed0000 R11: 0000000000000206 R12: 000055d3f9b76260
[   31.478800] R13: 000055d3f9b76240 R14: 0000000000000000 R15: 00000000ffffffff
[   31.479505] ---[ end trace 91599f8f056cc37f ]---

I believe the problem is that nova_init_blockmap_from_inode() defines a nova_inode_info_header but only fills in some of its fields. nova_free_inode_log(), which is called before nova_init_blockmap_from_inode() returns, attempts to dereference the alter_pi_addr field, which hasn't been set and can contain a bad pointer. Zeroing out the inode info header struct fixes the issue for me. I'll submit a PR soon.