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