[libvirt] [PATCH 8/8] save: support O_DIRECT during qemu saves

Eric Blake eblake at redhat.com
Thu Jul 14 14:24:35 UTC 2011


Wire together the previous patches to support O_DIRECT via API
request in qemu.

* src/qemu/qemu_driver.c (qemuDomainSaveInternal, doCoreDump):
Add parameter.
(qemuDomainSaveFlags, qemuDomainManagedSave, qemudDomainCoreDump)
(processWatchdogEvent): Update callers.
---
 src/qemu/qemu_driver.c |   53 ++++++++++++++++++++++++++++++++---------------
 1 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ceeef1c..7687e18 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -87,6 +87,7 @@
 #include "configmake.h"
 #include "threadpool.h"
 #include "locking/lock_manager.h"
+#include "virdirect.h"

 #define VIR_FROM_THIS VIR_FROM_QEMU

@@ -2110,7 +2111,7 @@ qemuCompressProgramName(int compress)
 static int
 qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr dom,
                        virDomainObjPtr vm, const char *path,
-                       int compressed)
+                       int compressed, bool direct)
 {
     char *xml = NULL;
     struct qemud_save_header header;
@@ -2125,6 +2126,7 @@ qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr dom,
     int fd = -1;
     uid_t uid = getuid();
     gid_t gid = getgid();
+    virDirectFdPtr directFd = NULL;

     memset(&header, 0, sizeof(header));
     memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
@@ -2208,14 +2210,14 @@ qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr dom,

     /* First try creating the file as root */
     if (!is_reg) {
-        fd = open(path, O_WRONLY | O_TRUNC);
+        fd = open(path, O_WRONLY | O_TRUNC | (direct ? O_DIRECT : 0));
         if (fd < 0) {
             virReportSystemError(errno, _("unable to open %s"), path);
             goto endjob;
         }
     } else {
-        if ((fd = virFileOpenAs(path, O_CREAT|O_TRUNC|O_WRONLY,
-                                S_IRUSR|S_IWUSR,
+        int oflags = O_CREAT | O_TRUNC | O_WRONLY | (direct ? O_DIRECT : 0);
+        if ((fd = virFileOpenAs(path, oflags, S_IRUSR | S_IWUSR,
                                 uid, gid, 0)) < 0) {
             /* If we failed as root, and the error was permission-denied
                (EACCES or EPERM), assume it's on a network-connected share
@@ -2261,7 +2263,7 @@ qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr dom,

             /* Retry creating the file as driver->user */

-            if ((fd = virFileOpenAs(path, O_CREAT|O_TRUNC|O_WRONLY,
+            if ((fd = virFileOpenAs(path, oflags,
                                     S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
                                     driver->user, driver->group,
                                     VIR_FILE_OPEN_AS_UID)) < 0) {
@@ -2279,6 +2281,9 @@ qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr dom,
         }
     }

+    if (direct && (directFd = virDirectFdNew(&fd, path)) == NULL)
+        goto endjob;
+
     /* Write header to file, followed by XML */
     if (qemuDomainSaveHeader(fd, path, xml, &header) < 0) {
         VIR_FORCE_CLOSE(fd);
@@ -2294,6 +2299,8 @@ qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr dom,
         virReportSystemError(errno, _("unable to close %s"), path);
         goto endjob;
     }
+    if (virDirectFdClose(directFd) < 0)
+        goto endjob;

     ret = 0;

@@ -2326,6 +2333,7 @@ endjob:

 cleanup:
     VIR_FORCE_CLOSE(fd);
+    virDirectFdFree(directFd);
     VIR_FREE(xml);
     if (ret != 0 && is_reg)
         unlink(path);
@@ -2361,7 +2369,7 @@ qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml,
     int ret = -1;
     virDomainObjPtr vm = NULL;

-    virCheckFlags(0, -1);
+    virCheckFlags(VIR_DOMAIN_SAVE_DIRECT, -1);
     if (dxml) {
         qemuReportError(VIR_ERR_INVALID_ARG, "%s",
                         _("xml modification unsupported"));
@@ -2403,7 +2411,8 @@ qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml,
         goto cleanup;
     }

-    ret = qemuDomainSaveInternal(driver, dom, vm, path, compressed);
+    ret = qemuDomainSaveInternal(driver, dom, vm, path, compressed,
+                                 (flags & VIR_DOMAIN_SAVE_DIRECT) != 0);
     vm = NULL;

 cleanup:
@@ -2441,7 +2450,7 @@ qemuDomainManagedSave(virDomainPtr dom, unsigned int flags)
     int ret = -1;
     int compressed;

-    virCheckFlags(0, -1);
+    virCheckFlags(VIR_DOMAIN_SAVE_DIRECT, -1);

     qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -2466,7 +2475,8 @@ qemuDomainManagedSave(virDomainPtr dom, unsigned int flags)
     VIR_INFO("Saving state to %s", name);

     compressed = QEMUD_SAVE_FORMAT_RAW;
-    ret = qemuDomainSaveInternal(driver, dom, vm, name, compressed);
+    ret = qemuDomainSaveInternal(driver, dom, vm, name, compressed,
+                                 (flags & VIR_DOMAIN_SAVE_DIRECT) != 0);
     vm = NULL;

 cleanup:
@@ -2550,18 +2560,24 @@ static int
 doCoreDump(struct qemud_driver *driver,
            virDomainObjPtr vm,
            const char *path,
-           enum qemud_save_formats compress)
+           enum qemud_save_formats compress,
+           bool direct)
 {
     int fd = -1;
     int ret = -1;
+    virDirectFdPtr directFd = NULL;

     /* Create an empty file with appropriate ownership.  */
-    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
+    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY | (direct ? O_DIRECT : 0),
+                   S_IRUSR|S_IWUSR)) < 0) {
         qemuReportError(VIR_ERR_OPERATION_FAILED,
                         _("failed to create '%s'"), path);
         goto cleanup;
     }

+    if (direct && (directFd = virDirectFdNew(&fd, path)) == NULL)
+        goto cleanup;
+
     if (qemuMigrationToFile(driver, vm, fd, 0, path,
                             qemuCompressProgramName(compress), true, false) < 0)
         goto cleanup;
@@ -2572,11 +2588,14 @@ doCoreDump(struct qemud_driver *driver,
                              path);
         goto cleanup;
     }
+    if (virDirectFdClose(directFd) < 0)
+        goto cleanup;

     ret = 0;

 cleanup:
     VIR_FORCE_CLOSE(fd);
+    virDirectFdClose(directFd);
     if (ret != 0)
         unlink(path);
     return ret;
@@ -2620,7 +2639,7 @@ static int qemudDomainCoreDump(virDomainPtr dom,
     int ret = -1;
     virDomainEventPtr event = NULL;

-    virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1);
+    virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH | VIR_DUMP_DIRECT, -1);

     qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -2661,7 +2680,8 @@ static int qemudDomainCoreDump(virDomainPtr dom,
         }
     }

-    ret = doCoreDump(driver, vm, path, getCompressionType(driver));
+    ret = doCoreDump(driver, vm, path, getCompressionType(driver),
+                     (flags & VIR_DUMP_DIRECT) != 0);
     if (ret < 0)
         goto endjob;

@@ -2832,10 +2852,9 @@ static void processWatchdogEvent(void *data, void *opaque)
                 goto endjob;
             }

-            ret = doCoreDump(driver,
-                             wdEvent->vm,
-                             dumpfile,
-                             getCompressionType(driver));
+            /* XXX wire up qemu.conf to support whether to do direct dumps */
+            ret = doCoreDump(driver, wdEvent->vm, dumpfile,
+                             getCompressionType(driver), false);
             if (ret < 0)
                 qemuReportError(VIR_ERR_OPERATION_FAILED,
                                 "%s", _("Dump failed"));
-- 
1.7.4.4




More information about the libvir-list mailing list