[libvirt] [PATCH] conf: Make full use of goto lable
by Osier Yang
* virDomainDefParse: There is a goto label "no_memory", which
reports OOM error, and it then fallthrough lable "error". This
patch changes things like following:
virReportOOMError();
goto error;
into:
goto no_memory;
---
src/conf/domain_conf.c | 21 +++++++--------------
1 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5360863..f80ab43 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5832,8 +5832,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
char *set = tmp;
def->cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0) {
- virReportOOMError();
- goto error;
+ goto no_memory;
}
if (virDomainCpuSetParse((const char **)&set,
0, def->cpumask,
@@ -5894,8 +5893,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
int nodemasklen = VIR_DOMAIN_CPUMASK_LEN;
if (VIR_ALLOC_N(def->numatune.memory.nodemask, nodemasklen) < 0) {
- virReportOOMError();
- goto error;
+ goto no_memory;
}
/* "nodeset" leads same syntax with "cpuset". */
@@ -6010,8 +6008,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
if (def->os.bootloader) {
def->os.type = strdup("xen");
if (!def->os.type) {
- virReportOOMError();
- goto error;
+ goto no_memory;
}
} else {
virDomainReportError(VIR_ERR_OS_TYPE,
@@ -6028,8 +6025,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
def->virtType == VIR_DOMAIN_VIRT_XEN) {
VIR_FREE(def->os.type);
if (!(def->os.type = strdup("xen"))) {
- virReportOOMError();
- goto error;
+ goto no_memory;
}
}
@@ -6056,8 +6052,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
goto error;
}
if (!(def->os.arch = strdup(defaultArch))) {
- virReportOOMError();
- goto error;
+ goto no_memory;
}
}
@@ -6069,8 +6064,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
virDomainVirtTypeToString(def->virtType));
if (defaultMachine != NULL) {
if (!(def->os.machine = strdup(defaultMachine))) {
- virReportOOMError();
- goto error;
+ goto no_memory;
}
}
}
@@ -6403,8 +6397,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
virDomainInputDefPtr input;
if (VIR_ALLOC(input) < 0) {
- virReportOOMError();
- goto error;
+ goto no_memory;
}
if (STREQ(def->os.type, "hvm")) {
input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
--
1.7.4
13 years, 5 months
[libvirt] [PATCH v2] Add support for fd: protocol
by Corey Bryant
sVirt provides SELinux MAC isolation for Qemu guest processes and their
corresponding resources (image files). sVirt provides this support
by labeling guests and resources with security labels that are stored
in file system extended attributes. Some file systems, such as NFS, do
not support the extended attribute security namespace, which is needed
for image file isolation when using the sVirt SELinux security driver
in libvirt.
The proposed solution entails a combination of Qemu, libvirt, and
SELinux patches that work together to isolate multiple guests' images
when they're stored in the same NFS mount. This results in an
environment where sVirt isolation and NFS image file isolation can both
be provided.
This patch contains the Qemu code to support this solution. I would
like to solicit input from the libvirt community prior to starting
the libvirt patch.
Currently, Qemu opens an image file in addition to performing the
necessary read and write operations. The proposed solution will move
the open out of Qemu and into libvirt. Once libvirt opens an image
file for the guest, it will pass the file descriptor to Qemu via a
new fd: protocol.
If the image file resides in an NFS mount, the following SELinux policy
changes will provide image isolation:
- A new SELinux boolean is created (e.g. virt_read_write_nfs) to
allow Qemu (svirt_t) to only have SELinux read and write
permissions on nfs_t files
- Qemu (svirt_t) also gets SELinux use permissions on libvirt
(virtd_t) file descriptors
Following is a sample invocation of Qemu using the fd: protocol on
the command line:
qemu -drive file=fd:4,format=qcow2
The fd: protocol is also supported by the drive_add monitor command.
This requires that the specified file descriptor is passed to the
monitor alongside a prior getfd monitor command.
There are some additional features provided by certain image types
where Qemu reopens the image file. All of these scenarios will be
unsupported for the fd: protocol, at least for this patch:
- The -snapshot command line option
- The savevm monitor command
- The snapshot_blkdev monitor command
- Starting Qemu with a backing file
The thought is that this support can be added in the future, but is
not required for the initial fd: support.
This patch was tested with the following formats: raw, cow, qcow,
qcow2, qed, and vmdk, using the fd: protocol from the command line
and the monitor. Tests were also run to verify existing file name
support and qemu-img were not regressed. Non-valid file descriptors,
fd: without format, snapshot and backing files were also tested.
Signed-off-by: Corey Bryant <coreyb(a)linux.vnet.ibm.com>
---
block.c | 16 ++++++++++
block.h | 1 +
block/cow.c | 5 +++
block/qcow.c | 5 +++
block/qcow2.c | 5 +++
block/qed.c | 4 ++
block/raw-posix.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++------
block/vmdk.c | 5 +++
block_int.h | 1 +
blockdev.c | 10 ++++++
monitor.c | 5 +++
monitor.h | 1 +
qemu-options.hx | 8 +++--
qemu-tool.c | 5 +++
14 files changed, 140 insertions(+), 12 deletions(-)
diff --git a/block.c b/block.c
index 24a25d5..500db84 100644
--- a/block.c
+++ b/block.c
@@ -536,6 +536,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
char tmp_filename[PATH_MAX];
char backing_filename[PATH_MAX];
+ if (bdrv_is_fd_protocol(bs)) {
+ return -ENOTSUP;
+ }
+
/* if snapshot, we create a temporary backing file and open it
instead of opening 'filename' directly */
@@ -585,6 +589,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
/* Find the right image format driver */
if (!drv) {
+ /* format must be specified for fd: protocol */
+ if (bdrv_is_fd_protocol(bs)) {
+ return -ENOTSUP;
+ }
ret = find_image_format(filename, &drv);
}
@@ -1460,6 +1468,11 @@ int bdrv_enable_write_cache(BlockDriverState *bs)
return bs->enable_write_cache;
}
+int bdrv_is_fd_protocol(BlockDriverState *bs)
+{
+ return bs->fd_protocol;
+}
+
/* XXX: no longer used */
void bdrv_set_change_cb(BlockDriverState *bs,
void (*change_cb)(void *opaque, int reason),
@@ -1964,6 +1977,9 @@ int bdrv_snapshot_create(BlockDriverState *bs,
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
+ if (bdrv_is_fd_protocol(bs)) {
+ return -ENOTSUP;
+ }
if (drv->bdrv_snapshot_create)
return drv->bdrv_snapshot_create(bs, sn_info);
if (bs->file)
diff --git a/block.h b/block.h
index da7d39c..dd46d52 100644
--- a/block.h
+++ b/block.h
@@ -182,6 +182,7 @@ int bdrv_is_removable(BlockDriverState *bs);
int bdrv_is_read_only(BlockDriverState *bs);
int bdrv_is_sg(BlockDriverState *bs);
int bdrv_enable_write_cache(BlockDriverState *bs);
+int bdrv_is_fd_protocol(BlockDriverState *bs);
int bdrv_is_inserted(BlockDriverState *bs);
int bdrv_media_changed(BlockDriverState *bs);
int bdrv_is_locked(BlockDriverState *bs);
diff --git a/block/cow.c b/block/cow.c
index 4cf543c..e17f8e7 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -82,6 +82,11 @@ static int cow_open(BlockDriverState *bs, int flags)
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
cow_header.backing_file);
+ if (bs->backing_file[0] != '\0' && bdrv_is_fd_protocol(bs)) {
+ /* backing file currently not supported by fd: protocol */
+ goto fail;
+ }
+
bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
s->cow_sectors_offset = (bitmap_size + 511) & ~511;
return 0;
diff --git a/block/qcow.c b/block/qcow.c
index a26c886..1e46bdb 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -157,6 +157,11 @@ static int qcow_open(BlockDriverState *bs, int flags)
if (bdrv_pread(bs->file, header.backing_file_offset, bs->backing_file, len) != len)
goto fail;
bs->backing_file[len] = '\0';
+
+ if (bs->backing_file[0] != '\0' && bdrv_is_fd_protocol(bs)) {
+ /* backing file currently not supported by fd: protocol */
+ goto fail;
+ }
}
return 0;
diff --git a/block/qcow2.c b/block/qcow2.c
index 8451ded..8b9c160 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -270,6 +270,11 @@ static int qcow2_open(BlockDriverState *bs, int flags)
goto fail;
}
bs->backing_file[len] = '\0';
+
+ if (bs->backing_file[0] != '\0' && bdrv_is_fd_protocol(bs)) {
+ ret = -ENOTSUP;
+ goto fail;
+ }
}
if (qcow2_read_snapshots(bs) < 0) {
ret = -EINVAL;
diff --git a/block/qed.c b/block/qed.c
index 3970379..5028897 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -446,6 +446,10 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags)
return ret;
}
+ if (bs->backing_file[0] != '\0' && bdrv_is_fd_protocol(bs)) {
+ return -ENOTSUP;
+ }
+
if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) {
pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw");
}
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 4cd7d7a..c72de3d 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -28,6 +28,7 @@
#include "block_int.h"
#include "module.h"
#include "block/raw-posix-aio.h"
+#include "monitor.h"
#ifdef CONFIG_COCOA
#include <paths.h>
@@ -183,7 +184,8 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
int bdrv_flags, int open_flags)
{
BDRVRawState *s = bs->opaque;
- int fd, ret;
+ int fd = -1;
+ int ret;
ret = raw_normalize_devicepath(&filename);
if (ret != 0) {
@@ -205,15 +207,17 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
if (!(bdrv_flags & BDRV_O_CACHE_WB))
s->open_flags |= O_DSYNC;
- s->fd = -1;
- fd = qemu_open(filename, s->open_flags, 0644);
- if (fd < 0) {
- ret = -errno;
- if (ret == -EROFS)
- ret = -EACCES;
- return ret;
+ if (s->fd == -1) {
+ fd = qemu_open(filename, s->open_flags, 0644);
+ if (fd < 0) {
+ ret = -errno;
+ if (ret == -EROFS) {
+ ret = -EACCES;
+ }
+ return ret;
+ }
+ s->fd = fd;
}
- s->fd = fd;
s->aligned_buf = NULL;
if ((bdrv_flags & BDRV_O_NOCACHE)) {
@@ -270,6 +274,7 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVRawState *s = bs->opaque;
+ s->fd = -1;
s->type = FTYPE_FILE;
return raw_open_common(bs, filename, flags, 0);
}
@@ -890,6 +895,60 @@ static BlockDriver bdrv_file = {
.create_options = raw_create_options,
};
+static int raw_open_fd(BlockDriverState *bs, const char *filename, int flags)
+{
+ BDRVRawState *s = bs->opaque;
+ const char *fd_str;
+ int fd;
+
+ /* extract the file descriptor - fail if it's not fd: */
+ if (!strstart(filename, "fd:", &fd_str)) {
+ return -EINVAL;
+ }
+
+ if (!qemu_isdigit(fd_str[0])) {
+ /* get fd from monitor */
+ fd = qemu_get_fd(fd_str);
+ if (fd == -1) {
+ return -EBADF;
+ }
+ } else {
+ char *endptr = NULL;
+
+ fd = strtol(fd_str, &endptr, 10);
+ if (*endptr || (fd == 0 && fd_str == endptr)) {
+ return -EBADF;
+ }
+ }
+
+ s->fd = fd;
+ s->type = FTYPE_FILE;
+
+ return raw_open_common(bs, filename, flags, 0);
+}
+
+static BlockDriver bdrv_file_fd = {
+ .format_name = "file",
+ .protocol_name = "fd",
+ .instance_size = sizeof(BDRVRawState),
+ .bdrv_probe = NULL, /* no probe for protocols */
+ .bdrv_file_open = raw_open_fd,
+ .bdrv_read = raw_read,
+ .bdrv_write = raw_write,
+ .bdrv_close = raw_close,
+ .bdrv_flush = raw_flush,
+ .bdrv_discard = raw_discard,
+
+ .bdrv_aio_readv = raw_aio_readv,
+ .bdrv_aio_writev = raw_aio_writev,
+ .bdrv_aio_flush = raw_aio_flush,
+
+ .bdrv_truncate = raw_truncate,
+ .bdrv_getlength = raw_getlength,
+
+ .create_options = raw_create_options,
+};
+
/***********************************************/
/* host device */
@@ -998,6 +1057,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
}
#endif
+ s->fd = -1;
s->type = FTYPE_FILE;
#if defined(__linux__)
{
@@ -1168,6 +1228,7 @@ static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
BDRVRawState *s = bs->opaque;
int ret;
+ s->fd = -1;
s->type = FTYPE_FD;
/* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
@@ -1280,6 +1341,7 @@ static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVRawState *s = bs->opaque;
+ s->fd = -1;
s->type = FTYPE_CD;
/* open will not fail even if no CD is inserted, so add O_NONBLOCK */
@@ -1503,6 +1565,7 @@ static void bdrv_file_init(void)
* Register all the drivers. Note that order is important, the driver
* registered last will get probed first.
*/
+ bdrv_register(&bdrv_file_fd);
bdrv_register(&bdrv_file);
bdrv_register(&bdrv_host_device);
#ifdef __linux__
diff --git a/block/vmdk.c b/block/vmdk.c
index 922b23d..2ea808e 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -353,6 +353,11 @@ static int vmdk_parent_open(BlockDriverState *bs)
return -1;
pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
+
+ if (bs->backing_file[0] != '\0' && bdrv_is_fd_protocol(bs)) {
+ /* backing file currently not supported by fd: protocol */
+ return -1;
+ }
}
return 0;
diff --git a/block_int.h b/block_int.h
index fa91337..a305ee2 100644
--- a/block_int.h
+++ b/block_int.h
@@ -152,6 +152,7 @@ struct BlockDriverState {
int encrypted; /* if true, the media is encrypted */
int valid_key; /* if true, a valid encryption key has been set */
int sg; /* if true, the device is a /dev/sg* */
+ int fd_protocol; /* if true, the fd: protocol was specified */
/* event callback when inserting/removing */
void (*change_cb)(void *opaque, int reason);
void *change_opaque;
diff --git a/blockdev.c b/blockdev.c
index e81e0ab..a536c20 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -546,6 +546,10 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
+ if (strncmp(file, "fd:", 3) == 0) {
+ dinfo->bdrv->fd_protocol = 1;
+ }
+
ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
if (ret < 0) {
error_report("could not open disk image %s: %s",
@@ -606,6 +610,12 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
goto out;
}
+ if (bdrv_is_fd_protocol(bs)) {
+ qerror_report(QERR_UNSUPPORTED);
+ ret = -1;
+ goto out;
+ }
+
pstrcpy(old_filename, sizeof(old_filename), bs->filename);
old_drv = bs->drv;
diff --git a/monitor.c b/monitor.c
index 59a3e76..ea60be2 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2832,6 +2832,11 @@ int monitor_get_fd(Monitor *mon, const char *fdname)
return -1;
}
+int qemu_get_fd(const char *fdname)
+{
+ return cur_mon ? monitor_get_fd(cur_mon, fdname) : -1;
+}
+
static const mon_cmd_t mon_cmds[] = {
#include "hmp-commands.h"
{ NULL, NULL, },
diff --git a/monitor.h b/monitor.h
index 4f2d328..de5b987 100644
--- a/monitor.h
+++ b/monitor.h
@@ -51,6 +51,7 @@ int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
void *opaque);
int monitor_get_fd(Monitor *mon, const char *fdname);
+int qemu_get_fd(const char *fdname);
void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
GCC_FMT_ATTR(2, 0);
diff --git a/qemu-options.hx b/qemu-options.hx
index 1d5ad8b..f9b66f4 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -116,7 +116,7 @@ using @file{/dev/cdrom} as filename (@pxref{host_drives}).
ETEXI
DEF("drive", HAS_ARG, QEMU_OPTION_drive,
- "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
+ "-drive [file=[fd:]file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
" [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
" [,cache=writethrough|writeback|none|unsafe][,format=f]\n"
" [,serial=s][,addr=A][,id=name][,aio=threads|native]\n"
@@ -129,10 +129,12 @@ STEXI
Define a new drive. Valid options are:
@table @option
-@item file=@var{file}
+@item file=[fd:]@var{file}
This option defines which disk image (@pxref{disk_images}) to use with
this drive. If the filename contains comma, you must double it
-(for instance, "file=my,,file" to use file "my,file").
+(for instance, "file=my,,file" to use file "my,file"). @option{fd:}@var{file}
+specifies the file descriptor of an already open disk image.
+@option{format=}@var{format} is required by @option{fd:}@var{file}.
@item if=@var{interface}
This option defines on which type on interface the drive is connected.
Available types are: ide, scsi, sd, mtd, floppy, pflash, virtio.
diff --git a/qemu-tool.c b/qemu-tool.c
index 41e5c41..8fe6b8c 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -96,3 +96,8 @@ int64_t qemu_get_clock_ns(QEMUClock *clock)
{
return 0;
}
+
+int qemu_get_fd(const char *fdname)
+{
+ return -1;
+}
--
1.7.1
13 years, 5 months
[libvirt] [PATCH] conf: Fix one memory leak
by Osier Yang
Free def->numatune.memory.nodemask in virDomainDefFree.
---
src/conf/domain_conf.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5360863..38a8587 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1092,6 +1092,8 @@ void virDomainDefFree(virDomainDefPtr def)
virDomainVcpupinDefFree(def->cputune.vcpupin, def->cputune.nvcpupin);
+ VIR_FREE(def->numatune.memory.nodemask);
+
virSysinfoDefFree(def->sysinfo);
if (def->namespaceData && def->ns.free)
--
1.7.4
13 years, 5 months
[libvirt] [PATCH 0/7 v2] python: Implement missing stream/event ops
by Cole Robinson
Currently it isn't possible to implement the equivalent of 'virsh console'
with the python bindings. This series implements the missing functionality
required to do so.
v2:
Pushed first 3 patches
Actually export virEvent APIs in libvirt.h
DV had comments on patch 1 and patch 6 that I didn't address, if I
haven't managed to convince him (or others) with my latest mails I
can do another rev of the series.
Cole Robinson (7):
python: Implement virStreamSend/Recv
python: Implement virStreamSend/RecvAll helpers
Promote virEvent*Handle/Timeout to public API
events: Correct virEventAddTimeout docs
python: Add bindings for virEvent*Handle/Timeout
python: events: Fix C->Python handle callback prototype
python: Mark event callback wrappers as private
daemon/libvirtd.c | 1 -
daemon/mdns.c | 1 -
examples/domain-events/events-python/event-test.py | 6 +-
include/libvirt/libvirt.h.in | 14 +
python/generator.py | 12 +-
python/libvirt-override-virConnect.py | 102 +++----
python/libvirt-override-virStream.py | 101 +++++++-
python/libvirt-override.c | 274 +++++++++++++++++---
python/libvirt-override.py | 80 ++++++-
python/typewrappers.c | 14 +
python/typewrappers.h | 1 +
src/conf/domain_event.c | 1 -
src/conf/domain_event.h | 1 -
src/fdstream.c | 1 -
src/libvirt_private.syms | 9 -
src/libvirt_public.syms | 6 +
src/libxl/libxl_driver.c | 1 -
src/lxc/lxc_driver.c | 1 -
src/network/bridge_driver.c | 1 -
src/node_device/node_device_hal.c | 1 -
src/node_device/node_device_udev.c | 1 -
src/openvz/openvz_driver.c | 1 -
src/qemu/qemu_domain.c | 1 -
src/qemu/qemu_driver.c | 1 -
src/qemu/qemu_monitor.c | 1 -
src/remote/remote_driver.c | 1 -
src/test/test_driver.c | 1 -
src/uml/uml_driver.c | 1 -
src/util/event.c | 56 ++++
src/util/event.h | 73 ------
src/util/util.c | 1 -
src/vbox/vbox_tmpl.c | 1 -
src/xen/xen_inotify.c | 1 -
src/xen/xs_internal.c | 1 -
tools/console.c | 1 -
35 files changed, 559 insertions(+), 211 deletions(-)
--
1.7.4.4
13 years, 5 months
[libvirt] virt-dmesg and virt-uname
by Richard W.M. Jones
I just pushed the virt-dmesg package to Fedora Rawhide[1].
http://koji.fedoraproject.org/koji/buildinfo?buildID=248890
This tool uses libvirt to let you list the kernel messages from a
Linux KVM guest without needing to log in or run any special agent in
the guest. It's useful when a guest crashes or gets stuck.
Usage is pretty simple:
# virt-dmesg F14x64 | head
<6>[ 0.000000] Initializing cgroup subsys cpuset
<6>[ 0.000000] Initializing cgroup subsys cpu
<5>[ 0.000000] Linux version 2.6.35.13-91.fc14.x86_64 (mockbuild(a)x86-15.phx2.fedoraproject.org) (gcc version 4.5.1 20100924 (Red Hat 4.5.1-4) (GCC) ) #1 SMP Tue May 3 13:23:06 UTC 2011
<6>[ 0.000000] Command line: ro root=/dev/mapper/vg_f13x64-lv_root rd_LVM_LV=vg_f13x64/lv_root rd_LVM_LV=vg_f13x64/lv_swap rd_NO_LUKS rd_NO_MD rd_NO_DM LANG=en_US.UTF-8 SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=uk rhgb quiet
<6>[ 0.000000] BIOS-provided physical RAM map:
<6>[ 0.000000] BIOS-e820: 0000000000000000 - 000000000009f400 (usable)
<6>[ 0.000000] BIOS-e820: 000000000009f400 - 00000000000a0000 (reserved)
<6>[ 0.000000] BIOS-e820: 00000000000f0000 - 0000000000100000 (reserved)
<6>[ 0.000000] BIOS-e820: 0000000000100000 - 000000003fffd000 (usable)
<6>[ 0.000000] BIOS-e820: 000000003fffd000 - 0000000040000000 (reserved)
In some cases virt-dmesg won't be able to find the symbol table, in
which case you can fall back to dumping out the kernel and grepping
it, eg:
# virt-dmesg --dump-kernel F14x64 | strings | grep '^<[0-9]>' | less
There's an accompanying tool called virt-uname which does what you
would think:
# virt-uname F14x64
Linux f14x64.home.annexia.org 2.6.35.13-91.fc14.x86_64 #1 SMP Tue May 3 13:23:06 UTC 2011 x86_64 (none)
Please let me know if you find (Linux) guests for which virt-dmesg
doesn't work properly (particularly the --dump-kernel option which
ought to work for any Linux guest). Describe the guest as accurately
as you can and provide the output of 'virt-dmesg -v Guest'.
Rich.
[1] Sadly because of some regressions in libvirt, it *won't* work in
Fedora 15 or earlier unless you are able to upgrade to
libvirt >= 0.9.1-3.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
virt-top is 'top' for virtual machines. Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://et.redhat.com/~rjones/virt-top
13 years, 5 months
[libvirt] [PATCH 1/3] virsh: clarify snapshot vs. save
by Eric Blake
* tools/virsh.c (info_snapshot_create, info_save): Clarify
description.
* tools/virsh.pod (save): Likewise.
---
tools/virsh.c | 6 +++---
tools/virsh.pod | 8 +++++++-
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 1c0b1dc..6b5f3d9 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -1469,7 +1469,7 @@ cmdStart(vshControl *ctl, const vshCmd *cmd)
*/
static const vshCmdInfo info_save[] = {
{"help", N_("save a domain state to a file")},
- {"desc", N_("Save a running domain.")},
+ {"desc", N_("Save the RAM state of a running domain.")},
{NULL, NULL}
};
@@ -10947,8 +10947,8 @@ cmdQuit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
* "snapshot-create" command
*/
static const vshCmdInfo info_snapshot_create[] = {
- {"help", N_("Create a snapshot")},
- {"desc", N_("Snapshot create")},
+ {"help", N_("Create a snapshot from XML")},
+ {"desc", N_("Create a snapshot (disk and RAM) from XML")},
{NULL, NULL}
};
diff --git a/tools/virsh.pod b/tools/virsh.pod
index c6879cb..33f72ed 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -594,7 +594,8 @@ the state file was created.
=item B<save> I<domain-id> I<state-file>
-Saves a running domain to a state file so that it can be restored
+Saves a running domain (RAM, but not disk state) to a state file so that
+it can be restored
later. Once saved, the domain will no longer be running on the
system, thus the memory allocated for the domain will be free for
other domains to use. B<virsh restore> restores from this state file.
@@ -603,6 +604,11 @@ This is roughly equivalent to doing a hibernate on a running computer,
with all the same limitations. Open network connections may be
severed upon restore, as TCP timeouts may have expired.
+Domain saved state files assume that disk images will be unchanged
+between the creation and restore point. For a more complete system
+restore point, where the disk state is saved alongside the memory
+state, see the B<snapshot> family of commands.
+
=item B<schedinfo> optional I<--set> B<parameter=value> I<domain-id> I<--config>
I<--live> I<--current>
--
1.7.1
13 years, 5 months
[libvirt] [PATCH v2]: set and restore MAC address of a NIC when using PASSTHROUGH mode
by Gerhard Stenzel
This is a rework of the patch Dirk sent out last week.
The attached patch addresses the problem that when a PASSTHROUGH
mode DIRECT NIC connection is made the MAC address of the NIC is
not automatically set and reset to the configured VM MAC and
back again.
The patch fixes this problem by setting and resetting the MAC
while remembering the previous setting while the VM is running.
This also works if libvirtd is restarted while the VM is running.
The patch passes make syntax-check
Signed-off-by: Dirk Herrendoerfer <d.herrendoerfer at herrendoerfer.name>
Signed-off-by: Gerhard Stenzel <gerhard.stenzel(a)de.ibm.com>
---
src/libvirt_macvtap.syms | 2 +
src/qemu/qemu_command.c | 48 +++++++++++++++
src/qemu/qemu_process.c | 45 ++++++++++++++
src/util/macvtap.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++
src/util/macvtap.h | 6 ++
5 files changed, 250 insertions(+), 0 deletions(-)
Index: libvirt/src/libvirt_macvtap.syms
===================================================================
--- libvirt.orig/src/libvirt_macvtap.syms
+++ libvirt/src/libvirt_macvtap.syms
@@ -5,6 +5,8 @@
# macvtap.h
delMacvtap;
+getMacaddr;
openMacvtapTap;
+setMacaddr;
vpAssociatePortProfileId;
vpDisassociatePortProfileId;
Index: libvirt/src/qemu/qemu_command.c
===================================================================
--- libvirt.orig/src/qemu/qemu_command.c
+++ libvirt/src/qemu/qemu_command.c
@@ -125,6 +125,77 @@ qemuPhysIfaceConnect(virDomainDefPtr def
net->model && STREQ(net->model, "virtio"))
vnet_hdr = 1;
+ /** Note: When using PASSTHROUGH mode with MACVTAP devices the link
+ * device's MAC address must be set to the VMs MAC address. In
+ * order to not confuse the first switch or bridge in line this MAC
+ * address must be reset when the VM is shut down.
+ * This is especially important when using SRIOV capable cards that
+ * emulate their switch in firmware.
+ */
+ if (net->data.direct.mode == VIR_DOMAIN_NETDEV_MACVTAP_MODE_PASSTHRU) {
+ unsigned char oldmac[6];
+ rc = getMacaddr(&oldmac, net->data.direct.linkdev);
+ if (rc) {
+ virReportSystemError(rc,
+ _("Getting MAC address from '%s' "
+ "to '%02x:%02x:%02x:%02x:%02x:%02x' failed."),
+ net->data.direct.linkdev,
+ oldmac[0], oldmac[1], oldmac[2],
+ oldmac[3], oldmac[4], oldmac[5]);
+ } else {
+ char *oldmacpath = NULL;
+ char *oldmacname = NULL;
+ char *newmacname = NULL;
+ char *basedir = "/var/run/libvirt/network";
+
+ if (virAsprintf(&oldmacname,"%02x:%02x:%02x:%02x:%02x:%02x",
+ oldmac[0], oldmac[1], oldmac[2],
+ oldmac[3], oldmac[4], oldmac[5]) < 0) {
+ virReportOOMError();
+ }
+ if (virAsprintf(&oldmacpath,"%s/%s", basedir, oldmacname) < 0) {
+ virReportOOMError();
+ }
+
+ if (virAsprintf(&newmacname, "%s/%s@%02x:%02x:%02x:%02x:%02x:%02x",
+ basedir,
+ net->data.direct.linkdev,
+ net->mac[0],net->mac[1],net->mac[2],
+ net->mac[3],net->mac[4],net->mac[5]) < 0) {
+ virReportOOMError();
+ }
+
+ rc = symlink (oldmacname, newmacname);
+ if (rc) {
+ virReportSystemError(errno,
+ _("MAC link file creation failed for %s."),
+ net->data.direct.linkdev);
+ }
+ rc = creat(oldmacpath, S_IWUSR);
+ if (rc) {
+ virReportSystemError(errno,
+ _("MAC link file creation failed for %s."),
+ oldmacpath);
+ }
+ rc = VIR_CLOSE(rc);
+ if (rc) {
+ virReportSystemError(errno,
+ _("MAC link file closing failed for %s."),
+ oldmacpath);
+ }
+ }
+
+ rc = setMacaddr(net->mac, net->data.direct.linkdev);
+ if (rc) {
+ virReportSystemError(errno,
+ _("Setting MAC address on '%s' to "
+ "'%02x:%02x:%02x:%02x:%02x:%02x' failed."),
+ net->data.direct.linkdev,
+ net->mac[0], net->mac[1], net->mac[2],
+ net->mac[3], net->mac[4], net->mac[5]);
+ }
+ }
+
rc = openMacvtapTap(net->ifname, net->mac, net->data.direct.linkdev,
net->data.direct.mode, vnet_hdr, def->uuid,
&net->data.direct.virtPortProfile, &res_ifname,
Index: libvirt/src/qemu/qemu_process.c
===================================================================
--- libvirt.orig/src/qemu/qemu_process.c
+++ libvirt/src/qemu/qemu_process.c
@@ -2708,6 +2708,48 @@ void qemuProcessStop(struct qemud_driver
if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
delMacvtap(net->ifname, net->mac, net->data.direct.linkdev,
&net->data.direct.virtPortProfile);
+
+ if (net->data.direct.mode == VIR_DOMAIN_NETDEV_MACVTAP_MODE_PASSTHRU) {
+ char *newmacname = NULL;
+ char *oldmacname = NULL;
+ char *oldmacpath = NULL;
+ char *basedir = "/var/run/libvirt/network";
+
+ if (virAsprintf(&newmacname, "%s/%s@%02x:%02x:%02x:%02x:%02x:%02x",
+ basedir,
+ net->data.direct.linkdev,
+ net->mac[0],net->mac[1],net->mac[2],
+ net->mac[3],net->mac[4],net->mac[5]) < 0) {
+ virReportOOMError();
+ }
+
+ ret = virFileResolveLink(newmacname, &oldmacpath);
+ if (ret < 0) {
+ virReportSystemError(errno,
+ _("Reading MAC address from '%s' failed !"),
+ newmacname);
+ } else {
+ unsigned char oldmac[6];
+
+ oldmacname = basename(oldmacpath);
+
+ if (virParseMacAddr(oldmacname, &oldmac[0]) != 0) {
+ virReportSystemError(VIR_ERR_INTERNAL_ERROR,
+ _("Cannot parse MAC address from '%s'"),
+ oldmacname);
+ }
+
+ VIR_WARN(("Resetting MAC address on '%s' "
+ "to '%02x:%02x:%02x:%02x:%02x:%02x'."),
+ net->data.direct.linkdev,
+ oldmac[0],oldmac[1],oldmac[2],
+ oldmac[3],oldmac[4],oldmac[5]);
+ /*reset mac and remove link file-ignore results*/
+ ret = setMacaddr(oldmac, net->data.direct.linkdev);
+ ret = unlink(oldmacpath);
+ ret = unlink(newmacname);
+ }
+ }
VIR_FREE(net->ifname);
}
}
Index: libvirt/src/util/macvtap.c
===================================================================
--- libvirt.orig/src/util/macvtap.c
+++ libvirt/src/util/macvtap.c
@@ -87,6 +87,7 @@
# define LLDPAD_PID_FILE "/var/run/lldpad.pid"
+#define MACADDRSIZE 6
enum virVirtualPortOp {
ASSOCIATE = 0x1,
@@ -191,6 +192,149 @@ err_exit:
# if WITH_MACVTAP
+/**
+ * getMacaddr:
+ * Get the MAC address of a network device
+ *
+ * @macaddress: Pointer where the MAC address will be stored
+ * @srcdev: The interface name of the NIC to get the MAC from
+ *
+ * Returns zero in case of success,
+ * negative value otherwise with error reported.
+ *
+ */
+int
+getMacaddr(const unsigned char *macaddress, const char *srcdev )
+{
+ int sockfd;
+ int io;
+ struct ifreq ifr;
+
+ strcpy(ifr.ifr_name, srcdev);
+
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if(sockfd < 0){
+ return -1;
+ }
+
+ io = ioctl(sockfd, SIOCGIFHWADDR, (char *)&ifr);
+ if(io < 0){
+ return -1;
+ }
+
+ memcpy(macaddress, ifr.ifr_ifru.ifru_hwaddr.sa_data, MACADDRSIZE);
+
+ return 0;
+}
+
+/**
+ * setMacaddr:
+ * Set the MAC address of a network device
+ *
+ * @macaddress: MAC address to assign to the NIC
+ * @srcdev: The interface name of the NIC
+ *
+ * Returns zero in case of success,
+ * negative value otherwise with error reported.
+ *
+ */
+int
+setMacaddr(const unsigned char *macaddress, const char *srcdev )
+{
+ int rc = 0;
+ struct nlmsghdr *resp;
+ struct nlmsgerr *err;
+ struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
+ int ifindex;
+ unsigned char *recvbuf = NULL;
+ unsigned int recvbuflen;
+ struct nl_msg *nl_msg;
+
+ if (ifaceGetIndex(true, srcdev, &ifindex) != 0)
+ return -1;
+
+ nl_msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_REQUEST);
+
+ if (!nl_msg) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
+ goto buffer_too_small;
+
+ if (nla_put_u32(nl_msg, IFLA_LINK, ifindex) < 0)
+ goto buffer_too_small;
+
+ if (nla_put(nl_msg, IFLA_ADDRESS, MACADDRSIZE, macaddress) < 0)
+ goto buffer_too_small;
+
+ if (srcdev &&
+ nla_put(nl_msg, IFLA_IFNAME, strlen(srcdev)+1, srcdev) < 0)
+ goto buffer_too_small;
+
+ if (nlComm(nl_msg, &recvbuf, &recvbuflen, 0) < 0) {
+ rc = -1;
+ goto err_exit;
+ }
+
+ if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL)
+ goto malformed_resp;
+
+ resp = (struct nlmsghdr *)recvbuf;
+
+ switch (resp->nlmsg_type) {
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr *)NLMSG_DATA(resp);
+ if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
+ goto malformed_resp;
+
+ switch (err->error) {
+
+ case 0:
+ break;
+
+ case -EEXIST:
+ rc = -1;
+ break;
+
+ default:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("error setting device mac address"));
+ rc = -1;
+ }
+ break;
+
+ case NLMSG_DONE:
+ break;
+
+ default:
+ goto malformed_resp;
+ }
+
+err_exit:
+ nlmsg_free(nl_msg);
+
+ VIR_FREE(recvbuf);
+
+ return rc;
+
+malformed_resp:
+ nlmsg_free(nl_msg);
+
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed netlink response message"));
+ VIR_FREE(recvbuf);
+ return -1;
+
+buffer_too_small:
+ nlmsg_free(nl_msg);
+
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("allocated netlink buffer is too small"));
+ return -1;
+}
+
static int
link_add(const char *type,
const unsigned char *macaddress, int macaddrsize,
Index: libvirt/src/util/macvtap.h
===================================================================
--- libvirt.orig/src/util/macvtap.h
+++ libvirt/src/util/macvtap.h
@@ -75,6 +75,10 @@ enum virVMOperationType {
# include "internal.h"
+int getMacaddr(const unsigned char *macaddress, const char *srcdev );
+
+int setMacaddr(const unsigned char *macaddress, const char *srcdev );
+
int openMacvtapTap(const char *ifname,
const unsigned char *macaddress,
const char *linkdev,
===================================================================
Best regards,
Gerhard Stenzel
-------------------------------------------------------------------------------------
IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Martin Jetter
Geschaeftsfuehrung: Dirk Wittkopp
Sitz der Gesellschaft: Boeblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294
13 years, 5 months
[libvirt] [PATCH] virsh: Fix compile error due to const mismatch in cmdVcpupin
by Matthias Bolte
Broken by commit c4a8ca71b10eb adding the reset option.
Instead of altering a const string move the while loop into an
else clause.
---
tools/virsh.c | 110 ++++++++++++++++++++++++++++-----------------------------
1 files changed, 54 insertions(+), 56 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index e04c9fc..0e9efad 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -3000,7 +3000,7 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd)
int cpumaplen;
int i, cpu, lastcpu, maxcpu;
bool unuse = false;
- char *cur;
+ const char *cur;
int config = vshCommandOptBool(cmd, "config");
int live = vshCommandOptBool(cmd, "live");
int current = vshCommandOptBool(cmd, "current");
@@ -3061,72 +3061,70 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd)
cpumap = vshCalloc(ctl, 0, cpumaplen);
/* Parse cpulist */
- cur = cpulist;
- if (*cur == 0) {
+ if (*cpulist == '\0') {
goto parse_error;
- } else if (*cur == 'r') {
+ } else if (*cpulist == 'r') {
for (cpu = 0; cpu < maxcpu; cpu++)
VIR_USE_CPU(cpumap, cpu);
- *cur = 0;
- }
-
- while (*cur != 0) {
-
- /* the char '^' denotes exclusive */
- if (*cur == '^') {
- cur++;
- unuse = true;
- }
-
- /* parse physical CPU number */
- if (!c_isdigit(*cur))
- goto parse_error;
- cpu = virParseNumber(&cur);
- if (cpu < 0) {
- goto parse_error;
- }
- if (cpu >= maxcpu) {
- vshError(ctl, _("Physical CPU %d doesn't exist."), cpu);
- goto parse_error;
- }
- virSkipSpaces(&cur);
-
- if ((*cur == ',') || (*cur == 0)) {
- if (unuse) {
- VIR_UNUSE_CPU(cpumap, cpu);
- } else {
- VIR_USE_CPU(cpumap, cpu);
+ } else {
+ cur = cpulist;
+ while (*cur != '\0') {
+ /* the char '^' denotes exclusive */
+ if (*cur == '^') {
+ cur++;
+ unuse = true;
}
- } else if (*cur == '-') {
- /* the char '-' denotes range */
- if (unuse) {
+
+ /* parse physical CPU number */
+ if (!c_isdigit(*cur))
goto parse_error;
- }
- cur++;
- virSkipSpaces(&cur);
- /* parse the end of range */
- lastcpu = virParseNumber(&cur);
- if (lastcpu < cpu) {
+ cpu = virParseNumber(&cur);
+ if (cpu < 0) {
goto parse_error;
}
- if (lastcpu >= maxcpu) {
- vshError(ctl, _("Physical CPU %d doesn't exist."), maxcpu);
+ if (cpu >= maxcpu) {
+ vshError(ctl, _("Physical CPU %d doesn't exist."), cpu);
goto parse_error;
}
- for (i = cpu; i <= lastcpu; i++) {
- VIR_USE_CPU(cpumap, i);
- }
virSkipSpaces(&cur);
- }
- if (*cur == ',') {
- cur++;
- virSkipSpaces(&cur);
- unuse = false;
- } else if (*cur == 0) {
- break;
- } else {
- goto parse_error;
+ if ((*cur == ',') || (*cur == '\0')) {
+ if (unuse) {
+ VIR_UNUSE_CPU(cpumap, cpu);
+ } else {
+ VIR_USE_CPU(cpumap, cpu);
+ }
+ } else if (*cur == '-') {
+ /* the char '-' denotes range */
+ if (unuse) {
+ goto parse_error;
+ }
+ cur++;
+ virSkipSpaces(&cur);
+ /* parse the end of range */
+ lastcpu = virParseNumber(&cur);
+ if (lastcpu < cpu) {
+ goto parse_error;
+ }
+ if (lastcpu >= maxcpu) {
+ vshError(ctl, _("Physical CPU %d doesn't exist."), maxcpu);
+ goto parse_error;
+ }
+ for (i = cpu; i <= lastcpu; i++) {
+ VIR_USE_CPU(cpumap, i);
+ }
+ virSkipSpaces(&cur);
+ }
+
+ if (*cur == ',') {
+ cur++;
+ virSkipSpaces(&cur);
+ unuse = false;
+ } else if (*cur == '\0') {
+ break;
+ } else {
+ goto parse_error;
+ }
}
}
--
1.7.0.4
13 years, 5 months
[libvirt] [PATCH] Fix compile warnings in virsh vcpupin
by Daniel P. Berrange
The 'char *cur' variable was being assigned from a
'const char *' string, thus discarding constness.
As well as causing a compile warning, it masked a
piece of code which attempts to assign to the
previously const string.
* tools/virsh.c: Fix const-ness of 'cur' variable in vcpupin
---
tools/virsh.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 3df0683..ed26b93 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -3000,7 +3000,7 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd)
int cpumaplen;
int i, cpu, lastcpu, maxcpu;
bool unuse = false;
- char *cur;
+ const char *cur;
int config = vshCommandOptBool(cmd, "config");
int live = vshCommandOptBool(cmd, "live");
int current = vshCommandOptBool(cmd, "current");
@@ -3067,7 +3067,7 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd)
} else if (*cur == 'r') {
for (cpu = 0; cpu < maxcpu; cpu++)
VIR_USE_CPU(cpumap, cpu);
- *cur = 0;
+ cur = "";
}
while (*cur != 0) {
--
1.7.4.4
13 years, 5 months
[libvirt] nwfilter: limit VM traffic to specific MAC
by Shahar Havivi
Hi,
I am trying to add custom filter to block VM traffic to other VMs by limiting
the traffic only to the gateways MAC address.
The filter XML:
<filter name='rhev' chain='root'>
<uuid>cd4e5890-ccc9-1b0f-303f-e7fe7123646d</uuid>
<filterref filter='allow-dhcp'/>
<rule action='drop' direction='out' priority='500'>
<mac match='no' dstmacaddr='$MAC'/>
</rule>
</filter>
The MAC is not the interface MAC address it's the gateways MAC that pass as a
parameter (I use the gateway address hardcoded as well).
The VM is getting DHCP ip but cannot get any traffic,
I notice that when I edit (comment and uncomment) the drop rule, the filter is
working fine, ie no traffic other then the gateway.
1. Am I doing something wrong?
1. What is the table name that libvirt use for ebtables?
Shahar.
13 years, 5 months