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

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