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

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