From: Greg Kroah-Hartman Date: Wed, 5 Aug 2020 14:32:02 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v5.7.14~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0f43ac5df98010d634f8044d9a64171b30e95e2c;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: ext4-fix-direct-i-o-read-error.patch --- diff --git a/queue-5.4/ext4-fix-direct-i-o-read-error.patch b/queue-5.4/ext4-fix-direct-i-o-read-error.patch new file mode 100644 index 00000000000..3701487dccb --- /dev/null +++ b/queue-5.4/ext4-fix-direct-i-o-read-error.patch @@ -0,0 +1,144 @@ +From jiangying8582@126.com Wed Aug 5 16:29:58 2020 +From: Jiang Ying +Date: Wed, 5 Aug 2020 15:57:21 +0800 +Subject: ext4: fix direct I/O read error +To: tytso@mit.edu, adilger.kernel@dilger.ca, linux-ext4@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org +Cc: wanglong19@meituan.com, heguanjun@meituan.com, jack@suse.cz +Message-ID: <1596614241-178185-1-git-send-email-jiangying8582@126.com> + +From: Jiang Ying + +This patch is used to fix ext4 direct I/O read error when +the read size is not aligned with block size. + +Then, I will use a test to explain the error. + +(1) Make a file that is not aligned with block size: + $dd if=/dev/zero of=./test.jar bs=1000 count=3 + +(2) I wrote a source file named "direct_io_read_file.c" as following: + + #include + #include + #include + #include + #include + #include + #include + #define BUF_SIZE 1024 + + int main() + { + int fd; + int ret; + + unsigned char *buf; + ret = posix_memalign((void **)&buf, 512, BUF_SIZE); + if (ret) { + perror("posix_memalign failed"); + exit(1); + } + fd = open("./test.jar", O_RDONLY | O_DIRECT, 0755); + if (fd < 0){ + perror("open ./test.jar failed"); + exit(1); + } + + do { + ret = read(fd, buf, BUF_SIZE); + printf("ret=%d\n",ret); + if (ret < 0) { + perror("write test.jar failed"); + } + } while (ret > 0); + + free(buf); + close(fd); + } + +(3) Compile the source file: + $gcc direct_io_read_file.c -D_GNU_SOURCE + +(4) Run the test program: + $./a.out + + The result is as following: + ret=1024 + ret=1024 + ret=952 + ret=-1 + write test.jar failed: Invalid argument. + +I have tested this program on XFS filesystem, XFS does not have +this problem, because XFS use iomap_dio_rw() to do direct I/O +read. And the comparing between read offset and file size is done +in iomap_dio_rw(), the code is as following: + + if (pos < size) { + retval = filemap_write_and_wait_range(mapping, pos, + pos + iov_length(iov, nr_segs) - 1); + + if (!retval) { + retval = mapping->a_ops->direct_IO(READ, iocb, + iov, pos, nr_segs); + } + ... + } + +...only when "pos < size", direct I/O can be done, or 0 will be return. + +I have tested the fix patch on Ext4, it is up to the mustard of +EINVAL in man2(read) as following: + #include + ssize_t read(int fd, void *buf, size_t count); + + EINVAL + fd is attached to an object which is unsuitable for reading; + or the file was opened with the O_DIRECT flag, and either the + address specified in buf, the value specified in count, or the + current file offset is not suitably aligned. + +So I think this patch can be applied to fix ext4 direct I/O error. + +However Ext4 introduces direct I/O read using iomap infrastructure +on kernel 5.5, the patch is commit +("ext4: introduce direct I/O read using iomap infrastructure"), +then Ext4 will be the same as XFS, they all use iomap_dio_rw() to do direct +I/O read. So this problem does not exist on kernel 5.5 for Ext4. + +>From above description, we can see this problem exists on all the kernel +versions between kernel 3.14 and kernel 5.4. It will cause the Applications +to fail to read. For example, when the search service downloads a new full +index file, the search engine is loading the previous index file and is +processing the search request, it can not use buffer io that may squeeze +the previous index file in use from pagecache, so the serch service must +use direct I/O read. + +Please apply this patch on these kernel versions, or please use the method +on kernel 5.5 to fix this problem. + +Fixes: 9fe55eea7e4b ("Fix race when checking i_size on direct i/o read") +Reviewed-by: Jan Kara +Co-developed-by: Wang Long +Signed-off-by: Wang Long +Signed-off-by: Jiang Ying +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inode.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3836,6 +3836,11 @@ static ssize_t ext4_direct_IO_read(struc + struct inode *inode = mapping->host; + size_t count = iov_iter_count(iter); + ssize_t ret; ++ loff_t offset = iocb->ki_pos; ++ loff_t size = i_size_read(inode); ++ ++ if (offset >= size) ++ return 0; + + /* + * Shared inode_lock is enough for us - it protects against concurrent diff --git a/queue-5.4/series b/queue-5.4/series index c8e9801b9f2..ba5f8337850 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -4,3 +4,4 @@ random-fix-circular-include-dependency-on-arm64-after-addition-of-percpu.h.patch random32-remove-net_rand_state-from-the-latent-entropy-gcc-plugin.patch random32-move-the-pseudo-random-32-bit-definitions-to-prandom.h.patch arm64-workaround-circular-dependency-in-pointer_auth.h.patch +ext4-fix-direct-i-o-read-error.patch