mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
writeback: Fix NULL pointer dereference issue with inode->i_wb
There is a potential race between evict() and __mark_inode_dirty() observed with EXT4 FS. The ext4/jbd2 context is marking the inode as dirty while at the same time evict() is happening on another core. Due to this race, __mark_inode_dirty() is adding the inode to bdi_writeback IO dirty list, after evict() path has removed this inode from the writeback list. This results NULL pointer dereference issue when accessing inode->i_wb from writeback thread as below - locked_inode_to_wb_and_lock_list+0x2c/0x2a0 inode_to_wb_and_lock_list+0x24/0x30 writeback_sb_inodes+0x2cc/0x444 __writeback_inodes_wb+0x78/0xbc wb_writeback+0x1c8/0x3d0 wb_workfn+0x1a8/0x4d4 process_one_work+0x1c0/0x3d4 worker_thread+0x224/0x344 kthread+0x120/0x130 ret_from_fork+0x10/0x18 Fix this by checking for the inode->i_state I_WILL_FREE or I_FREEING before and after adding to the writeback list. If it is observed to be in freeing path before adding, then simply return. If it is after adding to the writeback list, then remove this inode from the writeback list in __mark_inode_dirty() context itself. Change-Id: I1e5f15d81dae01f0dd7a108b1861adc83105ed7b Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
This commit is contained in:
parent
44b48b1070
commit
0f5052ff8d
@ -2187,7 +2187,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
|
||||
if (inode_unhashed(inode))
|
||||
goto out_unlock_inode;
|
||||
}
|
||||
if (inode->i_state & I_FREEING)
|
||||
if (inode->i_state & (I_WILL_FREE | I_FREEING))
|
||||
goto out_unlock_inode;
|
||||
|
||||
/*
|
||||
@ -2217,6 +2217,12 @@ void __mark_inode_dirty(struct inode *inode, int flags)
|
||||
wakeup_bdi = inode_io_list_move_locked(inode, wb,
|
||||
dirty_list);
|
||||
|
||||
if (inode->i_state & (I_WILL_FREE | I_FREEING)) {
|
||||
inode_io_list_del_locked(inode, wb);
|
||||
spin_unlock(&wb->list_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_unlock(&wb->list_lock);
|
||||
trace_writeback_dirty_inode_enqueue(inode);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user