debuggers.hg

annotate tools/libxl/libxl.c @ 22319:063927551e9c

tools: cpupools: xl: commands and library changes

Support of cpu pools in libxl and xl:
library functions
xl cpupool-create
xl cpupool-list
xl cpupool-destroy
xl cpupool-cpu-add
xl cpupool-cpu-remove
xl cpupool-migrate
Renamed all cpu pool related names to *cpupool*

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