From 12315cd7790ccb6f61bfee246d42f17cb8fa4f08 Mon Sep 17 00:00:00 2001 From: Jim Fehlig Date: Fri, 30 Aug 2013 11:18:31 -0600 Subject: [PATCH] libxl: Introduce libxl_domain.[ch] Create libxl_domain.[ch] and move all functions operating on libxlDomainObjPrivate to these files. This will be useful for future patches that e.g. add job support for libxlDomainObjPrivate. --- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/libxl/libxl_conf.c | 2 +- src/libxl/libxl_conf.h | 18 -- src/libxl/libxl_domain.c | 470 +++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_domain.h | 62 ++++++ src/libxl/libxl_driver.c | 436 +----------------------------------- 7 files changed, 537 insertions(+), 453 deletions(-) create mode 100644 src/libxl/libxl_domain.c create mode 100644 src/libxl/libxl_domain.h diff --git a/po/POTFILES.in b/po/POTFILES.in index aa604fd60a..2a0605b87f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -67,6 +67,7 @@ src/lxc/lxc_conf.c src/lxc/lxc_controller.c src/lxc/lxc_driver.c src/lxc/lxc_process.c +src/libxl/libxl_domain.c src/libxl/libxl_driver.c src/libxl/libxl_conf.c src/network/bridge_driver.c diff --git a/src/Makefile.am b/src/Makefile.am index 097682cfe2..83f514a396 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -657,6 +657,7 @@ XENAPI_DRIVER_SOURCES = \ LIBXL_DRIVER_SOURCES = \ libxl/libxl_conf.c libxl/libxl_conf.h \ + libxl/libxl_domain.c libxl/libxl_domain.h \ libxl/libxl_driver.c libxl/libxl_driver.h UML_DRIVER_SOURCES = \ diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index f8937a4aa3..f9ffe5de56 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -39,7 +39,7 @@ #include "viralloc.h" #include "viruuid.h" #include "capabilities.h" -#include "libxl_driver.h" +#include "libxl_domain.h" #include "libxl_conf.h" #include "libxl_utils.h" #include "virstoragefile.h" diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index 0498012f1c..68e770c88d 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -89,24 +89,6 @@ struct _libxlDriverPrivate { typedef struct _libxlEventHookInfo libxlEventHookInfo; typedef libxlEventHookInfo *libxlEventHookInfoPtr; -typedef struct _libxlDomainObjPrivate libxlDomainObjPrivate; -typedef libxlDomainObjPrivate *libxlDomainObjPrivatePtr; -struct _libxlDomainObjPrivate { - virObjectLockable parent; - - /* per domain log stream for libxl messages */ - FILE *logger_file; - xentoollog_logger *logger; - /* per domain libxl ctx */ - libxl_ctx *ctx; - /* console */ - virChrdevsPtr devs; - libxl_evgen_domain_death *deathW; - - /* list of libxl timeout registrations */ - libxlEventHookInfoPtr timerRegistrations; -}; - # define LIBXL_SAVE_MAGIC "libvirt-xml\n \0 \r" # define LIBXL_SAVE_VERSION 1 diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c new file mode 100644 index 0000000000..0abf80bf09 --- /dev/null +++ b/src/libxl/libxl_domain.c @@ -0,0 +1,470 @@ +/* + * libxl_domain.c: libxl domain object private state + * + * Copyright (C) 2011-2013 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Authors: + * Jim Fehlig + */ + +#include + +#include "libxl_domain.h" + +#include "viralloc.h" +#include "virfile.h" +#include "virerror.h" +#include "virlog.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_LIBXL + + +/* Append an event registration to the list of registrations */ +#define LIBXL_EV_REG_APPEND(head, add) \ + do { \ + libxlEventHookInfoPtr temp; \ + if (head) { \ + temp = head; \ + while (temp->next) \ + temp = temp->next; \ + temp->next = add; \ + } else { \ + head = add; \ + } \ + } while (0) + +/* Remove an event registration from the list of registrations */ +#define LIBXL_EV_REG_REMOVE(head, del) \ + do { \ + libxlEventHookInfoPtr temp; \ + if (head == del) { \ + head = head->next; \ + } else { \ + temp = head; \ + while (temp->next && temp->next != del) \ + temp = temp->next; \ + if (temp->next) { \ + temp->next = del->next; \ + } \ + } \ + } while (0) + +/* Object used to store info related to libxl event registrations */ +struct _libxlEventHookInfo { + libxlEventHookInfoPtr next; + libxlDomainObjPrivatePtr priv; + void *xl_priv; + int id; +}; + +static virClassPtr libxlDomainObjPrivateClass; + +static void +libxlDomainObjPrivateDispose(void *obj); + +static int +libxlDomainObjPrivateOnceInit(void) +{ + if (!(libxlDomainObjPrivateClass = virClassNew(virClassForObjectLockable(), + "libxlDomainObjPrivate", + sizeof(libxlDomainObjPrivate), + libxlDomainObjPrivateDispose))) + return -1; + + return 0; +} + +VIR_ONCE_GLOBAL_INIT(libxlDomainObjPrivate) + +static void +libxlDomainObjEventHookInfoFree(void *obj) +{ + libxlEventHookInfoPtr info = obj; + + /* Drop reference on libxlDomainObjPrivate */ + virObjectUnref(info->priv); + VIR_FREE(info); +} + +static void +libxlDomainObjFDEventCallback(int watch ATTRIBUTE_UNUSED, + int fd, + int vir_events, + void *fd_info) +{ + libxlEventHookInfoPtr info = fd_info; + int events = 0; + + virObjectLock(info->priv); + if (vir_events & VIR_EVENT_HANDLE_READABLE) + events |= POLLIN; + if (vir_events & VIR_EVENT_HANDLE_WRITABLE) + events |= POLLOUT; + if (vir_events & VIR_EVENT_HANDLE_ERROR) + events |= POLLERR; + if (vir_events & VIR_EVENT_HANDLE_HANGUP) + events |= POLLHUP; + + virObjectUnlock(info->priv); + libxl_osevent_occurred_fd(info->priv->ctx, info->xl_priv, fd, 0, events); +} + +static int +libxlDomainObjFDRegisterEventHook(void *priv, + int fd, + void **hndp, + short events, + void *xl_priv) +{ + int vir_events = VIR_EVENT_HANDLE_ERROR; + libxlEventHookInfoPtr info; + + if (VIR_ALLOC(info) < 0) + return -1; + + info->priv = priv; + /* + * Take a reference on the domain object. Reference is dropped in + * libxlDomainObjEventHookInfoFree, ensuring the domain object outlives + * the fd event objects. + */ + virObjectRef(info->priv); + info->xl_priv = xl_priv; + + if (events & POLLIN) + vir_events |= VIR_EVENT_HANDLE_READABLE; + if (events & POLLOUT) + vir_events |= VIR_EVENT_HANDLE_WRITABLE; + + info->id = virEventAddHandle(fd, vir_events, libxlDomainObjFDEventCallback, + info, libxlDomainObjEventHookInfoFree); + if (info->id < 0) { + virObjectUnref(info->priv); + VIR_FREE(info); + return -1; + } + + *hndp = info; + + return 0; +} + +static int +libxlDomainObjFDModifyEventHook(void *priv ATTRIBUTE_UNUSED, + int fd ATTRIBUTE_UNUSED, + void **hndp, + short events) +{ + libxlEventHookInfoPtr info = *hndp; + int vir_events = VIR_EVENT_HANDLE_ERROR; + + virObjectLock(info->priv); + if (events & POLLIN) + vir_events |= VIR_EVENT_HANDLE_READABLE; + if (events & POLLOUT) + vir_events |= VIR_EVENT_HANDLE_WRITABLE; + + virEventUpdateHandle(info->id, vir_events); + virObjectUnlock(info->priv); + + return 0; +} + +static void +libxlDomainObjFDDeregisterEventHook(void *priv ATTRIBUTE_UNUSED, + int fd ATTRIBUTE_UNUSED, + void *hnd) +{ + libxlEventHookInfoPtr info = hnd; + libxlDomainObjPrivatePtr p = info->priv; + + virObjectLock(p); + virEventRemoveHandle(info->id); + virObjectUnlock(p); +} + +static void +libxlDomainObjTimerCallback(int timer ATTRIBUTE_UNUSED, void *timer_info) +{ + libxlEventHookInfoPtr info = timer_info; + libxlDomainObjPrivatePtr p = info->priv; + + virObjectLock(p); + /* + * libxl expects the event to be deregistered when calling + * libxl_osevent_occurred_timeout, but we dont want the event info + * destroyed. Disable the timeout and only remove it after returning + * from libxl. + */ + virEventUpdateTimeout(info->id, -1); + virObjectUnlock(p); + libxl_osevent_occurred_timeout(p->ctx, info->xl_priv); + virObjectLock(p); + /* + * Timeout could have been freed while the lock was dropped. + * Only remove it from the list if it still exists. + */ + if (virEventRemoveTimeout(info->id) == 0) + LIBXL_EV_REG_REMOVE(p->timerRegistrations, info); + virObjectUnlock(p); +} + +static int +libxlDomainObjTimeoutRegisterEventHook(void *priv, + void **hndp, + struct timeval abs_t, + void *xl_priv) +{ + libxlEventHookInfoPtr info; + struct timeval now; + struct timeval res; + static struct timeval zero; + int timeout; + + if (VIR_ALLOC(info) < 0) + return -1; + + info->priv = priv; + /* + * Also take a reference on the domain object. Reference is dropped in + * libxlDomainObjEventHookInfoFree, ensuring the domain object outlives the + * timeout event objects. + */ + virObjectRef(info->priv); + info->xl_priv = xl_priv; + + gettimeofday(&now, NULL); + timersub(&abs_t, &now, &res); + /* Ensure timeout is not overflowed */ + if (timercmp(&res, &zero, <)) { + timeout = 0; + } else if (res.tv_sec > INT_MAX / 1000) { + timeout = INT_MAX; + } else { + timeout = res.tv_sec * 1000 + (res.tv_usec + 999) / 1000; + } + info->id = virEventAddTimeout(timeout, libxlDomainObjTimerCallback, + info, libxlDomainObjEventHookInfoFree); + if (info->id < 0) { + virObjectUnref(info->priv); + VIR_FREE(info); + return -1; + } + + virObjectLock(info->priv); + LIBXL_EV_REG_APPEND(info->priv->timerRegistrations, info); + virObjectUnlock(info->priv); + *hndp = info; + + return 0; +} + +/* + * Note: There are two changes wrt timeouts starting with xen-unstable + * changeset 26469: + * + * 1. Timeout modify callbacks will only be invoked with an abs_t of {0,0}, + * i.e. make the timeout fire immediately. Prior to this commit, timeout + * modify callbacks were never invoked. + * + * 2. Timeout deregister hooks will no longer be called. + */ +static int +libxlDomainObjTimeoutModifyEventHook(void *priv ATTRIBUTE_UNUSED, + void **hndp, + struct timeval abs_t ATTRIBUTE_UNUSED) +{ + libxlEventHookInfoPtr info = *hndp; + + virObjectLock(info->priv); + /* Make the timeout fire */ + virEventUpdateTimeout(info->id, 0); + virObjectUnlock(info->priv); + + return 0; +} + +static void +libxlDomainObjTimeoutDeregisterEventHook(void *priv ATTRIBUTE_UNUSED, + void *hnd) +{ + libxlEventHookInfoPtr info = hnd; + libxlDomainObjPrivatePtr p = info->priv; + + virObjectLock(p); + /* + * Only remove the timeout from the list if removal from the + * event loop is successful. + */ + if (virEventRemoveTimeout(info->id) == 0) + LIBXL_EV_REG_REMOVE(p->timerRegistrations, info); + virObjectUnlock(p); +} + + +static const libxl_osevent_hooks libxl_event_callbacks = { + .fd_register = libxlDomainObjFDRegisterEventHook, + .fd_modify = libxlDomainObjFDModifyEventHook, + .fd_deregister = libxlDomainObjFDDeregisterEventHook, + .timeout_register = libxlDomainObjTimeoutRegisterEventHook, + .timeout_modify = libxlDomainObjTimeoutModifyEventHook, + .timeout_deregister = libxlDomainObjTimeoutDeregisterEventHook, +}; + +static void * +libxlDomainObjPrivateAlloc(void) +{ + libxlDomainObjPrivatePtr priv; + + if (libxlDomainObjPrivateInitialize() < 0) + return NULL; + + if (!(priv = virObjectLockableNew(libxlDomainObjPrivateClass))) + return NULL; + + if (!(priv->devs = virChrdevAlloc())) { + virObjectUnref(priv); + return NULL; + } + + return priv; +} + +static void +libxlDomainObjPrivateDispose(void *obj) +{ + libxlDomainObjPrivatePtr priv = obj; + + if (priv->deathW) + libxl_evdisable_domain_death(priv->ctx, priv->deathW); + + virChrdevFree(priv->devs); + + xtl_logger_destroy(priv->logger); + if (priv->logger_file) + VIR_FORCE_FCLOSE(priv->logger_file); + + libxl_ctx_free(priv->ctx); +} + +static void +libxlDomainObjPrivateFree(void *data) +{ + libxlDomainObjPrivatePtr priv = data; + + if (priv->deathW) { + libxl_evdisable_domain_death(priv->ctx, priv->deathW); + priv->deathW = NULL; + } + + virObjectUnref(priv); +} + +virDomainXMLPrivateDataCallbacks libxlDomainXMLPrivateDataCallbacks = { + .alloc = libxlDomainObjPrivateAlloc, + .free = libxlDomainObjPrivateFree, +}; + + +static int +libxlDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, + virDomainDefPtr def, + virCapsPtr caps ATTRIBUTE_UNUSED, + void *opaque ATTRIBUTE_UNUSED) +{ + if (dev->type == VIR_DOMAIN_DEVICE_CHR && + dev->data.chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE && + dev->data.chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE && + STRNEQ(def->os.type, "hvm")) + dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN; + + return 0; +} + +virDomainDefParserConfig libxlDomainDefParserConfig = { + .macPrefix = { 0x00, 0x16, 0x3e }, + .devicesPostParseCallback = libxlDomainDeviceDefPostParse, +}; + +int +libxlDomainObjPrivateInitCtx(virDomainObjPtr vm) +{ + libxlDomainObjPrivatePtr priv = vm->privateData; + char *log_file; + int ret = -1; + + if (priv->ctx) + return 0; + + if (virAsprintf(&log_file, "%s/%s.log", LIBXL_LOG_DIR, vm->def->name) < 0) + return -1; + + if ((priv->logger_file = fopen(log_file, "a")) == NULL) { + virReportSystemError(errno, + _("failed to open logfile %s"), + log_file); + goto cleanup; + } + + priv->logger = + (xentoollog_logger *)xtl_createlogger_stdiostream(priv->logger_file, + XTL_DEBUG, 0); + if (!priv->logger) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot create libxenlight logger for domain %s"), + vm->def->name); + goto cleanup; + } + + if (libxl_ctx_alloc(&priv->ctx, LIBXL_VERSION, 0, priv->logger)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed libxl context initialization")); + goto cleanup; + } + + libxl_osevent_register_hooks(priv->ctx, &libxl_event_callbacks, priv); + + ret = 0; + +cleanup: + VIR_FREE(log_file); + return ret; +} + +void +libxlDomainObjRegisteredTimeoutsCleanup(libxlDomainObjPrivatePtr priv) +{ + libxlEventHookInfoPtr info; + + virObjectLock(priv); + info = priv->timerRegistrations; + while (info) { + /* + * libxl expects the event to be deregistered when calling + * libxl_osevent_occurred_timeout, but we dont want the event info + * destroyed. Disable the timeout and only remove it after returning + * from libxl. + */ + virEventUpdateTimeout(info->id, -1); + libxl_osevent_occurred_timeout(priv->ctx, info->xl_priv); + virEventRemoveTimeout(info->id); + info = info->next; + } + priv->timerRegistrations = NULL; + virObjectUnlock(priv); +} diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h new file mode 100644 index 0000000000..e4695ef2f8 --- /dev/null +++ b/src/libxl/libxl_domain.h @@ -0,0 +1,62 @@ +/* + * libxl_domain.h: libxl domain object private state + * + * Copyright (C) 2011-2013 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Authors: + * Jim Fehlig + */ + +#ifndef LIBXL_DOMAIN_H +# define LIBXL_DOMAIN_H + +# include + +# include "domain_conf.h" +# include "libxl_conf.h" +# include "virchrdev.h" + +typedef struct _libxlDomainObjPrivate libxlDomainObjPrivate; +typedef libxlDomainObjPrivate *libxlDomainObjPrivatePtr; +struct _libxlDomainObjPrivate { + virObjectLockable parent; + + /* per domain log stream for libxl messages */ + FILE *logger_file; + xentoollog_logger *logger; + /* per domain libxl ctx */ + libxl_ctx *ctx; + /* console */ + virChrdevsPtr devs; + libxl_evgen_domain_death *deathW; + + /* list of libxl timeout registrations */ + libxlEventHookInfoPtr timerRegistrations; +}; + + +extern virDomainXMLPrivateDataCallbacks libxlDomainXMLPrivateDataCallbacks; +extern virDomainDefParserConfig libxlDomainDefParserConfig; + + +int +libxlDomainObjPrivateInitCtx(virDomainObjPtr vm); + +void +libxlDomainObjRegisteredTimeoutsCleanup(libxlDomainObjPrivatePtr priv); + +#endif /* LIBXL_DOMAIN_H */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 91beb306df..ff4f6bebe9 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -41,6 +41,7 @@ #include "viralloc.h" #include "viruuid.h" #include "vircommand.h" +#include "libxl_domain.h" #include "libxl_driver.h" #include "libxl_conf.h" #include "xen_xm.h" @@ -63,45 +64,6 @@ /* Number of Xen scheduler parameters */ #define XEN_SCHED_CREDIT_NPARAM 2 -/* Append an event registration to the list of registrations */ -#define LIBXL_EV_REG_APPEND(head, add) \ - do { \ - libxlEventHookInfoPtr temp; \ - if (head) { \ - temp = head; \ - while (temp->next) \ - temp = temp->next; \ - temp->next = add; \ - } else { \ - head = add; \ - } \ - } while (0) - -/* Remove an event registration from the list of registrations */ -#define LIBXL_EV_REG_REMOVE(head, del) \ - do { \ - libxlEventHookInfoPtr temp; \ - if (head == del) { \ - head = head->next; \ - } else { \ - temp = head; \ - while (temp->next && temp->next != del) \ - temp = temp->next; \ - if (temp->next) { \ - temp->next = del->next; \ - } \ - } \ - } while (0) - -/* Object used to store info related to libxl event registrations */ -struct _libxlEventHookInfo { - libxlEventHookInfoPtr next; - libxlDomainObjPrivatePtr priv; - void *xl_priv; - int id; -}; - -static virClassPtr libxlDomainObjPrivateClass; static libxlDriverPrivatePtr libxl_driver = NULL; @@ -114,24 +76,6 @@ static int libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, bool start_paused, int restore_fd); -static void -libxlDomainObjPrivateDispose(void *obj); - -/* Function definitions */ -static int -libxlDomainObjPrivateOnceInit(void) -{ - if (!(libxlDomainObjPrivateClass = virClassNew(virClassForObjectLockable(), - "libxlDomainObjPrivate", - sizeof(libxlDomainObjPrivate), - libxlDomainObjPrivateDispose))) - return -1; - - return 0; -} - -VIR_ONCE_GLOBAL_INIT(libxlDomainObjPrivate) - static void libxlDriverLock(libxlDriverPrivatePtr driver) { @@ -144,382 +88,6 @@ libxlDriverUnlock(libxlDriverPrivatePtr driver) virMutexUnlock(&driver->lock); } -static void -libxlEventHookInfoFree(void *obj) -{ - libxlEventHookInfoPtr info = obj; - - /* Drop reference on libxlDomainObjPrivate */ - virObjectUnref(info->priv); - VIR_FREE(info); -} - -static void -libxlFDEventCallback(int watch ATTRIBUTE_UNUSED, - int fd, - int vir_events, - void *fd_info) -{ - libxlEventHookInfoPtr info = fd_info; - int events = 0; - - virObjectLock(info->priv); - if (vir_events & VIR_EVENT_HANDLE_READABLE) - events |= POLLIN; - if (vir_events & VIR_EVENT_HANDLE_WRITABLE) - events |= POLLOUT; - if (vir_events & VIR_EVENT_HANDLE_ERROR) - events |= POLLERR; - if (vir_events & VIR_EVENT_HANDLE_HANGUP) - events |= POLLHUP; - - virObjectUnlock(info->priv); - libxl_osevent_occurred_fd(info->priv->ctx, info->xl_priv, fd, 0, events); -} - -static int -libxlFDRegisterEventHook(void *priv, int fd, void **hndp, - short events, void *xl_priv) -{ - int vir_events = VIR_EVENT_HANDLE_ERROR; - libxlEventHookInfoPtr info; - - if (VIR_ALLOC(info) < 0) - return -1; - - info->priv = priv; - /* - * Take a reference on the domain object. Reference is dropped in - * libxlEventHookInfoFree, ensuring the domain object outlives the fd - * event objects. - */ - virObjectRef(info->priv); - info->xl_priv = xl_priv; - - if (events & POLLIN) - vir_events |= VIR_EVENT_HANDLE_READABLE; - if (events & POLLOUT) - vir_events |= VIR_EVENT_HANDLE_WRITABLE; - - info->id = virEventAddHandle(fd, vir_events, libxlFDEventCallback, - info, libxlEventHookInfoFree); - if (info->id < 0) { - virObjectUnref(info->priv); - VIR_FREE(info); - return -1; - } - - *hndp = info; - - return 0; -} - -static int -libxlFDModifyEventHook(void *priv ATTRIBUTE_UNUSED, - int fd ATTRIBUTE_UNUSED, - void **hndp, - short events) -{ - libxlEventHookInfoPtr info = *hndp; - int vir_events = VIR_EVENT_HANDLE_ERROR; - - virObjectLock(info->priv); - if (events & POLLIN) - vir_events |= VIR_EVENT_HANDLE_READABLE; - if (events & POLLOUT) - vir_events |= VIR_EVENT_HANDLE_WRITABLE; - - virEventUpdateHandle(info->id, vir_events); - virObjectUnlock(info->priv); - - return 0; -} - -static void -libxlFDDeregisterEventHook(void *priv ATTRIBUTE_UNUSED, - int fd ATTRIBUTE_UNUSED, - void *hnd) -{ - libxlEventHookInfoPtr info = hnd; - libxlDomainObjPrivatePtr p = info->priv; - - virObjectLock(p); - virEventRemoveHandle(info->id); - virObjectUnlock(p); -} - -static void -libxlTimerCallback(int timer ATTRIBUTE_UNUSED, void *timer_info) -{ - libxlEventHookInfoPtr info = timer_info; - libxlDomainObjPrivatePtr p = info->priv; - - virObjectLock(p); - /* - * libxl expects the event to be deregistered when calling - * libxl_osevent_occurred_timeout, but we dont want the event info - * destroyed. Disable the timeout and only remove it after returning - * from libxl. - */ - virEventUpdateTimeout(info->id, -1); - virObjectUnlock(p); - libxl_osevent_occurred_timeout(p->ctx, info->xl_priv); - virObjectLock(p); - /* - * Timeout could have been freed while the lock was dropped. - * Only remove it from the list if it still exists. - */ - if (virEventRemoveTimeout(info->id) == 0) - LIBXL_EV_REG_REMOVE(p->timerRegistrations, info); - virObjectUnlock(p); -} - -static int -libxlTimeoutRegisterEventHook(void *priv, - void **hndp, - struct timeval abs_t, - void *xl_priv) -{ - libxlEventHookInfoPtr info; - struct timeval now; - struct timeval res; - static struct timeval zero; - int timeout; - - if (VIR_ALLOC(info) < 0) - return -1; - - info->priv = priv; - /* - * Also take a reference on the domain object. Reference is dropped in - * libxlEventHookInfoFree, ensuring the domain object outlives the timeout - * event objects. - */ - virObjectRef(info->priv); - info->xl_priv = xl_priv; - - gettimeofday(&now, NULL); - timersub(&abs_t, &now, &res); - /* Ensure timeout is not overflowed */ - if (timercmp(&res, &zero, <)) - timeout = 0; - else if (res.tv_sec > INT_MAX / 1000) - timeout = INT_MAX; - else - timeout = res.tv_sec * 1000 + (res.tv_usec + 999) / 1000; - - info->id = virEventAddTimeout(timeout, libxlTimerCallback, - info, libxlEventHookInfoFree); - if (info->id < 0) { - virObjectUnref(info->priv); - VIR_FREE(info); - return -1; - } - - virObjectLock(info->priv); - LIBXL_EV_REG_APPEND(info->priv->timerRegistrations, info); - virObjectUnlock(info->priv); - *hndp = info; - - return 0; -} - -/* - * Note: There are two changes wrt timeouts starting with xen-unstable - * changeset 26469: - * - * 1. Timeout modify callbacks will only be invoked with an abs_t of {0,0}, - * i.e. make the timeout fire immediately. Prior to this commit, timeout - * modify callbacks were never invoked. - * - * 2. Timeout deregister hooks will no longer be called. - */ -static int -libxlTimeoutModifyEventHook(void *priv ATTRIBUTE_UNUSED, - void **hndp, - struct timeval abs_t ATTRIBUTE_UNUSED) -{ - libxlEventHookInfoPtr info = *hndp; - - virObjectLock(info->priv); - /* Make the timeout fire */ - virEventUpdateTimeout(info->id, 0); - virObjectUnlock(info->priv); - - return 0; -} - -static void -libxlTimeoutDeregisterEventHook(void *priv ATTRIBUTE_UNUSED, - void *hnd) -{ - libxlEventHookInfoPtr info = hnd; - libxlDomainObjPrivatePtr p = info->priv; - - virObjectLock(p); - /* - * Only remove the timeout from the list if removal from the - * event loop is successful. - */ - if (virEventRemoveTimeout(info->id) == 0) - LIBXL_EV_REG_REMOVE(p->timerRegistrations, info); - virObjectUnlock(p); -} - -static void -libxlRegisteredTimeoutsCleanup(libxlDomainObjPrivatePtr priv) -{ - libxlEventHookInfoPtr info; - - virObjectLock(priv); - info = priv->timerRegistrations; - while (info) { - /* - * libxl expects the event to be deregistered when calling - * libxl_osevent_occurred_timeout, but we dont want the event info - * destroyed. Disable the timeout and only remove it after returning - * from libxl. - */ - virEventUpdateTimeout(info->id, -1); - libxl_osevent_occurred_timeout(priv->ctx, info->xl_priv); - virEventRemoveTimeout(info->id); - info = info->next; - } - priv->timerRegistrations = NULL; - virObjectUnlock(priv); -} - -static const libxl_osevent_hooks libxl_event_callbacks = { - .fd_register = libxlFDRegisterEventHook, - .fd_modify = libxlFDModifyEventHook, - .fd_deregister = libxlFDDeregisterEventHook, - .timeout_register = libxlTimeoutRegisterEventHook, - .timeout_modify = libxlTimeoutModifyEventHook, - .timeout_deregister = libxlTimeoutDeregisterEventHook, -}; - -static int -libxlDomainObjPrivateInitCtx(virDomainObjPtr vm) -{ - libxlDomainObjPrivatePtr priv = vm->privateData; - char *log_file; - int ret = -1; - - if (priv->ctx) - return 0; - - if (virAsprintf(&log_file, "%s/%s.log", LIBXL_LOG_DIR, vm->def->name) < 0) - return -1; - - if ((priv->logger_file = fopen(log_file, "a")) == NULL) { - virReportSystemError(errno, - _("failed to open logfile %s"), - log_file); - goto cleanup; - } - - priv->logger = - (xentoollog_logger *)xtl_createlogger_stdiostream(priv->logger_file, - XTL_DEBUG, 0); - if (!priv->logger) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot create libxenlight logger for domain %s"), - vm->def->name); - goto cleanup; - } - - if (libxl_ctx_alloc(&priv->ctx, LIBXL_VERSION, 0, priv->logger)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Failed libxl context initialization")); - goto cleanup; - } - - libxl_osevent_register_hooks(priv->ctx, &libxl_event_callbacks, priv); - - ret = 0; - -cleanup: - VIR_FREE(log_file); - return ret; -} - -static void * -libxlDomainObjPrivateAlloc(void) -{ - libxlDomainObjPrivatePtr priv; - - if (libxlDomainObjPrivateInitialize() < 0) - return NULL; - - if (!(priv = virObjectLockableNew(libxlDomainObjPrivateClass))) - return NULL; - - if (!(priv->devs = virChrdevAlloc())) { - virObjectUnref(priv); - return NULL; - } - - return priv; -} - -static void -libxlDomainObjPrivateDispose(void *obj) -{ - libxlDomainObjPrivatePtr priv = obj; - - if (priv->deathW) - libxl_evdisable_domain_death(priv->ctx, priv->deathW); - - virChrdevFree(priv->devs); - - xtl_logger_destroy(priv->logger); - if (priv->logger_file) - VIR_FORCE_FCLOSE(priv->logger_file); - - libxl_ctx_free(priv->ctx); -} - -static void -libxlDomainObjPrivateFree(void *data) -{ - libxlDomainObjPrivatePtr priv = data; - - if (priv->deathW) { - libxl_evdisable_domain_death(priv->ctx, priv->deathW); - priv->deathW = NULL; - } - - virObjectUnref(priv); -} - -virDomainXMLPrivateDataCallbacks libxlDomainXMLPrivateDataCallbacks = { - .alloc = libxlDomainObjPrivateAlloc, - .free = libxlDomainObjPrivateFree, -}; - - -static int -libxlDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, - virDomainDefPtr def, - virCapsPtr caps ATTRIBUTE_UNUSED, - void *opaque ATTRIBUTE_UNUSED) -{ - if (dev->type == VIR_DOMAIN_DEVICE_CHR && - dev->data.chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE && - dev->data.chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE && - STRNEQ(def->os.type, "hvm")) - dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN; - - return 0; -} - - -virDomainDefParserConfig libxlDomainDefParserConfig = { - .macPrefix = { 0x00, 0x16, 0x3e }, - .devicesPostParseCallback = libxlDomainDeviceDefPostParse, -}; - - /* driver must be locked before calling */ static void libxlDomainEventQueue(libxlDriverPrivatePtr driver, virDomainEventPtr event) @@ -728,7 +296,7 @@ libxlVmCleanup(libxlDriverPrivatePtr driver, vm->newDef = NULL; } - libxlRegisteredTimeoutsCleanup(priv); + libxlDomainObjRegisteredTimeoutsCleanup(priv); } /*