Files
xen/tools/libxl/libxl_internal.h
T
Olaf Hering b46dfd222e libxl: add pid path to libxl__spawner_starting
libxl_spawner_record_pid() should be able to write the pid to arbitrary paths.

v2:
 - use const char* for ->pid_path, and update comment

Signed-off-by: Olaf Hering <olaf@aepfle.de>
Acked-by: Ian Jackson <ian.jackson.citrix.com>
Committed-by: Ian Jackson <ian.jackson.citrix.com>
2011-10-27 11:20:25 +02:00

560 lines
22 KiB
C

/*
* Copyright (C) 2009 Citrix Ltd.
* Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
* Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
*
* This program 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; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* This program 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.
*/
#ifndef LIBXL_INTERNAL_H
#define LIBXL_INTERNAL_H
#include <stdint.h>
#include <stdarg.h>
#include <stdlib.h>
#include <xs.h>
#include <xenctrl.h>
#include "xentoollog.h"
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
#define _hidden __attribute__((visibility("hidden")))
#define _protected __attribute__((visibility("protected")))
#else
#define _hidden
#define _protected
#endif
#include "flexarray.h"
#include "libxl_utils.h"
#include "_libxl_types_internal.h"
#include "libxl_json.h"
#define LIBXL_DESTROY_TIMEOUT 10
#define LIBXL_DEVICE_MODEL_START_TIMEOUT 10
#define LIBXL_XENCONSOLE_LIMIT 1048576
#define LIBXL_XENCONSOLE_PROTOCOL "vt100"
#define LIBXL_MAXMEM_CONSTANT 1024
#define LIBXL_PV_EXTRA_MEMORY 1024
#define LIBXL_HVM_EXTRA_MEMORY 2048
#define LIBXL_MIN_DOM0_MEM (128*1024)
#define QEMU_SIGNATURE "DeviceModelRecord0002"
#define STUBDOM_CONSOLE_LOGGING 0
#define STUBDOM_CONSOLE_SAVE 1
#define STUBDOM_CONSOLE_RESTORE 2
#define STUBDOM_CONSOLE_SERIAL 3
#define STUBDOM_SPECIAL_CONSOLES 3
#define SAVEFILE "/var/lib/xen/qemu-save"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#define LIBXL__LOGGING_ENABLED
#ifdef LIBXL__LOGGING_ENABLED
#define LIBXL__LOG(ctx, loglevel, _f, _a...) libxl__log(ctx, loglevel, -1, __FILE__, __LINE__, __func__, _f, ##_a)
#define LIBXL__LOG_ERRNO(ctx, loglevel, _f, _a...) libxl__log(ctx, loglevel, errno, __FILE__, __LINE__, __func__, _f, ##_a)
#define LIBXL__LOG_ERRNOVAL(ctx, loglevel, errnoval, _f, _a...) libxl__log(ctx, loglevel, errnoval, __FILE__, __LINE__, __func__, _f, ##_a)
#else
#define LIBXL__LOG(ctx, loglevel, _f, _a...)
#define LIBXL__LOG_ERRNO(ctx, loglevel, _f, _a...)
#define LIBXL__LOG_ERRNOVAL(ctx, loglevel, errnoval, _f, _a...)
#endif
/* all of these macros preserve errno (saving and restoring) */
/* logging */
_hidden void libxl__logv(libxl_ctx *ctx, xentoollog_level msglevel, int errnoval,
const char *file /* may be 0 */, int line /* ignored if !file */,
const char *func /* may be 0 */,
char *fmt, va_list al)
__attribute__((format(printf,7,0)));
_hidden void libxl__log(libxl_ctx *ctx, xentoollog_level msglevel, int errnoval,
const char *file /* may be 0 */, int line /* ignored if !file */,
const char *func /* may be 0 */,
char *fmt, ...)
__attribute__((format(printf,7,8)));
/* these functions preserve errno (saving and restoring) */
struct libxl__ctx {
xentoollog_logger *lg;
xc_interface *xch;
struct xs_handle *xsh;
/* for callers who reap children willy-nilly; caller must only
* set this after libxl_init and before any other call - or
* may leave them untouched */
int (*waitpid_instead)(pid_t pid, int *status, int flags);
libxl_version_info version_info;
};
typedef struct {
uint32_t backend_devid;
uint32_t backend_domid;
uint32_t devid;
uint32_t domid;
libxl__device_kind backend_kind;
libxl__device_kind kind;
} libxl__device;
#define XC_PCI_BDF "0x%x, 0x%x, 0x%x, 0x%x"
#define AUTO_PHP_SLOT 0x100
#define SYSFS_PCI_DEV "/sys/bus/pci/devices"
#define SYSFS_PCIBACK_DRIVER "/sys/bus/pci/drivers/pciback"
#define XENSTORE_PID_FILE "/var/run/xenstored.pid"
#define PROC_PCI_NUM_RESOURCES 7
#define PCI_BAR_IO 0x01
#define PRINTF_ATTRIBUTE(x, y) __attribute__((format(printf, x, y)))
typedef struct {
/* mini-GC */
int alloc_maxsize;
void **alloc_ptrs;
libxl_ctx *owner;
} libxl__gc;
#define LIBXL_INIT_GC(ctx) (libxl__gc){ .alloc_maxsize = 0, .alloc_ptrs = 0, .owner = ctx }
static inline libxl_ctx *libxl__gc_owner(libxl__gc *gc)
{
return gc->owner;
}
/*
* Memory allocation tracking/helpers
*
* See comment "libxl memory management" in libxl.h for a description
* of the framework which these calls belong to.
*
* These functions deal with memory allocations of type (a) and (d) in
* that description.
*
* All pointers returned by these functions are registered for garbage
* collection on exit from the outermost libxl callframe.
*/
/* register @ptr in @gc for free on exit from outermost libxl callframe. */
_hidden int libxl__ptr_add(libxl__gc *gc, void *ptr);
/* if this is the outermost libxl callframe then free all pointers in @gc */
_hidden void libxl__free_all(libxl__gc *gc);
/* allocate and zero @bytes. (similar to a gc'd malloc(3)+memzero()) */
_hidden void *libxl__zalloc(libxl__gc *gc, int bytes);
/* allocate and zero memory for an array of @nmemb members of @size each.
* (similar to a gc'd calloc(3)). */
_hidden void *libxl__calloc(libxl__gc *gc, size_t nmemb, size_t size);
/* change the size of the memory block pointed to by @ptr to @new_size bytes.
* unlike other allocation functions here any additional space between the
* oldsize and @new_size is not initialised (similar to a gc'd realloc(3)). */
_hidden void *libxl__realloc(libxl__gc *gc, void *ptr, size_t new_size);
/* print @fmt into an allocated string large enoughto contain the result.
* (similar to gc'd asprintf(3)). */
_hidden char *libxl__sprintf(libxl__gc *gc, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
/* duplicate the string @c (similar to a gc'd strdup(3)). */
_hidden char *libxl__strdup(libxl__gc *gc, const char *c);
/* duplicate at most @n bytes of string @c (similar to a gc'd strndup(3)). */
_hidden char *libxl__strndup(libxl__gc *gc, const char *c, size_t n);
/* strip the last path component from @s and return as a newly allocated
* string. (similar to a gc'd dirname(3)). */
_hidden char *libxl__dirname(libxl__gc *gc, const char *s);
_hidden char **libxl__xs_kvs_of_flexarray(libxl__gc *gc, flexarray_t *array, int length);
_hidden int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
char *dir, char **kvs);
_hidden int libxl__xs_write(libxl__gc *gc, xs_transaction_t t,
char *path, const char *fmt, ...) PRINTF_ATTRIBUTE(4, 5);
/* Each fn returns 0 on success.
* On error: returns -1, sets errno (no logging) */
_hidden char *libxl__xs_get_dompath(libxl__gc *gc, uint32_t domid);
/* On error: logs, returns NULL, sets errno. */
_hidden char *libxl__xs_read(libxl__gc *gc, xs_transaction_t t, char *path);
_hidden char **libxl__xs_directory(libxl__gc *gc, xs_transaction_t t,
char *path, unsigned int *nb);
/* On error: returns NULL, sets errno (no logging) */
/* from xl_dom */
_hidden libxl_domain_type libxl__domain_type(libxl__gc *gc, uint32_t domid);
_hidden int libxl__domain_shutdown_reason(libxl__gc *gc, uint32_t domid);
#define LIBXL__DOMAIN_IS_TYPE(gc, domid, type) \
libxl__domain_type((gc), (domid)) == LIBXL_DOMAIN_TYPE_##type
typedef struct {
uint32_t store_port;
unsigned long store_mfn;
uint32_t console_port;
unsigned long console_mfn;
} libxl__domain_build_state;
_hidden int libxl__build_pre(libxl__gc *gc, uint32_t domid,
libxl_domain_build_info *info, libxl__domain_build_state *state);
_hidden int libxl__build_post(libxl__gc *gc, uint32_t domid,
libxl_domain_build_info *info, libxl__domain_build_state *state,
char **vms_ents, char **local_ents);
_hidden int libxl__build_pv(libxl__gc *gc, uint32_t domid,
libxl_domain_build_info *info, libxl__domain_build_state *state);
_hidden int libxl__build_hvm(libxl__gc *gc, uint32_t domid,
libxl_domain_build_info *info,
libxl_device_model_info *dm_info,
libxl__domain_build_state *state);
_hidden int libxl__domain_rename(libxl__gc *gc, uint32_t domid,
const char *old_name, const char *new_name,
xs_transaction_t trans);
_hidden int libxl__domain_restore_common(libxl__gc *gc, uint32_t domid,
libxl_domain_build_info *info,
libxl__domain_build_state *state,
int fd);
_hidden int libxl__domain_suspend_common(libxl__gc *gc, uint32_t domid, int fd,
libxl_domain_type type,
int live, int debug);
_hidden int libxl__domain_save_device_model(libxl__gc *gc, uint32_t domid, int fd);
_hidden void libxl__userdata_destroyall(libxl__gc *gc, uint32_t domid);
/* from xl_device */
_hidden char *libxl__device_disk_string_of_backend(libxl_disk_backend backend);
_hidden char *libxl__device_disk_string_of_format(libxl_disk_format format);
_hidden int libxl__device_disk_set_backend(libxl__gc*, libxl_device_disk*);
_hidden int libxl__device_physdisk_major_minor(const char *physpath, int *major, int *minor);
_hidden int libxl__device_disk_dev_number(const char *virtpath,
int *pdisk, int *ppartition);
_hidden int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
libxl_device_console *console,
libxl__domain_build_state *state);
_hidden int libxl__device_generic_add(libxl__gc *gc, libxl__device *device,
char **bents, char **fents);
_hidden char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device);
_hidden char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device);
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
libxl__device *dev);
_hidden int libxl__device_remove(libxl__gc *gc, libxl__device *dev, int wait);
_hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
_hidden int libxl__devices_destroy(libxl__gc *gc, uint32_t domid, int force);
_hidden int libxl__wait_for_backend(libxl__gc *gc, char *be_path, char *state);
/* from libxl_pci */
_hidden int libxl__device_pci_add(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev, int starting);
_hidden int libxl__create_pci_backend(libxl__gc *gc, uint32_t domid,
libxl_device_pci *pcidev, int num);
_hidden int libxl__device_pci_destroy_all(libxl__gc *gc, uint32_t domid);
/* xl_exec */
/* higher-level double-fork and separate detach eg as for device models */
typedef struct {
/* put this in your own status structure as returned to application */
/* all fields are private to libxl_spawn_... */
pid_t intermediate;
int fd;
char *what; /* malloc'd in spawn_spawn */
} libxl__spawn_starting;
typedef struct {
char *dom_path; /* from libxl_malloc, only for libxl_spawner_record_pid */
const char *pid_path; /* only for libxl_spawner_record_pid */
int domid;
libxl__spawn_starting *for_spawn;
} libxl__spawner_starting;
/* from xl_create */
_hidden int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info, uint32_t *domid);
_hidden int libxl__domain_build(libxl__gc *gc,
libxl_domain_build_info *info,
libxl_device_model_info *dm_info,
uint32_t domid,
libxl__domain_build_state *state);
/* for device model creation */
_hidden const char *libxl__domain_device_model(libxl__gc *gc,
libxl_device_model_info *info);
_hidden int libxl__create_device_model(libxl__gc *gc,
libxl_device_model_info *info,
libxl_device_disk *disk, int num_disks,
libxl_device_nic *vifs, int num_vifs,
libxl__spawner_starting **starting_r);
_hidden int libxl__create_xenpv_qemu(libxl__gc *gc, uint32_t domid,
libxl_device_model_info *dm_info,
libxl_device_vfb *vfb,
libxl__spawner_starting **starting_r);
_hidden int libxl__need_xenpv_qemu(libxl__gc *gc,
int nr_consoles, libxl_device_console *consoles,
int nr_vfbs, libxl_device_vfb *vfbs,
int nr_disks, libxl_device_disk *disks);
/* Caller must either: pass starting_r==0, or on successful
* return pass *starting_r (which will be non-0) to
* libxl_confirm_device_model or libxl_detach_device_model. */
_hidden int libxl__confirm_device_model_startup(libxl__gc *gc,
libxl__spawner_starting *starting);
_hidden int libxl__detach_device_model(libxl__gc *gc, libxl__spawner_starting *starting);
_hidden int libxl__wait_for_device_model(libxl__gc *gc,
uint32_t domid, char *state,
libxl__spawn_starting *spawning,
int (*check_callback)(libxl__gc *gc,
uint32_t domid,
const char *state,
void *userdata),
void *check_callback_userdata);
_hidden int libxl__spawn_spawn(libxl__gc *gc,
libxl__spawn_starting *starting,
const char *what,
void (*intermediate_hook)(void *for_spawn, pid_t innerchild),
void *hook_data);
_hidden int libxl__destroy_device_model(libxl__gc *gc, uint32_t domid);
_hidden void libxl_spawner_record_pid(void *for_spawn, pid_t innerchild);
/* Logs errors. A copy of "what" is taken. Return values:
* < 0 error, for_spawn need not be detached
* +1 caller is the parent, must call detach on *for_spawn eventually
* 0 caller is now the inner child, should probably call libxl__exec
* Caller, may pass 0 for for_spawn, in which case no need to detach.
*/
_hidden int libxl__spawn_detach(libxl__gc *gc,
libxl__spawn_starting *for_spawn);
/* Logs errors. Idempotent, but only permitted after successful
* call to libxl__spawn_spawn, and no point calling it again if it fails. */
_hidden int libxl__spawn_check(libxl__gc *gc,
void *for_spawn);
/* Logs errors but also returns them.
* for_spawn must actually be a libxl__spawn_starting* but
* we take void* so you can pass this function directly to
* libxl__wait_for_device_model. Caller must still call detach. */
/* low-level stuff, for synchronous subprocesses etc. */
_hidden void libxl__exec(int stdinfd, int stdoutfd, int stderrfd,
const char *arg0, char **args); // logs errors, never returns
_hidden void libxl__log_child_exitstatus(libxl__gc *gc,
const char *what, pid_t pid, int status);
_hidden char *libxl__abs_path(libxl__gc *gc, const char *s, const char *path);
#define LIBXL__LOG_DEBUG XTL_DEBUG
#define LIBXL__LOG_INFO XTL_INFO
#define LIBXL__LOG_WARNING XTL_WARN
#define LIBXL__LOG_ERROR XTL_ERROR
_hidden char *libxl__domid_to_name(libxl__gc *gc, uint32_t domid);
_hidden char *libxl__cpupoolid_to_name(libxl__gc *gc, uint32_t poolid);
_hidden int libxl__enum_from_string(const libxl_enum_string_table *t,
const char *s, int *e);
_hidden yajl_gen_status libxl__yajl_gen_asciiz(yajl_gen hand, const char *str);
_hidden yajl_gen_status libxl__string_gen_json(yajl_gen hand, const char *p);
typedef yajl_gen_status (*libxl__gen_json_callback)(yajl_gen hand, void *);
_hidden char *libxl__object_to_json(libxl_ctx *ctx, const char *type,
libxl__gen_json_callback gen, void *p);
/* holds the CPUID response for a single CPUID leaf
* input contains the value of the EAX and ECX register,
* and each policy string contains a filter to apply to
* the host given values for that particular leaf.
*/
struct libxl__cpuid_policy {
uint32_t input[2];
char *policy[4];
};
/*
* blktap2 support
*/
/* libxl__blktap_enabled:
* return true if blktap/blktap2 support is available.
*/
_hidden int libxl__blktap_enabled(libxl__gc *gc);
/* libxl__blktap_devpath:
* Argument: path and disk image as specified in config file.
* The type specifies whether this is aio, qcow, qcow2, etc.
* returns device path xenstore wants to have. returns NULL
* if no device corresponds to the disk.
*/
_hidden char *libxl__blktap_devpath(libxl__gc *gc,
const char *disk,
libxl_disk_format format);
/* libxl__device_destroy_tapdisk:
* Destroys any tapdisk process associated with the backend represented
* by be_path.
*/
_hidden void libxl__device_destroy_tapdisk(libxl__gc *gc, char *be_path);
_hidden char *libxl__uuid2string(libxl__gc *gc, const libxl_uuid uuid);
struct libxl__xen_console_reader {
char *buffer;
unsigned int size;
unsigned int count;
unsigned int clear;
unsigned int incremental;
unsigned int index;
};
_hidden int libxl__error_set(libxl__gc *gc, int code);
_hidden int libxl__file_reference_map(libxl_file_reference *f);
_hidden int libxl__file_reference_unmap(libxl_file_reference *f);
_hidden int libxl__fd_set_cloexec(int fd);
_hidden int libxl__e820_alloc(libxl__gc *gc, uint32_t domid, libxl_domain_config *d_config);
/* parse the string @s as a sequence of 6 colon separated bytes in to @mac */
_hidden int libxl__parse_mac(const char *s, libxl_mac mac);
/* compare mac address @a and @b. 0 if the same, -ve if a<b and +ve if a>b */
_hidden int libxl__compare_macs(libxl_mac *a, libxl_mac *b);
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
/* from libxl_qmp */
typedef struct libxl__qmp_handler libxl__qmp_handler;
/* Initialise and connect to the QMP socket.
* Return an handler or NULL if there is an error
*/
_hidden libxl__qmp_handler *libxl__qmp_initialize(libxl_ctx *ctx,
uint32_t domid);
/* ask to QEMU the serial port information and store it in xenstore. */
_hidden int libxl__qmp_query_serial(libxl__qmp_handler *qmp);
/* close and free the QMP handler */
_hidden void libxl__qmp_close(libxl__qmp_handler *qmp);
/* remove the socket file, if the file has already been removed,
* nothing happen */
_hidden void libxl__qmp_cleanup(libxl__gc *gc, uint32_t domid);
/* this helper calls qmp_initialize, query_serial and qmp_close */
_hidden int libxl__qmp_initializations(libxl_ctx *ctx, uint32_t domid);
/* from libxl_json */
#include <yajl/yajl_gen.h>
_hidden yajl_gen_status libxl__yajl_gen_asciiz(yajl_gen hand, const char *str);
_hidden yajl_gen_status libxl__yajl_gen_enum(yajl_gen hand, const char *str);
typedef enum {
JSON_ERROR,
JSON_NULL,
JSON_TRUE,
JSON_FALSE,
JSON_INTEGER,
JSON_DOUBLE,
JSON_STRING,
JSON_MAP,
JSON_ARRAY,
JSON_ANY
} libxl__json_node_type;
typedef struct libxl__json_object {
libxl__json_node_type type;
union {
long i;
double d;
char *string;
/* List of libxl__json_object */
flexarray_t *array;
/* List of libxl__json_map_node */
flexarray_t *map;
} u;
struct libxl__json_object *parent;
} libxl__json_object;
typedef struct {
char *map_key;
libxl__json_object *obj;
} libxl__json_map_node;
typedef struct libxl__yajl_ctx libxl__yajl_ctx;
static inline bool libxl__json_object_is_string(const libxl__json_object *o)
{
return o != NULL && o->type == JSON_STRING;
}
static inline bool libxl__json_object_is_integer(const libxl__json_object *o)
{
return o != NULL && o->type == JSON_INTEGER;
}
static inline bool libxl__json_object_is_map(const libxl__json_object *o)
{
return o != NULL && o->type == JSON_MAP;
}
static inline bool libxl__json_object_is_array(const libxl__json_object *o)
{
return o != NULL && o->type == JSON_ARRAY;
}
static inline
const char *libxl__json_object_get_string(const libxl__json_object *o)
{
if (libxl__json_object_is_string(o))
return o->u.string;
else
return NULL;
}
static inline
flexarray_t *libxl__json_object_get_map(const libxl__json_object *o)
{
if (libxl__json_object_is_map(o))
return o->u.map;
else
return NULL;
}
static inline
flexarray_t *libxl__json_object_get_array(const libxl__json_object *o)
{
if (libxl__json_object_is_array(o))
return o->u.array;
else
return NULL;
}
static inline long libxl__json_object_get_integer(const libxl__json_object *o)
{
if (libxl__json_object_is_integer(o))
return o->u.i;
else
return -1;
}
_hidden libxl__json_object *libxl__json_array_get(const libxl__json_object *o,
int i);
_hidden
libxl__json_map_node *libxl__json_map_node_get(const libxl__json_object *o,
int i);
_hidden const libxl__json_object *libxl__json_map_get(const char *key,
const libxl__json_object *o,
libxl__json_node_type expected_type);
_hidden void libxl__json_object_free(libxl__gc *gc, libxl__json_object *obj);
_hidden libxl__json_object *libxl__json_parse(libxl__gc *gc, const char *s);
#endif
/*
* Local variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/