Hi All, commit 9fe55eea7e4b ("Fix race when checking i_size on direct i/o read") has removed the pos check due to the race case. Now if I want to do direct read on a file which size is not sector alignment, it will return EINVAL in the last round. That means I have to handle the case by checking file size in user space, which I think is a bit inconvenient. I've gone through the direct io read code, and found that in do_blockdev_direct_IO, it does try to handle the EOF case, but unfortunately it retruns EINVAL earlier when checking alignment at the entry of this function. /* Once we sampled i_size check for reads beyond EOF */ dio->i_size = i_size_read(inode); if (iov_iter_rw(iter) == READ && offset >= dio->i_size) { ... retval = 0; goto out; } So I wonder if we can handle this in kernel space before alignment check, so that it behaves the same as some old kernels, e.g. 3.10. All comments are always welcome. Thanks, Joseph My test program, which behaves different in 3.10 and 4.9. --------------------------------------------------------- #define _GNU_SOURCE #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <sys/stat.h> #include <errno.h> #include <string.h> #include <stdio.h> #define BUFFER_SIZE 4096 #define SECTOR_SIZE 512 int main(int argc, char *argv[]) { char *file = "/tmp/testfile"; size_t len = 1024; ssize_t more = (ssize_t)len; off_t offset = 0, off = 0; ssize_t ret = 0; int fd; char *buf; ret = posix_memalign((void **)&buf, SECTOR_SIZE, BUFFER_SIZE); if (ret < 0) { printf("posix_memalign failed\n"); return ret; } memset(buf, 0, BUFFER_SIZE); fd = open(file, O_DIRECT); if (fd < 0) { ret = -errno; goto free; } while (more) { ret = pread(fd, buf + off, more, offset + off); if (ret < 0) { printf("pread failed, error = %d\n", -errno); goto out; } printf("pread %d bytes\n", ret); if (ret == 0) break; more -= ret; off += ret; } out: close(fd); free: free(buf); return ret; }