mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
block: take the inode lock for buffered write fallback
Commitc0e473a0d2("block: fix race between set_blocksize and read paths") added shared inode locking around ordinary buffered writes, but missed the direct-I/O fallback path. Move the lock into blkdev_buffered_write() so both paths serialize with set_blocksize(). Also correct the comment claiming that this path takes invalidate_lock; it only takes i_rwsem. Fixes:c0e473a0d2("block: fix race between set_blocksize and read paths") Signed-off-by: Julian Sun <sunjunchao@bytedance.com> Link: https://patch.msgid.link/20261015091105.1315605-3-sunjunchao@bytedance.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
a08bf4b9f8
commit
1b1be9ea4e
21
block/fops.c
21
block/fops.c
|
|
@ -714,12 +714,22 @@ blkdev_direct_write(struct kiocb *iocb, struct iov_iter *from)
|
||||||
|
|
||||||
static ssize_t blkdev_buffered_write(struct kiocb *iocb, struct iov_iter *from)
|
static ssize_t blkdev_buffered_write(struct kiocb *iocb, struct iov_iter *from)
|
||||||
{
|
{
|
||||||
|
struct inode *inode = bdev_file_inode(iocb->ki_filp);
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
/* Buffered fallback waits for writeback, which NOWAIT cannot allow. */
|
/* Buffered fallback waits for writeback, which NOWAIT cannot allow. */
|
||||||
if (iocb->ki_flags & IOCB_NOWAIT)
|
if (iocb->ki_flags & IOCB_NOWAIT)
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
return iomap_file_buffered_write(iocb, from, &blkdev_iomap_ops, NULL,
|
/*
|
||||||
NULL);
|
* Take i_rwsem to avoid racing with set_blocksize() changing
|
||||||
|
* i_blkbits/folio order and truncating the page cache.
|
||||||
|
*/
|
||||||
|
inode_lock_shared(inode);
|
||||||
|
ret = iomap_file_buffered_write(iocb, from, &blkdev_iomap_ops, NULL,
|
||||||
|
NULL);
|
||||||
|
inode_unlock_shared(inode);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -808,14 +818,7 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||||
need_sync = true;
|
need_sync = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
|
||||||
* Take i_rwsem and invalidate_lock to avoid racing with
|
|
||||||
* set_blocksize changing i_blkbits/folio order and punching
|
|
||||||
* out the pagecache.
|
|
||||||
*/
|
|
||||||
inode_lock_shared(bd_inode);
|
|
||||||
ret = blkdev_buffered_write(iocb, from);
|
ret = blkdev_buffered_write(iocb, from);
|
||||||
inode_unlock_shared(bd_inode);
|
|
||||||
need_sync = true;
|
need_sync = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user