Description
Issue
In the function nova_init_inode_list_from_inode
, struct nova_inode_info_header sih
is not zero-out, leading to Read Fault in nova_free_inode_log
due to the memory copy from the primary inode to the alternative inode (invalid address).
On the contrary, in the function nova_init_blockmap_from_inode
, sih
is zero-out correctly and won't cause this issue.
Reproduce
Theoretically, umounting NOVA and then remounting it will trigger this issue due to the normal recovery. However, it depends on whether sih
is already zero-out when allocated on the stack.
In my tests, the remount after a fully umounting does not trigger this bug. It can only be triggered if the system crashes when blocknode
's log_head
and log_tail
is set (at Line 532 and 533 as the below code snippet shows). If log_head
and log_tail
is not set, NOVA will go to the failure recovery and does not init inode list from inode. Indeed, after Line 533, no other metadata/data will be persisted to the PM device. Have no idea why the crash leads to garbage numbers in sih
.
Lines 529 to 535 in 976a4d1
Reason
Lines 283 to 362 in 976a4d1
In this function, nova_init_inode_list_from_inode
, sih
is declared at Line 287 without zeroout. Then, sih
is used to free logs when calling nova_free_inode_log
at Line 360.
Lines 1409 to 1446 in 976a4d1
In this function, nova_free_inode_log
, alter_pi
will be synced with the primary inode, at Line 1428-1435, leading to Read Fault if alter_pi
has the garbage number.
Lines 196 to 210 in 976a4d1
In this function, nova_init_blockmap_from_inode
, on the contrary, sih
is zeroed out at Line 209. Thus, it won't cause Read Fault when freeing logs since if (alter_pi)
is false (at Line 1431 in nova_free_inode_log
).
Fix
Zeroing out sih
, so that the synchronization between the primary inode and the alternative inode won't be triggered since if (alter_pi)
is false (at Line 1431 in nova_free_inode_log
).
// zero out sih at Line 298 in function `nova_init_inode_list_from_inode`.
memset(&sih, 0, sizeof(struct nova_inode_info_header));