|
|
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 |
|