]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Aug 2020 14:32:02 +0000 (16:32 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Aug 2020 14:32:02 +0000 (16:32 +0200)
added patches:
ext4-fix-direct-i-o-read-error.patch

queue-5.4/ext4-fix-direct-i-o-read-error.patch [new file with mode: 0644]
queue-5.4/series

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 (file)
index 0000000..3701487
--- /dev/null
@@ -0,0 +1,144 @@
+From jiangying8582@126.com  Wed Aug  5 16:29:58 2020
+From: Jiang Ying <jiangying8582@126.com>
+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 <jiangying8582@126.com>
+
+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 <stdio.h>
+       #include <stdlib.h>
+       #include <unistd.h>
+       #include <sys/file.h>
+       #include <sys/types.h>
+       #include <sys/stat.h>
+       #include <string.h>
+       #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 <unistd.h>
+       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 <b1b4705d54ab>
+("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 <jack@suse.cz>
+Co-developed-by: Wang Long <wanglong19@meituan.com>
+Signed-off-by: Wang Long <wanglong19@meituan.com>
+Signed-off-by: Jiang Ying <jiangying8582@126.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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
index c8e9801b9f2bec5f21b71be91bd3cc260f451c2b..ba5f833785034f80d9715d743c3ee70519443636 100644 (file)
@@ -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