On Fri, Sep 30, 2016 at 09:30:21AM +0200, Miklos Szeredi wrote: > On Fri, Sep 30, 2016 at 12:50 AM, Al Viro <viro@xxxxxxxxxxxxxxxxxx> wrote: > > On Thu, Sep 29, 2016 at 10:53:55PM +0200, Miklos Szeredi wrote: > > > >> The EFAULT logic seems to be missing across the board. And callers > >> don't expect a zero return value. Most will loop indefinitely. > > > > Nope. copy_page_to_iter() *never* returns -EFAULT. Including the iovec > > one - check copy_page_to_iter_iovec(). Any caller that does not expect > > a zero return value from that primitive is a bug, triggerable as soon as > > you feed it an iovec with NULL ->iov_base. > > Right. > > I was actually looking at iov_iter_get_pages() callers... FWIW, that's interesting - O_DIRECT readv()/writev() reacts to fault anywhere as "nothing done, return -EFAULT now", rather than a short read/write. Despite that some IO is actually done. Note, BTW, that we are not even consistent between the filesystems - local block ones do IO and give -EFAULT, while NFS, Lustre and FUSE do short read/write, reporting -EFAULT only upon shortening to nothing. So does ceph, except that shortening might be for more than one page. Considering how weak POSIX is in that area, we are probably not violating anything, but... it would be more convenient if we treated those as short read/write, same way for all filesystems. Linus, do you have any objections against such behaviour change? AFAICS, all it takes is this: diff --git a/fs/direct-io.c b/fs/direct-io.c index 7c3ce73..3a8ebda 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -246,6 +246,8 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async) if ((dio->op == REQ_OP_READ) && ((offset + transferred) > dio->i_size)) transferred = dio->i_size - offset; + if (ret == -EFAULT) + ret = 0; } if (ret == 0) -- To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html