Skip to content

Commit acf9ed3

Browse files
adam900710morbidrsa
authored andcommitted
btrfs: retry faulting in the pages after a zero sized short direct write
Currently btrfs_direct_write() will not try to fault in the pages, but directly fall back to buffered writes, if the first page of the buffer can not be faulted in. For example, during generic/362 with nodatasum mount option, there is a write at file offset 0, length PAGE_SIZE, and the page is not faulted in. Then we go the following callchain and directly fall back to buffered IO: btrfs_direct_write() |- btrfs_dio_write() |- __iomap_dio_rw() | |- iomap_iter() | | |- btrfs_dio_iomap_begin() | | Now an ordered extent is allocated for the 4K write. | | | |- iomi.status = iomap_dio_iter() | | Where iomap_dio_iter() returned -EFAULT. | | | |- ret = iomap_iter() | | |- btrfs_dio_iomap_end() | | | | return -ENOTBLK | | |- return -ENOTBLK | |- if (ret == -ENOTBLK) { ret = 0; } | Now the return value is reset to 0. | |- ret = iomap_dio_complete() | Since no byte is submitted, @ret is now zero. | |- if (iov_iter_count() > 0 && (ret == -EFAULT || ret > 0)) | @ret is zero, thus not meeting the above retry condition | |- Fallback to buffered Just slightly loosen the condition to allow retry faulting in pages after a zero sized short write. Unlike the previous two bug fixes, this one is not really cause any real bug, but only reducing the chance to do zero-copy direct IO. Thus it doesn't really require stable-CC nor fixes-tag. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent ff66fe6 commit acf9ed3

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

fs/btrfs/direct-io.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,7 @@ ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
978978
if (ret > 0)
979979
written = ret;
980980

981-
if (iov_iter_count(from) > 0 && (ret == -EFAULT || ret > 0)) {
981+
if (iov_iter_count(from) > 0 && (ret == -EFAULT || ret >= 0)) {
982982
const size_t left = iov_iter_count(from);
983983
/*
984984
* We have more data left to write. Try to fault in as many as

0 commit comments

Comments
 (0)