qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 7/8] block: add witness argument to drive-reopen


From: Paolo Bonzini
Subject: [Qemu-devel] [PATCH 7/8] block: add witness argument to drive-reopen
Date: Fri, 13 Apr 2012 18:23:17 +0200

Management needs a way for QEMU to confirm that no I/O has been sent to the
target and not to the source.  To provide this guarantee we rely on a file
in local persistent storage.  QEMU receives a file descriptor via SCM_RIGHTS
and writes a single byte to it.  If it fails, it will fail the drive-reopen
command too and management knows that no I/O request has been issued to the
new destination.  Likewise, if management finds the file to have nonzero
size it knows that the target is valid and that indeed I/O requests could
have been submitted to it.

The argument does not have an HMP equivalent.

Signed-off-by: Paolo Bonzini <address@hidden>
---
 blockdev.c       |   24 +++++++++++++++++++++---
 hmp.c            |    2 +-
 qapi-schema.json |   10 +++++++++-
 qmp-commands.hx  |   12 +++++++++++-
 4 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 08953fa..78b72f2 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -660,7 +660,7 @@ void do_commit(Monitor *mon, const QDict *qdict)
 }
 
 static void change_blockdev_image(BlockDriverState *bs, const char 
*new_image_file,
-                                  const char *format, Error **errp)
+                                  const char *format, int fd, Error **errp)
 {
     BlockDriver *old_drv, *proto_drv;
     BlockDriver *drv = NULL;
@@ -702,6 +702,16 @@ static void change_blockdev_image(BlockDriverState *bs, 
const char *new_image_fi
 
     bdrv_close(bs);
     ret = bdrv_open(bs, new_image_file, flags, drv);
+
+    if (ret == 0 && fd != -1) {
+        ret = write(fd, "", 1) == 1 ? 0 : -1;
+        qemu_fdatasync(fd);
+        close(fd);
+        if (ret < 0) {
+            bdrv_close(bs);
+        }
+    }
+
     /*
      * If reopening the image file we just created fails, fall back
      * and try to re-open the original image. If that fails too, we
@@ -718,9 +725,20 @@ static void change_blockdev_image(BlockDriverState *bs, 
const char *new_image_fi
 }
 
 void qmp_drive_reopen(const char *device, const char *new_image_file,
-                      bool has_format, const char *format, Error **errp)
+                      bool has_format, const char *format,
+                      bool has_witness, const char *witness,
+                      Error **errp)
 {
     BlockDriverState *bs;
+    int fd = -1;
+
+    if (has_witness) {
+        fd = monitor_get_fd(cur_mon, witness);
+        if (fd == -1) {
+            error_set(errp, QERR_FD_NOT_FOUND, witness);
+            return;
+        }
+    }
 
     bs = bdrv_find(device);
     if (!bs) {
@@ -731,7 +749,7 @@ void qmp_drive_reopen(const char *device, const char 
*new_image_file,
         block_job_cancel_sync(bs->job);
     }
     change_blockdev_image(bs, new_image_file,
-                          has_format ? format : NULL, errp);
+                          has_format ? format : NULL, fd, errp);
 }
 
 static void blockdev_do_action(int kind, void *data, Error **errp)
diff --git a/hmp.c b/hmp.c
index 28697ec..f67c441 100644
--- a/hmp.c
+++ b/hmp.c
@@ -744,7 +744,7 @@ void hmp_drive_reopen(Monitor *mon, const QDict *qdict)
     const char *format = qdict_get_try_str(qdict, "format");
     Error *errp = NULL;
 
-    qmp_drive_reopen(device, filename, !!format, format, &errp);
+    qmp_drive_reopen(device, filename, !!format, format, false, NULL, &errp);
     hmp_handle_error(mon, &errp);
 }
 
diff --git a/qapi-schema.json b/qapi-schema.json
index 0bf3a25..2e5a925 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1228,6 +1228,13 @@
 #
 # @format: #optional the format of the new image, default is 'qcow2'.
 #
+# @witness: A file descriptor name that was passed via getfd.  QEMU will write
+#   a single byte to this file descriptor before completing the command
+#   successfully.  If the byte is not written to the file, it is
+#   guaranteed that the guest has not issued any I/O to the new image.
+#   Failure to write the byte is fatal just like failure to open the new
+#   image, and will cause the guest to revert to the currently open file.
+#
 # Returns: nothing on success
 #          If @device is not a valid block device, DeviceNotFound
 #          If @new-image-file can't be opened, OpenFileFailed
@@ -1236,7 +1243,8 @@
 # Since 1.1
 ##
 { 'command': 'drive-reopen',
-  'data': { 'device': 'str', 'new-image-file': 'str', '*format': 'str' } }
+  'data': { 'device': 'str', 'new-image-file': 'str', '*format': 'str',
+            '*witness': 'str' } }
 
 ##
 # @human-monitor-command:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 6ea0ef5..fedfc36 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -829,7 +829,7 @@ EQMP
 
     {
         .name       = "drive-reopen",
-        .args_type  = "device:B,new-image-file:s,format:s?",
+        .args_type  = "device:B,new-image-file:s,format:s?,witness:s?",
         .mhandler.cmd_new = qmp_marshal_input_drive_reopen,
     },
 
@@ -842,11 +842,21 @@ guest is expecting the drive to change its content, the 
new image should
 contain the same data of the current one.  One use case is to terminate
 a drive-mirror command.
 
+The command can optionally write a single byte to a file descriptor name
+that was passed via SCM rights (getfd).  QEMU will write a single byte
+to this file descriptor before completing the command successfully.
+If the byte is not written to the file, it is guaranteed that the
+guest has not issued any I/O to the new image.  Failure to write the
+byte is fatal just like failure to open the new image, and will cause
+the guest to revert to the currently open file.
+
+
 Arguments:
 
 - "device": device name to operate on (json-string)
 - "new-image-file": name of new image file (json-string)
 - "format": format of new image (json-string, optional)
+- "witness": file descriptor previously passed via SCM rights (json-string, 
optional)
 
 Example:
 
-- 
1.7.9.3





reply via email to

[Prev in Thread] Current Thread [Next in Thread]