debuggers.hg

annotate tools/libxl/libxl.c @ 22023:51147d5b17c3

xl: Implement per-API-call garbage-collection lifetime

Currently scratch variables allocated by libxl have the same lifetime as
the context. While this is suitable for one off invocations of xl. It is
not so great for a daemon process linking to libxl. In that case there
will be prolific leakage of heap memory.

My proposed solution involves create a new libxl_gc structure, which
contains a pointer to an owning context as well as the garbage
collection data. Top-level library functions which expect to do a lot of
scratch allocations put gc struct on the stack and initialize it with a
macro. Before returning they then call libxl_free_all on this struct.
This means that static helper functions called by such functions will
usually take a gc instead of a ctx as a first parameter.

The patch touches almost every code-path so a close review and testing
would be much appreciated. I have tested with valgrind all of the parts
I could which looked non-straightforward. Suffice to say that it seems
crash-free even if we have exposed a few real memory leaks. These are
for cases where we return eg. block list to an xl caller but there is no
appropriate block_list_free() function to call. Ian Campbells work in
this area should sew up all these loose ends.

Signed-off-by: Gianni Tedesco <gianni.tedesco@citrix.com>
committer: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Gianni Tedesco <gianni.tedesco@citrix.com>
date Thu Aug 12 18:55:16 2010 +0100 (2010-08-12)
parents ca51dba3a7b1
children b991ed313c73
rev   line source
keir@20462 1 /*
keir@20462 2 * Copyright (C) 2009 Citrix Ltd.
keir@20462 3 * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
keir@20462 4 * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
keir@20462 5 *
keir@20462 6 * This program is free software; you can redistribute it and/or modify
keir@20462 7 * it under the terms of the GNU Lesser General Public License as published
keir@20462 8 * by the Free Software Foundation; version 2.1 only. with the special
keir@20462 9 * exception on linking described in file LICENSE.
keir@20462 10 *
keir@20462 11 * This program is distributed in the hope that it will be useful,
keir@20462 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
keir@20462 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
keir@20462 14 * GNU Lesser General Public License for more details.
keir@20462 15 */
keir@20462 16
keir@20513 17 #include "libxl_osdeps.h"
keir@20513 18
keir@20462 19 #include <stdio.h>
keir@20462 20 #include <string.h>
keir@20462 21 #include <stdlib.h>
keir@20462 22 #include <sys/types.h>
zhigang@21941 23 #include <sys/stat.h>
keir@20462 24 #include <fcntl.h>
keir@20462 25 #include <sys/select.h>
Ian@21848 26 #include <sys/mman.h>
keir@20514 27 #include <sys/wait.h>
keir@20462 28 #include <signal.h>
keir@20468 29 #include <unistd.h> /* for write, unlink and close */
keir@20509 30 #include <stdint.h>
keir@20509 31 #include <inttypes.h>
keir@20514 32 #include <assert.h>
keir@20513 33
keir@20462 34 #include "libxl.h"
keir@20462 35 #include "libxl_utils.h"
keir@20462 36 #include "libxl_internal.h"
keir@20462 37 #include "flexarray.h"
Ian@21903 38 #include "tap-ctl.h"
keir@20462 39
keir@20860 40 #define PAGE_TO_MEMKB(pages) ((pages) * 4)
keir@20860 41
ian@21930 42 int libxl_ctx_init(libxl_ctx *ctx, int version, xentoollog_logger *lg)
keir@20462 43 {
keir@20788 44 if (version != LIBXL_VERSION)
keir@20788 45 return ERROR_VERSION;
ian@21930 46 memset(ctx, 0, sizeof(libxl_ctx));
keir@21532 47 ctx->lg = lg;
keir@21266 48 memset(&ctx->version_info, 0, sizeof(libxl_version_info));
keir@20462 49
keir@21532 50 ctx->xch = xc_interface_open(lg,lg,0);
keir@21529 51 if (!ctx->xch) {
keir@21681 52 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno,
keir@21681 53 "cannot open libxc handle");
keir@20819 54 return ERROR_FAIL;
keir@20819 55 }
keir@20819 56
keir@20462 57 ctx->xsh = xs_daemon_open();
keir@20819 58 if (!ctx->xsh) {
keir@21681 59 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno,
keir@21681 60 "cannot connect to xenstore");
keir@20819 61 xc_interface_close(ctx->xch);
keir@20819 62 return ERROR_FAIL;
keir@20819 63 }
keir@20462 64 return 0;
keir@20462 65 }
keir@20462 66
gianni@22008 67 static void do_free_version_info(libxl_version_info *info);
ian@21930 68 int libxl_ctx_free(libxl_ctx *ctx)
keir@20462 69 {
keir@20462 70 xc_interface_close(ctx->xch);
gianni@22008 71 do_free_version_info(&ctx->version_info);
keir@21186 72 if (ctx->xsh) xs_daemon_close(ctx->xsh);
keir@20462 73 return 0;
keir@20462 74 }
keir@20462 75
keir@20462 76 /******************************************************************************/
keir@20462 77
ian@21930 78 int libxl_domain_make(libxl_ctx *ctx, libxl_domain_create_info *info,
keir@20462 79 uint32_t *domid)
keir@20462 80 {
gianni@22023 81 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21184 82 int flags, ret, i, rc;
keir@20468 83 char *uuid_string;
keir@20646 84 char *rw_paths[] = { "device", "device/suspend/event-channel" , "data"};
keir@20462 85 char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers",
keir@20646 86 "control", "attr", "messages" };
ian@21894 87 char *dom_path, *vm_path;
keir@20462 88 struct xs_permissions roperm[2];
keir@20462 89 struct xs_permissions rwperm[1];
keir@20462 90 xs_transaction_t t;
keir@20468 91 xen_domain_handle_t handle;
keir@20462 92
keir@21188 93 uuid_string = libxl_uuid2string(ctx, info->uuid);
gianni@22023 94 if (!uuid_string) {
gianni@22023 95 libxl_free_all(&gc);
gianni@22023 96 return ERROR_NOMEM;
gianni@22023 97 }
keir@20462 98
keir@20462 99 flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0;
keir@20462 100 flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0;
keir@21274 101 flags |= info->oos ? 0 : XEN_DOMCTL_CDF_oos_off;
keir@20824 102 *domid = -1;
keir@20462 103
keir@20580 104 /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
keir@20580 105 memcpy(handle, info->uuid, sizeof(xen_domain_handle_t));
keir@20468 106
keir@20468 107 ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid);
keir@20462 108 if (ret < 0) {
keir@20512 109 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "domain creation fail");
gianni@22023 110 libxl_free_all(&gc);
keir@20462 111 return ERROR_FAIL;
keir@20462 112 }
keir@20462 113
keir@21368 114 ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid);
keir@21368 115 if (ret < 0) {
keir@21368 116 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "domain move fail");
gianni@22023 117 libxl_free_all(&gc);
keir@21368 118 return ERROR_FAIL;
keir@21368 119 }
keir@21368 120
gianni@22023 121 dom_path = libxl_xs_get_dompath(&gc, *domid);
gianni@22023 122 if (!dom_path) {
gianni@22023 123 libxl_free_all(&gc);
keir@20512 124 return ERROR_FAIL;
gianni@22023 125 }
gianni@22023 126
gianni@22023 127 vm_path = libxl_sprintf(&gc, "/vm/%s", uuid_string);
ian@21894 128 if (!vm_path) {
keir@20462 129 XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate create paths");
gianni@22023 130 libxl_free_all(&gc);
keir@20462 131 return ERROR_FAIL;
keir@20462 132 }
keir@20462 133
keir@20462 134 roperm[0].id = 0;
keir@20462 135 roperm[0].perms = XS_PERM_NONE;
keir@20462 136 roperm[1].id = *domid;
keir@20462 137 roperm[1].perms = XS_PERM_READ;
keir@20462 138 rwperm[0].id = *domid;
keir@20462 139 rwperm[0].perms = XS_PERM_NONE;
keir@20462 140
keir@20462 141 retry_transaction:
keir@20462 142 t = xs_transaction_start(ctx->xsh);
keir@20462 143 xs_rm(ctx->xsh, t, dom_path);
keir@20462 144 xs_mkdir(ctx->xsh, t, dom_path);
keir@20462 145 xs_set_permissions(ctx->xsh, t, dom_path, roperm, ARRAY_SIZE(roperm));
keir@20462 146
keir@20462 147 xs_rm(ctx->xsh, t, vm_path);
keir@20462 148 xs_mkdir(ctx->xsh, t, vm_path);
keir@20462 149 xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
keir@20462 150
gianni@22023 151 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
keir@21184 152 rc = libxl_domain_rename(ctx, *domid, 0, info->name, t);
gianni@22023 153 if (rc) {
gianni@22023 154 libxl_free_all(&gc);
gianni@22023 155 return rc;
gianni@22023 156 }
keir@20462 157
keir@20462 158 for (i = 0; i < ARRAY_SIZE(rw_paths); i++) {
gianni@22023 159 char *path = libxl_sprintf(&gc, "%s/%s", dom_path, rw_paths[i]);
keir@20462 160 xs_mkdir(ctx->xsh, t, path);
keir@20462 161 xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm));
keir@20462 162 }
keir@20462 163 for (i = 0; i < ARRAY_SIZE(ro_paths); i++) {
gianni@22023 164 char *path = libxl_sprintf(&gc, "%s/%s", dom_path, ro_paths[i]);
keir@20462 165 xs_mkdir(ctx->xsh, t, path);
keir@20462 166 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
keir@20462 167 }
keir@20462 168
gianni@22023 169 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
gianni@22023 170 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/name", vm_path), info->name, strlen(info->name));
keir@21389 171 if (info->poolname)
gianni@22023 172 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/pool_name", vm_path), info->poolname, strlen(info->poolname));
gianni@22023 173
gianni@22023 174 libxl_xs_writev(&gc, t, dom_path, info->xsdata);
gianni@22023 175 libxl_xs_writev(&gc, t, libxl_sprintf(&gc, "%s/platform", dom_path), info->platformdata);
gianni@22023 176
gianni@22023 177 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1);
keir@20462 178
keir@20462 179 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20462 180 if (errno == EAGAIN)
keir@20462 181 goto retry_transaction;
gianni@22023 182
gianni@22023 183 libxl_free_all(&gc);
keir@20462 184 return 0;
keir@20462 185 }
keir@20462 186
ian@21930 187 int libxl_domain_rename(libxl_ctx *ctx, uint32_t domid,
keir@21184 188 const char *old_name, const char *new_name,
gianni@22023 189 xs_transaction_t trans)
gianni@22023 190 {
gianni@22023 191 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21184 192 char *dom_path = 0;
keir@21184 193 const char *name_path;
keir@21184 194 char *got_old_name;
keir@21184 195 unsigned int got_old_len;
keir@21184 196 xs_transaction_t our_trans = 0;
keir@21184 197 int rc;
keir@21184 198
gianni@22023 199 dom_path = libxl_xs_get_dompath(&gc, domid);
keir@21184 200 if (!dom_path) goto x_nomem;
keir@21184 201
gianni@22023 202 name_path= libxl_sprintf(&gc, "%s/name", dom_path);
keir@21184 203 if (!name_path) goto x_nomem;
keir@21184 204
keir@21184 205 retry_transaction:
keir@21184 206 if (!trans) {
keir@21184 207 trans = our_trans = xs_transaction_start(ctx->xsh);
keir@21184 208 if (!our_trans) {
keir@21184 209 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno,
keir@21184 210 "create xs transaction for domain (re)name");
keir@21184 211 goto x_fail;
keir@21184 212 }
keir@21184 213 }
keir@21184 214
keir@21184 215 if (old_name) {
keir@21184 216 got_old_name = xs_read(ctx->xsh, trans, name_path, &got_old_len);
keir@21184 217 if (!got_old_name) {
keir@21184 218 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno, "check old name"
keir@21184 219 " for domain %"PRIu32" allegedly named `%s'",
keir@21184 220 domid, old_name);
keir@21184 221 goto x_fail;
keir@21184 222 }
keir@21184 223 if (strcmp(old_name, got_old_name)) {
keir@21184 224 XL_LOG(ctx, XL_LOG_ERROR, "domain %"PRIu32" allegedly named "
keir@21184 225 "`%s' is actually named `%s' - racing ?",
keir@21184 226 domid, old_name, got_old_name);
keir@21184 227 free(got_old_name);
keir@21184 228 goto x_fail;
keir@21184 229 }
keir@21184 230 free(got_old_name);
keir@21184 231 }
keir@21184 232 if (!xs_write(ctx->xsh, trans, name_path,
keir@21184 233 new_name, strlen(new_name))) {
keir@21184 234 XL_LOG(ctx, XL_LOG_ERROR, "failed to write new name `%s'"
keir@21184 235 " for domain %"PRIu32" previously named `%s'",
keir@21531 236 new_name, domid, old_name);
keir@21184 237 goto x_fail;
keir@21184 238 }
keir@21184 239
keir@21184 240 if (our_trans) {
keir@21184 241 if (!xs_transaction_end(ctx->xsh, our_trans, 0)) {
keir@21184 242 trans = our_trans = 0;
keir@21184 243 if (errno != EAGAIN) {
keir@21184 244 XL_LOG(ctx, XL_LOG_ERROR, "failed to commit new name `%s'"
keir@21184 245 " for domain %"PRIu32" previously named `%s'",
keir@21531 246 new_name, domid, old_name);
keir@21184 247 goto x_fail;
keir@21184 248 }
keir@21184 249 XL_LOG(ctx, XL_LOG_DEBUG, "need to retry rename transaction"
keir@21184 250 " for domain %"PRIu32" (name_path=\"%s\", new_name=\"%s\")",
keir@21184 251 domid, name_path, new_name);
keir@21184 252 goto retry_transaction;
keir@21184 253 }
keir@21184 254 our_trans = 0;
keir@21184 255 }
keir@21184 256
keir@21184 257 rc = 0;
keir@21184 258 x_rc:
keir@21184 259 if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1);
gianni@22023 260 libxl_free_all(&gc);
keir@21184 261 return rc;
keir@21184 262
keir@21184 263 x_fail: rc = ERROR_FAIL; goto x_rc;
keir@21184 264 x_nomem: rc = ERROR_NOMEM; goto x_rc;
keir@21184 265 }
keir@21184 266
ian@21930 267 int libxl_domain_build(libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid, libxl_domain_build_state *state)
keir@20462 268 {
gianni@22023 269 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20462 270 char **vments = NULL, **localents = NULL;
keir@21438 271 struct timeval start_time;
keir@20829 272 int i, ret;
keir@20829 273
keir@20829 274 ret = build_pre(ctx, domid, info, state);
gianni@22023 275 if (ret)
gianni@22023 276 goto out;
keir@20462 277
keir@21438 278 gettimeofday(&start_time, NULL);
keir@21438 279
keir@20462 280 if (info->hvm) {
keir@20829 281 ret = build_hvm(ctx, domid, info, state);
gianni@22023 282 if (ret)
gianni@22023 283 goto out;
gianni@22023 284
gianni@22023 285 vments = libxl_calloc(&gc, 7, sizeof(char *));
keir@20516 286 vments[0] = "rtc/timeoffset";
keir@20516 287 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
keir@20516 288 vments[2] = "image/ostype";
keir@20516 289 vments[3] = "hvm";
keir@21438 290 vments[4] = "start_time";
gianni@22023 291 vments[5] = libxl_sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
keir@20462 292 } else {
keir@20829 293 ret = build_pv(ctx, domid, info, state);
gianni@22023 294 if (ret)
gianni@22023 295 goto out;
gianni@22023 296
gianni@22023 297 vments = libxl_calloc(&gc, 11, sizeof(char *));
keir@20578 298 i = 0;
keir@20578 299 vments[i++] = "image/ostype";
keir@20578 300 vments[i++] = "linux";
keir@20578 301 vments[i++] = "image/kernel";
Ian@21848 302 vments[i++] = (char*) info->kernel.path;
keir@21438 303 vments[i++] = "start_time";
gianni@22023 304 vments[i++] = libxl_sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
Ian@21848 305 if (info->u.pv.ramdisk.path) {
keir@20578 306 vments[i++] = "image/ramdisk";
Ian@21848 307 vments[i++] = (char*) info->u.pv.ramdisk.path;
keir@20578 308 }
keir@20578 309 if (info->u.pv.cmdline) {
keir@20578 310 vments[i++] = "image/cmdline";
keir@20578 311 vments[i++] = (char*) info->u.pv.cmdline;
keir@20578 312 }
keir@20462 313 }
keir@20829 314 ret = build_post(ctx, domid, info, state, vments, localents);
keir@20829 315 out:
Ian@21848 316 libxl_file_reference_unmap(ctx, &info->kernel);
Ian@21848 317 if (!info->hvm)
Ian@21848 318 libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk);
Ian@21848 319
gianni@22023 320 libxl_free_all(&gc);
keir@20829 321 return ret;
keir@20462 322 }
keir@20462 323
ian@21930 324 int libxl_domain_restore(libxl_ctx *ctx, libxl_domain_build_info *info,
keir@20565 325 uint32_t domid, int fd, libxl_domain_build_state *state,
keir@20565 326 libxl_device_model_info *dm_info)
keir@20462 327 {
gianni@22023 328 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20462 329 char **vments = NULL, **localents = NULL;
keir@21438 330 struct timeval start_time;
keir@21183 331 int i, ret, esave, flags;
keir@20462 332
keir@20829 333 ret = build_pre(ctx, domid, info, state);
gianni@22023 334 if (ret)
gianni@22023 335 goto out;
keir@20829 336
keir@20829 337 ret = restore_common(ctx, domid, info, state, fd);
gianni@22023 338 if (ret)
gianni@22023 339 goto out;
keir@20829 340
keir@21438 341 gettimeofday(&start_time, NULL);
keir@21438 342
keir@20462 343 if (info->hvm) {
gianni@22023 344 vments = libxl_calloc(&gc, 7, sizeof(char *));
keir@20516 345 vments[0] = "rtc/timeoffset";
keir@20516 346 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
keir@20565 347 vments[2] = "image/ostype";
keir@20565 348 vments[3] = "hvm";
keir@21438 349 vments[4] = "start_time";
gianni@22023 350 vments[5] = libxl_sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
keir@20462 351 } else {
gianni@22023 352 vments = libxl_calloc(&gc, 11, sizeof(char *));
keir@20627 353 i = 0;
keir@20627 354 vments[i++] = "image/ostype";
keir@20627 355 vments[i++] = "linux";
keir@20627 356 vments[i++] = "image/kernel";
Ian@21848 357 vments[i++] = (char*) info->kernel.path;
keir@21438 358 vments[i++] = "start_time";
gianni@22023 359 vments[i++] = libxl_sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
Ian@21848 360 if (info->u.pv.ramdisk.path) {
keir@20627 361 vments[i++] = "image/ramdisk";
Ian@21848 362 vments[i++] = (char*) info->u.pv.ramdisk.path;
keir@20627 363 }
keir@20627 364 if (info->u.pv.cmdline) {
keir@20627 365 vments[i++] = "image/cmdline";
keir@20627 366 vments[i++] = (char*) info->u.pv.cmdline;
keir@20627 367 }
keir@20462 368 }
keir@20829 369 ret = build_post(ctx, domid, info, state, vments, localents);
gianni@22023 370 if (ret)
gianni@22023 371 goto out;
keir@20829 372
keir@21417 373 dm_info->saved_state = NULL;
keir@21417 374 if (info->hvm) {
keir@21417 375 ret = asprintf(&dm_info->saved_state,
keir@21417 376 "/var/lib/xen/qemu-save.%d", domid);
keir@21417 377 ret = (ret < 0) ? ERROR_FAIL : 0;
keir@21417 378 }
keir@21417 379
keir@20829 380 out:
Ian@21848 381 libxl_file_reference_unmap(ctx, &info->kernel);
Ian@21848 382 if (!info->hvm)
Ian@21848 383 libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk);
Ian@21848 384
keir@21183 385 esave = errno;
keir@21183 386
keir@21183 387 flags = fcntl(fd, F_GETFL);
keir@21183 388 if (flags == -1) {
keir@21183 389 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to get flags on restore fd");
keir@21183 390 } else {
keir@21183 391 flags &= ~O_NONBLOCK;
keir@21183 392 if (fcntl(fd, F_SETFL, flags) == -1)
keir@21183 393 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to put restore fd"
keir@21183 394 " back to blocking mode");
keir@21183 395 }
keir@21183 396
keir@21183 397 errno = esave;
gianni@22023 398 libxl_free_all(&gc);
keir@20829 399 return ret;
keir@20462 400 }
keir@20462 401
ian@21930 402 int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid)
keir@20629 403 {
gianni@22023 404 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 405 int rc = 0;
gianni@22023 406
keir@20629 407 if (is_hvm(ctx, domid)) {
keir@20629 408 XL_LOG(ctx, XL_LOG_DEBUG, "Called domain_resume on "
keir@20629 409 "non-cooperative hvm domain %u", domid);
gianni@22023 410 rc = ERROR_NI;
gianni@22023 411 goto out;
keir@20629 412 }
keir@20629 413 if (xc_domain_resume(ctx->xch, domid, 1)) {
keir@20629 414 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@20629 415 "xc_domain_resume failed for domain %u",
keir@20629 416 domid);
gianni@22023 417 rc = ERROR_FAIL;
gianni@22023 418 goto out;
keir@20629 419 }
keir@20629 420 if (!xs_resume_domain(ctx->xsh, domid)) {
keir@20629 421 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@20629 422 "xs_resume_domain failed for domain %u",
keir@20629 423 domid);
gianni@22023 424 rc = ERROR_FAIL;
keir@20629 425 }
gianni@22023 426 out:
gianni@22023 427 libxl_free_all(&gc);
keir@20629 428 return 0;
keir@20629 429 }
keir@20629 430
ian@21920 431 /*
ian@21920 432 * Preserves a domain but rewrites xenstore etc to make it unique so
ian@21920 433 * that the domain can be restarted.
ian@21920 434 *
ian@21920 435 * Does not modify info so that it may be reused.
ian@21920 436 */
ian@21930 437 int libxl_domain_preserve(libxl_ctx *ctx, uint32_t domid,
Ian@21969 438 libxl_domain_create_info *info, const char *name_suffix, libxl_uuid new_uuid)
ian@21920 439 {
gianni@22023 440 libxl_gc gc = LIBXL_INIT_GC(ctx);
ian@21920 441 struct xs_permissions roperm[2];
ian@21920 442 xs_transaction_t t;
ian@21920 443 char *preserved_name;
ian@21920 444 char *uuid_string;
ian@21920 445 char *vm_path;
ian@21920 446 char *dom_path;
ian@21920 447
ian@21920 448 int rc;
ian@21920 449
gianni@22023 450 preserved_name = libxl_sprintf(&gc, "%s%s", info->name, name_suffix);
gianni@22023 451 if (!preserved_name) {
gianni@22023 452 libxl_free_all(&gc);
gianni@22023 453 return ERROR_NOMEM;
gianni@22023 454 }
ian@21920 455
ian@21920 456 uuid_string = libxl_uuid2string(ctx, new_uuid);
gianni@22023 457 if (!uuid_string) {
gianni@22023 458 libxl_free_all(&gc);
gianni@22023 459 return ERROR_NOMEM;
gianni@22023 460 }
gianni@22023 461
gianni@22023 462 dom_path = libxl_xs_get_dompath(&gc, domid);
gianni@22023 463 if (!dom_path) {
gianni@22023 464 libxl_free_all(&gc);
gianni@22023 465 return ERROR_FAIL;
gianni@22023 466 }
gianni@22023 467
gianni@22023 468 vm_path = libxl_sprintf(&gc, "/vm/%s", uuid_string);
gianni@22023 469 if (!vm_path) {
gianni@22023 470 libxl_free_all(&gc);
gianni@22023 471 return ERROR_FAIL;
gianni@22023 472 }
ian@21920 473
ian@21920 474 roperm[0].id = 0;
ian@21920 475 roperm[0].perms = XS_PERM_NONE;
ian@21920 476 roperm[1].id = domid;
ian@21920 477 roperm[1].perms = XS_PERM_READ;
ian@21920 478
ian@21920 479 retry_transaction:
ian@21920 480 t = xs_transaction_start(ctx->xsh);
ian@21920 481
ian@21920 482 xs_rm(ctx->xsh, t, vm_path);
ian@21920 483 xs_mkdir(ctx->xsh, t, vm_path);
ian@21920 484 xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
ian@21920 485
gianni@22023 486 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
ian@21920 487 rc = libxl_domain_rename(ctx, domid, info->name, preserved_name, t);
ian@21920 488 if (rc) return rc;
ian@21920 489
gianni@22023 490 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
ian@21920 491
ian@21920 492 if (!xs_transaction_end(ctx->xsh, t, 0))
ian@21920 493 if (errno == EAGAIN)
ian@21920 494 goto retry_transaction;
ian@21920 495
gianni@22023 496 libxl_free_all(&gc);
ian@21920 497 return 0;
ian@21920 498 }
ian@21920 499
keir@21189 500 static void xcinfo2xlinfo(const xc_domaininfo_t *xcinfo,
ian@21930 501 libxl_dominfo *xlinfo)
ian@21895 502 {
keir@21189 503 memcpy(&(xlinfo->uuid), xcinfo->handle, sizeof(xen_domain_handle_t));
keir@21189 504 xlinfo->domid = xcinfo->domain;
keir@21189 505
ian@21895 506 xlinfo->dying = !!(xcinfo->flags&XEN_DOMINF_dying);
ian@21895 507 xlinfo->shutdown = !!(xcinfo->flags&XEN_DOMINF_shutdown);
ian@21895 508 xlinfo->paused = !!(xcinfo->flags&XEN_DOMINF_paused);
ian@21895 509 xlinfo->blocked = !!(xcinfo->flags&XEN_DOMINF_blocked);
ian@21895 510 xlinfo->running = !!(xcinfo->flags&XEN_DOMINF_running);
ian@21914 511
ian@21914 512 if (xlinfo->shutdown || xlinfo->dying)
ian@21914 513 xlinfo->shutdown_reason = (xcinfo->flags>>XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask;
ian@21914 514 else
ian@21914 515 xlinfo->shutdown_reason = ~0;
ian@21895 516
keir@21189 517 xlinfo->max_memkb = PAGE_TO_MEMKB(xcinfo->tot_pages);
keir@21189 518 xlinfo->cpu_time = xcinfo->cpu_time;
keir@21189 519 xlinfo->vcpu_max_id = xcinfo->max_vcpu_id;
keir@21189 520 xlinfo->vcpu_online = xcinfo->nr_online_vcpus;
keir@21189 521 }
keir@21189 522
ian@21930 523 libxl_dominfo * libxl_list_domain(libxl_ctx *ctx, int *nb_domain)
keir@20462 524 {
ian@21930 525 libxl_dominfo *ptr;
keir@20867 526 int i, ret;
keir@20822 527 xc_domaininfo_t info[1024];
keir@20822 528 int size = 1024;
keir@20462 529
ian@21930 530 ptr = calloc(size, sizeof(libxl_dominfo));
gianni@21892 531 if (!ptr) {
gianni@21892 532 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "allocating domain info");
gianni@21892 533 return NULL;
gianni@21892 534 }
keir@20822 535
keir@20860 536 ret = xc_domain_getinfolist(ctx->xch, 0, 1024, info);
gianni@21892 537 if (ret<0) {
gianni@21892 538 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "geting domain info list");
gianni@21892 539 return NULL;
gianni@21892 540 }
keir@20784 541
keir@21189 542 for (i = 0; i < ret; i++) {
keir@21189 543 xcinfo2xlinfo(&info[i], &ptr[i]);
keir@20462 544 }
keir@20867 545 *nb_domain = ret;
keir@20462 546 return ptr;
keir@20462 547 }
keir@20462 548
ian@21930 549 int libxl_domain_info(libxl_ctx *ctx, libxl_dominfo *info_r,
keir@21189 550 uint32_t domid) {
keir@21189 551 xc_domaininfo_t xcinfo;
keir@21189 552 int ret;
keir@21189 553
keir@21189 554 ret = xc_domain_getinfolist(ctx->xch, domid, 1, &xcinfo);
gianni@21892 555 if (ret<0) {
gianni@21892 556 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "geting domain info list");
gianni@21892 557 return ERROR_FAIL;
gianni@21892 558 }
keir@21189 559 if (ret==0 || xcinfo.domain != domid) return ERROR_INVAL;
keir@21189 560
keir@21189 561 xcinfo2xlinfo(&xcinfo, info_r);
keir@21189 562 return 0;
keir@21189 563 }
keir@21189 564
ian@21930 565 libxl_poolinfo * libxl_list_pool(libxl_ctx *ctx, int *nb_pool)
keir@21368 566 {
ian@21930 567 libxl_poolinfo *ptr;
keir@21368 568 int i, ret;
keir@21368 569 xc_cpupoolinfo_t info[256];
keir@21368 570 int size = 256;
keir@21368 571
ian@21930 572 ptr = calloc(size, sizeof(libxl_poolinfo));
gianni@21892 573 if (!ptr) {
gianni@21892 574 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "allocating cpupool info");
gianni@21892 575 return NULL;
gianni@21892 576 }
keir@21368 577
keir@21368 578 ret = xc_cpupool_getinfo(ctx->xch, 0, 256, info);
gianni@21892 579 if (ret<0) {
gianni@21892 580 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting cpupool info");
gianni@21892 581 return NULL;
gianni@21892 582 }
keir@21368 583
keir@21368 584 for (i = 0; i < ret; i++) {
keir@21368 585 ptr[i].poolid = info[i].cpupool_id;
keir@21368 586 }
keir@21368 587 *nb_pool = ret;
keir@21368 588 return ptr;
keir@21368 589 }
keir@21368 590
keir@20860 591 /* this API call only list VM running on this host. a VM can be an aggregate of multiple domains. */
ian@21930 592 libxl_vminfo * libxl_list_vm(libxl_ctx *ctx, int *nb_vm)
keir@20860 593 {
ian@21930 594 libxl_vminfo *ptr;
keir@20860 595 int index, i, ret;
keir@20860 596 xc_domaininfo_t info[1024];
keir@20860 597 int size = 1024;
keir@20860 598
ian@21930 599 ptr = calloc(size, sizeof(libxl_dominfo));
keir@20860 600 if (!ptr)
keir@20860 601 return NULL;
keir@20860 602
keir@20860 603 ret = xc_domain_getinfolist(ctx->xch, 1, 1024, info);
gianni@21892 604 if (ret<0) {
gianni@21892 605 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "geting domain info list");
gianni@21892 606 return NULL;
gianni@21892 607 }
keir@20860 608 for (index = i = 0; i < ret; i++) {
keir@20860 609 if (libxl_is_stubdom(ctx, info[i].domain, NULL))
keir@20860 610 continue;
keir@20860 611 memcpy(&(ptr[index].uuid), info[i].handle, sizeof(xen_domain_handle_t));
keir@20860 612 ptr[index].domid = info[i].domain;
keir@20860 613
keir@20860 614 index++;
keir@20860 615 }
keir@20860 616 *nb_vm = index;
keir@20860 617 return ptr;
keir@20860 618 }
keir@20860 619
ian@21930 620 int libxl_domain_suspend(libxl_ctx *ctx, libxl_domain_suspend_info *info,
keir@20462 621 uint32_t domid, int fd)
keir@20462 622 {
keir@20565 623 int hvm = is_hvm(ctx, domid);
keir@20565 624 int live = info != NULL && info->flags & XL_SUSPEND_LIVE;
keir@21543 625 int debug = info != NULL && info->flags & XL_SUSPEND_DEBUG;
gianni@22023 626 int rc = 0;
keir@20462 627
keir@20462 628 core_suspend(ctx, domid, fd, hvm, live, debug);
keir@20565 629 if (hvm)
gianni@22023 630 rc = save_device_model(ctx, domid, fd);
gianni@22023 631 return rc;
keir@20462 632 }
keir@20462 633
ian@21930 634 int libxl_domain_pause(libxl_ctx *ctx, uint32_t domid)
keir@20462 635 {
gianni@21892 636 int ret;
gianni@21892 637 ret = xc_domain_pause(ctx->xch, domid);
gianni@21892 638 if (ret<0) {
gianni@21892 639 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "pausing domain %d", domid);
gianni@21892 640 return ERROR_FAIL;
gianni@21892 641 }
Ian@21888 642 return 0;
keir@20462 643 }
keir@20462 644
ian@21930 645 int libxl_domain_core_dump(libxl_ctx *ctx, uint32_t domid,
gianni@21892 646 const char *filename)
sstabellini@21870 647 {
gianni@21892 648 int ret;
gianni@21892 649 ret = xc_domain_dumpcore(ctx->xch, domid, filename);
gianni@21892 650 if (ret<0) {
gianni@21892 651 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "core dumping domain %d to %s",
gianni@21892 652 domid, filename);
Ian@21888 653 return ERROR_FAIL;
gianni@21892 654 }
Ian@21888 655 return 0;
sstabellini@21870 656 }
sstabellini@21870 657
ian@21930 658 int libxl_domain_unpause(libxl_ctx *ctx, uint32_t domid)
keir@20462 659 {
gianni@22023 660 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20779 661 char *path;
keir@20565 662 char *state;
gianni@22023 663 int ret, rc = 0;
keir@20565 664
keir@20565 665 if (is_hvm(ctx, domid)) {
gianni@22023 666 path = libxl_sprintf(&gc, "/local/domain/0/device-model/%d/state", domid);
gianni@22023 667 state = libxl_xs_read(&gc, XBT_NULL, path);
keir@20565 668 if (state != NULL && !strcmp(state, "paused")) {
gianni@22023 669 libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "/local/domain/0/device-model/%d/command", domid), "continue");
keir@20565 670 libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL);
keir@20565 671 }
keir@20565 672 }
gianni@21892 673 ret = xc_domain_unpause(ctx->xch, domid);
gianni@21892 674 if (ret<0) {
gianni@21892 675 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unpausing domain %d", domid);
gianni@22023 676 rc = ERROR_FAIL;
gianni@21892 677 }
gianni@22023 678 libxl_free_all(&gc);
gianni@22023 679 return rc;
keir@20462 680 }
keir@20462 681
keir@20462 682 static char *req_table[] = {
keir@20462 683 [0] = "poweroff",
keir@20462 684 [1] = "reboot",
keir@20462 685 [2] = "suspend",
keir@20462 686 [3] = "crash",
keir@20462 687 [4] = "halt",
keir@20462 688 };
keir@20462 689
ian@21930 690 int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid, int req)
keir@20462 691 {
gianni@22023 692 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20462 693 char *shutdown_path;
keir@20462 694 char *dom_path;
keir@20462 695
gianni@22023 696 if (req > ARRAY_SIZE(req_table)) {
gianni@22023 697 libxl_free_all(&gc);
keir@20462 698 return ERROR_INVAL;
gianni@22023 699 }
gianni@22023 700
gianni@22023 701 dom_path = libxl_xs_get_dompath(&gc, domid);
gianni@22023 702 if (!dom_path) {
gianni@22023 703 libxl_free_all(&gc);
keir@20512 704 return ERROR_FAIL;
gianni@22023 705 }
gianni@22023 706
gianni@22023 707 shutdown_path = libxl_sprintf(&gc, "%s/control/shutdown", dom_path);
keir@20462 708
keir@20462 709 xs_write(ctx->xsh, XBT_NULL, shutdown_path, req_table[req], strlen(req_table[req]));
keir@21552 710 if (is_hvm(ctx,domid)) {
keir@20462 711 unsigned long acpi_s_state = 0;
keir@20462 712 unsigned long pvdriver = 0;
gianni@21892 713 int ret;
gianni@21892 714 ret = xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_ACPI_S_STATE, &acpi_s_state);
gianni@21892 715 if (ret<0) {
gianni@21892 716 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting ACPI S-state");
gianni@21892 717 return ERROR_FAIL;
gianni@21892 718 }
gianni@21892 719 ret = xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
gianni@21892 720 if (ret<0) {
gianni@21892 721 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting HVM callback IRQ");
gianni@21892 722 return ERROR_FAIL;
gianni@21892 723 }
gianni@21892 724 if (!pvdriver || acpi_s_state != 0) {
gianni@21892 725 ret = xc_domain_shutdown(ctx->xch, domid, req);
gianni@21892 726 if (ret<0) {
gianni@21892 727 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unpausing domain");
gianni@21892 728 return ERROR_FAIL;
gianni@21892 729 }
gianni@21892 730 }
keir@20462 731 }
gianni@22023 732 libxl_free_all(&gc);
Ian@21888 733 return 0;
keir@20462 734 }
keir@20462 735
ian@21930 736 int libxl_get_wait_fd(libxl_ctx *ctx, int *fd)
keir@20545 737 {
keir@20545 738 *fd = xs_fileno(ctx->xsh);
keir@20545 739 return 0;
keir@20545 740 }
keir@20545 741
ian@21930 742 int libxl_wait_for_domain_death(libxl_ctx *ctx, uint32_t domid, libxl_waiter *waiter)
keir@20637 743 {
keir@20637 744 waiter->path = strdup("@releaseDomain");
ian@21913 745 if (asprintf(&(waiter->token), "%d", LIBXL_EVENT_DOMAIN_DEATH) < 0)
keir@21417 746 return -1;
keir@20637 747 if (!xs_watch(ctx->xsh, waiter->path, waiter->token))
keir@20637 748 return -1;
keir@20637 749 return 0;
keir@20637 750 }
keir@20637 751
ian@21930 752 int libxl_wait_for_disk_ejects(libxl_ctx *ctx, uint32_t guest_domid, libxl_device_disk *disks, int num_disks, libxl_waiter *waiter)
keir@20637 753 {
gianni@22023 754 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 755 int i, rc = -1;
keir@20637 756 uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid);
keir@20637 757
keir@20637 758 if (!domid)
keir@20637 759 domid = guest_domid;
keir@20637 760
keir@20637 761 for (i = 0; i < num_disks; i++) {
keir@21417 762 if (asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject",
gianni@22023 763 libxl_xs_get_dompath(&gc, domid),
keir@21417 764 device_disk_dev_number(disks[i].virtpath)) < 0)
gianni@22023 765 goto out;
ian@21913 766 if (asprintf(&(waiter[i].token), "%d", LIBXL_EVENT_DISK_EJECT) < 0)
gianni@22023 767 goto out;
keir@20637 768 xs_watch(ctx->xsh, waiter->path, waiter->token);
keir@20637 769 }
gianni@22023 770 rc = 0;
gianni@22023 771 out:
gianni@22023 772 libxl_free_all(&gc);
gianni@22023 773 return rc;
keir@20637 774 }
keir@20637 775
ian@21930 776 int libxl_get_event(libxl_ctx *ctx, libxl_event *event)
keir@20545 777 {
keir@20545 778 unsigned int num;
keir@20637 779 char **events = xs_read_watch(ctx->xsh, &num);
keir@20637 780 if (num != 2) {
keir@20637 781 free(events);
gianni@21892 782 return ERROR_FAIL;
keir@20637 783 }
keir@20637 784 event->path = strdup(events[XS_WATCH_PATH]);
keir@20637 785 event->token = strdup(events[XS_WATCH_TOKEN]);
keir@20637 786 event->type = atoi(event->token);
keir@20637 787 free(events);
keir@20637 788 return 0;
keir@20637 789 }
keir@20637 790
ian@21930 791 int libxl_stop_waiting(libxl_ctx *ctx, libxl_waiter *waiter)
keir@20637 792 {
keir@20637 793 if (!xs_unwatch(ctx->xsh, waiter->path, waiter->token))
gianni@21892 794 return ERROR_FAIL;
keir@20637 795 else
keir@20637 796 return 0;
keir@20637 797 }
keir@20637 798
keir@20637 799 int libxl_free_event(libxl_event *event)
keir@20637 800 {
keir@20637 801 free(event->path);
keir@20637 802 free(event->token);
keir@20637 803 return 0;
keir@20637 804 }
keir@20637 805
keir@20637 806 int libxl_free_waiter(libxl_waiter *waiter)
keir@20637 807 {
keir@20637 808 free(waiter->path);
keir@20637 809 free(waiter->token);
keir@20637 810 return 0;
keir@20637 811 }
keir@20637 812
ian@21930 813 int libxl_event_get_domain_death_info(libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_dominfo *info)
keir@20637 814 {
ian@21916 815 if (libxl_domain_info(ctx, info, domid) < 0)
ian@21916 816 return 0;
ian@21916 817
ian@21916 818 if (info->running || (!info->shutdown && !info->dying))
ian@21916 819 return ERROR_INVAL;
ian@21916 820
ian@21916 821 return 1;
keir@20545 822 }
keir@20545 823
ian@21930 824 int libxl_event_get_disk_eject_info(libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_device_disk *disk)
keir@20637 825 {
gianni@22023 826 libxl_gc gc = LIBXL_INIT_GC(ctx);
ian@21916 827 char *path;
ian@21916 828 char *backend;
ian@21916 829 char *value;
ian@21916 830
gianni@22023 831 value = libxl_xs_read(&gc, XBT_NULL, event->path);
gianni@22023 832
gianni@22023 833 if (!value || strcmp(value, "eject")) {
gianni@22023 834 libxl_free_all(&gc);
ian@21916 835 return 0;
gianni@22023 836 }
ian@21916 837
ian@21916 838 path = strdup(event->path);
ian@21916 839 path[strlen(path) - 6] = '\0';
gianni@22023 840 backend = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend", path));
ian@21916 841
ian@21916 842 disk->backend_domid = 0;
ian@21916 843 disk->domid = domid;
ian@21916 844 disk->physpath = NULL;
ian@21916 845 disk->phystype = 0;
ian@21916 846 /* this value is returned to the user: do not free right away */
gianni@22023 847 disk->virtpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/dev", backend));
ian@21916 848 disk->unpluggable = 1;
ian@21916 849 disk->readwrite = 0;
ian@21916 850 disk->is_cdrom = 1;
ian@21916 851
ian@21916 852 free(path);
gianni@22023 853 libxl_free_all(&gc);
ian@21916 854 return 1;
keir@20637 855 }
keir@20637 856
ian@21930 857 static int libxl_destroy_device_model(libxl_ctx *ctx, uint32_t domid)
keir@20462 858 {
gianni@22023 859 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20462 860 char *pid;
keir@20462 861 int ret;
keir@20462 862
gianni@22023 863 pid = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "/local/domain/%d/image/device-model-pid", domid));
keir@20462 864 if (!pid) {
keir@20542 865 int stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20542 866 if (!stubdomid) {
keir@20542 867 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't find device model's pid");
gianni@22023 868 ret = ERROR_INVAL;
gianni@22023 869 goto out;
keir@20542 870 }
keir@20542 871 XL_LOG(ctx, XL_LOG_ERROR, "Device model is a stubdom, domid=%d\n", stubdomid);
gianni@22023 872 ret = libxl_domain_destroy(ctx, stubdomid, 0);
gianni@22023 873 goto out;
keir@20462 874 }
gianni@22023 875 xs_rm(ctx->xsh, XBT_NULL, libxl_sprintf(&gc, "/local/domain/0/device-model/%d", domid));
keir@20462 876
keir@20462 877 ret = kill(atoi(pid), SIGHUP);
keir@20462 878 if (ret < 0 && errno == ESRCH) {
keir@20512 879 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model already exited");
keir@20462 880 ret = 0;
keir@20462 881 } else if (ret == 0) {
keir@20512 882 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model signaled");
keir@20462 883 ret = 0;
keir@20462 884 } else {
keir@20512 885 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to kill Device Model [%d]",
keir@20512 886 atoi(pid));
keir@20462 887 }
gianni@22023 888 out:
gianni@22023 889 libxl_free_all(&gc);
keir@20462 890 return ret;
keir@20462 891 }
keir@20462 892
ian@21930 893 int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid, int force)
keir@20462 894 {
gianni@22023 895 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20801 896 char *dom_path;
ian@21894 897 char *vm_path;
keir@20628 898 int rc, dm_present;
keir@20628 899
keir@20628 900 if (is_hvm(ctx, domid)) {
keir@20628 901 dm_present = 1;
keir@20628 902 } else {
keir@20628 903 char *pid;
gianni@22023 904 pid = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "/local/domain/%d/image/device-model-pid", domid));
keir@20628 905 dm_present = (pid != NULL);
keir@20628 906 }
keir@20462 907
gianni@22023 908 dom_path = libxl_xs_get_dompath(&gc, domid);
gianni@22023 909 if (!dom_path) {
gianni@22023 910 rc = ERROR_FAIL;
gianni@22023 911 goto out;
gianni@22023 912 }
keir@20512 913
keir@20482 914 if (libxl_device_pci_shutdown(ctx, domid) < 0)
keir@20512 915 XL_LOG(ctx, XL_LOG_ERROR, "pci shutdown failed for domid %d", domid);
keir@20628 916 if (dm_present) {
keir@20628 917 xs_write(ctx->xsh, XBT_NULL,
gianni@22023 918 libxl_sprintf(&gc, "/local/domain/0/device-model/%d/command", domid),
keir@20628 919 "shutdown", strlen("shutdown"));
keir@20628 920 }
keir@20512 921 rc = xc_domain_pause(ctx->xch, domid);
keir@20512 922 if (rc < 0) {
keir@20512 923 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_pause failed for %d", domid);
keir@20462 924 }
keir@20628 925 if (dm_present) {
keir@20628 926 if (libxl_destroy_device_model(ctx, domid) < 0)
keir@20628 927 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_device_model failed for %d", domid);
keir@20628 928 }
keir@20462 929 if (libxl_devices_destroy(ctx, domid, force) < 0)
keir@20512 930 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_devices failed for %d", domid);
ian@21891 931
gianni@22023 932 vm_path = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/vm", dom_path));
keir@20823 933 if (vm_path)
keir@20823 934 if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
keir@20823 935 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", vm_path);
keir@20779 936
ian@21891 937 if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
ian@21891 938 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", dom_path);
ian@21891 939
keir@21190 940 libxl__userdata_destroyall(ctx, domid);
keir@21190 941
keir@20545 942 rc = xc_domain_destroy(ctx->xch, domid);
keir@20545 943 if (rc < 0) {
keir@20545 944 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid);
gianni@22023 945 rc = ERROR_FAIL;
gianni@22023 946 goto out;
keir@20545 947 }
gianni@22023 948 rc = 0;
gianni@22023 949 out:
gianni@22023 950 libxl_free_all(&gc);
keir@20462 951 return 0;
keir@20462 952 }
keir@20462 953
ian@21930 954 int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num)
keir@20564 955 {
gianni@22023 956 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 957 char *p = libxl_sprintf(&gc, "%s/xenconsole", libxl_private_bindir_path());
gianni@22023 958 char *domid_s = libxl_sprintf(&gc, "%d", domid);
gianni@22023 959 char *cons_num_s = libxl_sprintf(&gc, "%d", cons_num);
gianni@22023 960 execl(p, p, domid_s, "--num", cons_num_s, (void *)NULL);
gianni@22023 961 libxl_free_all(&gc);
gianni@22023 962 return ERROR_FAIL;
keir@20564 963 }
keir@20564 964
ian@21930 965 int libxl_primary_console_exec(libxl_ctx *ctx, uint32_t domid_vm)
sstabellini@21867 966 {
sstabellini@21867 967 uint32_t stubdomid = libxl_get_stubdom_id(ctx, domid_vm);
sstabellini@21867 968 if (stubdomid)
sstabellini@21867 969 return libxl_console_exec(ctx, stubdomid, 1);
sstabellini@21867 970 else
sstabellini@21867 971 return libxl_console_exec(ctx, domid_vm, 0);
sstabellini@21867 972 }
sstabellini@21867 973
ian@21930 974 int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass)
sstabellini@21879 975 {
gianni@22023 976 libxl_gc gc = LIBXL_INIT_GC(ctx);
sstabellini@21879 977 const char *vnc_port, *vfb_back;
sstabellini@21879 978 const char *vnc_listen = NULL, *vnc_pass = NULL;
sstabellini@21879 979 int port = 0, autopass_fd = -1;
sstabellini@21879 980 char *vnc_bin, *args[] = {
sstabellini@21879 981 "vncviewer",
sstabellini@21879 982 NULL, /* hostname:display */
sstabellini@21879 983 NULL, /* -autopass */
sstabellini@21879 984 NULL,
sstabellini@21879 985 };
sstabellini@21879 986
gianni@22023 987 vnc_port = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 988 libxl_sprintf(&gc,
sstabellini@21879 989 "/local/domain/%d/console/vnc-port", domid));
sstabellini@21879 990 if ( vnc_port )
sstabellini@21879 991 port = atoi(vnc_port) - 5900;
sstabellini@21879 992
gianni@22023 993 vfb_back = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 994 libxl_sprintf(&gc,
sstabellini@21879 995 "/local/domain/%d/device/vfb/0/backend", domid));
sstabellini@21879 996 if ( vfb_back ) {
gianni@22023 997 vnc_listen = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 998 libxl_sprintf(&gc,
sstabellini@21879 999 "/local/domain/%d/console/vnc-listen", domid));
sstabellini@21879 1000 if ( autopass )
gianni@22023 1001 vnc_pass = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 1002 libxl_sprintf(&gc,
sstabellini@21879 1003 "/local/domain/%d/console/vnc-pass", domid));
sstabellini@21879 1004 }
sstabellini@21879 1005
sstabellini@21879 1006 if ( NULL == vnc_listen )
sstabellini@21879 1007 vnc_listen = "localhost";
sstabellini@21879 1008
sstabellini@21879 1009 if ( (vnc_bin = getenv("VNCVIEWER")) )
sstabellini@21879 1010 args[0] = vnc_bin;
sstabellini@21879 1011
gianni@22023 1012 args[1] = libxl_sprintf(&gc, "%s:%d", vnc_listen, port);
sstabellini@21879 1013
sstabellini@21879 1014 if ( vnc_pass ) {
sstabellini@21879 1015 char tmpname[] = "/tmp/vncautopass.XXXXXX";
sstabellini@21879 1016 autopass_fd = mkstemp(tmpname);
sstabellini@21879 1017 if ( autopass_fd < 0 )
sstabellini@21879 1018 goto skip_autopass;
sstabellini@21879 1019
sstabellini@21879 1020 if ( unlink(tmpname) )
sstabellini@21879 1021 /* should never happen */
sstabellini@21879 1022 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unlink %s failed", tmpname);
sstabellini@21879 1023
sstabellini@21879 1024 if ( libxl_write_exactly(ctx, autopass_fd, vnc_pass, strlen(vnc_pass),
sstabellini@21879 1025 tmpname, "vnc password") ) {
sstabellini@21879 1026 do { close(autopass_fd); } while(errno == EINTR);
sstabellini@21879 1027 goto skip_autopass;
sstabellini@21879 1028 }
sstabellini@21879 1029
sstabellini@21879 1030 args[2] = "-autopass";
sstabellini@21879 1031 }
sstabellini@21879 1032
sstabellini@21879 1033 skip_autopass:
gianni@22023 1034 libxl_free_all(&gc);
sstabellini@21879 1035 libxl_exec(autopass_fd, -1, -1, args[0], args);
sstabellini@21879 1036 return 0;
sstabellini@21879 1037 }
sstabellini@21879 1038
gianni@22023 1039 static char ** libxl_build_device_model_args_old(libxl_gc *gc,
keir@20462 1040 libxl_device_model_info *info,
keir@20462 1041 libxl_device_nic *vifs,
keir@20462 1042 int num_vifs)
keir@20462 1043 {
keir@20462 1044 int num = 0, i;
keir@20462 1045 flexarray_t *dm_args;
keir@20462 1046 dm_args = flexarray_make(16, 1);
gianni@22023 1047
keir@20462 1048 if (!dm_args)
keir@20462 1049 return NULL;
keir@20462 1050
keir@20516 1051 flexarray_set(dm_args, num++, "qemu-dm");
keir@20516 1052 flexarray_set(dm_args, num++, "-d");
keir@20462 1053
gianni@22023 1054 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", info->domid));
keir@20462 1055
keir@20462 1056 if (info->dom_name) {
keir@20516 1057 flexarray_set(dm_args, num++, "-domain-name");
keir@20516 1058 flexarray_set(dm_args, num++, info->dom_name);
keir@20462 1059 }
keir@20462 1060 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
keir@20516 1061 flexarray_set(dm_args, num++, "-vnc");
keir@20462 1062 if (info->vncdisplay) {
keir@20462 1063 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
keir@21362 1064 flexarray_set(
keir@21362 1065 dm_args, num++,
gianni@22023 1066 libxl_sprintf(gc, "%s:%d%s",
keir@21362 1067 info->vnclisten,
keir@21362 1068 info->vncdisplay,
keir@21362 1069 info->vncpasswd ? ",password" : ""));
keir@20462 1070 } else {
gianni@22023 1071 flexarray_set(dm_args, num++, libxl_sprintf(gc, "127.0.0.1:%d", info->vncdisplay));
keir@20462 1072 }
keir@20462 1073 } else if (info->vnclisten) {
keir@20462 1074 if (strchr(info->vnclisten, ':') != NULL) {
keir@20516 1075 flexarray_set(dm_args, num++, info->vnclisten);
keir@20462 1076 } else {
gianni@22023 1077 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%s:0", info->vnclisten));
keir@20462 1078 }
keir@20462 1079 } else {
keir@20516 1080 flexarray_set(dm_args, num++, "127.0.0.1:0");
keir@20462 1081 }
keir@20462 1082 if (info->vncunused) {
keir@20516 1083 flexarray_set(dm_args, num++, "-vncunused");
keir@20462 1084 }
keir@20462 1085 }
keir@21378 1086 if (info->sdl) {
keir@20516 1087 flexarray_set(dm_args, num++, "-sdl");
keir@20462 1088 if (info->opengl) {
keir@20516 1089 flexarray_set(dm_args, num++, "-disable-opengl");
keir@20462 1090 }
keir@20462 1091 }
keir@20462 1092 if (info->keymap) {
keir@20516 1093 flexarray_set(dm_args, num++, "-k");
keir@20516 1094 flexarray_set(dm_args, num++, info->keymap);
keir@20462 1095 }
keir@20462 1096 if (info->nographic && (!info->sdl && !info->vnc)) {
keir@20516 1097 flexarray_set(dm_args, num++, "-nographic");
keir@20462 1098 }
keir@20462 1099 if (info->serial) {
keir@20516 1100 flexarray_set(dm_args, num++, "-serial");
keir@20516 1101 flexarray_set(dm_args, num++, info->serial);
keir@20462 1102 }
keir@20509 1103 if (info->type == XENFV) {
Ian@21733 1104 int ioemu_vifs = 0;
Ian@21733 1105
keir@20509 1106 if (info->videoram) {
keir@20516 1107 flexarray_set(dm_args, num++, "-videoram");
gianni@22023 1108 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", info->videoram));
keir@20509 1109 }
keir@20509 1110 if (info->stdvga) {
keir@20516 1111 flexarray_set(dm_args, num++, "-std-vga");
keir@20509 1112 }
keir@20509 1113
keir@20509 1114 if (info->boot) {
keir@20516 1115 flexarray_set(dm_args, num++, "-boot");
keir@20516 1116 flexarray_set(dm_args, num++, info->boot);
keir@20509 1117 }
stefano@21890 1118 if (info->usb || info->usbdevice) {
keir@20516 1119 flexarray_set(dm_args, num++, "-usb");
keir@20509 1120 if (info->usbdevice) {
keir@20516 1121 flexarray_set(dm_args, num++, "-usbdevice");
keir@20516 1122 flexarray_set(dm_args, num++, info->usbdevice);
keir@20509 1123 }
keir@20509 1124 }
Ian@21801 1125 if (info->soundhw) {
Ian@21801 1126 flexarray_set(dm_args, num++, "-soundhw");
Ian@21801 1127 flexarray_set(dm_args, num++, info->soundhw);
Ian@21801 1128 }
keir@20509 1129 if (info->apic) {
keir@20516 1130 flexarray_set(dm_args, num++, "-acpi");
keir@20509 1131 }
keir@21570 1132 if (info->vcpus > 1) {
keir@21570 1133 flexarray_set(dm_args, num++, "-vcpus");
gianni@22023 1134 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", info->vcpus));
keir@21570 1135 }
keir@21570 1136 if (info->vcpu_avail) {
keir@21570 1137 flexarray_set(dm_args, num++, "-vcpu_avail");
gianni@22023 1138 flexarray_set(dm_args, num++, libxl_sprintf(gc, "0x%x", info->vcpu_avail));
keir@21570 1139 }
keir@20509 1140 for (i = 0; i < num_vifs; i++) {
keir@20509 1141 if (vifs[i].nictype == NICTYPE_IOEMU) {
gianni@22023 1142 char *smac = libxl_sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20780 1143 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2],
keir@20780 1144 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
keir@20781 1145 if (!vifs[i].ifname)
gianni@22023 1146 vifs[i].ifname = libxl_sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid);
keir@20516 1147 flexarray_set(dm_args, num++, "-net");
gianni@22023 1148 flexarray_set(dm_args, num++, libxl_sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s",
keir@20780 1149 vifs[i].devid, smac, vifs[i].model));
keir@20516 1150 flexarray_set(dm_args, num++, "-net");
gianni@22023 1151 flexarray_set(dm_args, num++, libxl_sprintf(gc, "tap,vlan=%d,ifname=%s,bridge=%s,script=no",
keir@20509 1152 vifs[i].devid, vifs[i].ifname, vifs[i].bridge));
Ian@21733 1153 ioemu_vifs++;
keir@20509 1154 }
keir@20462 1155 }
Ian@21733 1156 /* If we have no emulated nics, tell qemu not to create any */
Ian@21733 1157 if ( ioemu_vifs == 0 ) {
Ian@21733 1158 flexarray_set(dm_args, num++, "-net");
Ian@21733 1159 flexarray_set(dm_args, num++, "none");
Ian@21733 1160 }
keir@20462 1161 }
keir@20565 1162 if (info->saved_state) {
keir@20565 1163 flexarray_set(dm_args, num++, "-loadvm");
keir@20565 1164 flexarray_set(dm_args, num++, info->saved_state);
keir@20565 1165 }
keir@20509 1166 for (i = 0; info->extra && info->extra[i] != NULL; i++)
keir@20509 1167 flexarray_set(dm_args, num++, info->extra[i]);
keir@20516 1168 flexarray_set(dm_args, num++, "-M");
keir@20509 1169 if (info->type == XENPV)
keir@20516 1170 flexarray_set(dm_args, num++, "xenpv");
keir@20509 1171 else
keir@20516 1172 flexarray_set(dm_args, num++, "xenfv");
keir@20462 1173 flexarray_set(dm_args, num++, NULL);
keir@20462 1174 return (char **) flexarray_contents(dm_args);
keir@20462 1175 }
keir@20462 1176
gianni@22023 1177 static char ** libxl_build_device_model_args_new(libxl_gc *gc,
anthony@21989 1178 libxl_device_model_info *info,
anthony@21989 1179 libxl_device_nic *vifs,
anthony@21989 1180 int num_vifs)
anthony@21989 1181 {
anthony@21989 1182 int num = 0, i;
anthony@21989 1183 flexarray_t *dm_args;
anthony@21989 1184 int nb;
anthony@21989 1185 libxl_device_disk *disks;
anthony@21989 1186
anthony@21989 1187 dm_args = flexarray_make(16, 1);
anthony@21989 1188 if (!dm_args)
anthony@21989 1189 return NULL;
anthony@21989 1190
anthony@21989 1191 flexarray_set(dm_args, num++, "qemu-system-xen");
anthony@21989 1192 flexarray_set(dm_args, num++, "-xen-domid");
anthony@21989 1193
gianni@22023 1194 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", info->domid));
anthony@21989 1195
anthony@21989 1196 if (info->dom_name) {
anthony@21989 1197 flexarray_set(dm_args, num++, "-name");
anthony@21989 1198 flexarray_set(dm_args, num++, info->dom_name);
anthony@21989 1199 }
anthony@21989 1200 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
anthony@21989 1201 int display = 0;
anthony@21989 1202 const char *listen = "127.0.0.1";
anthony@21989 1203
anthony@21989 1204 flexarray_set(dm_args, num++, "-vnc");
anthony@21989 1205
anthony@21989 1206 if (info->vncdisplay) {
anthony@21989 1207 display = info->vncdisplay;
anthony@21989 1208 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
anthony@21989 1209 listen = info->vnclisten;
anthony@21989 1210 }
anthony@21989 1211 } else if (info->vnclisten) {
anthony@21989 1212 listen = info->vnclisten;
anthony@21989 1213 }
anthony@21989 1214
anthony@21989 1215 if (strchr(listen, ':') != NULL)
anthony@21989 1216 flexarray_set(dm_args, num++,
gianni@22023 1217 libxl_sprintf(gc, "%s%s", listen,
anthony@21989 1218 info->vncunused ? ",to=99" : ""));
anthony@21989 1219 else
anthony@21989 1220 flexarray_set(dm_args, num++,
gianni@22023 1221 libxl_sprintf(gc, "%s:%d%s", listen, display,
anthony@21989 1222 info->vncunused ? ",to=99" : ""));
anthony@21989 1223 }
anthony@21989 1224 if (info->sdl) {
anthony@21989 1225 flexarray_set(dm_args, num++, "-sdl");
anthony@21989 1226 }
anthony@21989 1227 if (info->keymap) {
anthony@21989 1228 flexarray_set(dm_args, num++, "-k");
anthony@21989 1229 flexarray_set(dm_args, num++, info->keymap);
anthony@21989 1230 }
anthony@21989 1231 if (info->nographic && (!info->sdl && !info->vnc)) {
anthony@21989 1232 flexarray_set(dm_args, num++, "-nographic");
anthony@21989 1233 }
anthony@21989 1234 if (info->serial) {
anthony@21989 1235 flexarray_set(dm_args, num++, "-serial");
anthony@21989 1236 flexarray_set(dm_args, num++, info->serial);
anthony@21989 1237 }
anthony@21989 1238 if (info->type == XENFV) {
anthony@21989 1239 int ioemu_vifs = 0;
anthony@21989 1240
anthony@21989 1241 if (info->stdvga) {
anthony@21989 1242 flexarray_set(dm_args, num++, "-vga");
anthony@21989 1243 flexarray_set(dm_args, num++, "std");
anthony@21989 1244 }
anthony@21989 1245
anthony@21989 1246 if (info->boot) {
anthony@21989 1247 flexarray_set(dm_args, num++, "-boot");
gianni@22023 1248 flexarray_set(dm_args, num++, libxl_sprintf(gc, "order=%s", info->boot));
anthony@21989 1249 }
anthony@21989 1250 if (info->usb || info->usbdevice) {
anthony@21989 1251 flexarray_set(dm_args, num++, "-usb");
anthony@21989 1252 if (info->usbdevice) {
anthony@21989 1253 flexarray_set(dm_args, num++, "-usbdevice");
anthony@21989 1254 flexarray_set(dm_args, num++, info->usbdevice);
anthony@21989 1255 }
anthony@21989 1256 }
anthony@21989 1257 if (info->soundhw) {
anthony@21989 1258 flexarray_set(dm_args, num++, "-soundhw");
anthony@21989 1259 flexarray_set(dm_args, num++, info->soundhw);
anthony@21989 1260 }
anthony@21989 1261 if (!info->apic) {
anthony@21989 1262 flexarray_set(dm_args, num++, "-no-acpi");
anthony@21989 1263 }
anthony@21989 1264 if (info->vcpus > 1) {
anthony@21989 1265 flexarray_set(dm_args, num++, "-smp");
anthony@21989 1266 if (info->vcpu_avail)
gianni@22023 1267 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d,maxcpus=%d", info->vcpus, info->vcpu_avail));
anthony@21989 1268 else
gianni@22023 1269 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", info->vcpus));
anthony@21989 1270 }
anthony@21989 1271 for (i = 0; i < num_vifs; i++) {
anthony@21989 1272 if (vifs[i].nictype == NICTYPE_IOEMU) {
gianni@22023 1273 char *smac = libxl_sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x",
anthony@21989 1274 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2],
anthony@21989 1275 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
anthony@21989 1276 if (!vifs[i].ifname)
gianni@22023 1277 vifs[i].ifname = libxl_sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid);
anthony@21989 1278 flexarray_set(dm_args, num++, "-net");
gianni@22023 1279 flexarray_set(dm_args, num++, libxl_sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s",
anthony@21989 1280 vifs[i].devid, smac, vifs[i].model));
anthony@21989 1281 flexarray_set(dm_args, num++, "-net");
gianni@22023 1282 flexarray_set(dm_args, num++, libxl_sprintf(gc, "tap,vlan=%d,ifname=%s,script=no",
anthony@21990 1283 vifs[i].devid, vifs[i].ifname));
anthony@21989 1284 ioemu_vifs++;
anthony@21989 1285 }
anthony@21989 1286 }
anthony@21989 1287 /* If we have no emulated nics, tell qemu not to create any */
anthony@21989 1288 if ( ioemu_vifs == 0 ) {
anthony@21989 1289 flexarray_set(dm_args, num++, "-net");
anthony@21989 1290 flexarray_set(dm_args, num++, "none");
anthony@21989 1291 }
anthony@21989 1292 }
anthony@21989 1293 if (info->saved_state) {
anthony@21989 1294 flexarray_set(dm_args, num++, "-loadvm");
anthony@21989 1295 flexarray_set(dm_args, num++, info->saved_state);
anthony@21989 1296 }
anthony@21989 1297 for (i = 0; info->extra && info->extra[i] != NULL; i++)
anthony@21989 1298 flexarray_set(dm_args, num++, info->extra[i]);
anthony@21989 1299 flexarray_set(dm_args, num++, "-M");
anthony@21989 1300 if (info->type == XENPV)
anthony@21989 1301 flexarray_set(dm_args, num++, "xenpv");
anthony@21989 1302 else
anthony@21989 1303 flexarray_set(dm_args, num++, "xenfv");
anthony@21989 1304
gianni@22023 1305 disks = libxl_device_disk_list(libxl_gc_owner(gc), info->domid, &nb);
anthony@21989 1306 for (; nb > 0; --nb, ++disks) {
anthony@21989 1307 if ( disks->is_cdrom ) {
anthony@21989 1308 flexarray_set(dm_args, num++, "-cdrom");
anthony@21989 1309 flexarray_set(dm_args, num++, disks->physpath);
anthony@21989 1310 }else{
gianni@22023 1311 flexarray_set(dm_args, num++, libxl_sprintf(gc, "-%s", disks->virtpath));
anthony@21989 1312 flexarray_set(dm_args, num++, disks->physpath);
anthony@21989 1313 }
anthony@21989 1314 }
gianni@22023 1315 free(disks);
anthony@21989 1316
anthony@21989 1317 flexarray_set(dm_args, num++, NULL);
anthony@21989 1318 return (char **) flexarray_contents(dm_args);
anthony@21989 1319 }
anthony@21989 1320
gianni@22023 1321 static char ** libxl_build_device_model_args(libxl_gc *gc,
anthony@21989 1322 libxl_device_model_info *info,
anthony@21989 1323 libxl_device_nic *vifs,
anthony@21989 1324 int num_vifs)
anthony@21989 1325 {
gianni@22023 1326 libxl_ctx *ctx = libxl_gc_owner(gc);
anthony@21989 1327 int new_qemu;
anthony@21989 1328
anthony@21989 1329 new_qemu = libxl_check_device_model_version(ctx, info->device_model);
anthony@21989 1330
anthony@21989 1331 if (new_qemu == 1) {
gianni@22023 1332 return libxl_build_device_model_args_new(gc, info, vifs, num_vifs);
anthony@21989 1333 } else {
gianni@22023 1334 return libxl_build_device_model_args_old(gc, info, vifs, num_vifs);
anthony@21989 1335 }
anthony@21989 1336 }
anthony@21989 1337
keir@20834 1338 void dm_xenstore_record_pid(void *for_spawn, pid_t innerchild)
keir@20834 1339 {
ian@21930 1340 libxl_device_model_starting *starting = for_spawn;
keir@20514 1341 char *kvs[3];
keir@20820 1342 int rc;
keir@20820 1343 struct xs_handle *xsh;
keir@20514 1344
keir@20820 1345 xsh = xs_daemon_open();
keir@20514 1346 /* we mustn't use the parent's handle in the child */
keir@20514 1347
keir@20514 1348 kvs[0] = "image/device-model-pid";
keir@21417 1349 if (asprintf(&kvs[1], "%d", innerchild) < 0)
keir@21417 1350 return;
keir@20514 1351 kvs[2] = NULL;
keir@20820 1352
keir@20820 1353 rc = xs_writev(xsh, XBT_NULL, starting->dom_path, kvs);
keir@20820 1354 if (rc)
keir@20820 1355 return;
keir@20820 1356 xs_daemon_close(xsh);
keir@20514 1357 }
keir@20514 1358
ian@21930 1359 static int libxl_vfb_and_vkb_from_device_model_info(libxl_ctx *ctx,
keir@20542 1360 libxl_device_model_info *info,
keir@20542 1361 libxl_device_vfb *vfb,
keir@20542 1362 libxl_device_vkb *vkb)
keir@20542 1363 {
keir@20542 1364 memset(vfb, 0x00, sizeof(libxl_device_vfb));
keir@20542 1365 memset(vkb, 0x00, sizeof(libxl_device_vkb));
keir@20542 1366
keir@20542 1367 vfb->backend_domid = 0;
keir@20542 1368 vfb->devid = 0;
keir@20542 1369 vfb->vnc = info->vnc;
keir@20542 1370 vfb->vnclisten = info->vnclisten;
keir@20542 1371 vfb->vncdisplay = info->vncdisplay;
keir@20542 1372 vfb->vncunused = info->vncunused;
keir@21362 1373 vfb->vncpasswd = info->vncpasswd;
keir@20542 1374 vfb->keymap = info->keymap;
keir@20542 1375 vfb->sdl = info->sdl;
keir@20542 1376 vfb->opengl = info->opengl;
keir@20542 1377
keir@20542 1378 vkb->backend_domid = 0;
keir@20542 1379 vkb->devid = 0;
keir@20542 1380 return 0;
keir@20542 1381 }
keir@20542 1382
ian@21930 1383 static int libxl_write_dmargs(libxl_ctx *ctx, int domid, int guest_domid, char **args)
keir@20542 1384 {
gianni@22023 1385 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20542 1386 int i;
keir@20542 1387 char *vm_path;
keir@20542 1388 char *dmargs, *path;
keir@20542 1389 int dmargs_size;
keir@20542 1390 struct xs_permissions roperm[2];
keir@20542 1391 xs_transaction_t t;
keir@20542 1392
keir@20542 1393 roperm[0].id = 0;
keir@20542 1394 roperm[0].perms = XS_PERM_NONE;
keir@20542 1395 roperm[1].id = domid;
keir@20542 1396 roperm[1].perms = XS_PERM_READ;
keir@20542 1397
gianni@22023 1398 vm_path = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "/local/domain/%d/vm", guest_domid));
keir@20542 1399
keir@20542 1400 i = 0;
keir@20542 1401 dmargs_size = 0;
keir@20542 1402 while (args[i] != NULL) {
keir@20542 1403 dmargs_size = dmargs_size + strlen(args[i]) + 1;
keir@20542 1404 i++;
keir@20542 1405 }
keir@20542 1406 dmargs_size++;
keir@20542 1407 dmargs = (char *) malloc(dmargs_size);
keir@20542 1408 i = 1;
keir@20542 1409 dmargs[0] = '\0';
keir@20542 1410 while (args[i] != NULL) {
keir@20542 1411 if (strcmp(args[i], "-sdl") && strcmp(args[i], "-M") && strcmp(args[i], "xenfv")) {
keir@20542 1412 strcat(dmargs, " ");
keir@20542 1413 strcat(dmargs, args[i]);
keir@20542 1414 }
keir@20542 1415 i++;
keir@20542 1416 }
gianni@22023 1417 path = libxl_sprintf(&gc, "%s/image/dmargs", vm_path);
keir@20542 1418
keir@20542 1419 retry_transaction:
keir@20542 1420 t = xs_transaction_start(ctx->xsh);
keir@20542 1421 xs_write(ctx->xsh, t, path, dmargs, strlen(dmargs));
keir@20542 1422 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
gianni@22023 1423 xs_set_permissions(ctx->xsh, t, libxl_sprintf(&gc, "%s/rtc/timeoffset", vm_path), roperm, ARRAY_SIZE(roperm));
keir@20542 1424 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20542 1425 if (errno == EAGAIN)
keir@20542 1426 goto retry_transaction;
keir@20542 1427 free(dmargs);
gianni@22023 1428 libxl_free_all(&gc);
keir@20542 1429 return 0;
keir@20542 1430 }
keir@20542 1431
ian@21930 1432 static int libxl_create_stubdom(libxl_ctx *ctx,
keir@20542 1433 libxl_device_model_info *info,
keir@20542 1434 libxl_device_disk *disks, int num_disks,
keir@20542 1435 libxl_device_nic *vifs, int num_vifs,
keir@20542 1436 libxl_device_vfb *vfb,
keir@20542 1437 libxl_device_vkb *vkb,
keir@20542 1438 libxl_device_model_starting **starting_r)
keir@20542 1439 {
gianni@22023 1440 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20843 1441 int i, num_console = 1, ret;
keir@20570 1442 libxl_device_console *console;
keir@20542 1443 libxl_domain_create_info c_info;
keir@20542 1444 libxl_domain_build_info b_info;
keir@20542 1445 libxl_domain_build_state state;
keir@20542 1446 uint32_t domid;
keir@20542 1447 char **args;
keir@20542 1448 struct xs_permissions perm[2];
keir@20542 1449 xs_transaction_t t;
keir@20594 1450 libxl_device_model_starting *dm_starting = 0;
keir@20542 1451
gianni@22023 1452 args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
gianni@22023 1453 if (!args) {
gianni@22023 1454 ret = ERROR_FAIL;
gianni@22023 1455 goto out;
gianni@22023 1456 }
keir@20542 1457
keir@20542 1458 memset(&c_info, 0x00, sizeof(libxl_domain_create_info));
keir@20542 1459 c_info.hvm = 0;
gianni@22023 1460 c_info.name = libxl_sprintf(&gc, "%s-dm", _libxl_domid_to_name(&gc, info->domid));
keir@20801 1461 for (i = 0; i < 16; i++)
keir@20801 1462 c_info.uuid[i] = info->uuid[i];
keir@20542 1463
keir@20542 1464 memset(&b_info, 0x00, sizeof(libxl_domain_build_info));
keir@20542 1465 b_info.max_vcpus = 1;
keir@20542 1466 b_info.max_memkb = 32 * 1024;
keir@20647 1467 b_info.target_memkb = b_info.max_memkb;
gianni@22023 1468 b_info.kernel.path = libxl_abs_path(&gc, "ioemu-stubdom.gz", libxl_xenfirmwaredir_path());
gianni@22023 1469 b_info.u.pv.cmdline = libxl_sprintf(&gc, " -d %d", info->domid);
Ian@21848 1470 b_info.u.pv.ramdisk.path = "";
keir@20542 1471 b_info.u.pv.features = "";
keir@20542 1472 b_info.hvm = 0;
keir@20542 1473
keir@20843 1474 ret = libxl_domain_make(ctx, &c_info, &domid);
gianni@22023 1475 if (ret)
gianni@22023 1476 goto out_free;
keir@20843 1477 ret = libxl_domain_build(ctx, &b_info, domid, &state);
gianni@22023 1478 if (ret)
gianni@22023 1479 goto out_free;
keir@20542 1480
keir@20542 1481 libxl_write_dmargs(ctx, domid, info->domid, args);
gianni@22023 1482 libxl_xs_write(&gc, XBT_NULL,
gianni@22023 1483 libxl_sprintf(&gc, "%s/image/device-model-domid", libxl_xs_get_dompath(&gc, info->domid)),
keir@20843 1484 "%d", domid);
gianni@22023 1485 libxl_xs_write(&gc, XBT_NULL,
gianni@22023 1486 libxl_sprintf(&gc, "%s/target", libxl_xs_get_dompath(&gc, domid)),
keir@20843 1487 "%d", info->domid);
gianni@21892 1488 ret = xc_domain_set_target(ctx->xch, domid, info->domid);
gianni@21892 1489 if (ret<0) {
gianni@21892 1490 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting target domain %d -> %d", domid, info->domid);
gianni@22023 1491 ret = ERROR_FAIL;
gianni@22023 1492 goto out_free;
gianni@21892 1493 }
keir@20542 1494 xs_set_target(ctx->xsh, domid, info->domid);
keir@20542 1495
keir@20542 1496 perm[0].id = domid;
keir@20542 1497 perm[0].perms = XS_PERM_NONE;
keir@20542 1498 perm[1].id = info->domid;
keir@20542 1499 perm[1].perms = XS_PERM_READ;
keir@20542 1500 retry_transaction:
keir@20542 1501 t = xs_transaction_start(ctx->xsh);
gianni@22023 1502 xs_mkdir(ctx->xsh, t, libxl_sprintf(&gc, "/local/domain/0/device-model/%d", info->domid));
gianni@22023 1503 xs_set_permissions(ctx->xsh, t, libxl_sprintf(&gc, "/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm));
gianni@22023 1504 xs_mkdir(ctx->xsh, t, libxl_sprintf(&gc, "/local/domain/%d/device/vfs", domid));
gianni@22023 1505 xs_set_permissions(ctx->xsh, t, libxl_sprintf(&gc, "/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm));
keir@20542 1506 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20542 1507 if (errno == EAGAIN)
keir@20542 1508 goto retry_transaction;
keir@20542 1509
keir@20542 1510 for (i = 0; i < num_disks; i++) {
keir@20781 1511 disks[i].domid = domid;
keir@20843 1512 ret = libxl_device_disk_add(ctx, domid, &disks[i]);
gianni@22023 1513 if (ret)
gianni@22023 1514 goto out_free;
keir@20542 1515 }
keir@20542 1516 for (i = 0; i < num_vifs; i++) {
keir@20781 1517 vifs[i].domid = domid;
keir@20843 1518 ret = libxl_device_nic_add(ctx, domid, &vifs[i]);
gianni@22023 1519 if (ret)
gianni@22023 1520 goto out_free;
keir@20542 1521 }
keir@20781 1522 vfb->domid = domid;
keir@20843 1523 ret = libxl_device_vfb_add(ctx, domid, vfb);
gianni@22023 1524 if (ret)
gianni@22023 1525 goto out_free;
keir@20781 1526 vkb->domid = domid;
keir@20843 1527 ret = libxl_device_vkb_add(ctx, domid, vkb);
gianni@22023 1528 if (ret)
gianni@22023 1529 goto out_free;
keir@20542 1530
keir@20570 1531 if (info->serial)
keir@20570 1532 num_console++;
keir@20843 1533
gianni@22023 1534 console = libxl_calloc(&gc, num_console, sizeof(libxl_device_console));
gianni@22023 1535 if (!console) {
gianni@22023 1536 ret = ERROR_NOMEM;
gianni@22023 1537 goto out_free;
gianni@22023 1538 }
keir@20843 1539
keir@20570 1540 for (i = 0; i < num_console; i++) {
keir@20781 1541 console[i].devid = i;
keir@20781 1542 console[i].constype = CONSTYPE_IOEMU;
keir@20781 1543 console[i].domid = domid;
keir@20570 1544 if (!i)
keir@20781 1545 console[i].build_state = &state;
keir@20843 1546 ret = libxl_device_console_add(ctx, domid, &console[i]);
gianni@22023 1547 if (ret)
gianni@22023 1548 goto out_free;
keir@20570 1549 }
keir@20594 1550 if (libxl_create_xenpv_qemu(ctx, vfb, num_console, console, &dm_starting) < 0) {
gianni@22023 1551 ret = ERROR_FAIL;
gianni@22023 1552 goto out_free;
keir@20594 1553 }
keir@20594 1554 if (libxl_confirm_device_model_startup(ctx, dm_starting) < 0) {
gianni@22023 1555 ret = ERROR_FAIL;
gianni@22023 1556 goto out_free;
keir@20594 1557 }
keir@20542 1558
keir@20542 1559 libxl_domain_unpause(ctx, domid);
keir@20542 1560
keir@20594 1561 if (starting_r) {
gianni@22023 1562 *starting_r = calloc(sizeof(libxl_device_model_starting), 1);
keir@20598 1563 (*starting_r)->domid = info->domid;
gianni@22023 1564 (*starting_r)->dom_path = libxl_xs_get_dompath(&gc, info->domid);
keir@20594 1565 (*starting_r)->for_spawn = NULL;
keir@20594 1566 }
keir@20594 1567
gianni@22023 1568 ret = 0;
gianni@22023 1569
gianni@22023 1570 out_free:
keir@20542 1571 free(args);
gianni@22023 1572 out:
gianni@22023 1573 libxl_free_all(&gc);
gianni@22023 1574 return ret;
keir@20542 1575 }
keir@20542 1576
ian@21930 1577 int libxl_create_device_model(libxl_ctx *ctx,
keir@20462 1578 libxl_device_model_info *info,
keir@20542 1579 libxl_device_disk *disks, int num_disks,
keir@20514 1580 libxl_device_nic *vifs, int num_vifs,
keir@20514 1581 libxl_device_model_starting **starting_r)
keir@20462 1582 {
gianni@22023 1583 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20546 1584 char *path, *logfile;
keir@20514 1585 int logfile_w, null;
keir@20546 1586 int rc;
keir@20462 1587 char **args;
ian@21930 1588 libxl_device_model_starting buf_starting, *p;
keir@21362 1589 xs_transaction_t t;
keir@21362 1590 char *vm_path;
keir@21362 1591 char **pass_stuff;
keir@20514 1592
keir@20542 1593 if (strstr(info->device_model, "stubdom-dm")) {
keir@20542 1594 libxl_device_vfb vfb;
keir@20542 1595 libxl_device_vkb vkb;
keir@20542 1596
keir@20542 1597 libxl_vfb_and_vkb_from_device_model_info(ctx, info, &vfb, &vkb);
gianni@22023 1598 rc = libxl_create_stubdom(ctx, info, disks, num_disks, vifs, num_vifs, &vfb, &vkb, starting_r);
gianni@22023 1599 goto out;
keir@20542 1600 }
keir@20542 1601
gianni@22023 1602 args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
gianni@22023 1603 if (!args) {
gianni@22023 1604 rc = ERROR_FAIL;
gianni@22023 1605 goto out;
gianni@22023 1606 }
gianni@22023 1607
gianni@22023 1608 path = libxl_sprintf(&gc, "/local/domain/0/device-model/%d", info->domid);
keir@20462 1609 xs_mkdir(ctx->xsh, XBT_NULL, path);
gianni@22023 1610 libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/disable_pf", path), "%d", !info->xen_platform_pci);
gianni@22023 1611
gianni@22023 1612 libxl_create_logfile(ctx, libxl_sprintf(&gc, "qemu-dm-%s", info->dom_name), &logfile);
keir@20467 1613 logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
keir@20546 1614 free(logfile);
keir@20462 1615 null = open("/dev/null", O_RDONLY);
keir@20514 1616
keir@20514 1617 if (starting_r) {
keir@20516 1618 rc = ERROR_NOMEM;
gianni@22023 1619 *starting_r = calloc(sizeof(libxl_device_model_starting), 1);
gianni@22023 1620 if (!*starting_r)
gianni@22023 1621 goto out_close;
keir@20594 1622 p = *starting_r;
gianni@22023 1623 p->for_spawn = calloc(sizeof(libxl_spawn_starting), 1);
keir@20594 1624 } else {
keir@20594 1625 p = &buf_starting;
keir@20594 1626 p->for_spawn = NULL;
keir@20594 1627 }
keir@20514 1628
keir@20594 1629 p->domid = info->domid;
gianni@22023 1630 p->dom_path = libxl_xs_get_dompath(&gc, info->domid);
gianni@22023 1631 if (!p->dom_path) {
gianni@22023 1632 rc = ERROR_FAIL;
gianni@22023 1633 goto out_close;
gianni@22023 1634 }
keir@20594 1635
keir@21362 1636 if (info->vncpasswd) {
gianni@22023 1637 retry_transaction:
keir@21362 1638 /* Find uuid and the write the vnc password to xenstore for qemu. */
keir@21362 1639 t = xs_transaction_start(ctx->xsh);
gianni@22023 1640 vm_path = libxl_xs_read(&gc,t,libxl_sprintf(&gc, "%s/vm", p->dom_path));
keir@21362 1641 if (vm_path) {
keir@21362 1642 /* Now write the vncpassword into it. */
gianni@22023 1643 pass_stuff = libxl_calloc(&gc, 2, sizeof(char *));
keir@21362 1644 pass_stuff[0] = "vncpasswd";
keir@21362 1645 pass_stuff[1] = info->vncpasswd;
gianni@22023 1646 libxl_xs_writev(&gc,t,vm_path,pass_stuff);
keir@21362 1647 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@21362 1648 if (errno == EAGAIN)
keir@21362 1649 goto retry_transaction;
keir@21362 1650 }
keir@21362 1651 }
keir@21362 1652
keir@20594 1653 rc = libxl_spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid);
gianni@22023 1654 if (rc < 0)
gianni@22023 1655 goto out_close;
keir@20514 1656 if (!rc) { /* inner child */
keir@20833 1657 libxl_exec(null, logfile_w, logfile_w,
gianni@22023 1658 libxl_abs_path(&gc, info->device_model, libxl_private_bindir_path()),
keir@21353 1659 args);
keir@20514 1660 }
keir@20514 1661
keir@20514 1662 rc = 0;
gianni@22023 1663
gianni@22023 1664 out_close:
keir@20462 1665 close(null);
keir@20462 1666 close(logfile_w);
gianni@22023 1667 free(args);
gianni@22023 1668 out:
gianni@22023 1669 libxl_free_all(&gc);
keir@20514 1670 return rc;
keir@20514 1671 }
keir@20514 1672
ian@21930 1673 int libxl_detach_device_model(libxl_ctx *ctx,
keir@20779 1674 libxl_device_model_starting *starting)
keir@20779 1675 {
keir@20514 1676 int rc;
keir@20594 1677 rc = libxl_spawn_detach(ctx, starting->for_spawn);
gianni@22023 1678 if (starting->for_spawn)
gianni@22023 1679 free(starting->for_spawn);
gianni@22023 1680 free(starting);
keir@20514 1681 return rc;
keir@20514 1682 }
keir@20462 1683
keir@20514 1684
ian@21930 1685 int libxl_confirm_device_model_startup(libxl_ctx *ctx,
keir@20779 1686 libxl_device_model_starting *starting)
keir@20779 1687 {
gianni@21965 1688 int problem = libxl_wait_for_device_model(ctx, starting->domid, "running", NULL, NULL);
gianni@21965 1689 int detach;
gianni@21965 1690 if ( !problem )
gianni@21965 1691 problem = libxl_spawn_check(ctx, starting->for_spawn);
gianni@21965 1692 detach = libxl_detach_device_model(ctx, starting);
keir@20514 1693 return problem ? problem : detach;
keir@20462 1694 }
keir@20462 1695
keir@20514 1696
keir@20462 1697 /******************************************************************************/
keir@20566 1698
gianni@22023 1699 static char *get_blktap2_device(libxl_gc *gc,
Ian@21903 1700 const char *name, const char *type)
Ian@21903 1701 {
Ian@21903 1702 int minor = tap_ctl_find_minor(type, name);
Ian@21903 1703 if (minor < 0)
Ian@21903 1704 return NULL;
gianni@22023 1705 return libxl_sprintf(gc, "/dev/xen/blktap-2/tapdev%d", minor);
Ian@21903 1706 }
Ian@21903 1707
gianni@22023 1708 static char *make_blktap2_device(libxl_gc *gc,
Ian@21903 1709 const char *name, const char *type)
Ian@21903 1710 {
Ian@21903 1711 char *params, *devname = NULL;
Ian@21903 1712 int err;
gianni@22023 1713 params = libxl_sprintf(gc, "%s:%s", type, name);
Ian@21903 1714 err = tap_ctl_create(params, &devname);
Ian@21903 1715 if (!err)
gianni@22023 1716 libxl_ptr_add(gc, devname);
Ian@21903 1717 return err ? NULL : devname;
Ian@21903 1718 }
Ian@21903 1719
ian@21930 1720 int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20462 1721 {
gianni@22023 1722 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20462 1723 flexarray_t *front;
keir@20462 1724 flexarray_t *back;
keir@20462 1725 char *backend_type;
keir@20462 1726 unsigned int boffset = 0;
keir@20462 1727 unsigned int foffset = 0;
keir@20462 1728 int devid;
keir@20462 1729 libxl_device device;
gianni@22023 1730 int major, minor, rc;
keir@20462 1731
keir@20462 1732 front = flexarray_make(16, 1);
gianni@22023 1733 if (!front) {
gianni@22023 1734 rc = ERROR_NOMEM;
gianni@22023 1735 goto out;
gianni@22023 1736 }
keir@20462 1737 back = flexarray_make(16, 1);
gianni@22023 1738 if (!back) {
gianni@22023 1739 rc = ERROR_NOMEM;
gianni@22023 1740 goto out_free;
gianni@22023 1741 }
keir@20462 1742
keir@20462 1743 backend_type = device_disk_backend_type_of_phystype(disk->phystype);
keir@20462 1744 devid = device_disk_dev_number(disk->virtpath);
keir@20947 1745 if (devid==-1) {
Christoph@21953 1746 XL_LOG(ctx, XL_LOG_ERROR, "Invalid or unsupported"
keir@20947 1747 " virtual disk identifier %s", disk->virtpath);
gianni@22023 1748 rc = ERROR_INVAL;
gianni@22023 1749 goto out_free;
keir@20947 1750 }
keir@20462 1751
keir@20462 1752 device.backend_devid = devid;
keir@20462 1753 device.backend_domid = disk->backend_domid;
keir@20462 1754 device.devid = devid;
keir@20462 1755 device.domid = disk->domid;
keir@20462 1756 device.kind = DEVICE_VBD;
keir@20462 1757
keir@20462 1758 switch (disk->phystype) {
keir@20462 1759 case PHYSTYPE_PHY: {
keir@20462 1760
keir@20509 1761 device_physdisk_major_minor(disk->physpath, &major, &minor);
keir@20516 1762 flexarray_set(back, boffset++, "physical-device");
gianni@22023 1763 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%x:%x", major, minor));
keir@20462 1764
keir@20516 1765 flexarray_set(back, boffset++, "params");
keir@20516 1766 flexarray_set(back, boffset++, disk->physpath);
keir@20462 1767
keir@20462 1768 device.backend_kind = DEVICE_VBD;
keir@20462 1769 break;
keir@20462 1770 }
keir@20566 1771 case PHYSTYPE_FILE:
keir@20566 1772 /* let's pretend is tap:aio for the moment */
keir@20566 1773 disk->phystype = PHYSTYPE_AIO;
Ian@21903 1774 case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case PHYSTYPE_VHD: {
Ian@21903 1775 const char *msg;
Ian@21903 1776 if (!tap_ctl_check(&msg)) {
Ian@21903 1777 const char *type = device_disk_string_of_phystype(disk->phystype);
Ian@21903 1778 char *dev;
gianni@22023 1779 dev = get_blktap2_device(&gc, disk->physpath, type);
keir@21632 1780 if (!dev)
gianni@22023 1781 dev = make_blktap2_device(&gc, disk->physpath, type);
gianni@22023 1782 if (!dev) {
gianni@22023 1783 rc = ERROR_FAIL;
gianni@22023 1784 goto out_free;
gianni@22023 1785 }
keir@20566 1786 flexarray_set(back, boffset++, "tapdisk-params");
gianni@22023 1787 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%s:%s", device_disk_string_of_phystype(disk->phystype), disk->physpath));
keir@20566 1788 flexarray_set(back, boffset++, "params");
gianni@22023 1789 flexarray_set(back, boffset++, libxl_strdup(&gc, dev));
keir@20566 1790 backend_type = "phy";
keir@20566 1791 device_physdisk_major_minor(dev, &major, &minor);
keir@20566 1792 flexarray_set(back, boffset++, "physical-device");
gianni@22023 1793 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%x:%x", major, minor));
keir@20566 1794 device.backend_kind = DEVICE_VBD;
keir@20566 1795
keir@20566 1796 break;
keir@20566 1797 }
keir@20516 1798 flexarray_set(back, boffset++, "params");
gianni@22023 1799 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%s:%s",
keir@20462 1800 device_disk_string_of_phystype(disk->phystype), disk->physpath));
keir@20462 1801
keir@20462 1802 device.backend_kind = DEVICE_TAP;
keir@20462 1803 break;
Ian@21903 1804 }
keir@20846 1805 default:
keir@20846 1806 XL_LOG(ctx, XL_LOG_ERROR, "unrecognized disk physical type: %d\n", disk->phystype);
gianni@22023 1807 rc = ERROR_INVAL;
gianni@22023 1808 goto out_free;
keir@20462 1809 }
keir@20462 1810
keir@20516 1811 flexarray_set(back, boffset++, "frontend-id");
gianni@22023 1812 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", disk->domid));
keir@20516 1813 flexarray_set(back, boffset++, "online");
keir@20516 1814 flexarray_set(back, boffset++, "1");
keir@20516 1815 flexarray_set(back, boffset++, "removable");
gianni@22023 1816 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", (disk->unpluggable) ? 1 : 0));
keir@20516 1817 flexarray_set(back, boffset++, "bootable");
gianni@22023 1818 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 1819 flexarray_set(back, boffset++, "state");
gianni@22023 1820 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 1821 flexarray_set(back, boffset++, "dev");
keir@20516 1822 flexarray_set(back, boffset++, disk->virtpath);
keir@20516 1823 flexarray_set(back, boffset++, "type");
keir@20516 1824 flexarray_set(back, boffset++, backend_type);
keir@20516 1825 flexarray_set(back, boffset++, "mode");
keir@20516 1826 flexarray_set(back, boffset++, disk->readwrite ? "w" : "r");
keir@20462 1827
keir@20516 1828 flexarray_set(front, foffset++, "backend-id");
gianni@22023 1829 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", disk->backend_domid));
keir@20516 1830 flexarray_set(front, foffset++, "state");
gianni@22023 1831 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 1832 flexarray_set(front, foffset++, "virtual-device");
gianni@22023 1833 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", devid));
keir@20516 1834 flexarray_set(front, foffset++, "device-type");
keir@20516 1835 flexarray_set(front, foffset++, disk->is_cdrom ? "cdrom" : "disk");
keir@20462 1836
keir@20462 1837 if (0 /* protocol != native*/) {
keir@20516 1838 flexarray_set(front, foffset++, "protocol");
keir@20516 1839 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */
keir@20462 1840 }
keir@20462 1841
keir@20462 1842 libxl_device_generic_add(ctx, &device,
gianni@22023 1843 libxl_xs_kvs_of_flexarray(&gc, back, boffset),
gianni@22023 1844 libxl_xs_kvs_of_flexarray(&gc, front, foffset));
gianni@22023 1845
gianni@22023 1846 rc = 0;
gianni@22023 1847
gianni@22023 1848 out_free:
keir@20516 1849 flexarray_free(back);
keir@20516 1850 flexarray_free(front);
gianni@22023 1851 out:
gianni@22023 1852 libxl_free_all(&gc);
gianni@22023 1853 return rc;
keir@20462 1854 }
keir@20462 1855
ian@21930 1856 int libxl_device_disk_del(libxl_ctx *ctx,
keir@20626 1857 libxl_device_disk *disk, int wait)
keir@20462 1858 {
keir@20626 1859 libxl_device device;
keir@20626 1860 int devid;
keir@20462 1861
keir@20626 1862 devid = device_disk_dev_number(disk->virtpath);
keir@20626 1863 device.backend_domid = disk->backend_domid;
keir@20626 1864 device.backend_devid = devid;
keir@20626 1865 device.backend_kind =
keir@20626 1866 (disk->phystype == PHYSTYPE_PHY) ? DEVICE_VBD : DEVICE_TAP;
keir@20626 1867 device.domid = disk->domid;
keir@20626 1868 device.devid = devid;
keir@20626 1869 device.kind = DEVICE_VBD;
keir@20626 1870 return libxl_device_del(ctx, &device, wait);
keir@20462 1871 }
keir@20462 1872
gianni@22023 1873 char * libxl_device_disk_local_attach(libxl_ctx *ctx, libxl_device_disk *disk)
Ian@21849 1874 {
gianni@22023 1875 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 1876 char *dev = NULL, *ret;
Ian@21849 1877 int phystype = disk->phystype;
Ian@21849 1878 switch (phystype) {
Ian@21849 1879 case PHYSTYPE_PHY: {
Ian@21849 1880 fprintf(stderr, "attaching PHY disk %s to domain 0\n", disk->physpath);
Ian@21849 1881 dev = disk->physpath;
Ian@21849 1882 break;
Ian@21849 1883 }
Ian@21849 1884 case PHYSTYPE_FILE:
Ian@21849 1885 /* let's pretend is tap:aio for the moment */
Ian@21849 1886 phystype = PHYSTYPE_AIO;
Ian@21903 1887 case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case PHYSTYPE_VHD: {
Ian@21903 1888 const char *msg;
Ian@21903 1889 if (!tap_ctl_check(&msg)) {
Ian@21903 1890 const char *type = device_disk_string_of_phystype(phystype);
gianni@22023 1891 dev = get_blktap2_device(&gc, disk->physpath, type);
Ian@21903 1892 if (!dev)
gianni@22023 1893 dev = make_blktap2_device(&gc, disk->physpath, type);
Ian@21903 1894 }
Ian@21849 1895 break;
Ian@21903 1896 }
Ian@21849 1897 default:
Ian@21849 1898 XL_LOG(ctx, XL_LOG_ERROR, "unrecognized disk physical type: %d\n", phystype);
Ian@21849 1899 break;
Ian@21849 1900 }
gianni@22023 1901 ret = strdup(dev);
gianni@22023 1902 libxl_free_all(&gc);
gianni@22023 1903 return ret;
Ian@21849 1904 }
Ian@21849 1905
ian@21930 1906 int libxl_device_disk_local_detach(libxl_ctx *ctx, libxl_device_disk *disk)
Ian@21849 1907 {
Ian@21849 1908 /* Nothing to do for PHYSTYPE_PHY. */
Ian@21849 1909
Ian@21849 1910 /*
Ian@21849 1911 * For other device types assume that the blktap2 process is
Ian@21849 1912 * needed by the soon to be started domain and do nothing.
Ian@21849 1913 */
Ian@21849 1914
Ian@21849 1915 return 0;
Ian@21849 1916 }
Ian@21849 1917
keir@20462 1918 /******************************************************************************/
ian@21930 1919 int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
keir@20462 1920 {
gianni@22023 1921 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20462 1922 flexarray_t *front;
keir@20462 1923 flexarray_t *back;
keir@20462 1924 unsigned int boffset = 0;
keir@20462 1925 unsigned int foffset = 0;
keir@20462 1926 libxl_device device;
keir@21407 1927 char *dompath, **l;
gianni@22023 1928 unsigned int nb, rc;
keir@20462 1929
keir@20462 1930 front = flexarray_make(16, 1);
gianni@22023 1931 if (!front) {
gianni@22023 1932 rc = ERROR_NOMEM;
gianni@22023 1933 goto out;
gianni@22023 1934 }
keir@20462 1935 back = flexarray_make(16, 1);
gianni@22023 1936 if (!back) {
gianni@22023 1937 rc = ERROR_NOMEM;
gianni@22023 1938 goto out_free;
gianni@22023 1939 }
keir@20462 1940
keir@21407 1941 if (nic->devid == -1) {
gianni@22023 1942 if (!(dompath = libxl_xs_get_dompath(&gc, domid))) {
gianni@22023 1943 rc = ERROR_FAIL;
gianni@22023 1944 goto out_free;
keir@21407 1945 }
gianni@22023 1946 if (!(l = libxl_xs_directory(&gc, XBT_NULL,
gianni@22023 1947 libxl_sprintf(&gc, "%s/device/vif", dompath), &nb))) {
keir@21407 1948 nic->devid = 0;
keir@21407 1949 } else {
keir@21407 1950 nic->devid = strtoul(l[nb - 1], NULL, 10) + 1;
keir@21407 1951 }
keir@21407 1952 }
keir@21407 1953
keir@20462 1954 device.backend_devid = nic->devid;
keir@20462 1955 device.backend_domid = nic->backend_domid;
keir@20462 1956 device.backend_kind = DEVICE_VIF;
keir@20462 1957 device.devid = nic->devid;
keir@20462 1958 device.domid = nic->domid;
keir@20462 1959 device.kind = DEVICE_VIF;
keir@20462 1960
keir@20516 1961 flexarray_set(back, boffset++, "frontend-id");
gianni@22023 1962 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", nic->domid));
keir@20516 1963 flexarray_set(back, boffset++, "online");
keir@20516 1964 flexarray_set(back, boffset++, "1");
keir@20516 1965 flexarray_set(back, boffset++, "state");
gianni@22023 1966 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 1967 flexarray_set(back, boffset++, "script");
keir@20516 1968 flexarray_set(back, boffset++, nic->script);
keir@20516 1969 flexarray_set(back, boffset++, "mac");
gianni@22023 1970 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 1971 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 1972 nic->mac[3], nic->mac[4], nic->mac[5]));
Ian@21732 1973 flexarray_set(back, boffset++, "bridge");
gianni@22023 1974 flexarray_set(back, boffset++, libxl_strdup(&gc, nic->bridge));
keir@20516 1975 flexarray_set(back, boffset++, "handle");
gianni@22023 1976 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", nic->devid));
keir@20462 1977
keir@20516 1978 flexarray_set(front, foffset++, "backend-id");
gianni@22023 1979 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", nic->backend_domid));
keir@20516 1980 flexarray_set(front, foffset++, "state");
gianni@22023 1981 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 1982 flexarray_set(front, foffset++, "handle");
gianni@22023 1983 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", nic->devid));
keir@20516 1984 flexarray_set(front, foffset++, "mac");
gianni@22023 1985 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 1986 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 1987 nic->mac[3], nic->mac[4], nic->mac[5]));
keir@20462 1988 if (0 /* protocol != native*/) {
keir@20516 1989 flexarray_set(front, foffset++, "protocol");
keir@20516 1990 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */
keir@20462 1991 }
keir@20462 1992
keir@20462 1993 libxl_device_generic_add(ctx, &device,
gianni@22023 1994 libxl_xs_kvs_of_flexarray(&gc, back, boffset),
gianni@22023 1995 libxl_xs_kvs_of_flexarray(&gc, front, foffset));
keir@20462 1996
keir@20462 1997 /* FIXME: wait for plug */
gianni@22023 1998 rc = 0;
gianni@22023 1999 out_free:
keir@20516 2000 flexarray_free(back);
keir@20516 2001 flexarray_free(front);
gianni@22023 2002 out:
gianni@22023 2003 libxl_free_all(&gc);
gianni@22023 2004 return rc;
keir@20462 2005 }
keir@20462 2006
ian@21930 2007 int libxl_device_nic_del(libxl_ctx *ctx,
keir@20626 2008 libxl_device_nic *nic, int wait)
keir@20462 2009 {
keir@20626 2010 libxl_device device;
keir@20462 2011
keir@20626 2012 device.backend_devid = nic->devid;
keir@20626 2013 device.backend_domid = nic->backend_domid;
keir@20626 2014 device.backend_kind = DEVICE_VIF;
keir@20626 2015 device.devid = nic->devid;
keir@20626 2016 device.domid = nic->domid;
keir@20626 2017 device.kind = DEVICE_VIF;
keir@20626 2018
keir@20626 2019 return libxl_device_del(ctx, &device, wait);
keir@20462 2020 }
keir@20462 2021
gianni@22009 2022 void libxl_free_nics_list(libxl_nicinfo *nics, unsigned int nb)
gianni@22009 2023 {
gianni@22009 2024 unsigned int i;
gianni@22009 2025 for(i = 0; i < nb; i++) {
gianni@22009 2026 free(nics[i].backend);
gianni@22009 2027 free(nics[i].frontend);
gianni@22009 2028 free(nics[i].script);
gianni@22009 2029 }
gianni@22009 2030 free(nics);
gianni@22009 2031 }
gianni@22009 2032
ian@21930 2033 libxl_nicinfo *libxl_list_nics(libxl_ctx *ctx, uint32_t domid, unsigned int *nb)
keir@21408 2034 {
gianni@22023 2035 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21408 2036 char *dompath, *nic_path_fe;
gianni@22009 2037 char **l, **list;
keir@21408 2038 char *val, *tok;
keir@21408 2039 unsigned int nb_nics, i;
keir@21408 2040 libxl_nicinfo *res, *nics;
keir@21408 2041
gianni@22023 2042 dompath = libxl_xs_get_dompath(&gc, domid);
gianni@22023 2043 if (!dompath)
gianni@22023 2044 goto err;
gianni@22023 2045 list = l = libxl_xs_directory(&gc, XBT_NULL,
gianni@22023 2046 libxl_sprintf(&gc, "%s/device/vif", dompath), &nb_nics);
gianni@22023 2047 if (!l)
gianni@22023 2048 goto err;
gianni@22009 2049 nics = res = calloc(nb_nics, sizeof (libxl_device_nic));
gianni@22023 2050 if (!res)
gianni@22023 2051 goto err;
keir@21408 2052 for (*nb = nb_nics; nb_nics > 0; --nb_nics, ++l, ++nics) {
gianni@22023 2053 nic_path_fe = libxl_sprintf(&gc, "%s/device/vif/%s", dompath, *l);
keir@21408 2054
gianni@22009 2055 nics->backend = xs_read(ctx->xsh, XBT_NULL,
gianni@22023 2056 libxl_sprintf(&gc, "%s/backend", nic_path_fe), NULL);
gianni@22023 2057 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend-id", nic_path_fe));
keir@21408 2058 nics->backend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21408 2059
keir@21408 2060 nics->devid = strtoul(*l, NULL, 10);
gianni@22023 2061 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/state", nic_path_fe));
keir@21408 2062 nics->state = val ? strtoul(val, NULL, 10) : -1;
gianni@22023 2063 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/mac", nic_path_fe));
keir@21408 2064 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21408 2065 ++i, tok = strtok(NULL, ":")) {
keir@21408 2066 nics->mac[i] = strtoul(tok, NULL, 16);
keir@21408 2067 }
gianni@22023 2068 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/event-channel", nic_path_fe));
keir@21408 2069 nics->evtch = val ? strtol(val, NULL, 10) : -1;
gianni@22023 2070 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/tx-ring-ref", nic_path_fe));
keir@21408 2071 nics->rref_tx = val ? strtol(val, NULL, 10) : -1;
gianni@22023 2072 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/rx-ring-ref", nic_path_fe));
keir@21408 2073 nics->rref_rx = val ? strtol(val, NULL, 10) : -1;
gianni@22009 2074 nics->frontend = xs_read(ctx->xsh, XBT_NULL,
gianni@22023 2075 libxl_sprintf(&gc, "%s/frontend", nics->backend), NULL);
gianni@22023 2076 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/frontend-id", nics->backend));
keir@21408 2077 nics->frontend_id = val ? strtoul(val, NULL, 10) : -1;
gianni@22009 2078 nics->script = xs_read(ctx->xsh, XBT_NULL,
gianni@22023 2079 libxl_sprintf(&gc, "%s/script", nics->backend), NULL);
keir@21408 2080 }
keir@21408 2081
gianni@22023 2082 libxl_free_all(&gc);
keir@21408 2083 return res;
gianni@22023 2084 err:
gianni@22023 2085 libxl_free_all(&gc);
gianni@22023 2086 return NULL;
keir@21408 2087 }
keir@21408 2088
keir@21580 2089 /******************************************************************************/
ian@21930 2090 int libxl_device_net2_add(libxl_ctx *ctx, uint32_t domid, libxl_device_net2 *net2)
keir@21580 2091 {
gianni@22023 2092 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21580 2093 flexarray_t *front, *back;
keir@21580 2094 unsigned int boffset = 0, foffset = 0;
keir@21580 2095 libxl_device device;
keir@21580 2096 char *dompath, *dom, **l;
keir@21580 2097 unsigned int nb;
gianni@22023 2098 int rc;
keir@21580 2099
keir@21580 2100 front = flexarray_make(16, 1);
gianni@22023 2101 if (!front) {
gianni@22023 2102 rc = ERROR_NOMEM;
gianni@22023 2103 goto err;
gianni@22023 2104 }
keir@21580 2105 back = flexarray_make(16, 1);
gianni@22023 2106 if (!back) {
gianni@22023 2107 rc = ERROR_NOMEM;
gianni@22023 2108 goto err_free;
keir@21580 2109 }
gianni@22023 2110
gianni@22023 2111 if (!(dompath = libxl_xs_get_dompath(&gc, domid))) {
gianni@22023 2112 rc = ERROR_FAIL;
gianni@22023 2113 goto err_free;
gianni@22023 2114 }
gianni@22023 2115 dom = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/name", dompath));
keir@21580 2116
keir@21580 2117 if (net2->devid == -1) {
gianni@22023 2118 if (!(l = libxl_xs_directory(&gc, XBT_NULL,
gianni@22023 2119 libxl_sprintf(&gc, "%s/device/vif2", dompath), &nb))) {
keir@21580 2120 net2->devid = 0;
keir@21580 2121 } else {
keir@21580 2122 net2->devid = strtoul(l[nb - 1], NULL, 10) + 1;
keir@21580 2123 }
keir@21580 2124 }
keir@21580 2125
keir@21580 2126 device.backend_devid = net2->devid;
keir@21580 2127 device.backend_domid = net2->backend_domid;
keir@21580 2128 device.backend_kind = DEVICE_VIF2;
keir@21580 2129 device.devid = net2->devid;
keir@21580 2130 device.domid = net2->domid;
keir@21580 2131 device.kind = DEVICE_VIF2;
keir@21580 2132
keir@21580 2133 flexarray_set(back, boffset++, "domain");
keir@21580 2134 flexarray_set(back, boffset++, dom);
keir@21580 2135 flexarray_set(back, boffset++, "frontend-id");
gianni@22023 2136 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->domid));
keir@21580 2137
keir@21580 2138 flexarray_set(back, boffset++, "local-trusted");
gianni@22023 2139 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->back_trusted));
keir@21580 2140 flexarray_set(back, boffset++, "mac");
gianni@22023 2141 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 2142 net2->back_mac[0], net2->back_mac[1],
keir@21580 2143 net2->back_mac[2], net2->back_mac[3],
keir@21580 2144 net2->back_mac[4], net2->back_mac[5]));
keir@21580 2145
keir@21580 2146 flexarray_set(back, boffset++, "remote-trusted");
gianni@22023 2147 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->trusted));
keir@21580 2148 flexarray_set(back, boffset++, "remote-mac");
gianni@22023 2149 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 2150 net2->front_mac[0], net2->front_mac[1],
keir@21580 2151 net2->front_mac[2], net2->front_mac[3],
keir@21580 2152 net2->front_mac[4], net2->front_mac[5]));
keir@21580 2153
keir@21580 2154 flexarray_set(back, boffset++, "max-bypasses");
gianni@22023 2155 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->max_bypasses));
keir@21580 2156 flexarray_set(back, boffset++, "filter-mac");
gianni@22023 2157 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", !!(net2->filter_mac)));
keir@21580 2158 flexarray_set(back, boffset++, "handle");
gianni@22023 2159 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->devid));
keir@21580 2160 flexarray_set(back, boffset++, "online");
keir@21580 2161 flexarray_set(back, boffset++, "1");
keir@21580 2162 flexarray_set(back, boffset++, "state");
keir@21580 2163 flexarray_set(back, boffset++, "1");
keir@21580 2164
keir@21580 2165 flexarray_set(front, foffset++, "backend-id");
gianni@22023 2166 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", net2->backend_domid));
keir@21580 2167
keir@21580 2168 flexarray_set(front, foffset++, "local-trusted");
gianni@22023 2169 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", net2->trusted));
keir@21580 2170 flexarray_set(front, foffset++, "mac");
gianni@22023 2171 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 2172 net2->front_mac[0], net2->front_mac[1],
keir@21580 2173 net2->front_mac[2], net2->front_mac[3],
keir@21580 2174 net2->front_mac[4], net2->front_mac[5]));
keir@21580 2175
keir@21580 2176 flexarray_set(front, foffset++, "remote-trusted");
gianni@22023 2177 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", net2->back_trusted));
keir@21580 2178 flexarray_set(front, foffset++, "remote-mac");
gianni@22023 2179 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 2180 net2->back_mac[0], net2->back_mac[1],
keir@21580 2181 net2->back_mac[2], net2->back_mac[3],
keir@21580 2182 net2->back_mac[4], net2->back_mac[5]));
keir@21580 2183
keir@21580 2184 flexarray_set(front, foffset++, "filter-mac");
gianni@22023 2185 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", !!(net2->filter_mac)));
keir@21580 2186 flexarray_set(front, foffset++, "state");
keir@21580 2187 flexarray_set(front, foffset++, "1");
keir@21580 2188
keir@21580 2189 libxl_device_generic_add(ctx, &device,
gianni@22023 2190 libxl_xs_kvs_of_flexarray(&gc, back, boffset),
gianni@22023 2191 libxl_xs_kvs_of_flexarray(&gc, front, foffset));
keir@21580 2192
keir@21580 2193 /* FIXME: wait for plug */
gianni@22023 2194 rc = 0;
gianni@22023 2195 err_free:
keir@21580 2196 flexarray_free(back);
keir@21580 2197 flexarray_free(front);
gianni@22023 2198 err:
gianni@22023 2199 libxl_free_all(&gc);
gianni@22023 2200 return rc;
keir@21580 2201 }
keir@21408 2202
ian@21930 2203 libxl_net2info *libxl_device_net2_list(libxl_ctx *ctx, uint32_t domid, unsigned int *nb)
keir@21581 2204 {
gianni@22023 2205 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21581 2206 char *dompath, *net2_path_fe;
keir@21581 2207 char **l;
keir@21581 2208 char *val, *tok;
keir@21581 2209 unsigned int nb_net2s, i;
keir@21581 2210 libxl_net2info *res, *net2s;
keir@21581 2211
gianni@22023 2212 dompath = libxl_xs_get_dompath(&gc, domid);
gianni@22023 2213 if (!dompath)
gianni@22023 2214 goto err;
gianni@22023 2215 l = libxl_xs_directory(&gc, XBT_NULL,
gianni@22023 2216 libxl_sprintf(&gc, "%s/device/vif2", dompath), &nb_net2s);
gianni@22023 2217 if (!l)
gianni@22023 2218 goto err;
gianni@22023 2219 res = calloc(nb_net2s, sizeof (libxl_net2info));
gianni@22023 2220 if (!res)
gianni@22023 2221 goto err;
keir@21581 2222 net2s = res;
keir@21581 2223 for (*nb = nb_net2s; nb_net2s > 0; --nb_net2s, ++l, ++net2s) {
gianni@22023 2224 net2_path_fe = libxl_sprintf(&gc, "%s/device/vif2/%s", dompath, *l);
gianni@22023 2225
gianni@22023 2226 net2s->backend = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 2227 libxl_sprintf(&gc, "%s/backend", net2_path_fe));
gianni@22023 2228 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend-id", net2_path_fe));
keir@21581 2229 net2s->backend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21581 2230
keir@21581 2231 net2s->devid = strtoul(*l, NULL, 10);
gianni@22023 2232 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/state", net2_path_fe));
keir@21581 2233 net2s->state = val ? strtoul(val, NULL, 10) : -1;
keir@21581 2234
gianni@22023 2235 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/mac", net2_path_fe));
keir@21581 2236 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21581 2237 ++i, tok = strtok(NULL, ":")) {
keir@21581 2238 net2s->mac[i] = strtoul(tok, NULL, 16);
keir@21581 2239 }
gianni@22023 2240 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/remote-trusted", net2_path_fe));
keir@21581 2241 net2s->trusted = val ? strtoul(val, NULL, 10) : -1;
keir@21581 2242
gianni@22023 2243 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/remote-mac", net2_path_fe));
keir@21581 2244 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21581 2245 ++i, tok = strtok(NULL, ":")) {
keir@21581 2246 net2s->back_mac[i] = strtoul(tok, NULL, 16);
keir@21581 2247 }
gianni@22023 2248 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/filter-mac", net2_path_fe));
keir@21581 2249 net2s->filter_mac = val ? strtoul(val, NULL, 10) : -1;
keir@21581 2250
gianni@22023 2251 net2s->frontend = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 2252 libxl_sprintf(&gc, "%s/frontend", net2s->backend));
gianni@22023 2253 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/frontend-id", net2s->backend));
keir@21581 2254 net2s->frontend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21581 2255 }
keir@21581 2256
gianni@22023 2257 libxl_free_all(&gc);
keir@21581 2258 return res;
gianni@22023 2259 err:
gianni@22023 2260 libxl_free_all(&gc);
gianni@22023 2261 return NULL;
keir@21581 2262 }
keir@21581 2263
ian@21930 2264 int libxl_device_net2_del(libxl_ctx *ctx, libxl_device_net2 *net2, int wait)
keir@21582 2265 {
keir@21582 2266 libxl_device device;
keir@21582 2267
keir@21582 2268 device.backend_devid = net2->devid;
keir@21582 2269 device.backend_domid = net2->backend_domid;
keir@21582 2270 device.backend_kind = DEVICE_VIF2;
keir@21582 2271 device.devid = net2->devid;
keir@21582 2272 device.domid = net2->domid;
keir@21582 2273 device.kind = DEVICE_VIF2;
keir@21582 2274
keir@21582 2275 return libxl_device_del(ctx, &device, wait);
keir@21582 2276 }
keir@21582 2277
keir@21581 2278
keir@20462 2279 /******************************************************************************/
ian@21930 2280 int libxl_device_console_add(libxl_ctx *ctx, uint32_t domid, libxl_device_console *console)
keir@20462 2281 {
gianni@22023 2282 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20509 2283 flexarray_t *front;
keir@20509 2284 flexarray_t *back;
keir@20509 2285 unsigned int boffset = 0;
keir@20509 2286 unsigned int foffset = 0;
keir@20509 2287 libxl_device device;
gianni@22023 2288 int rc;
keir@20509 2289
keir@20509 2290 if (console->build_state) {
keir@20509 2291 xs_transaction_t t;
gianni@22023 2292 char **ents = (char **) libxl_calloc(&gc, 9, sizeof(char *));
keir@20516 2293 ents[0] = "console/port";
gianni@22023 2294 ents[1] = libxl_sprintf(&gc, "%"PRIu32, console->build_state->console_port);
keir@20516 2295 ents[2] = "console/ring-ref";
gianni@22023 2296 ents[3] = libxl_sprintf(&gc, "%lu", console->build_state->console_mfn);
keir@20516 2297 ents[4] = "console/limit";
gianni@22023 2298 ents[5] = libxl_sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT);
keir@20516 2299 ents[6] = "console/type";
keir@20509 2300 if (console->constype == CONSTYPE_XENCONSOLED)
keir@20509 2301 ents[7] = "xenconsoled";
keir@20509 2302 else
keir@20509 2303 ents[7] = "ioemu";
keir@20509 2304 retry_transaction:
keir@20509 2305 t = xs_transaction_start(ctx->xsh);
gianni@22023 2306 libxl_xs_writev(&gc, t, libxl_xs_get_dompath(&gc, console->domid), ents);
keir@20509 2307 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20509 2308 if (errno == EAGAIN)
keir@20509 2309 goto retry_transaction;
keir@20509 2310 }
keir@20509 2311
keir@20509 2312 front = flexarray_make(16, 1);
gianni@22023 2313 if (!front) {
gianni@22023 2314 rc = ERROR_NOMEM;
gianni@22023 2315 goto out;
gianni@22023 2316 }
keir@20509 2317 back = flexarray_make(16, 1);
gianni@22023 2318 if (!back) {
gianni@22023 2319 rc = ERROR_NOMEM;
gianni@22023 2320 goto out_free;
gianni@22023 2321 }
keir@20509 2322
keir@20509 2323 device.backend_devid = console->devid;
keir@20509 2324 device.backend_domid = console->backend_domid;
keir@20509 2325 device.backend_kind = DEVICE_CONSOLE;
keir@20509 2326 device.devid = console->devid;
keir@20509 2327 device.domid = console->domid;
keir@20509 2328 device.kind = DEVICE_CONSOLE;
keir@20509 2329
keir@20516 2330 flexarray_set(back, boffset++, "frontend-id");
gianni@22023 2331 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", console->domid));
keir@20516 2332 flexarray_set(back, boffset++, "online");
keir@20516 2333 flexarray_set(back, boffset++, "1");
keir@20516 2334 flexarray_set(back, boffset++, "state");
gianni@22023 2335 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 2336 flexarray_set(back, boffset++, "domain");
gianni@22023 2337 flexarray_set(back, boffset++, _libxl_domid_to_name(&gc, domid));
keir@20516 2338 flexarray_set(back, boffset++, "protocol");
keir@20516 2339 flexarray_set(back, boffset++, LIBXL_XENCONSOLE_PROTOCOL);
keir@20509 2340
keir@20516 2341 flexarray_set(front, foffset++, "backend-id");
gianni@22023 2342 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", console->backend_domid));
keir@20516 2343 flexarray_set(front, foffset++, "state");
gianni@22023 2344 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 2345 flexarray_set(front, foffset++, "limit");
gianni@22023 2346 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT));
keir@20516 2347 flexarray_set(front, foffset++, "protocol");
keir@20516 2348 flexarray_set(front, foffset++, LIBXL_XENCONSOLE_PROTOCOL);
keir@20516 2349 flexarray_set(front, foffset++, "type");
keir@20509 2350 if (console->constype == CONSTYPE_XENCONSOLED)
keir@20516 2351 flexarray_set(front, foffset++, "xenconsoled");
keir@20509 2352 else
keir@20516 2353 flexarray_set(front, foffset++, "ioemu");
keir@20509 2354
keir@20509 2355 libxl_device_generic_add(ctx, &device,
gianni@22023 2356 libxl_xs_kvs_of_flexarray(&gc, back, boffset),
gianni@22023 2357 libxl_xs_kvs_of_flexarray(&gc, front, foffset));
gianni@22023 2358 rc = 0;
gianni@22023 2359 out_free:
keir@20516 2360 flexarray_free(back);
keir@20516 2361 flexarray_free(front);
gianni@22023 2362 out:
gianni@22023 2363 libxl_free_all(&gc);
gianni@22023 2364 return rc;
keir@20509 2365 }
keir@20509 2366
keir@20509 2367 /******************************************************************************/
ian@21930 2368 int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb)
keir@20509 2369 {
gianni@22023 2370 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20509 2371 flexarray_t *front;
keir@20509 2372 flexarray_t *back;
keir@20509 2373 unsigned int boffset = 0;
keir@20509 2374 unsigned int foffset = 0;
keir@20509 2375 libxl_device device;
gianni@22023 2376 int rc;
keir@20509 2377
keir@20509 2378 front = flexarray_make(16, 1);
gianni@22023 2379 if (!front) {
gianni@22023 2380 rc = ERROR_NOMEM;
gianni@22023 2381 goto out;
gianni@22023 2382 }
keir@20509 2383 back = flexarray_make(16, 1);
gianni@22023 2384 if (!back) {
gianni@22023 2385 rc = ERROR_NOMEM;
gianni@22023 2386 goto out_free;
gianni@22023 2387 }
keir@20509 2388
keir@20509 2389 device.backend_devid = vkb->devid;
keir@20509 2390 device.backend_domid = vkb->backend_domid;
keir@20509 2391 device.backend_kind = DEVICE_VKBD;
keir@20509 2392 device.devid = vkb->devid;
keir@20509 2393 device.domid = vkb->domid;
keir@20509 2394 device.kind = DEVICE_VKBD;
keir@20509 2395
keir@20516 2396 flexarray_set(back, boffset++, "frontend-id");
gianni@22023 2397 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vkb->domid));
keir@20516 2398 flexarray_set(back, boffset++, "online");
keir@20516 2399 flexarray_set(back, boffset++, "1");
keir@20516 2400 flexarray_set(back, boffset++, "state");
gianni@22023 2401 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 2402 flexarray_set(back, boffset++, "domain");
gianni@22023 2403 flexarray_set(back, boffset++, _libxl_domid_to_name(&gc, domid));
keir@20509 2404
keir@20516 2405 flexarray_set(front, foffset++, "backend-id");
gianni@22023 2406 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", vkb->backend_domid));
keir@20516 2407 flexarray_set(front, foffset++, "state");
gianni@22023 2408 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
keir@20509 2409
keir@20509 2410 libxl_device_generic_add(ctx, &device,
gianni@22023 2411 libxl_xs_kvs_of_flexarray(&gc, back, boffset),
gianni@22023 2412 libxl_xs_kvs_of_flexarray(&gc, front, foffset));
gianni@22023 2413 rc = 0;
gianni@22023 2414 out_free:
keir@20516 2415 flexarray_free(back);
keir@20516 2416 flexarray_free(front);
gianni@22023 2417 out:
gianni@22023 2418 libxl_free_all(&gc);
gianni@22023 2419 return rc;
keir@20462 2420 }
keir@20462 2421
ian@21930 2422 int libxl_device_vkb_clean_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 2423 {
keir@20462 2424 return ERROR_NI;
keir@20462 2425 }
keir@20462 2426
ian@21930 2427 int libxl_device_vkb_hard_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 2428 {
keir@20462 2429 return ERROR_NI;
keir@20462 2430 }
keir@20462 2431
ian@21930 2432 libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *num)
keir@20637 2433 {
gianni@22023 2434 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20637 2435 char *be_path_tap, *be_path_vbd;
keir@21411 2436 libxl_device_disk *dend, *disks, *ret = NULL;
keir@21411 2437 char **b, **l = NULL;
keir@20637 2438 unsigned int numl;
keir@20637 2439 char *type;
keir@20637 2440
gianni@22023 2441 be_path_vbd = libxl_sprintf(&gc, "%s/backend/vbd/%d", libxl_xs_get_dompath(&gc, 0), domid);
gianni@22023 2442 be_path_tap = libxl_sprintf(&gc, "%s/backend/tap/%d", libxl_xs_get_dompath(&gc, 0), domid);
gianni@22023 2443
gianni@22023 2444 b = l = libxl_xs_directory(&gc, XBT_NULL, be_path_vbd, &numl);
keir@20637 2445 if (l) {
keir@21411 2446 ret = realloc(ret, sizeof(libxl_device_disk) * numl);
keir@21411 2447 disks = ret;
keir@21411 2448 *num = numl;
keir@21411 2449 dend = ret + *num;
keir@21411 2450 for (; disks < dend; ++disks, ++l) {
keir@21411 2451 disks->backend_domid = 0;
keir@21411 2452 disks->domid = domid;
gianni@22023 2453 disks->physpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/params", be_path_vbd, *l));
gianni@22023 2454 libxl_string_to_phystype(ctx, libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/type", be_path_vbd, *l)), &(disks->phystype));
gianni@22023 2455 disks->virtpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/dev", be_path_vbd, *l));
gianni@22023 2456 disks->unpluggable = atoi(libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/removable", be_path_vbd, *l)));
gianni@22023 2457 if (!strcmp(libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/mode", be_path_vbd, *l)), "w"))
keir@21411 2458 disks->readwrite = 1;
keir@20637 2459 else
keir@21411 2460 disks->readwrite = 0;
gianni@22023 2461 type = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/device-type", libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/frontend", be_path_vbd, *l))));
keir@21411 2462 disks->is_cdrom = !strcmp(type, "cdrom");
keir@20637 2463 }
keir@20637 2464 }
gianni@22023 2465 b = l = libxl_xs_directory(&gc, XBT_NULL, be_path_tap, &numl);
keir@20637 2466 if (l) {
keir@21411 2467 ret = realloc(ret, sizeof(libxl_device_disk) * (*num + numl));
keir@21411 2468 disks = ret + *num;
keir@21411 2469 *num += numl;
keir@21411 2470 for (dend = ret + *num; disks < dend; ++disks, ++l) {
keir@21411 2471 disks->backend_domid = 0;
keir@21411 2472 disks->domid = domid;
gianni@22023 2473 disks->physpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/params", be_path_tap, *l));
gianni@22023 2474 libxl_string_to_phystype(ctx, libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/type", be_path_tap, *l)), &(disks->phystype));
gianni@22023 2475 disks->virtpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/dev", be_path_tap, *l));
gianni@22023 2476 disks->unpluggable = atoi(libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/removable", be_path_tap, *l)));
gianni@22023 2477 if (!strcmp(libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/mode", be_path_tap, *l)), "w"))
keir@21411 2478 disks->readwrite = 1;
keir@20637 2479 else
keir@21411 2480 disks->readwrite = 0;
gianni@22023 2481 type = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/device-type", libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/frontend", be_path_tap, *l))));
keir@21411 2482 disks->is_cdrom = !strcmp(type, "cdrom");
keir@20637 2483 }
keir@20637 2484 }
gianni@22023 2485 libxl_free_all(&gc);
keir@21411 2486 return ret;
keir@21411 2487 }
keir@21411 2488
ian@21930 2489 int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
keir@21411 2490 libxl_device_disk *disk, libxl_diskinfo *diskinfo)
keir@21411 2491 {
gianni@22023 2492 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21411 2493 char *dompath, *diskpath;
keir@21411 2494 char *val;
keir@21411 2495
gianni@22023 2496 dompath = libxl_xs_get_dompath(&gc, domid);
keir@21411 2497 diskinfo->devid = device_disk_dev_number(disk->virtpath);
keir@21411 2498
keir@21411 2499 /* tap devices entries in xenstore are written as vbd devices. */
gianni@22023 2500 diskpath = libxl_sprintf(&gc, "%s/device/vbd/%d", dompath, diskinfo->devid);
gianni@22023 2501 diskinfo->backend = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 2502 libxl_sprintf(&gc, "%s/backend", diskpath));
keir@21411 2503 if (!diskinfo->backend) {
gianni@22023 2504 libxl_free_all(&gc);
keir@21411 2505 return ERROR_FAIL;
keir@21411 2506 }
gianni@22023 2507 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend-id", diskpath));
keir@21411 2508 diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
gianni@22023 2509 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/state", diskpath));
keir@21411 2510 diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
gianni@22023 2511 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/event-channel", diskpath));
keir@21411 2512 diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
gianni@22023 2513 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/ring-ref", diskpath));
keir@21411 2514 diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
gianni@22023 2515 diskinfo->frontend = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 2516 libxl_sprintf(&gc, "%s/frontend", diskinfo->backend));
gianni@22023 2517 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/frontend-id", diskinfo->backend));
keir@21411 2518 diskinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21411 2519
gianni@22023 2520 libxl_free_all(&gc);
keir@21411 2521 return 0;
keir@20637 2522 }
keir@20637 2523
ian@21930 2524 int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20637 2525 {
keir@20637 2526 int num, i;
keir@20637 2527 uint32_t stubdomid;
keir@20637 2528 libxl_device_disk *disks;
keir@20637 2529
keir@20637 2530 if (!disk->physpath) {
keir@20637 2531 disk->physpath = "";
keir@20637 2532 disk->phystype = PHYSTYPE_PHY;
keir@20637 2533 }
keir@20637 2534 disks = libxl_device_disk_list(ctx, domid, &num);
keir@20637 2535 for (i = 0; i < num; i++) {
keir@20637 2536 if (disks[i].is_cdrom && !strcmp(disk->virtpath, disks[i].virtpath))
keir@20637 2537 /* found */
keir@20637 2538 break;
keir@20637 2539 }
keir@20637 2540 if (i == num) {
keir@20637 2541 XL_LOG(ctx, XL_LOG_ERROR, "Virtual device not found");
gianni@22023 2542 free(disks);
gianni@21892 2543 return ERROR_FAIL;
keir@20637 2544 }
keir@20637 2545 libxl_device_disk_del(ctx, disks + i, 1);
keir@20637 2546 libxl_device_disk_add(ctx, domid, disk);
keir@20637 2547 stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20637 2548 if (stubdomid) {
keir@20781 2549 disks[i].domid = stubdomid;
keir@20637 2550 libxl_device_disk_del(ctx, disks + i, 1);
keir@20781 2551 disk->domid = stubdomid;
keir@20637 2552 libxl_device_disk_add(ctx, stubdomid, disk);
keir@20781 2553 disk->domid = domid;
keir@20637 2554 }
gianni@22023 2555 free(disks);
keir@20637 2556 return 0;
keir@20637 2557 }
keir@20637 2558
keir@20462 2559 /******************************************************************************/
gianni@22023 2560 static int libxl_build_xenpv_qemu_args(libxl_gc *gc,
keir@20509 2561 libxl_device_vfb *vfb,
keir@20509 2562 int num_console,
keir@20509 2563 libxl_device_console *console,
keir@20860 2564 libxl_device_model_info *info)
keir@20860 2565 {
gianni@22023 2566 libxl_ctx *ctx = libxl_gc_owner(gc);
keir@20509 2567 int i = 0, j = 0, num = 0;
keir@20509 2568 memset(info, 0x00, sizeof(libxl_device_model_info));
keir@20509 2569
keir@20509 2570 info->vnc = vfb->vnc;
keir@20509 2571 if (vfb->vnclisten)
gianni@22023 2572 info->vnclisten = libxl_strdup(gc, vfb->vnclisten);
keir@20509 2573 info->vncdisplay = vfb->vncdisplay;
keir@20509 2574 info->vncunused = vfb->vncunused;
keir@21362 2575 if (vfb->vncpasswd)
keir@21362 2576 info->vncpasswd = vfb->vncpasswd;
keir@20509 2577 if (vfb->keymap)
gianni@22023 2578 info->keymap = libxl_strdup(gc, vfb->keymap);
keir@20509 2579 info->sdl = vfb->sdl;
keir@20509 2580 info->opengl = vfb->opengl;
keir@20509 2581 for (i = 0; i < num_console; i++) {
keir@20509 2582 if (console->constype == CONSTYPE_IOEMU)
keir@20509 2583 num++;
keir@20509 2584 }
keir@20509 2585 if (num > 0) {
keir@20860 2586 uint32_t guest_domid;
keir@20860 2587 if (libxl_is_stubdom(ctx, vfb->domid, &guest_domid)) {
keir@20599 2588 char *filename;
gianni@22023 2589 char *name = libxl_sprintf(gc, "qemu-dm-%s", _libxl_domid_to_name(gc, guest_domid));
keir@20599 2590 libxl_create_logfile(ctx, name, &filename);
gianni@22023 2591 info->serial = libxl_sprintf(gc, "file:%s", filename);
keir@20599 2592 free(filename);
keir@20599 2593 } else {
keir@20599 2594 info->serial = "pty";
keir@20599 2595 }
keir@20509 2596 num--;
keir@20509 2597 }
keir@20509 2598 if (num > 0) {
gianni@22023 2599 info->extra = (char **) libxl_calloc(gc, num * 2 + 1, sizeof(char *));
keir@20509 2600 for (j = 0; j < num * 2; j = j + 2) {
keir@20509 2601 info->extra[j] = "-serial";
keir@20509 2602 info->extra[j + 1] = "pty";
keir@20509 2603 }
keir@20509 2604 info->extra[j] = NULL;
keir@20509 2605 }
keir@20509 2606 info->domid = vfb->domid;
gianni@22023 2607 info->dom_name = _libxl_domid_to_name(gc, vfb->domid);
gianni@22023 2608 info->device_model = libxl_abs_path(gc, "qemu-dm", libxl_libexec_path());
keir@20509 2609 info->type = XENPV;
keir@20509 2610 return 0;
keir@20509 2611 }
keir@20509 2612
ian@21930 2613 int libxl_create_xenpv_qemu(libxl_ctx *ctx, libxl_device_vfb *vfb,
keir@20514 2614 int num_console, libxl_device_console *console,
ian@21930 2615 libxl_device_model_starting **starting_r)
keir@20509 2616 {
gianni@22023 2617 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20509 2618 libxl_device_model_info info;
keir@20509 2619
gianni@22023 2620 libxl_build_xenpv_qemu_args(&gc, vfb, num_console, console, &info);
keir@20542 2621 libxl_create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r);
gianni@22023 2622 libxl_free_all(&gc);
keir@20509 2623 return 0;
keir@20509 2624 }
keir@20509 2625
ian@21930 2626 int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
keir@20462 2627 {
gianni@22023 2628 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20509 2629 flexarray_t *front;
keir@20509 2630 flexarray_t *back;
keir@20509 2631 unsigned int boffset = 0;
keir@20509 2632 unsigned int foffset = 0;
keir@20509 2633 libxl_device device;
gianni@22023 2634 int rc;
keir@20509 2635
keir@20509 2636 front = flexarray_make(16, 1);
gianni@22023 2637 if (!front) {
gianni@22023 2638 rc = ERROR_NOMEM;
gianni@22023 2639 goto out;
gianni@22023 2640 }
keir@20509 2641 back = flexarray_make(16, 1);
gianni@22023 2642 if (!back) {
gianni@22023 2643 rc = ERROR_NOMEM;
gianni@22023 2644 goto out_free;
gianni@22023 2645 }
keir@20509 2646
keir@20509 2647 device.backend_devid = vfb->devid;
keir@20509 2648 device.backend_domid = vfb->backend_domid;
keir@20509 2649 device.backend_kind = DEVICE_VFB;
keir@20509 2650 device.devid = vfb->devid;
keir@20509 2651 device.domid = vfb->domid;
keir@20509 2652 device.kind = DEVICE_VFB;
keir@20509 2653
keir@20516 2654 flexarray_set(back, boffset++, "frontend-id");
gianni@22023 2655 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->domid));
keir@20516 2656 flexarray_set(back, boffset++, "online");
keir@20516 2657 flexarray_set(back, boffset++, "1");
keir@20516 2658 flexarray_set(back, boffset++, "state");
gianni@22023 2659 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 2660 flexarray_set(back, boffset++, "domain");
gianni@22023 2661 flexarray_set(back, boffset++, _libxl_domid_to_name(&gc, domid));
keir@20516 2662 flexarray_set(back, boffset++, "vnc");
gianni@22023 2663 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->vnc));
keir@20516 2664 flexarray_set(back, boffset++, "vnclisten");
keir@20516 2665 flexarray_set(back, boffset++, vfb->vnclisten);
keir@21362 2666 flexarray_set(back, boffset++, "vncpasswd");
keir@21362 2667 flexarray_set(back, boffset++, vfb->vncpasswd);
keir@20516 2668 flexarray_set(back, boffset++, "vncdisplay");
gianni@22023 2669 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->vncdisplay));
keir@20516 2670 flexarray_set(back, boffset++, "vncunused");
gianni@22023 2671 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->vncunused));
keir@20516 2672 flexarray_set(back, boffset++, "sdl");
gianni@22023 2673 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->sdl));
keir@20516 2674 flexarray_set(back, boffset++, "opengl");
gianni@22023 2675 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->opengl));
keir@20509 2676 if (vfb->xauthority) {
keir@20516 2677 flexarray_set(back, boffset++, "xauthority");
keir@20516 2678 flexarray_set(back, boffset++, vfb->xauthority);
keir@20509 2679 }
keir@20509 2680 if (vfb->display) {
keir@20516 2681 flexarray_set(back, boffset++, "display");
keir@20516 2682 flexarray_set(back, boffset++, vfb->display);
keir@20509 2683 }
keir@20509 2684
keir@20516 2685 flexarray_set(front, foffset++, "backend-id");
gianni@22023 2686 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", vfb->backend_domid));
keir@20516 2687 flexarray_set(front, foffset++, "state");
gianni@22023 2688 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
keir@20509 2689
keir@20509 2690 libxl_device_generic_add(ctx, &device,
gianni@22023 2691 libxl_xs_kvs_of_flexarray(&gc, back, boffset),
gianni@22023 2692 libxl_xs_kvs_of_flexarray(&gc, front, foffset));
gianni@22023 2693 rc = 0;
gianni@22023 2694 out_free:
keir@20509 2695 flexarray_free(front);
keir@20509 2696 flexarray_free(back);
gianni@22023 2697 out:
gianni@22023 2698 libxl_free_all(&gc);
gianni@22023 2699 return rc;
keir@20462 2700 }
keir@20462 2701
ian@21930 2702 int libxl_device_vfb_clean_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 2703 {
keir@20462 2704 return ERROR_NI;
keir@20462 2705 }
keir@20462 2706
ian@21930 2707 int libxl_device_vfb_hard_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 2708 {
keir@20462 2709 return ERROR_NI;
keir@20462 2710 }
keir@20462 2711
keir@20462 2712 /******************************************************************************/
keir@20482 2713
ian@21930 2714 int libxl_domain_setmaxmem(libxl_ctx *ctx, uint32_t domid, uint32_t max_memkb)
keir@21404 2715 {
gianni@22023 2716 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21404 2717 char *mem, *endptr;
keir@21404 2718 uint32_t memorykb;
gianni@22023 2719 char *dompath = libxl_xs_get_dompath(&gc, domid);
gianni@22023 2720 int rc = 1;
gianni@22023 2721
gianni@22023 2722 mem = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/memory/target", dompath));
keir@21404 2723 if (!mem) {
keir@21404 2724 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot get memory info from %s/memory/target\n", dompath);
gianni@22023 2725 goto out;
keir@21404 2726 }
keir@21404 2727 memorykb = strtoul(mem, &endptr, 10);
keir@21404 2728 if (*endptr != '\0') {
keir@21404 2729 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "invalid memory %s from %s/memory/target\n", mem, dompath);
gianni@22023 2730 goto out;
keir@21404 2731 }
keir@21404 2732
keir@21404 2733 if (max_memkb < memorykb) {
keir@21404 2734 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "memory_static_max must be greater than or or equal to memory_dynamic_max\n");
gianni@22023 2735 goto out;
keir@21404 2736 }
keir@21404 2737
keir@21404 2738 if (domid != 0)
gianni@22023 2739 libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/memory/static-max", dompath), "%"PRIu32, max_memkb);
gianni@22023 2740
gianni@22023 2741 rc = 0;
gianni@22023 2742 out:
gianni@22023 2743 libxl_free_all(&gc);
gianni@22023 2744 return rc;
keir@21404 2745 }
keir@21404 2746
ian@21930 2747 int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid, uint32_t target_memkb, int enforce)
keir@20647 2748 {
gianni@22023 2749 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 2750 int rc = 1;
keir@21422 2751 uint32_t memorykb = 0, videoram = 0;
keir@21405 2752 char *memmax, *endptr, *videoram_s = NULL;
gianni@22023 2753 char *dompath = libxl_xs_get_dompath(&gc, domid);
keir@21374 2754 xc_domaininfo_t info;
ian@21930 2755 libxl_dominfo ptr;
keir@21374 2756 char *uuid;
keir@20542 2757
keir@21405 2758 if (domid) {
gianni@22023 2759 memmax = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/memory/static-max", dompath));
keir@21405 2760 if (!memmax) {
keir@21405 2761 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@21405 2762 "cannot get memory info from %s/memory/static-max\n", dompath);
gianni@22023 2763 goto out;
keir@21405 2764 }
keir@21405 2765 memorykb = strtoul(memmax, &endptr, 10);
keir@21405 2766 if (*endptr != '\0') {
keir@21405 2767 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@21405 2768 "invalid max memory %s from %s/memory/static-max\n", memmax, dompath);
gianni@22023 2769 goto out;
keir@21405 2770 }
keir@21405 2771
keir@21405 2772 if (target_memkb > memorykb) {
keir@21504 2773 XL_LOG(ctx, XL_LOG_ERROR,
keir@21405 2774 "memory_dynamic_max must be less than or equal to memory_static_max\n");
gianni@22023 2775 goto out;
keir@21405 2776 }
keir@21405 2777 }
keir@21405 2778
gianni@22023 2779 videoram_s = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/memory/videoram", dompath));
keir@21314 2780 videoram = videoram_s ? atoi(videoram_s) : 0;
keir@20647 2781
gianni@22023 2782 libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/memory/target", dompath), "%"PRIu32, target_memkb);
keir@21374 2783
keir@21374 2784 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &info);
keir@21374 2785 if (rc != 1 || info.domain != domid)
gianni@22023 2786 goto out;
keir@21374 2787 xcinfo2xlinfo(&info, &ptr);
keir@21374 2788 uuid = libxl_uuid2string(ctx, ptr.uuid);
gianni@22023 2789 libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "/vm/%s/memory", uuid), "%"PRIu32, target_memkb / 1024);
keir@21374 2790
keir@21422 2791 if (enforce || !domid)
keir@21422 2792 memorykb = target_memkb;
keir@21422 2793 rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb + LIBXL_MAXMEM_CONSTANT);
keir@21422 2794 if (rc != 0)
gianni@22023 2795 goto out;
keir@20647 2796 rc = xc_domain_memory_set_pod_target(ctx->xch, domid, (target_memkb - videoram) / 4, NULL, NULL, NULL);
gianni@22023 2797
gianni@22023 2798 out:
gianni@22023 2799 libxl_free_all(&gc);
keir@20647 2800 return rc;
keir@20647 2801 }
keir@20875 2802
ian@21930 2803 int libxl_button_press(libxl_ctx *ctx, uint32_t domid, libxl_button button)
keir@20875 2804 {
keir@20875 2805 int rc = -1;
keir@20875 2806
keir@20875 2807 switch (button) {
keir@20875 2808 case POWER_BUTTON:
keir@20875 2809 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_POWER, 0);
keir@20875 2810 break;
keir@20875 2811 case SLEEP_BUTTON:
keir@20875 2812 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_SLEEP, 0);
keir@20875 2813 break;
keir@20875 2814 default:
keir@20875 2815 break;
keir@20875 2816 }
keir@20875 2817
keir@20875 2818 return rc;
keir@20875 2819 }
keir@21141 2820
ian@21930 2821 int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
keir@21141 2822 {
keir@21141 2823 xc_physinfo_t xcphysinfo = { 0 };
keir@21141 2824 int rc;
keir@21141 2825
keir@21141 2826 rc = xc_physinfo(ctx->xch, &xcphysinfo);
keir@21141 2827 if (rc != 0) {
gianni@21892 2828 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting physinfo");
gianni@21892 2829 return ERROR_FAIL;
keir@21141 2830 }
keir@21141 2831 physinfo->threads_per_core = xcphysinfo.threads_per_core;
keir@21141 2832 physinfo->cores_per_socket = xcphysinfo.cores_per_socket;
keir@21142 2833 physinfo->max_cpu_id = xcphysinfo.max_cpu_id;
keir@21141 2834 physinfo->nr_cpus = xcphysinfo.nr_cpus;
keir@21141 2835 physinfo->cpu_khz = xcphysinfo.cpu_khz;
keir@21141 2836 physinfo->total_pages = xcphysinfo.total_pages;
keir@21141 2837 physinfo->free_pages = xcphysinfo.free_pages;
keir@21141 2838 physinfo->scrub_pages = xcphysinfo.scrub_pages;
keir@21264 2839 physinfo->nr_nodes = xcphysinfo.nr_nodes;
keir@21264 2840 memcpy(physinfo->hw_cap,xcphysinfo.hw_cap, sizeof(physinfo->hw_cap));
keir@21264 2841 physinfo->phys_cap = xcphysinfo.capabilities;
keir@21264 2842
keir@21141 2843 return 0;
keir@21141 2844 }
keir@21141 2845
gianni@22008 2846 static void do_free_version_info(libxl_version_info *info)
gianni@22008 2847 {
gianni@22008 2848 free(info->xen_version_extra);
gianni@22008 2849 free(info->compiler);
gianni@22008 2850 free(info->compile_by);
gianni@22008 2851 free(info->compile_domain);
gianni@22008 2852 free(info->compile_date);
gianni@22008 2853 free(info->capabilities);
gianni@22008 2854 free(info->changeset);
gianni@22008 2855 free(info->commandline);
gianni@22008 2856 }
gianni@22008 2857
ian@21930 2858 const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx)
keir@21266 2859 {
keir@21266 2860 union {
keir@21266 2861 xen_extraversion_t xen_extra;
keir@21266 2862 xen_compile_info_t xen_cc;
keir@21266 2863 xen_changeset_info_t xen_chgset;
keir@21266 2864 xen_capabilities_info_t xen_caps;
keir@21266 2865 xen_platform_parameters_t p_parms;
keir@21266 2866 xen_commandline_t xen_commandline;
keir@21266 2867 } u;
keir@21266 2868 long xen_version;
keir@21266 2869 libxl_version_info *info = &ctx->version_info;
keir@21266 2870
keir@21266 2871 if (info->xen_version_extra != NULL)
keir@21266 2872 return info;
keir@21266 2873
keir@21266 2874 xen_version = xc_version(ctx->xch, XENVER_version, NULL);
keir@21266 2875 info->xen_version_major = xen_version >> 16;
keir@21266 2876 info->xen_version_minor = xen_version & 0xFF;
gianni@22008 2877
keir@21266 2878 xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra);
gianni@22008 2879 info->xen_version_extra = strdup(u.xen_extra);
keir@21266 2880
keir@21266 2881 xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc);
gianni@22008 2882 info->compiler = strdup(u.xen_cc.compiler);
gianni@22008 2883 info->compile_by = strdup(u.xen_cc.compile_by);
gianni@22008 2884 info->compile_domain = strdup(u.xen_cc.compile_domain);
gianni@22008 2885 info->compile_date = strdup(u.xen_cc.compile_date);
keir@21266 2886
keir@21266 2887 xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps);
gianni@22008 2888 info->capabilities = strdup(u.xen_caps);
keir@21266 2889
keir@21266 2890 xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset);
gianni@22008 2891 info->changeset = strdup(u.xen_chgset);
keir@21266 2892
keir@21266 2893 xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms);
keir@21266 2894 info->virt_start = u.p_parms.virt_start;
keir@21266 2895
keir@21266 2896 info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL);
keir@21266 2897
keir@21266 2898 xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline);
gianni@22008 2899 info->commandline = strdup(u.xen_commandline);
keir@21266 2900
keir@21266 2901 return info;
keir@21266 2902 }
keir@21266 2903
ian@21930 2904 libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid,
sstabellini@22000 2905 int *nb_vcpu, int *nrcpus)
keir@21141 2906 {
ian@21930 2907 libxl_vcpuinfo *ptr, *ret;
keir@21141 2908 xc_domaininfo_t domaininfo;
keir@21141 2909 xc_vcpuinfo_t vcpuinfo;
keir@21141 2910 xc_physinfo_t physinfo = { 0 };
gianni@22015 2911 uint64_t *cpumaps;
gianni@22015 2912 unsigned num_cpuwords;
keir@21141 2913
keir@21141 2914 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
gianni@21892 2915 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting infolist");
keir@21141 2916 return NULL;
keir@21141 2917 }
keir@21141 2918 if (xc_physinfo(ctx->xch, &physinfo) == -1) {
gianni@21892 2919 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting physinfo");
keir@21141 2920 return NULL;
keir@21141 2921 }
sstabellini@22000 2922 *nrcpus = physinfo.max_cpu_id + 1;
gianni@22015 2923 ret = ptr = calloc(domaininfo.max_vcpu_id + 1, sizeof (libxl_vcpuinfo));
keir@21141 2924 if (!ptr) {
keir@21141 2925 return NULL;
keir@21141 2926 }
keir@21141 2927
gianni@22015 2928 num_cpuwords = ((physinfo.max_cpu_id + 64) / 64);
gianni@22015 2929 cpumaps = calloc(num_cpuwords * sizeof(*cpumaps), domaininfo.max_vcpu_id + 1);
keir@21141 2930 for (*nb_vcpu = 0; *nb_vcpu <= domaininfo.max_vcpu_id; ++*nb_vcpu, ++ptr) {
gianni@22015 2931 ptr->cpumap = cpumaps + (num_cpuwords * *nb_vcpu);
keir@21141 2932 if (!ptr->cpumap) {
keir@21141 2933 return NULL;
keir@21141 2934 }
keir@21141 2935 if (xc_vcpu_getinfo(ctx->xch, domid, *nb_vcpu, &vcpuinfo) == -1) {
gianni@21892 2936 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting vcpu info");
keir@21141 2937 return NULL;
keir@21141 2938 }
sstabellini@22000 2939 if (xc_vcpu_getaffinity(ctx->xch, domid, *nb_vcpu,
sstabellini@22000 2940 ptr->cpumap, ((*nrcpus) + 7) / 8) == -1) {
gianni@21892 2941 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting vcpu affinity");
keir@21141 2942 return NULL;
keir@21141 2943 }
keir@21141 2944 ptr->vcpuid = *nb_vcpu;
keir@21141 2945 ptr->cpu = vcpuinfo.cpu;
keir@21141 2946 ptr->online = !!vcpuinfo.online;
keir@21141 2947 ptr->blocked = !!vcpuinfo.blocked;
keir@21141 2948 ptr->running = !!vcpuinfo.running;
keir@21141 2949 ptr->vcpu_time = vcpuinfo.cpu_time;
keir@21141 2950 }
keir@21141 2951 return ret;
keir@21141 2952 }
keir@21142 2953
gianni@22015 2954 void libxl_free_vcpu_list(libxl_vcpuinfo *vcpu)
gianni@22015 2955 {
gianni@22015 2956 if ( vcpu )
gianni@22015 2957 free(vcpu[0].cpumap);
gianni@22015 2958 free(vcpu);
gianni@22015 2959 }
gianni@22015 2960
ian@21930 2961 int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
sstabellini@22000 2962 uint64_t *cpumap, int nrcpus)
keir@21142 2963 {
sstabellini@22000 2964 if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, cpumap, (nrcpus + 7) / 8)) {
gianni@21892 2965 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting vcpu affinity");
gianni@21892 2966 return ERROR_FAIL;
gianni@21892 2967 }
gianni@21892 2968 return 0;
keir@21142 2969 }
keir@21143 2970
ian@21930 2971 int libxl_set_vcpucount(libxl_ctx *ctx, uint32_t domid, uint32_t count)
keir@21143 2972 {
gianni@22023 2973 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21143 2974 xc_domaininfo_t domaininfo;
keir@21143 2975 char *dompath;
gianni@22023 2976 int i, rc = ERROR_FAIL;
keir@21143 2977
keir@21143 2978 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
gianni@21892 2979 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting domain info list");
gianni@22023 2980 goto out;
keir@21143 2981 }
keir@21143 2982 if (!count || ((domaininfo.max_vcpu_id + 1) < count)) {
gianni@22023 2983 rc = ERROR_INVAL;
gianni@22023 2984 goto out;
keir@21143 2985 }
gianni@22023 2986 if (!(dompath = libxl_xs_get_dompath(&gc, domid)))
gianni@22023 2987 goto out;
keir@21143 2988
keir@21143 2989 for (i = 0; i <= domaininfo.max_vcpu_id; ++i) {
gianni@22023 2990 libxl_xs_write(&gc, XBT_NULL,
gianni@22023 2991 libxl_sprintf(&gc, "%s/cpu/%u/availability", dompath, i),
keir@21143 2992 "%s", ((1 << i) & ((1 << count) - 1)) ? "online" : "offline");
keir@21143 2993 }
gianni@22023 2994 rc = 0;
gianni@22023 2995 out:
gianni@22023 2996 libxl_free_all(&gc);
gianni@22023 2997 return rc;
keir@21143 2998 }
keir@21265 2999
keir@21265 3000 /*
keir@21265 3001 * returns one of the XEN_SCHEDULER_* constants from public/domctl.h
keir@21265 3002 */
ian@21930 3003 int libxl_get_sched_id(libxl_ctx *ctx)
keir@21265 3004 {
keir@21265 3005 int sched, ret;
keir@21265 3006
gianni@21892 3007 if ((ret = xc_sched_id(ctx->xch, &sched)) != 0) {
gianni@21892 3008 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting domain info list");
gianni@21892 3009 return ERROR_FAIL;
gianni@21892 3010 }
keir@21265 3011 return sched;
keir@21265 3012 }
keir@21292 3013
ian@21930 3014 int libxl_sched_credit_domain_get(libxl_ctx *ctx, uint32_t domid, libxl_sched_credit *scinfo)
keir@21292 3015 {
keir@21292 3016 struct xen_domctl_sched_credit sdom;
keir@21292 3017 int rc;
keir@21292 3018
keir@21292 3019 rc = xc_sched_credit_domain_get(ctx->xch, domid, &sdom);
gianni@21892 3020 if (rc != 0) {
gianni@21892 3021 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting domain sched credit");
gianni@21892 3022 return ERROR_FAIL;
gianni@21892 3023 }
keir@21292 3024
keir@21292 3025 scinfo->weight = sdom.weight;
keir@21292 3026 scinfo->cap = sdom.cap;
keir@21292 3027
keir@21292 3028 return 0;
keir@21292 3029 }
keir@21292 3030
ian@21930 3031 int libxl_sched_credit_domain_set(libxl_ctx *ctx, uint32_t domid, libxl_sched_credit *scinfo)
keir@21292 3032 {
keir@21292 3033 struct xen_domctl_sched_credit sdom;
keir@21292 3034 xc_domaininfo_t domaininfo;
keir@21292 3035 int rc;
keir@21292 3036
keir@21292 3037 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo);
gianni@21892 3038 if (rc < 0) {
gianni@21892 3039 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting domain info list");
gianni@21892 3040 return ERROR_FAIL;
gianni@21892 3041 }
keir@21292 3042 if (rc != 1 || domaininfo.domain != domid)
gianni@21892 3043 return ERROR_INVAL;
keir@21292 3044
keir@21292 3045
keir@21292 3046 if (scinfo->weight < 1 || scinfo->weight > 65535) {
keir@21292 3047 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21292 3048 "Cpu weight out of range, valid values are within range from 1 to 65535");
gianni@21892 3049 return ERROR_INVAL;
keir@21292 3050 }
keir@21292 3051
keir@21292 3052 if (scinfo->cap < 0 || scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) {
keir@21292 3053 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21292 3054 "Cpu cap out of range, valid range is from 0 to %d for specified number of vcpus",
keir@21292 3055 ((domaininfo.max_vcpu_id + 1) * 100));
gianni@21892 3056 return ERROR_INVAL;
keir@21292 3057 }
keir@21292 3058
keir@21292 3059 sdom.weight = scinfo->weight;
keir@21292 3060 sdom.cap = scinfo->cap;
keir@21292 3061
keir@21292 3062 rc = xc_sched_credit_domain_set(ctx->xch, domid, &sdom);
gianni@21892 3063 if ( rc < 0 ) {
gianni@21892 3064 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting domain sched credit");
gianni@21892 3065 return ERROR_FAIL;
gianni@21892 3066 }
keir@21292 3067
keir@21292 3068 return 0;
keir@21292 3069 }
keir@21292 3070
keir@21393 3071 static int trigger_type_from_string(char *trigger_name)
keir@21393 3072 {
keir@21393 3073 if (!strcmp(trigger_name, "nmi"))
keir@21393 3074 return XEN_DOMCTL_SENDTRIGGER_NMI;
keir@21393 3075 else if (!strcmp(trigger_name, "reset"))
keir@21393 3076 return XEN_DOMCTL_SENDTRIGGER_RESET;
keir@21393 3077 else if (!strcmp(trigger_name, "init"))
keir@21393 3078 return XEN_DOMCTL_SENDTRIGGER_INIT;
keir@21393 3079 else if (!strcmp(trigger_name, "power"))
keir@21393 3080 return XEN_DOMCTL_SENDTRIGGER_POWER;
keir@21393 3081 else if (!strcmp(trigger_name, "sleep"))
keir@21393 3082 return XEN_DOMCTL_SENDTRIGGER_SLEEP;
keir@21393 3083 else
keir@21393 3084 return -1;
keir@21393 3085 }
keir@21393 3086
ian@21930 3087 int libxl_send_trigger(libxl_ctx *ctx, uint32_t domid, char *trigger_name, uint32_t vcpuid)
keir@21393 3088 {
keir@21393 3089 int rc = -1;
keir@21393 3090 int trigger_type = trigger_type_from_string(trigger_name);
keir@21393 3091
keir@21393 3092 if (trigger_type == -1) {
keir@21393 3093 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
keir@21393 3094 "Invalid trigger, valid triggers are <nmi|reset|init|power|sleep>");
gianni@21892 3095 return ERROR_INVAL;
keir@21393 3096 }
keir@21393 3097
keir@21393 3098 rc = xc_domain_send_trigger(ctx->xch, domid, trigger_type, vcpuid);
gianni@21892 3099 if (rc != 0) {
keir@21393 3100 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21393 3101 "Send trigger '%s' failed", trigger_name);
gianni@21892 3102 return ERROR_FAIL;
gianni@21892 3103 }
gianni@21892 3104
gianni@21892 3105 return 0;
keir@21393 3106 }
keir@21402 3107
ian@21930 3108 int libxl_send_sysrq(libxl_ctx *ctx, uint32_t domid, char sysrq)
keir@21402 3109 {
gianni@22023 3110 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 3111 char *dompath = libxl_xs_get_dompath(&gc, domid);
gianni@22023 3112
gianni@22023 3113 libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/control/sysrq", dompath), "%c", sysrq);
gianni@22023 3114
gianni@22023 3115 libxl_free_all(&gc);
keir@21402 3116 return 0;
keir@21402 3117 }
keir@21402 3118
ian@21930 3119 int libxl_send_debug_keys(libxl_ctx *ctx, char *keys)
keir@21472 3120 {
gianni@21892 3121 int ret;
gianni@21892 3122 ret = xc_send_debug_keys(ctx->xch, keys);
gianni@21892 3123 if ( ret < 0 ) {
gianni@21892 3124 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "sending debug keys");
gianni@21892 3125 return ERROR_FAIL;
gianni@21892 3126 }
gianni@21892 3127 return 0;
keir@21472 3128 }
keir@21472 3129
ian@21930 3130 libxl_xen_console_reader *
ian@21930 3131 libxl_xen_console_read_start(libxl_ctx *ctx, int clear)
keir@21496 3132 {
ian@21930 3133 libxl_xen_console_reader *cr;
keir@21496 3134 unsigned int size = 16384;
keir@21496 3135 char *buf = malloc(size);
keir@21496 3136
keir@21496 3137 if (!buf) {
keir@21496 3138 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot malloc buffer for libxl_xen_console_reader,"
keir@21496 3139 " size is %u", size);
keir@21496 3140 return NULL;
keir@21496 3141 }
keir@21496 3142
ian@21930 3143 cr = malloc(sizeof(libxl_xen_console_reader));
keir@21496 3144 if (!cr) {
keir@21496 3145 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot malloc libxl_xen_console_reader");
keir@21496 3146 return NULL;
keir@21496 3147 }
keir@21496 3148
ian@21930 3149 memset(cr, 0, sizeof(libxl_xen_console_reader));
keir@21496 3150 cr->buffer = buf;
keir@21496 3151 cr->size = size;
keir@21496 3152 cr->count = size;
keir@21496 3153 cr->clear = clear;
keir@21496 3154 cr->incremental = 1;
keir@21496 3155
keir@21496 3156 return cr;
keir@21496 3157 }
keir@21496 3158
keir@21496 3159 /* return values: *line_r
keir@21496 3160 * 1 success, whole line obtained from buffer non-0
keir@21496 3161 * 0 no more lines available right now 0
keir@21496 3162 * negative error code ERROR_* 0
keir@21496 3163 * On success *line_r is updated to point to a nul-terminated
keir@21496 3164 * string which is valid until the next call on the same console
keir@21496 3165 * reader. The libxl caller may overwrite parts of the string
keir@21496 3166 * if it wishes. */
ian@21930 3167 int libxl_xen_console_read_line(libxl_ctx *ctx,
ian@21930 3168 libxl_xen_console_reader *cr,
keir@21496 3169 char **line_r)
keir@21496 3170 {
keir@21496 3171 int ret;
keir@21496 3172
keir@21496 3173 memset(cr->buffer, 0, cr->size);
keir@21496 3174 ret = xc_readconsolering(ctx->xch, &cr->buffer, &cr->count,
keir@21496 3175 cr->clear, cr->incremental, &cr->index);
gianni@21892 3176 if (ret < 0) {
gianni@21892 3177 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "reading console ring buffer");
gianni@21892 3178 return ERROR_FAIL;
gianni@21892 3179 }
keir@21496 3180 if (!ret) {
keir@21496 3181 if (cr->count) {
keir@21496 3182 *line_r = cr->buffer;
keir@21496 3183 ret = 1;
keir@21496 3184 } else {
keir@21496 3185 *line_r = NULL;
keir@21496 3186 ret = 0;
keir@21496 3187 }
keir@21496 3188 }
keir@21496 3189
keir@21496 3190 return ret;
keir@21496 3191 }
keir@21496 3192
ian@21930 3193 void libxl_xen_console_read_finish(libxl_ctx *ctx,
ian@21930 3194 libxl_xen_console_reader *cr)
keir@21496 3195 {
keir@21496 3196 free(cr->buffer);
keir@21496 3197 free(cr);
keir@21496 3198 }
keir@21496 3199
ian@21930 3200 uint32_t libxl_vm_get_start_time(libxl_ctx *ctx, uint32_t domid)
keir@21425 3201 {
gianni@22023 3202 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 3203 char *dompath = libxl_xs_get_dompath(&gc, domid);
keir@21425 3204 char *vm_path, *start_time;
gianni@22023 3205 uint32_t ret;
keir@21425 3206
keir@21425 3207 vm_path = libxl_xs_read(
gianni@22023 3208 &gc, XBT_NULL, libxl_sprintf(&gc, "%s/vm", dompath));
keir@21425 3209 start_time = libxl_xs_read(
gianni@22023 3210 &gc, XBT_NULL, libxl_sprintf(&gc, "%s/start_time", vm_path));
keir@21425 3211 if (start_time == NULL) {
keir@21425 3212 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
keir@21425 3213 "Can't get start time of domain '%d'", domid);
gianni@22023 3214 ret = -1;
gianni@22023 3215 }else{
gianni@22023 3216 ret = strtoul(start_time, NULL, 10);
keir@21425 3217 }
gianni@22023 3218 libxl_free_all(&gc);
gianni@22023 3219 return ret;
keir@21425 3220 }
keir@21425 3221
ian@21930 3222 char *libxl_tmem_list(libxl_ctx *ctx, uint32_t domid, int use_long)
keir@21471 3223 {
keir@21471 3224 int rc;
keir@21471 3225 char _buf[32768];
keir@21471 3226
keir@21471 3227 rc = xc_tmem_control(ctx->xch, -1, TMEMC_LIST, domid, 32768, use_long,
keir@21471 3228 0, _buf);
keir@21471 3229 if (rc < 0) {
keir@21471 3230 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3231 "Can not get tmem list");
keir@21471 3232 return NULL;
keir@21471 3233 }
keir@21471 3234
keir@21471 3235 return strdup(_buf);
keir@21471 3236 }
keir@21471 3237
ian@21930 3238 int libxl_tmem_freeze(libxl_ctx *ctx, uint32_t domid)
keir@21471 3239 {
keir@21471 3240 int rc;
keir@21471 3241
keir@21471 3242 rc = xc_tmem_control(ctx->xch, -1, TMEMC_FREEZE, domid, 0, 0,
keir@21471 3243 0, NULL);
keir@21471 3244 if (rc < 0) {
keir@21471 3245 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3246 "Can not freeze tmem pools");
gianni@21892 3247 return ERROR_FAIL;
keir@21471 3248 }
keir@21471 3249
keir@21471 3250 return rc;
keir@21471 3251 }
keir@21471 3252
ian@21930 3253 int libxl_tmem_destroy(libxl_ctx *ctx, uint32_t domid)
keir@21471 3254 {
keir@21471 3255 int rc;
keir@21471 3256
keir@21471 3257 rc = xc_tmem_control(ctx->xch, -1, TMEMC_DESTROY, domid, 0, 0,
keir@21471 3258 0, NULL);
keir@21471 3259 if (rc < 0) {
keir@21471 3260 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3261 "Can not destroy tmem pools");
gianni@21892 3262 return ERROR_FAIL;
keir@21471 3263 }
keir@21471 3264
keir@21471 3265 return rc;
keir@21471 3266 }
keir@21471 3267
ian@21930 3268 int libxl_tmem_thaw(libxl_ctx *ctx, uint32_t domid)
keir@21471 3269 {
keir@21471 3270 int rc;
keir@21471 3271
keir@21471 3272 rc = xc_tmem_control(ctx->xch, -1, TMEMC_THAW, domid, 0, 0,
keir@21471 3273 0, NULL);
keir@21471 3274 if (rc < 0) {
keir@21471 3275 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3276 "Can not thaw tmem pools");
gianni@21892 3277 return ERROR_FAIL;
keir@21471 3278 }
keir@21471 3279
keir@21471 3280 return rc;
keir@21471 3281 }
keir@21471 3282
keir@21471 3283 static int32_t tmem_setop_from_string(char *set_name)
keir@21471 3284 {
keir@21471 3285 if (!strcmp(set_name, "weight"))
keir@21471 3286 return TMEMC_SET_WEIGHT;
keir@21471 3287 else if (!strcmp(set_name, "cap"))
keir@21471 3288 return TMEMC_SET_CAP;
keir@21471 3289 else if (!strcmp(set_name, "compress"))
keir@21471 3290 return TMEMC_SET_COMPRESS;
keir@21471 3291 else
keir@21471 3292 return -1;
keir@21471 3293 }
keir@21471 3294
ian@21930 3295 int libxl_tmem_set(libxl_ctx *ctx, uint32_t domid, char* name, uint32_t set)
keir@21471 3296 {
keir@21471 3297 int rc;
keir@21471 3298 int32_t subop = tmem_setop_from_string(name);
keir@21471 3299
keir@21471 3300 if (subop == -1) {
keir@21471 3301 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
keir@21471 3302 "Invalid set, valid sets are <weight|cap|compress>");
gianni@21892 3303 return ERROR_INVAL;
keir@21471 3304 }
keir@21471 3305 rc = xc_tmem_control(ctx->xch, -1, subop, domid, set, 0, 0, NULL);
keir@21471 3306 if (rc < 0) {
keir@21471 3307 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3308 "Can not set tmem %s", name);
gianni@21892 3309 return ERROR_FAIL;
keir@21471 3310 }
keir@21471 3311
keir@21471 3312 return rc;
keir@21471 3313 }
keir@21471 3314
ian@21930 3315 int libxl_tmem_shared_auth(libxl_ctx *ctx, uint32_t domid,