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

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