On Thu, 2022-07-21 at 17:41 +0700, Ammar Faizi wrote: > On 7/21/22 4:48 PM, Dylan Yudaken wrote: > > What fs are you using? testing on a fresh XFS fs read-write.t works > > for > > me > > I am using btrfs. > > After I got your email, I tried to run the test on an ext4 directory > and > it works fine. But fails on a btrfs directory. > > Any idea why does the test fail on a btrfs fs? > It seems to be a problem with blocking reads, buffer select and READV. My guess is that ext4/xfs are not blocking. in b66e65f41426 ("io_uring: never call io_buffer_select() for a buffer re-select"), this line was added in __io_iov_buffer_select - iov[0].iov_len = len; + req->rw.len = iov[0].iov_len = len; Basically stashing the buffer length in rw.len. The problem is that the next time around that breaks at if (req->rw.len != 1) return -EINVAL; The below fixes it as an example, but it's not great. Maybe someone can figure out a better patch? Otherwise I can try tomorrow: diff --git a/fs/io_uring.c b/fs/io_uring.c index 2b7bb62c7805..d9fa226f8e30 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -647,6 +647,8 @@ struct io_rw { u64 addr; u32 len; rwf_t flags; + u64 bufaddr; + u32 buflen; }; struct io_connect { @@ -3899,7 +3901,7 @@ static ssize_t io_compat_import(struct io_kiocb *req, struct iovec *iov, return -ENOBUFS; req->rw.addr = (unsigned long) buf; iov[0].iov_base = buf; - req->rw.len = iov[0].iov_len = (compat_size_t) len; + req->rw.buflen = iov[0].iov_len = (compat_size_t) len; return 0; } #endif @@ -3920,9 +3922,9 @@ static ssize_t __io_iov_buffer_select(struct io_kiocb *req, struct iovec *iov, buf = io_buffer_select(req, &len, issue_flags); if (!buf) return -ENOBUFS; - req->rw.addr = (unsigned long) buf; + req->rw.bufaddr = (unsigned long) buf; iov[0].iov_base = buf; - req->rw.len = iov[0].iov_len = len; + req->rw.buflen = iov[0].iov_len = len; return 0; } @@ -3930,8 +3932,8 @@ static ssize_t io_iov_buffer_select(struct io_kiocb *req, struct iovec *iov, unsigned int issue_flags) { if (req->flags & (REQ_F_BUFFER_SELECTED|REQ_F_BUFFER_RING)) { - iov[0].iov_base = u64_to_user_ptr(req->rw.addr); - iov[0].iov_len = req->rw.len; + iov[0].iov_base = u64_to_user_ptr(req->rw.bufaddr); + iov[0].iov_len = req->rw.buflen; return 0; } if (req->rw.len != 1)