Blame SOURCES/kvm-block-file-posix-File-locking-during-creation.patch

ae23c9
From f815f89794a322fd3d0c7275ecdebce5a50e4307 Mon Sep 17 00:00:00 2001
ae23c9
From: Max Reitz <mreitz@redhat.com>
ae23c9
Date: Mon, 18 Jun 2018 14:53:36 +0200
ae23c9
Subject: [PATCH 155/268] block/file-posix: File locking during creation
ae23c9
ae23c9
RH-Author: Max Reitz <mreitz@redhat.com>
ae23c9
Message-id: <20180618145337.633-3-mreitz@redhat.com>
ae23c9
Patchwork-id: 80749
ae23c9
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 2/3] block/file-posix: File locking during creation
ae23c9
Bugzilla: 1519144
ae23c9
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
ae23c9
RH-Acked-by: Fam Zheng <famz@redhat.com>
ae23c9
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
ae23c9
ae23c9
When creating a file, we should take the WRITE and RESIZE permissions.
ae23c9
We do not need either for the creation itself, but we do need them for
ae23c9
clearing and resizing it.  So we can take the proper permissions by
ae23c9
replacing O_TRUNC with an explicit truncation to 0, and by taking the
ae23c9
appropriate file locks between those two steps.
ae23c9
ae23c9
Signed-off-by: Max Reitz <mreitz@redhat.com>
ae23c9
Message-id: 20180509215336.31304-3-mreitz@redhat.com
ae23c9
Reviewed-by: Fam Zheng <famz@redhat.com>
ae23c9
Signed-off-by: Max Reitz <mreitz@redhat.com>
ae23c9
(cherry picked from commit b8cf1913a989b9ea6f248aaa233330047a62962e)
ae23c9
Signed-off-by: Max Reitz <mreitz@redhat.com>
ae23c9
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
ae23c9
---
ae23c9
 block/file-posix.c | 37 +++++++++++++++++++++++++++++++++++--
ae23c9
 1 file changed, 35 insertions(+), 2 deletions(-)
ae23c9
ae23c9
diff --git a/block/file-posix.c b/block/file-posix.c
ae23c9
index c98a4a1..370a483 100644
ae23c9
--- a/block/file-posix.c
ae23c9
+++ b/block/file-posix.c
ae23c9
@@ -1992,6 +1992,7 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
ae23c9
 {
ae23c9
     BlockdevCreateOptionsFile *file_opts;
ae23c9
     int fd;
ae23c9
+    int perm, shared;
ae23c9
     int result = 0;
ae23c9
 
ae23c9
     /* Validate options and set default values */
ae23c9
@@ -2006,14 +2007,44 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
ae23c9
     }
ae23c9
 
ae23c9
     /* Create file */
ae23c9
-    fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
ae23c9
-                   0644);
ae23c9
+    fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_BINARY, 0644);
ae23c9
     if (fd < 0) {
ae23c9
         result = -errno;
ae23c9
         error_setg_errno(errp, -result, "Could not create file");
ae23c9
         goto out;
ae23c9
     }
ae23c9
 
ae23c9
+    /* Take permissions: We want to discard everything, so we need
ae23c9
+     * BLK_PERM_WRITE; and truncation to the desired size requires
ae23c9
+     * BLK_PERM_RESIZE.
ae23c9
+     * On the other hand, we cannot share the RESIZE permission
ae23c9
+     * because we promise that after this function, the file has the
ae23c9
+     * size given in the options.  If someone else were to resize it
ae23c9
+     * concurrently, we could not guarantee that.
ae23c9
+     * Note that after this function, we can no longer guarantee that
ae23c9
+     * the file is not touched by a third party, so it may be resized
ae23c9
+     * then. */
ae23c9
+    perm = BLK_PERM_WRITE | BLK_PERM_RESIZE;
ae23c9
+    shared = BLK_PERM_ALL & ~BLK_PERM_RESIZE;
ae23c9
+
ae23c9
+    /* Step one: Take locks */
ae23c9
+    result = raw_apply_lock_bytes(fd, perm, shared, false, errp);
ae23c9
+    if (result < 0) {
ae23c9
+        goto out_close;
ae23c9
+    }
ae23c9
+
ae23c9
+    /* Step two: Check that nobody else has taken conflicting locks */
ae23c9
+    result = raw_check_lock_bytes(fd, perm, shared, errp);
ae23c9
+    if (result < 0) {
ae23c9
+        goto out_close;
ae23c9
+    }
ae23c9
+
ae23c9
+    /* Clear the file by truncating it to 0 */
ae23c9
+    result = raw_regular_truncate(fd, 0, PREALLOC_MODE_OFF, errp);
ae23c9
+    if (result < 0) {
ae23c9
+        goto out_close;
ae23c9
+    }
ae23c9
+
ae23c9
     if (file_opts->nocow) {
ae23c9
 #ifdef __linux__
ae23c9
         /* Set NOCOW flag to solve performance issue on fs like btrfs.
ae23c9
@@ -2029,6 +2060,8 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
ae23c9
 #endif
ae23c9
     }
ae23c9
 
ae23c9
+    /* Resize and potentially preallocate the file to the desired
ae23c9
+     * final size */
ae23c9
     result = raw_regular_truncate(fd, file_opts->size, file_opts->preallocation,
ae23c9
                                   errp);
ae23c9
     if (result < 0) {
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9