mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
block: fix recursive i_rwsem locking in blkdev_write_iter()
Commit2fec4fd97c("block: take i_rwsem for the direct I/O write fallback") takes i_rwsem around blkdev_buffered_write() in the direct write fallback to close a race with set_blocksize(). Commit1b1be9ea4e("block: take the inode lock for buffered write fallback") fixes the same race by taking i_rwsem inside blkdev_buffered_write() instead. With both commits applied, the fallback path takes i_rwsem recursively: blkdev_write_iter() inode_lock_shared(bd_inode) blkdev_buffered_write() inode_lock_shared(inode) syzbot reports this as: WARNING: possible recursive locking detected syz.0.40/6005 is trying to acquire lock: ffff888024956f68 (&sb->s_type->i_mutex_key#10){++++}-{4:4}, at: blkdev_buffered_write+0xd7/0x160 block/fops.c:738 but task is already holding lock: ffff888024956f68 (&sb->s_type->i_mutex_key#10){++++}-{4:4}, at: blkdev_write_iter+0x6c5/0x810 block/fops.c:815 rw_semaphore read locks are not recursive: once a writer is queued, new readers block behind it. If set_blocksize() calls inode_lock() between the two acquisitions, it waits for the first read lock to be released, while the second inode_lock_shared() waits behind set_blocksize(), and the task deadlocks. Drop the outer locking in the fallback. Fixes:1b1be9ea4e("block: take the inode lock for buffered write fallback") Reported-by: syzbot+bd975ef54294bec73f0e@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=bd975ef54294bec73f0e Cc: Tal Zussman <tz2294@columbia.edu> Cc: Julian Sun <sunjunchao@bytedance.com> Assisted-by: LLM Signed-off-by: Zhenxian Ma <mzx199711@gmail.com> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Link: https://patch.msgid.link/20261022062513.77372-1-mzx199711@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
87409eedc5
commit
21b88cc8ba
|
|
@ -808,9 +808,7 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
|||
} else {
|
||||
ssize_t ret2;
|
||||
|
||||
inode_lock_shared(bd_inode);
|
||||
ret2 = blkdev_buffered_write(iocb, from);
|
||||
inode_unlock_shared(bd_inode);
|
||||
ret = direct_write_fallback(iocb, from, ret,
|
||||
ret2);
|
||||
need_sync = true;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user