[libvirt] [PATCH] unify popen/fopen qemu wrappers
by Paolo Bonzini
While reading Chris's code for fd migration I noticed the duplication
between QEMUFilePopen and QEMUFileStdio. This fixes it, and makes
qemu_fopen more similar qemu_fdopen.
Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
---
hw/hw.h | 2 +-
migration-exec.c | 4 +-
savevm.c | 99 +++++++++++++++++++++++++++--------------------------
3 files changed, 53 insertions(+), 52 deletions(-)
diff --git a/hw/hw.h b/hw/hw.h
index 1e5783d..322f077 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -52,7 +52,7 @@ QEMUFile *qemu_fopen(const char *filename, const char *mode);
QEMUFile *qemu_fopen_socket(int fd);
QEMUFile *qemu_popen(FILE *popen_file, const char *mode);
QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
-int qemu_popen_fd(QEMUFile *f);
+int qemu_stdio_fd(QEMUFile *f);
void qemu_fflush(QEMUFile *f);
int qemu_fclose(QEMUFile *f);
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
diff --git a/migration-exec.c b/migration-exec.c
index e3616be..235f3f7 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -117,7 +117,7 @@ static void exec_accept_incoming_migration(void *opaque)
qemu_announce_self();
dprintf("successfully loaded vm state\n");
/* we've successfully migrated, close the fd */
- qemu_set_fd_handler2(qemu_popen_fd(f), NULL, NULL, NULL, NULL);
+ qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
if (autostart)
vm_start();
@@ -136,7 +136,7 @@ int exec_start_incoming_migration(const char *command)
return -errno;
}
- qemu_set_fd_handler2(qemu_popen_fd(f), NULL,
+ qemu_set_fd_handler2(qemu_stdio_fd(f), NULL,
exec_accept_incoming_migration, NULL,
(void *)(unsigned long)f);
diff --git a/savevm.c b/savevm.c
index 570377f..975e7ab 100644
--- a/savevm.c
+++ b/savevm.c
@@ -172,11 +172,11 @@ struct QEMUFile {
int has_error;
};
-typedef struct QEMUFilePopen
+typedef struct QEMUFileStdio
{
- FILE *popen_file;
+ FILE *stdio_file;
QEMUFile *file;
-} QEMUFilePopen;
+} QEMUFileStdio;
typedef struct QEMUFileSocket
{
@@ -206,16 +206,16 @@ static int socket_close(void *opaque)
return 0;
}
-static int popen_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
+static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
{
- QEMUFilePopen *s = opaque;
- return fwrite(buf, 1, size, s->popen_file);
+ QEMUFileStdio *s = opaque;
+ return fwrite(buf, 1, size, s->stdio_file);
}
-static int popen_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
+static int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
{
- QEMUFilePopen *s = opaque;
- FILE *fp = s->popen_file;
+ QEMUFileStdio *s = opaque;
+ FILE *fp = s->stdio_file;
int bytes;
do {
@@ -225,31 +225,39 @@ static int popen_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
return bytes;
}
-static int popen_close(void *opaque)
+static int stdio_pclose(void *opaque)
+{
+ QEMUFileStdio *s = opaque;
+ pclose(s->stdio_file);
+ qemu_free(s);
+ return 0;
+}
+
+static int stdio_fclose(void *opaque)
{
- QEMUFilePopen *s = opaque;
- pclose(s->popen_file);
+ QEMUFileStdio *s = opaque;
+ fclose(s->stdio_file);
qemu_free(s);
return 0;
}
-QEMUFile *qemu_popen(FILE *popen_file, const char *mode)
+QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
{
- QEMUFilePopen *s;
+ QEMUFileStdio *s;
- if (popen_file == NULL || mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
+ if (stdio_file == NULL || mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
fprintf(stderr, "qemu_popen: Argument validity check failed\n");
return NULL;
}
- s = qemu_mallocz(sizeof(QEMUFilePopen));
+ s = qemu_mallocz(sizeof(QEMUFileStdio));
- s->popen_file = popen_file;
+ s->stdio_file = stdio_file;
if(mode[0] == 'r') {
- s->file = qemu_fopen_ops(s, NULL, popen_get_buffer, popen_close, NULL, NULL);
+ s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_pclose, NULL, NULL);
} else {
- s->file = qemu_fopen_ops(s, popen_put_buffer, NULL, popen_close, NULL, NULL);
+ s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_pclose, NULL, NULL);
}
return s->file;
}
@@ -266,13 +274,13 @@ QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
return qemu_popen(popen_file, mode);
}
-int qemu_popen_fd(QEMUFile *f)
+int qemu_stdio_fd(QEMUFile *f)
{
- QEMUFilePopen *p;
+ QEMUFileStdio *p;
int fd;
- p = (QEMUFilePopen *)f->opaque;
- fd = fileno(p->popen_file);
+ p = (QEMUFileStdio *)f->opaque;
+ fd = fileno(p->stdio_file);
return fd;
}
@@ -286,53 +294,46 @@ QEMUFile *qemu_fopen_socket(int fd)
return s->file;
}
-typedef struct QEMUFileStdio
-{
- FILE *outfile;
-} QEMUFileStdio;
-
static int file_put_buffer(void *opaque, const uint8_t *buf,
int64_t pos, int size)
{
QEMUFileStdio *s = opaque;
- fseek(s->outfile, pos, SEEK_SET);
- fwrite(buf, 1, size, s->outfile);
+ fseek(s->stdio_file, pos, SEEK_SET);
+ fwrite(buf, 1, size, s->stdio_file);
return size;
}
static int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
{
QEMUFileStdio *s = opaque;
- fseek(s->outfile, pos, SEEK_SET);
- return fread(buf, 1, size, s->outfile);
-}
-
-static int file_close(void *opaque)
-{
- QEMUFileStdio *s = opaque;
- fclose(s->outfile);
- qemu_free(s);
- return 0;
+ fseek(s->stdio_file, pos, SEEK_SET);
+ return fread(buf, 1, size, s->stdio_file);
}
QEMUFile *qemu_fopen(const char *filename, const char *mode)
{
QEMUFileStdio *s;
+ if (mode == NULL ||
+ (mode[0] != 'r' && mode[0] != 'w') ||
+ mode[1] != 'b' || mode[2] != 0) {
+ fprintf(stderr, "qemu_fdopen: Argument validity check failed\n");
+ return NULL;
+ }
+
s = qemu_mallocz(sizeof(QEMUFileStdio));
- s->outfile = fopen(filename, mode);
- if (!s->outfile)
+ s->stdio_file = fopen(filename, mode);
+ if (!s->stdio_file)
goto fail;
- if (!strcmp(mode, "wb"))
- return qemu_fopen_ops(s, file_put_buffer, NULL, file_close, NULL, NULL);
- else if (!strcmp(mode, "rb"))
- return qemu_fopen_ops(s, NULL, file_get_buffer, file_close, NULL, NULL);
-
+ if(mode[0] == 'w') {
+ s->file = qemu_fopen_ops(s, file_put_buffer, NULL, stdio_fclose, NULL, NULL);
+ } else {
+ s->file = qemu_fopen_ops(s, NULL, file_get_buffer, stdio_fclose, NULL, NULL);
+ }
+ return s->file;
fail:
- if (s->outfile)
- fclose(s->outfile);
qemu_free(s);
return NULL;
}
--
1.6.2.5
15 years, 3 months
[libvirt] virConnectClose() sometimes seg faults libvirt 0.7.0
by Kaitlin Rupert
Hi,
I'm trying to track down a seg fault I'm seeing with the
libvirt-0.7.0-3.fc12.x86_64 rawhide version of libvirt.
I'm having trouble finding the exact set of steps, as I see the behavior
when interacting with the libvirt-cim providers.
Here's the stack trace I was able to get. Looks like the seg fault
actually occurs in netcf, which I haven't looked at much. Has anyone
seen this?
Program received signal SIGSEGV, Segmentation fault.
0x00007fffe4004383 in ?? ()
(gdb) bt
#0 0x00007fffe4004383 in ?? ()
#1 0x00007ffff6a5cbfc in xmlHashScanFull__internal_alias (
table=0x7fffe4005f50, f=<value optimized out>, data=<value
optimized out>)
at hash.c:849
#2 0x00007ffff6a5cc4c in xmlHashScan__internal_alias
(table=0x7fffe400ef10,
f=<value optimized out>, data=<value optimized out>) at hash.c:818
#3 0x00007ffff6ff5104 in xsltShutdownExts () from /usr/lib64/libxslt.so.1
#4 0x00007ffff6fe3e3d in xsltFreeStylesheet () from /usr/lib64/libxslt.so.1
#5 0x00007ffff7452961 in ?? () from /usr/lib64/libnetcf.so.1
#6 0x00007ffff74501d1 in ncf_close () from /usr/lib64/libnetcf.so.1
#7 0x000000000045bb8f in interfaceCloseInterface (conn=0x7fffe4000a90)
at interface_driver.c:164
#8 0x00007ffff7af46a6 in virConnectClose (conn=0x7fffe4000a90)
at libvirt.c:1244
#9 0x0000000000412828 in qemudFreeClient (client=can't compute CFA for
this frame
) at qemud.c:2146
#10 qemudRunLoop (client=can't compute CFA for this frame
) at qemud.c:2219
#11 0x0000000000415b43 in main (argc=<value optimized out>,
argv=<value optimized out>) at qemud.c:2994
---------------------------
Relevant part of the log:
17:13:15.930: debug : do_open:1056 : interface driver 2 Interface
returned SUCCESS
17:13:15.930: debug : do_open:1076 : storage driver 0 Test returned DECLINED
17:13:15.930: debug : do_open:1076 : storage driver 1 remote returned
DECLINED
17:13:15.930: debug : do_open:1076 : storage driver 2 storage returned
SUCCESS
17:13:15.930: debug : do_open:1096 : node driver 0 Test returned DECLINED
17:13:15.930: debug : do_open:1096 : node driver 1 remote returned DECLINED
17:13:15.930: debug : do_open:1096 : node driver 2 halDeviceMonitor
returned SUCCESS
17:13:15.930: debug : qemudDispatchClientFailure:1394 : Deregistering to
relay remote events
17:13:15.930: debug : virConnectDomainEventDeregister:8582 :
conn=0x7fffe014dd00, cb=0x41d620
17:13:15.930: debug : virConnectClose:1232 : conn=0x7fffe014dd00
--
Kaitlin Rupert
IBM Linux Technology Center
kaitlin(a)linux.vnet.ibm.com
15 years, 3 months
[libvirt] [PATCH] Compressed save image format for Qemu.
by Chris Lalancette
Implement a compressed save image format for qemu. While ideally
we would have the choice between compressed/non-compressed
available to the libvirt API, unfortunately there is no "flags"
parameter to the virDomainSave() API. Therefore, implement this
as a qemu.conf option. Both gzip and bzip2 are implemented, and
it should be very easy to implement additional compression
methods.
One open question is if/how we should detect the gzip and bzip2
binaries. One way to do it is to do compile-time setting of the
paths (via configure.in), but that doesn't seem like a great thing
to do. Another solution (my preferred solution) is not to detect
at all; when we go to run the commands that need them, if they
aren't available, or aren't available in one of the standard paths,
then we'll fail. Maybe somebody else has another option or
opinion, though.
In the future, we'll have a more robust (managed) save/restore API,
at which time we can expose this functionality properly in the API.
V2: get rid of redundant dd command and just use >> to append data.
V3: Add back the missing pieces for the enum and bumping the save version.
Signed-off-by: Chris Lalancette <clalance(a)redhat.com>
---
src/qemu.conf | 10 ++++++
src/qemu_conf.c | 11 +++++++
src/qemu_conf.h | 2 +
src/qemu_driver.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++----
4 files changed, 101 insertions(+), 7 deletions(-)
diff --git a/src/qemu.conf b/src/qemu.conf
index 653f487..86dcc9d 100644
--- a/src/qemu.conf
+++ b/src/qemu.conf
@@ -129,3 +129,13 @@
# "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
# "/dev/rtc", "/dev/hpet", "/dev/net/tun",
#]
+
+# The default format for Qemu/KVM guest save images is raw; that is, the
+# memory from the domain is dumped out directly to a file. If you have
+# guests with a large amount of memory, however, this can take up quite
+# a bit of space. If you would like to compress the images while they
+# are being saved to disk, you can also set "gzip" or "bzip2" for the
+# save_image_format. Note that this means you slow down the process
+# of saving a domain in order to save disk space.
+#
+# save_image_format = "raw"
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 7ca5a15..ed87e13 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -280,6 +280,17 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
driver->cgroupDeviceACL[i] = NULL;
}
+ p = virConfGetValue (conf, "save_image_format");
+ CHECK_TYPE ("save_image_format", VIR_CONF_STRING);
+ if (p && p->str) {
+ VIR_FREE(driver->saveImageFormat);
+ if (!(driver->saveImageFormat = strdup(p->str))) {
+ virReportOOMError(NULL);
+ virConfFree(conf);
+ return -1;
+ }
+ }
+
virConfFree (conf);
return 0;
}
diff --git a/src/qemu_conf.h b/src/qemu_conf.h
index 8f4ef6a..e34baab 100644
--- a/src/qemu_conf.h
+++ b/src/qemu_conf.h
@@ -111,6 +111,8 @@ struct qemud_driver {
char *securityDriverName;
virSecurityDriverPtr securityDriver;
+
+ char *saveImageFormat;
};
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 20906ef..8d700bf 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -3411,18 +3411,26 @@ static char *qemudEscapeShellArg(const char *in)
}
#define QEMUD_SAVE_MAGIC "LibvirtQemudSave"
-#define QEMUD_SAVE_VERSION 1
+#define QEMUD_SAVE_VERSION 2
+
+enum qemud_save_formats {
+ QEMUD_SAVE_FORMAT_RAW,
+ QEMUD_SAVE_FORMAT_GZIP,
+ QEMUD_SAVE_FORMAT_BZIP2,
+};
struct qemud_save_header {
char magic[sizeof(QEMUD_SAVE_MAGIC)-1];
int version;
int xml_len;
int was_running;
- int unused[16];
+ char compressed;
+ int unused[15];
};
static int qemudDomainSave(virDomainPtr dom,
- const char *path) {
+ const char *path)
+{
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
char *command = NULL;
@@ -3433,11 +3441,26 @@ static int qemudDomainSave(virDomainPtr dom,
struct qemud_save_header header;
int ret = -1;
virDomainEventPtr event = NULL;
+ int internalret;
memset(&header, 0, sizeof(header));
memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
header.version = QEMUD_SAVE_VERSION;
+ if (driver->saveImageFormat == NULL)
+ header.compressed = QEMUD_SAVE_FORMAT_RAW;
+ else if (STREQ(driver->saveImageFormat, "raw"))
+ header.compressed = QEMUD_SAVE_FORMAT_RAW;
+ else if (STREQ(driver->saveImageFormat, "gzip"))
+ header.compressed = QEMUD_SAVE_FORMAT_GZIP;
+ else if (STREQ(driver->saveImageFormat, "bzip2"))
+ header.compressed = QEMUD_SAVE_FORMAT_BZIP2;
+ else {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+ "%s", _("Invalid save image format specified in configuration file"));
+ return -1;
+ }
+
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -3510,11 +3533,25 @@ static int qemudDomainSave(virDomainPtr dom,
virReportOOMError(dom->conn);
goto cleanup;
}
- if (virAsprintf(&command, "migrate \"exec:"
- "dd of='%s' oflag=append conv=notrunc 2>/dev/null"
- "\"", safe_path) == -1) {
+
+ if (header.compressed == QEMUD_SAVE_FORMAT_RAW)
+ internalret = virAsprintf(&command, "migrate \"exec:"
+ "dd of='%s' oflag=append conv=notrunc 2>/dev/null"
+ "\"", safe_path);
+ else if (header.compressed == QEMUD_SAVE_FORMAT_GZIP)
+ internalret = virAsprintf(&command, "migrate \"exec:"
+ "gzip -c >> '%s' 2>/dev/null\"", safe_path);
+ else if (header.compressed == QEMUD_SAVE_FORMAT_BZIP2)
+ internalret = virAsprintf(&command, "migrate \"exec:"
+ "bzip2 -c >> '%s' 2>/dev/null\"", safe_path);
+ else {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("Invalid compress format %d"),
+ header.compressed);
+ goto cleanup;
+ }
+ if (internalret < 0) {
virReportOOMError(dom->conn);
- command = NULL;
goto cleanup;
}
@@ -4035,6 +4072,9 @@ static int qemudDomainRestore(virConnectPtr conn,
char *xml = NULL;
struct qemud_save_header header;
virDomainEventPtr event = NULL;
+ int intermediatefd = -1;
+ pid_t intermediate_pid = -1;
+ int childstat;
qemuDriverLock(driver);
/* Verify the header and read the XML */
@@ -4124,8 +4164,39 @@ static int qemudDomainRestore(virConnectPtr conn,
}
def = NULL;
+ if (header.version == 2) {
+ const char *intermediate_argv[3] = { NULL, "-dc", NULL };
+ if (header.compressed == QEMUD_SAVE_FORMAT_GZIP)
+ intermediate_argv[0] = "gzip";
+ else if (header.compressed == QEMUD_SAVE_FORMAT_BZIP2)
+ intermediate_argv[0] = "bzip2";
+ else if (header.compressed != QEMUD_SAVE_FORMAT_RAW) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("Unknown compressed save format %d"),
+ header.compressed);
+ goto cleanup;
+ }
+ if (intermediate_argv[0] != NULL) {
+ intermediatefd = fd;
+ fd = -1;
+ if (virExec(conn, intermediate_argv, NULL, NULL,
+ &intermediate_pid, intermediatefd, &fd, NULL, 0) < 0) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("Failed to start decompression binary %s"),
+ intermediate_argv[0]);
+ goto cleanup;
+ }
+ }
+ }
/* Set the migration source and start it up. */
ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd);
+ if (intermediate_pid != -1) {
+ /* Wait for intermediate process to exit */
+ while (waitpid(intermediate_pid, &childstat, 0) == -1 &&
+ errno == EINTR);
+ }
+ if (intermediatefd != -1)
+ close(intermediatefd);
close(fd);
fd = -1;
if (ret < 0) {
--
1.6.0.6
15 years, 3 months
[libvirt] [PATCH] Fix some URLs in virsh manpage
by Mark McLoughlin
* docs/virsh.pod: don't reference format.html anymore, reference
the formatdomain.html etc. pages
* virsh.1: re-generate
---
docs/virsh.pod | 6 +++---
virsh.1 | 8 ++++----
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/docs/virsh.pod b/docs/virsh.pod
index 9530ba6..10bb991 100644
--- a/docs/virsh.pod
+++ b/docs/virsh.pod
@@ -140,7 +140,7 @@ we are currently connected to. This includes a section on the host
capabilities in terms of CPU and features, and a set of description
for each kind of guest which can be virtualized. For a more complete
description see:
- L<http://libvirt.org/format.html#Capa1>
+ L<http://libvirt.org/formatcaps.html>
The XML also show the NUMA topology information if available.
=item B<list>
@@ -424,7 +424,7 @@ is not available the processes will provide an exit code of 1.
The following commands manipulate devices associated to domains.
The domain-id can be specified as an short integer, a name or a full UUID.
To better understand the values allowed as options for the command
-reading the documentation at L<http://libvirt.org/format.html> on the
+reading the documentation at L<http://libvirt.org/formatdomain.html> on the
format of the device sections to get the most accurate set of accepted values.
=over 4
@@ -476,7 +476,7 @@ if more than one are present on the domain.
The following commands manipulate networks. Libvirt has the capability to
define virtual networks which can then be used by domains and linked to
actual network devices. For more detailed information about this feature
-see the documentation at L<http://libvirt.org/format.html#Net1> . A lot
+see the documentation at L<http://libvirt.org/formatnetwork.html> . A lot
of the command for virtual networks are similar to the one used for domains,
but the way to name a virtual network is either by its name or UUID.
diff --git a/virsh.1 b/virsh.1
index ca03cc1..0a5b1c1 100644
--- a/virsh.1
+++ b/virsh.1
@@ -132,7 +132,7 @@
.\" ========================================================================
.\"
.IX Title "VIRSH 1"
-.TH VIRSH 1 "2009-07-02" "libvirt-0.6.4" "Virtualization Support"
+.TH VIRSH 1 "2009-08-11" "libvirt-0.7.0" "Virtualization Support"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@@ -263,7 +263,7 @@ we are currently connected to. This includes a section on the host
capabilities in terms of \s-1CPU\s0 and features, and a set of description
for each kind of guest which can be virtualized. For a more complete
description see:
- <http://libvirt.org/format.html#Capa1>
+ <http://libvirt.org/formatcaps.html>
The \s-1XML\s0 also show the \s-1NUMA\s0 topology information if available.
.IP "\fBlist\fR" 4
.IX Item "list"
@@ -501,7 +501,7 @@ is not available the processes will provide an exit code of 1.
The following commands manipulate devices associated to domains.
The domain-id can be specified as an short integer, a name or a full \s-1UUID\s0.
To better understand the values allowed as options for the command
-reading the documentation at <http://libvirt.org/format.html> on the
+reading the documentation at <http://libvirt.org/formatdomain.html> on the
format of the device sections to get the most accurate set of accepted values.
.IP "\fBattach-device\fR \fIdomain-id\fR \fI\s-1FILE\s0\fR" 4
.IX Item "attach-device domain-id FILE"
@@ -542,7 +542,7 @@ if more than one are present on the domain.
The following commands manipulate networks. Libvirt has the capability to
define virtual networks which can then be used by domains and linked to
actual network devices. For more detailed information about this feature
-see the documentation at <http://libvirt.org/format.html#Net1> . A lot
+see the documentation at <http://libvirt.org/formatnetwork.html> . A lot
of the command for virtual networks are similar to the one used for domains,
but the way to name a virtual network is either by its name or \s-1UUID\s0.
.IP "\fBnet-autostart\fR \fInetwork\fR optional \fI\-\-disable\fR" 4
--
1.6.2.5
15 years, 3 months
Re: [libvirt] Unable to create cgroup for driver
by Daniel P. Berrange
On Tue, Aug 11, 2009 at 02:45:06AM -0700, Shahar Klein wrote:
> Jun
> To avoid just configure --without-lxc
>
> Daniel here is the back-trace
> (Didn't have time to explore)
>
> [root@rain8 libvirt-0.7.0]# ./qemud/libvirtd
> 16:11:02.700: warning : qemudStartup:521 : Unable to create cgroup for driver: No such device or address
> Segmentation fault (core dumped)
>
> gdb ./qemud/.libs/libvirtd ../core.19690
>
> (gdb) where
> #0 virDomainEventCallbackListFree (list=0x0) at domain_event.c:41
> #1 0x000000000043ecee in lxcShutdown () at lxc_driver.c:1582
> #2 0x000000000043f122 in lxcStartup (privileged=1) at lxc_driver.c:1523
> #3 0x00007f05103e03c2 in virStateInitialize (privileged=1) at libvirt.c:785
> #4 0x00000000004134cf in main (argc=6776272, argv=<value optimized out>) at qemud.c:2970
Try out the following patch which ought to fix this problem
Regards,
Daniel
diff --git a/src/domain_conf.c b/src/domain_conf.c
index 2301a96..dd2b361 100644
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -532,6 +532,9 @@ void virDomainObjListFree(virDomainObjListPtr vms)
{
unsigned int i;
+ if (!vms)
+ return;
+
for (i = 0 ; i < vms->count ; i++)
virDomainObjFree(vms->objs[i]);
diff --git a/src/domain_event.c b/src/domain_event.c
index daa6fd5..0fa2822 100644
--- a/src/domain_event.c
+++ b/src/domain_event.c
@@ -38,6 +38,9 @@ void
virDomainEventCallbackListFree(virDomainEventCallbackListPtr list)
{
int i;
+ if (!list)
+ return;
+
for (i=0; i<list->count; i++) {
virFreeCallback freecb = list->callbacks[i]->freecb;
if (freecb)
diff --git a/src/lxc_driver.c b/src/lxc_driver.c
index a9c4f79..bd0cf0e 100644
--- a/src/lxc_driver.c
+++ b/src/lxc_driver.c
@@ -1439,10 +1439,12 @@ static int lxcStartup(int privileged)
lxcDriverLock(lxc_driver);
/* Check that this is a container enabled kernel */
- if(lxcContainerAvailable(0) < 0)
+ if (lxcContainerAvailable(0) < 0) {
+ VIR_INFO0("LXC support not available in this kernel, disabling driver");
goto cleanup;
+ }
- if(VIR_ALLOC(lxc_driver->domainEventCallbacks) < 0)
+ if (VIR_ALLOC(lxc_driver->domainEventCallbacks) < 0)
goto cleanup;
if (!(lxc_driver->domainEventQueue = virDomainEventQueueNew()))
goto cleanup;
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
15 years, 3 months
[libvirt] Unable to create cgroup for driver
by Jun Koi
Hi,
The libvirt 0.7 has a following error when i start libvirtd:
warning : qemudStartup:521 : Unable to create cgroup for driver: No
such device or address
Then it fails to start.
How can I fix this?
Thanks,
J
15 years, 3 months
[libvirt] [PATCH 00/20] Add support for (qcow*) volume encryption.
by Miloslav Trmač
Hello,
the following patches add full support for qcow/qcow2 volume encryption,
assuming a client that supports it.
(Main changes since the previous version:
* Use a separate API for "secret" management
* Auto-generate the encryption format and passphrase if not supplied
See the specific patch change logs for more details; patches without
change logs are entirely new.)
New XML tags are defined to represent encryption parameters (currently
format and passphrase, more can be added in the future), e.g.
<encryption format='qcow'>
<secret type='passphrase'
secret_id='724d95f2-0ed2-6ff9-84d0-0f3d1618428d'/>
</encryption>
The <encryption> tag can be added to a <volume> node passed to
virStorageVolCreateXML() to create an encrypted volume, or to a
<disk> node inside a <domain> to specify what encryption parameters to
use for a domain.
secret_id above refers to a separately-managed secret, which was set
using virSecretSetValue(). Other properties of the secret can be
managed using an XML representation.
Detailed documentation of the formats and features is inside the patches.
15 years, 3 months
[libvirt] [PATCH] add file descriptor migration
by Paolo Bonzini
This is the patch from Chris, with the accept removed and rebased above
my previous cleanup.
Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
Cc: Chris Lalancette <clalance(a)redhat.com>
Cc: Avi Kivity <avi(a)redhat.com>
---
Makefile | 2 +-
hw/hw.h | 1 +
migration-fd.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
migration.c | 4 ++
migration.h | 7 +++
savevm.c | 28 +++++++++++
6 files changed, 178 insertions(+), 1 deletions(-)
create mode 100644 migration-fd.c
diff --git a/Makefile b/Makefile
index 5279504..c7ff0be 100644
--- a/Makefile
+++ b/Makefile
@@ -93,7 +93,7 @@ obj-y += qdev.o qdev-properties.o ssi.o
obj-$(CONFIG_BRLAPI) += baum.o
obj-$(CONFIG_WIN32) += tap-win32.o
-obj-$(CONFIG_POSIX) += migration-exec.o
+obj-$(CONFIG_POSIX) += migration-exec.o migration-fd.o
audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS)
diff --git a/hw/hw.h b/hw/hw.h
index 322f077..91bf800 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -49,6 +49,7 @@ QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
QEMUFileRateLimit *rate_limit,
QEMUFileSetRateLimit *set_rate_limit);
QEMUFile *qemu_fopen(const char *filename, const char *mode);
+QEMUFile *qemu_fdopen(int fd, const char *mode);
QEMUFile *qemu_fopen_socket(int fd);
QEMUFile *qemu_popen(FILE *popen_file, const char *mode);
QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
diff --git a/migration-fd.c b/migration-fd.c
new file mode 100644
index 0000000..794c2ac
--- /dev/null
+++ b/migration-fd.c
@@ -0,0 +1,137 @@
+/*
+ * QEMU live migration via generic fd
+ *
+ * Copyright Red Hat, Inc. 2009
+ *
+ * Authors:
+ * Chris Lalancette <clalance(a)redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "qemu_socket.h"
+#include "migration.h"
+#include "monitor.h"
+#include "qemu-char.h"
+#include "sysemu.h"
+#include "buffered_file.h"
+#include "block.h"
+#include "qemu_socket.h"
+
+//#define DEBUG_MIGRATION_FD
+
+#ifdef DEBUG_MIGRATION_FD
+#define dprintf(fmt, ...) \
+ do { printf("migration-fd: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define dprintf(fmt, ...) \
+ do { } while (0)
+#endif
+
+static int fd_errno(FdMigrationState *s)
+{
+ return errno;
+}
+
+static int fd_write(FdMigrationState *s, const void * buf, size_t size)
+{
+ return write(s->fd, buf, size);
+}
+
+static int fd_close(FdMigrationState *s)
+{
+ dprintf("fd_close\n");
+ if (s->fd != -1) {
+ close(s->fd);
+ s->fd = -1;
+ }
+ return 0;
+}
+
+MigrationState *fd_start_outgoing_migration(Monitor *mon,
+ const char *fdname,
+ int64_t bandwidth_limit,
+ int detach)
+{
+ FdMigrationState *s;
+
+ s = qemu_mallocz(sizeof(*s));
+
+ s->fd = monitor_get_fd(mon, fdname);
+ if (s->fd == -1) {
+ dprintf("fd_migration: invalid file descriptor identifier\n");
+ goto err_after_alloc;
+ }
+
+ if (fcntl(s->fd, F_SETFD, O_NONBLOCK) == -1) {
+ dprintf("Unable to set nonblocking mode on file descriptor\n");
+ goto err_after_open;
+ }
+
+ s->get_error = fd_errno;
+ s->write = fd_write;
+ s->close = fd_close;
+ s->mig_state.cancel = migrate_fd_cancel;
+ s->mig_state.get_status = migrate_fd_get_status;
+ s->mig_state.release = migrate_fd_release;
+
+ s->state = MIG_STATE_ACTIVE;
+ s->mon_resume = NULL;
+ s->bandwidth_limit = bandwidth_limit;
+
+ if (!detach)
+ migrate_fd_monitor_suspend(s);
+
+ migrate_fd_connect(s);
+ return &s->mig_state;
+
+err_after_open:
+ close(s->fd);
+err_after_alloc:
+ qemu_free(s);
+ return NULL;
+}
+
+static void fd_accept_incoming_migration(void *opaque)
+{
+ QEMUFile *f = opaque;
+ int ret;
+
+ ret = qemu_loadvm_state(f);
+ if (ret < 0) {
+ fprintf(stderr, "load of migration failed\n");
+ goto err;
+ }
+ qemu_announce_self();
+ dprintf("successfully loaded vm state\n");
+ /* we've successfully migrated, close the fd */
+ qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
+ if (autostart)
+ vm_start();
+
+err:
+ qemu_fclose(f);
+}
+
+int fd_start_incoming_migration(const char *infd)
+{
+ int fd;
+ QEMUFile *f;
+
+ dprintf("Attempting to start an incoming migration via fd\n");
+
+ fd = strtol(infd, NULL, 0);
+ f = qemu_fdopen(fd, "rb");
+ if(f == NULL) {
+ dprintf("Unable to apply qemu wrapper to file descriptor\n");
+ return -errno;
+ }
+
+ qemu_set_fd_handler2(fd, NULL, fd_accept_incoming_migration, NULL,
+ (void *)(unsigned long)f);
+
+ return 0;
+}
diff --git a/migration.c b/migration.c
index ee64d41..0ca4399 100644
--- a/migration.c
+++ b/migration.c
@@ -43,6 +43,8 @@ void qemu_start_incoming_migration(const char *uri)
#if !defined(WIN32)
else if (strstart(uri, "exec:", &p))
exec_start_incoming_migration(p);
+ else if (strstart(uri, "fd:", &p))
+ fd_start_incoming_migration(p);
#endif
else
fprintf(stderr, "unknown migration protocol: %s\n", uri);
@@ -58,6 +60,8 @@ void do_migrate(Monitor *mon, int detach, const char *uri)
#if !defined(WIN32)
else if (strstart(uri, "exec:", &p))
s = exec_start_outgoing_migration(p, max_throttle, detach);
+ else if (strstart(uri, "fd:", &p))
+ s = fd_start_outgoing_migration(mon, p, max_throttle, detach);
#endif
else
monitor_printf(mon, "unknown migration protocol: %s\n", uri);
diff --git a/migration.h b/migration.h
index 37c7f8e..5033d02 100644
--- a/migration.h
+++ b/migration.h
@@ -73,6 +73,13 @@ MigrationState *tcp_start_outgoing_migration(const char *host_port,
int64_t bandwidth_limit,
int detach);
+int fd_start_incoming_migration(const char *path);
+
+MigrationState *fd_start_outgoing_migration(Monitor *mon,
+ const char *fdname,
+ int64_t bandwidth_limit,
+ int detach);
+
void migrate_fd_monitor_suspend(FdMigrationState *s);
void migrate_fd_error(FdMigrationState *s);
diff --git a/savevm.c b/savevm.c
index 975e7ab..4575653 100644
--- a/savevm.c
+++ b/savevm.c
@@ -285,6 +285,34 @@ int qemu_stdio_fd(QEMUFile *f)
return fd;
}
+QEMUFile *qemu_fdopen(int fd, const char *mode)
+{
+ QEMUFileStdio *s;
+
+ if (mode == NULL ||
+ (mode[0] != 'r' && mode[0] != 'w') ||
+ mode[1] != 'b' || mode[2] != 0) {
+ fprintf(stderr, "qemu_fdopen: Argument validity check failed\n");
+ return NULL;
+ }
+
+ s = qemu_mallocz(sizeof(QEMUFileStdio));
+ s->stdio_file = fdopen(fd, mode);
+ if (!s->stdio_file)
+ goto fail;
+
+ if(mode[0] == 'r') {
+ s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_fclose, NULL, NULL);
+ } else {
+ s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_fclose, NULL, NULL);
+ }
+ return s->file;
+
+fail:
+ qemu_free(s);
+ return NULL;
+}
+
QEMUFile *qemu_fopen_socket(int fd)
{
QEMUFileSocket *s = qemu_mallocz(sizeof(QEMUFileSocket));
--
1.6.2.5
15 years, 3 months