ubifs: Set/Clear I_LINKABLE under i_lock for whiteout inode
xfstests-generic/476 reports a warning message as below: WARNING: CPU: 2 PID: 30347 at fs/inode.c:361 inc_nlink+0x52/0x70 Call Trace: do_rename+0x502/0xd40 [ubifs] ubifs_rename+0x8b/0x180 [ubifs] vfs_rename+0x476/0x1080 do_renameat2+0x67c/0x7b0 __x64_sys_renameat2+0x6e/0x90 do_syscall_64+0x66/0xe0 entry_SYSCALL_64_after_hwframe+0x44/0xae Following race case can cause this: rename_whiteout(Thread 1) wb_workfn(Thread 2) ubifs_rename do_rename __writeback_single_inode spin_lock(&inode->i_lock) whiteout->i_state |= I_LINKABLE inode->i_state &= ~dirty; ---- How race happens on i_state: (tmp = whiteout->i_state | I_LINKABLE) (tmp = inode->i_state & ~dirty) (whiteout->i_state = tmp) (inode->i_state = tmp) ---- spin_unlock(&inode->i_lock) inc_nlink(whiteout) WARN_ON(!(inode->i_state & I_LINKABLE)) !!! Fix to add i_lock to avoid i_state update race condition. Fixes: 9e0a1fff8db56ea ("ubifs: Implement RENAME_WHITEOUT") Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com> Signed-off-by: Richard Weinberger <richard@nod.at>
This commit is contained in:
parent
07c32de44e
commit
a801fcfeef
@ -1337,7 +1337,10 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
spin_lock(&whiteout->i_lock);
|
||||
whiteout->i_state |= I_LINKABLE;
|
||||
spin_unlock(&whiteout->i_lock);
|
||||
|
||||
whiteout_ui = ubifs_inode(whiteout);
|
||||
whiteout_ui->data = dev;
|
||||
whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0));
|
||||
@ -1430,7 +1433,11 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
|
||||
inc_nlink(whiteout);
|
||||
mark_inode_dirty(whiteout);
|
||||
|
||||
spin_lock(&whiteout->i_lock);
|
||||
whiteout->i_state &= ~I_LINKABLE;
|
||||
spin_unlock(&whiteout->i_lock);
|
||||
|
||||
iput(whiteout);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user