Blame SOURCES/kvm-file-posix-Allow-byte-aligned-O_DIRECT-with-NFS.patch

8fced6
From 4e553943c8fe4924d194884b4719c5459210c686 Mon Sep 17 00:00:00 2001
8fced6
From: Kevin Wolf <kwolf@redhat.com>
8fced6
Date: Tue, 26 Jan 2021 17:21:03 -0500
8fced6
Subject: [PATCH 8/9] file-posix: Allow byte-aligned O_DIRECT with NFS
8fced6
8fced6
RH-Author: Kevin Wolf <kwolf@redhat.com>
8fced6
Message-id: <20210126172103.136060-3-kwolf@redhat.com>
8fced6
Patchwork-id: 100785
8fced6
O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 2/2] file-posix: Allow byte-aligned O_DIRECT with NFS
8fced6
Bugzilla: 1834281
8fced6
RH-Acked-by: Markus Armbruster <armbru@redhat.com>
8fced6
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
8fced6
RH-Acked-by: Max Reitz <mreitz@redhat.com>
8fced6
8fced6
Since commit a6b257a08e3 ('file-posix: Handle undetectable alignment'),
8fced6
we assume that if we open a file with O_DIRECT and alignment probing
8fced6
returns 1, we just couldn't find out the real alignment requirement
8fced6
because some filesystems make the requirement only for allocated blocks.
8fced6
In this case, a safe default of 4k is used.
8fced6
8fced6
This is too strict for NFS, which does actually allow byte-aligned
8fced6
requests even with O_DIRECT. Because we can't distinguish both cases
8fced6
with generic code, let's just look at the file system magic and disable
8fced6
s->needs_alignment for NFS. This way, O_DIRECT can still be used on NFS
8fced6
for images that are not aligned to 4k.
8fced6
8fced6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8fced6
Reviewed-by: Eric Blake <eblake@redhat.com>
8fced6
Message-Id: <20200716142601.111237-3-kwolf@redhat.com>
8fced6
Reviewed-by: Max Reitz <mreitz@redhat.com>
8fced6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8fced6
(cherry picked from commit 5edc85571e7b7269dce408735eba7507f18ac666)
8fced6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8fced6
Signed-off-by: Jon Maloy <jmaloy.redhat.com>
8fced6
---
8fced6
 block/file-posix.c | 26 +++++++++++++++++++++++++-
8fced6
 1 file changed, 25 insertions(+), 1 deletion(-)
8fced6
8fced6
diff --git a/block/file-posix.c b/block/file-posix.c
8fced6
index adafbfa1be..2d834fbdf6 100644
8fced6
--- a/block/file-posix.c
8fced6
+++ b/block/file-posix.c
8fced6
@@ -61,10 +61,12 @@
8fced6
 #include <sys/ioctl.h>
8fced6
 #include <sys/param.h>
8fced6
 #include <sys/syscall.h>
8fced6
+#include <sys/vfs.h>
8fced6
 #include <linux/cdrom.h>
8fced6
 #include <linux/fd.h>
8fced6
 #include <linux/fs.h>
8fced6
 #include <linux/hdreg.h>
8fced6
+#include <linux/magic.h>
8fced6
 #include <scsi/sg.h>
8fced6
 #ifdef __s390__
8fced6
 #include <asm/dasd.h>
8fced6
@@ -298,6 +300,28 @@ static int probe_physical_blocksize(int fd, unsigned int *blk_size)
8fced6
 #endif
8fced6
 }
8fced6
 
8fced6
+/*
8fced6
+ * Returns true if no alignment restrictions are necessary even for files
8fced6
+ * opened with O_DIRECT.
8fced6
+ *
8fced6
+ * raw_probe_alignment() probes the required alignment and assume that 1 means
8fced6
+ * the probing failed, so it falls back to a safe default of 4k. This can be
8fced6
+ * avoided if we know that byte alignment is okay for the file.
8fced6
+ */
8fced6
+static bool dio_byte_aligned(int fd)
8fced6
+{
8fced6
+#ifdef __linux__
8fced6
+    struct statfs buf;
8fced6
+    int ret;
8fced6
+
8fced6
+    ret = fstatfs(fd, &buf;;
8fced6
+    if (ret == 0 && buf.f_type == NFS_SUPER_MAGIC) {
8fced6
+        return true;
8fced6
+    }
8fced6
+#endif
8fced6
+    return false;
8fced6
+}
8fced6
+
8fced6
 /* Check if read is allowed with given memory buffer and length.
8fced6
  *
8fced6
  * This function is used to check O_DIRECT memory buffer and request alignment.
8fced6
@@ -602,7 +626,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
8fced6
 
8fced6
     s->has_discard = true;
8fced6
     s->has_write_zeroes = true;
8fced6
-    if ((bs->open_flags & BDRV_O_NOCACHE) != 0) {
8fced6
+    if ((bs->open_flags & BDRV_O_NOCACHE) != 0 && !dio_byte_aligned(s->fd)) {
8fced6
         s->needs_alignment = true;
8fced6
     }
8fced6
 
8fced6
-- 
8fced6
2.18.2
8fced6