debuggers.hg

annotate tools/libxl/libxl.c @ 22602:325cad6f67f9

libxl: constify libxl_create_cpupool()

Attached patch constifies libxl_create_cpupool().

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