debuggers.hg

annotate tools/libxl/libxl.c @ 22549:ab785e37499c

add missing libxl__free_all() calls

In various libxl functions libxl__free_all() was missing before return

Signed-off-by: juergen.gross@ts.fujitsu.com
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
committer: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Juergen Gross <juergen.gross@ts.fujitsu.com>
date Thu Dec 09 14:50:56 2010 +0100 (2010-12-09)
parents f57026cd5d19
children b1a8ea2f1d01
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@22040 2657 int libxl_create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb,
ian@21930 2658 libxl_device_model_starting **starting_r)
keir@20509 2659 {
ian@22167 2660 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@20509 2661 libxl_device_model_info info;
keir@20509 2662
stefano@22040 2663 libxl_build_xenpv_qemu_args(&gc, domid, vfb, &info);
keir@20542 2664 libxl_create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r);
ian@22164 2665 libxl__free_all(&gc);
keir@20509 2666 return 0;
keir@20509 2667 }
keir@20509 2668
ian@21930 2669 int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
keir@20462 2670 {
ian@22167 2671 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@20509 2672 flexarray_t *front;
keir@20509 2673 flexarray_t *back;
keir@20509 2674 unsigned int boffset = 0;
keir@20509 2675 unsigned int foffset = 0;
ian@22167 2676 libxl__device device;
gianni@22023 2677 int rc;
keir@20509 2678
keir@20509 2679 front = flexarray_make(16, 1);
gianni@22023 2680 if (!front) {
gianni@22023 2681 rc = ERROR_NOMEM;
gianni@22023 2682 goto out;
gianni@22023 2683 }
keir@20509 2684 back = flexarray_make(16, 1);
gianni@22023 2685 if (!back) {
gianni@22023 2686 rc = ERROR_NOMEM;
gianni@22023 2687 goto out_free;
gianni@22023 2688 }
keir@20509 2689
keir@20509 2690 device.backend_devid = vfb->devid;
keir@20509 2691 device.backend_domid = vfb->backend_domid;
keir@20509 2692 device.backend_kind = DEVICE_VFB;
keir@20509 2693 device.devid = vfb->devid;
keir@20509 2694 device.domid = vfb->domid;
keir@20509 2695 device.kind = DEVICE_VFB;
keir@20509 2696
keir@20516 2697 flexarray_set(back, boffset++, "frontend-id");
ian@22164 2698 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vfb->domid));
keir@20516 2699 flexarray_set(back, boffset++, "online");
keir@20516 2700 flexarray_set(back, boffset++, "1");
keir@20516 2701 flexarray_set(back, boffset++, "state");
ian@22164 2702 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", 1));
keir@20516 2703 flexarray_set(back, boffset++, "domain");
ian@22164 2704 flexarray_set(back, boffset++, libxl__domid_to_name(&gc, domid));
keir@20516 2705 flexarray_set(back, boffset++, "vnc");
ian@22164 2706 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vfb->vnc));
keir@20516 2707 flexarray_set(back, boffset++, "vnclisten");
keir@20516 2708 flexarray_set(back, boffset++, vfb->vnclisten);
keir@21362 2709 flexarray_set(back, boffset++, "vncpasswd");
keir@21362 2710 flexarray_set(back, boffset++, vfb->vncpasswd);
keir@20516 2711 flexarray_set(back, boffset++, "vncdisplay");
ian@22164 2712 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vfb->vncdisplay));
keir@20516 2713 flexarray_set(back, boffset++, "vncunused");
ian@22164 2714 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vfb->vncunused));
keir@20516 2715 flexarray_set(back, boffset++, "sdl");
ian@22164 2716 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vfb->sdl));
keir@20516 2717 flexarray_set(back, boffset++, "opengl");
ian@22164 2718 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vfb->opengl));
keir@20509 2719 if (vfb->xauthority) {
keir@20516 2720 flexarray_set(back, boffset++, "xauthority");
keir@20516 2721 flexarray_set(back, boffset++, vfb->xauthority);
keir@20509 2722 }
keir@20509 2723 if (vfb->display) {
keir@20516 2724 flexarray_set(back, boffset++, "display");
keir@20516 2725 flexarray_set(back, boffset++, vfb->display);
keir@20509 2726 }
keir@20509 2727
keir@20516 2728 flexarray_set(front, foffset++, "backend-id");
ian@22164 2729 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", vfb->backend_domid));
keir@20516 2730 flexarray_set(front, foffset++, "state");
ian@22164 2731 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", 1));
ian@22164 2732
ian@22164 2733 libxl__device_generic_add(ctx, &device,
ian@22164 2734 libxl__xs_kvs_of_flexarray(&gc, back, boffset),
ian@22164 2735 libxl__xs_kvs_of_flexarray(&gc, front, foffset));
gianni@22023 2736 rc = 0;
gianni@22023 2737 out_free:
keir@20509 2738 flexarray_free(front);
keir@20509 2739 flexarray_free(back);
gianni@22023 2740 out:
ian@22164 2741 libxl__free_all(&gc);
gianni@22023 2742 return rc;
keir@20462 2743 }
keir@20462 2744
ian@21930 2745 int libxl_device_vfb_clean_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 2746 {
keir@20462 2747 return ERROR_NI;
keir@20462 2748 }
keir@20462 2749
ian@21930 2750 int libxl_device_vfb_hard_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 2751 {
keir@20462 2752 return ERROR_NI;
keir@20462 2753 }
keir@20462 2754
keir@20462 2755 /******************************************************************************/
keir@20482 2756
ian@21930 2757 int libxl_domain_setmaxmem(libxl_ctx *ctx, uint32_t domid, uint32_t max_memkb)
keir@21404 2758 {
ian@22167 2759 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@21404 2760 char *mem, *endptr;
keir@21404 2761 uint32_t memorykb;
ian@22164 2762 char *dompath = libxl__xs_get_dompath(&gc, domid);
gianni@22023 2763 int rc = 1;
gianni@22023 2764
ian@22164 2765 mem = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/memory/target", dompath));
keir@21404 2766 if (!mem) {
ian@22165 2767 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot get memory info from %s/memory/target\n", dompath);
gianni@22023 2768 goto out;
keir@21404 2769 }
keir@21404 2770 memorykb = strtoul(mem, &endptr, 10);
keir@21404 2771 if (*endptr != '\0') {
ian@22165 2772 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "invalid memory %s from %s/memory/target\n", mem, dompath);
gianni@22023 2773 goto out;
keir@21404 2774 }
keir@21404 2775
keir@21404 2776 if (max_memkb < memorykb) {
ian@22165 2777 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "memory_static_max must be greater than or or equal to memory_dynamic_max\n");
gianni@22023 2778 goto out;
keir@21404 2779 }
keir@21404 2780
gianni@22023 2781 rc = 0;
gianni@22023 2782 out:
ian@22164 2783 libxl__free_all(&gc);
gianni@22023 2784 return rc;
keir@21404 2785 }
keir@21404 2786
stefano@22244 2787 static int libxl__fill_dom0_memory_info(libxl__gc *gc, uint32_t *target_memkb)
stefano@22244 2788 {
stefano@22244 2789 int rc;
stefano@22244 2790 libxl_dominfo info;
stefano@22245 2791 libxl_physinfo physinfo;
stefano@22244 2792 char *target = NULL, *endptr = NULL;
stefano@22244 2793 char *target_path = "/local/domain/0/memory/target";
stefano@22244 2794 char *max_path = "/local/domain/0/memory/static-max";
stefano@22245 2795 char *free_mem_slack_path = "/local/domain/0/memory/freemem-slack";
stefano@22244 2796 xs_transaction_t t;
stefano@22244 2797 libxl_ctx *ctx = libxl__gc_owner(gc);
stefano@22256 2798 uint32_t free_mem_slack = 0;
stefano@22244 2799
stefano@22244 2800 retry_transaction:
stefano@22244 2801 t = xs_transaction_start(ctx->xsh);
stefano@22244 2802
stefano@22244 2803 target = libxl__xs_read(gc, t, target_path);
stefano@22244 2804 if (target) {
stefano@22244 2805 *target_memkb = strtoul(target, &endptr, 10);
stefano@22244 2806 if (*endptr != '\0') {
stefano@22244 2807 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 2808 "invalid memory target %s from %s\n", target, target_path);
stefano@22244 2809 rc = ERROR_FAIL;
stefano@22244 2810 goto out;
stefano@22244 2811 }
stefano@22244 2812 rc = 0;
stefano@22244 2813 goto out;
stefano@22244 2814 }
stefano@22244 2815
stefano@22244 2816 rc = libxl_domain_info(ctx, &info, 0);
stefano@22244 2817 if (rc < 0)
stefano@22244 2818 return rc;
stefano@22244 2819
stefano@22245 2820 rc = libxl_get_physinfo(ctx, &physinfo);
stefano@22245 2821 if (rc < 0)
stefano@22245 2822 return rc;
stefano@22245 2823
stefano@22244 2824 libxl__xs_write(gc, t, target_path, "%"PRIu32,
stefano@22244 2825 (uint32_t) info.current_memkb);
stefano@22244 2826 libxl__xs_write(gc, t, max_path, "%"PRIu32,
stefano@22244 2827 (uint32_t) info.max_memkb);
stefano@22256 2828
stefano@22256 2829 free_mem_slack = (uint32_t) (PAGE_TO_MEMKB(physinfo.total_pages) -
stefano@22256 2830 info.current_memkb);
stefano@22256 2831 /* From empirical measurements the free_mem_slack shouldn't be more
stefano@22256 2832 * than 15% of the total memory present on the system. */
stefano@22256 2833 if (free_mem_slack > PAGE_TO_MEMKB(physinfo.total_pages) * 0.15)
stefano@22256 2834 free_mem_slack = PAGE_TO_MEMKB(physinfo.total_pages) * 0.15;
stefano@22256 2835 libxl__xs_write(gc, t, free_mem_slack_path, "%"PRIu32, free_mem_slack);
stefano@22244 2836
stefano@22244 2837 *target_memkb = (uint32_t) info.current_memkb;
stefano@22244 2838 rc = 0;
stefano@22244 2839
stefano@22244 2840 out:
stefano@22244 2841 if (!xs_transaction_end(ctx->xsh, t, 0))
stefano@22244 2842 if (errno == EAGAIN)
stefano@22244 2843 goto retry_transaction;
stefano@22244 2844
stefano@22244 2845
stefano@22244 2846 return rc;
stefano@22244 2847 }
stefano@22244 2848
stefano@22245 2849 /* returns how much memory should be left free in the system */
stefano@22245 2850 static int libxl__get_free_memory_slack(libxl__gc *gc, uint32_t *free_mem_slack)
stefano@22245 2851 {
stefano@22245 2852 int rc;
stefano@22245 2853 char *free_mem_slack_path = "/local/domain/0/memory/freemem-slack";
stefano@22245 2854 char *free_mem_slack_s, *endptr;
stefano@22245 2855 uint32_t target_memkb;
stefano@22245 2856
stefano@22245 2857 retry:
stefano@22245 2858 free_mem_slack_s = libxl__xs_read(gc, XBT_NULL, free_mem_slack_path);
stefano@22245 2859 if (!free_mem_slack_s) {
stefano@22245 2860 rc = libxl__fill_dom0_memory_info(gc, &target_memkb);
stefano@22245 2861 if (rc < 0)
stefano@22245 2862 return rc;
stefano@22245 2863 goto retry;
stefano@22245 2864 } else {
stefano@22245 2865 *free_mem_slack = strtoul(free_mem_slack_s, &endptr, 10);
stefano@22245 2866 if (*endptr != '\0') {
stefano@22245 2867 LIBXL__LOG_ERRNO(gc->owner, LIBXL__LOG_ERROR,
stefano@22245 2868 "invalid free_mem_slack %s from %s\n",
stefano@22245 2869 free_mem_slack_s, free_mem_slack_path);
stefano@22245 2870 return ERROR_FAIL;
stefano@22245 2871 }
stefano@22245 2872 }
stefano@22245 2873 return 0;
stefano@22245 2874 }
stefano@22245 2875
stefano@22244 2876 int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid,
stefano@22244 2877 int32_t target_memkb, int relative, int enforce)
keir@20647 2878 {
ian@22167 2879 libxl__gc gc = LIBXL_INIT_GC(ctx);
stefano@22243 2880 int rc = 1, abort = 0;
stefano@22244 2881 uint32_t memorykb = 0, videoram = 0;
stefano@22244 2882 uint32_t current_target_memkb = 0, new_target_memkb = 0;
stefano@22244 2883 char *memmax, *endptr, *videoram_s = NULL, *target = NULL;
ian@22164 2884 char *dompath = libxl__xs_get_dompath(&gc, domid);
keir@21374 2885 xc_domaininfo_t info;
ian@21930 2886 libxl_dominfo ptr;
keir@21374 2887 char *uuid;
stefano@22243 2888 xs_transaction_t t;
stefano@22243 2889
stefano@22243 2890 retry_transaction:
stefano@22243 2891 t = xs_transaction_start(ctx->xsh);
stefano@22243 2892
stefano@22244 2893 target = libxl__xs_read(&gc, t, libxl__sprintf(&gc,
stefano@22244 2894 "%s/memory/target", dompath));
stefano@22244 2895 if (!target && !domid) {
stefano@22244 2896 xs_transaction_end(ctx->xsh, t, 1);
stefano@22244 2897 rc = libxl__fill_dom0_memory_info(&gc, &current_target_memkb);
stefano@22244 2898 if (rc < 0) {
stefano@22244 2899 abort = 1;
stefano@22244 2900 goto out;
stefano@22244 2901 }
stefano@22244 2902 goto retry_transaction;
stefano@22244 2903 } else if (!target) {
stefano@22244 2904 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 2905 "cannot get target memory info from %s/memory/target\n",
stefano@22244 2906 dompath);
stefano@22244 2907 abort = 1;
stefano@22244 2908 goto out;
stefano@22244 2909 } else {
stefano@22244 2910 current_target_memkb = strtoul(target, &endptr, 10);
stefano@22244 2911 if (*endptr != '\0') {
ian@22165 2912 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 2913 "invalid memory target %s from %s/memory/target\n",
stefano@22244 2914 target, dompath);
stefano@22243 2915 abort = 1;
gianni@22023 2916 goto out;
keir@21405 2917 }
keir@21405 2918 }
stefano@22244 2919 memmax = libxl__xs_read(&gc, t, libxl__sprintf(&gc,
stefano@22244 2920 "%s/memory/static-max", dompath));
stefano@22244 2921 if (!memmax) {
stefano@22244 2922 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 2923 "cannot get memory info from %s/memory/static-max\n",
stefano@22244 2924 dompath);
stefano@22244 2925 abort = 1;
stefano@22244 2926 goto out;
stefano@22244 2927 }
stefano@22244 2928 memorykb = strtoul(memmax, &endptr, 10);
stefano@22244 2929 if (*endptr != '\0') {
stefano@22244 2930 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 2931 "invalid max memory %s from %s/memory/static-max\n",
stefano@22244 2932 memmax, dompath);
stefano@22244 2933 abort = 1;
stefano@22244 2934 goto out;
stefano@22244 2935 }
stefano@22244 2936
stefano@22244 2937 if (relative)
stefano@22244 2938 new_target_memkb = current_target_memkb + target_memkb;
stefano@22244 2939 else
stefano@22244 2940 new_target_memkb = target_memkb;
stefano@22244 2941 if (new_target_memkb > memorykb) {
stefano@22244 2942 LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
stefano@22244 2943 "memory_dynamic_max must be less than or equal to"
stefano@22244 2944 " memory_static_max\n");
stefano@22244 2945 abort = 1;
stefano@22244 2946 goto out;
stefano@22244 2947 }
stefano@22244 2948
gianni@22367 2949 if (!domid && new_target_memkb < LIBXL_MIN_DOM0_MEM) {
gianni@22367 2950 LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
gianni@22367 2951 "new target %d for dom0 is below the minimum threshold\n",
gianni@22367 2952 new_target_memkb);
gianni@22367 2953 abort = 1;
gianni@22367 2954 goto out;
gianni@22367 2955 }
stefano@22244 2956 videoram_s = libxl__xs_read(&gc, t, libxl__sprintf(&gc,
stefano@22244 2957 "%s/memory/videoram", dompath));
stefano@22244 2958 videoram = videoram_s ? atoi(videoram_s) : 0;
stefano@22244 2959
stefano@22244 2960 if (enforce) {
stefano@22244 2961 memorykb = new_target_memkb;
stefano@22244 2962 rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb +
stefano@22244 2963 LIBXL_MAXMEM_CONSTANT);
stefano@22244 2964 if (rc != 0) {
stefano@22244 2965 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 2966 "xc_domain_setmaxmem domid=%d memkb=%d failed "
stefano@22244 2967 "rc=%d\n", domid, memorykb + LIBXL_MAXMEM_CONSTANT, rc);
stefano@22244 2968 abort = 1;
stefano@22244 2969 goto out;
stefano@22244 2970 }
stefano@22244 2971 }
stefano@22244 2972
stefano@22251 2973 new_target_memkb -= videoram;
ian@22294 2974 rc = xc_domain_set_pod_target(ctx->xch, domid,
stefano@22251 2975 new_target_memkb / 4, NULL, NULL, NULL);
stefano@22243 2976 if (rc != 0) {
stefano@22243 2977 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
ian@22294 2978 "xc_domain_set_pod_target domid=%d, memkb=%d "
stefano@22251 2979 "failed rc=%d\n", domid, new_target_memkb / 4,
stefano@22243 2980 rc);
stefano@22243 2981 abort = 1;
stefano@22243 2982 goto out;
stefano@22243 2983 }
stefano@22243 2984
stefano@22244 2985 libxl__xs_write(&gc, t, libxl__sprintf(&gc, "%s/memory/target",
stefano@22244 2986 dompath), "%"PRIu32, new_target_memkb);
keir@21374 2987 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &info);
stefano@22243 2988 if (rc != 1 || info.domain != domid) {
stefano@22243 2989 abort = 1;
gianni@22023 2990 goto out;
stefano@22243 2991 }
keir@21374 2992 xcinfo2xlinfo(&info, &ptr);
ian@22164 2993 uuid = libxl__uuid2string(&gc, ptr.uuid);
stefano@22244 2994 libxl__xs_write(&gc, t, libxl__sprintf(&gc, "/vm/%s/memory", uuid),
stefano@22244 2995 "%"PRIu32, new_target_memkb / 1024);
gianni@22023 2996
gianni@22023 2997 out:
stefano@22243 2998 if (!xs_transaction_end(ctx->xsh, t, abort) && !abort)
stefano@22243 2999 if (errno == EAGAIN)
stefano@22243 3000 goto retry_transaction;
stefano@22243 3001
ian@22164 3002 libxl__free_all(&gc);
keir@20647 3003 return rc;
keir@20647 3004 }
keir@20875 3005
stefano@22244 3006 int libxl_get_memory_target(libxl_ctx *ctx, uint32_t domid, uint32_t *out_target)
stefano@22244 3007 {
stefano@22244 3008 libxl__gc gc = LIBXL_INIT_GC(ctx);
stefano@22244 3009 int rc = 1;
stefano@22244 3010 char *target = NULL, *endptr = NULL;
stefano@22244 3011 char *dompath = libxl__xs_get_dompath(&gc, domid);
stefano@22244 3012 uint32_t target_memkb;
stefano@22244 3013
stefano@22244 3014 target = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc,
stefano@22244 3015 "%s/memory/target", dompath));
stefano@22244 3016 if (!target && !domid) {
stefano@22244 3017 rc = libxl__fill_dom0_memory_info(&gc, &target_memkb);
stefano@22244 3018 if (rc < 0)
stefano@22244 3019 goto out;
stefano@22244 3020 } else if (!target) {
stefano@22244 3021 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 3022 "cannot get target memory info from %s/memory/target\n",
stefano@22244 3023 dompath);
stefano@22244 3024 goto out;
stefano@22244 3025 } else {
stefano@22244 3026 target_memkb = strtoul(target, &endptr, 10);
stefano@22244 3027 if (*endptr != '\0') {
stefano@22244 3028 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 3029 "invalid memory target %s from %s/memory/target\n",
stefano@22244 3030 target, dompath);
stefano@22244 3031 goto out;
stefano@22244 3032 }
stefano@22244 3033 }
stefano@22244 3034 *out_target = target_memkb;
stefano@22244 3035 rc = 0;
stefano@22244 3036
stefano@22244 3037 out:
stefano@22244 3038 libxl__free_all(&gc);
stefano@22244 3039 return rc;
stefano@22244 3040 }
stefano@22244 3041
stefano@22245 3042 int libxl_domain_need_memory(libxl_ctx *ctx, libxl_domain_build_info *b_info,
stefano@22245 3043 libxl_device_model_info *dm_info, uint32_t *need_memkb)
stefano@22245 3044 {
stefano@22245 3045 *need_memkb = b_info->target_memkb;
stefano@22245 3046 if (b_info->hvm) {
stefano@22245 3047 *need_memkb += b_info->shadow_memkb + LIBXL_HVM_EXTRA_MEMORY;
stefano@22245 3048 if (strstr(dm_info->device_model, "stubdom-dm"))
stefano@22245 3049 *need_memkb += 32 * 1024;
stefano@22245 3050 } else
stefano@22469 3051 *need_memkb += b_info->shadow_memkb + LIBXL_PV_EXTRA_MEMORY;
stefano@22245 3052 if (*need_memkb % (2 * 1024))
stefano@22245 3053 *need_memkb += (2 * 1024) - (*need_memkb % (2 * 1024));
stefano@22245 3054 return 0;
stefano@22245 3055 }
stefano@22245 3056
stefano@22245 3057 int libxl_get_free_memory(libxl_ctx *ctx, uint32_t *memkb)
stefano@22245 3058 {
stefano@22245 3059 int rc = 0;
stefano@22245 3060 libxl_physinfo info;
stefano@22245 3061 uint32_t freemem_slack;
stefano@22245 3062 libxl__gc gc = LIBXL_INIT_GC(ctx);
stefano@22245 3063
stefano@22245 3064 rc = libxl_get_physinfo(ctx, &info);
stefano@22245 3065 if (rc < 0)
stefano@22245 3066 goto out;
stefano@22245 3067 rc = libxl__get_free_memory_slack(&gc, &freemem_slack);
stefano@22245 3068 if (rc < 0)
stefano@22245 3069 goto out;
stefano@22245 3070
stefano@22245 3071 if ((info.free_pages + info.scrub_pages) * 4 > freemem_slack)
stefano@22245 3072 *memkb = (info.free_pages + info.scrub_pages) * 4 - freemem_slack;
stefano@22245 3073 else
stefano@22245 3074 *memkb = 0;
stefano@22245 3075
stefano@22245 3076 out:
stefano@22245 3077 libxl__free_all(&gc);
stefano@22245 3078 return rc;
stefano@22245 3079 }
stefano@22245 3080
stefano@22245 3081 int libxl_wait_for_free_memory(libxl_ctx *ctx, uint32_t domid, uint32_t
stefano@22245 3082 memory_kb, int wait_secs)
stefano@22245 3083 {
stefano@22245 3084 int rc = 0;
stefano@22245 3085 libxl_physinfo info;
stefano@22245 3086 uint32_t freemem_slack;
stefano@22245 3087 libxl__gc gc = LIBXL_INIT_GC(ctx);
stefano@22245 3088
stefano@22245 3089 rc = libxl__get_free_memory_slack(&gc, &freemem_slack);
stefano@22245 3090 if (rc < 0)
stefano@22245 3091 goto out;
stefano@22245 3092 while (wait_secs > 0) {
stefano@22245 3093 rc = libxl_get_physinfo(ctx, &info);
stefano@22245 3094 if (rc < 0)
stefano@22245 3095 goto out;
stefano@22245 3096 if (info.free_pages * 4 - freemem_slack >= memory_kb) {
stefano@22245 3097 rc = 0;
stefano@22245 3098 goto out;
stefano@22245 3099 }
stefano@22245 3100 wait_secs--;
stefano@22245 3101 sleep(1);
stefano@22245 3102 }
stefano@22245 3103 rc = ERROR_NOMEM;
stefano@22245 3104
stefano@22245 3105 out:
stefano@22245 3106 libxl__free_all(&gc);
stefano@22245 3107 return rc;
stefano@22245 3108 }
stefano@22245 3109
stefano@22245 3110 int libxl_wait_for_memory_target(libxl_ctx *ctx, uint32_t domid, int wait_secs)
stefano@22245 3111 {
stefano@22245 3112 int rc = 0;
stefano@22245 3113 uint32_t target_memkb = 0;
stefano@22245 3114 libxl_dominfo info;
stefano@22245 3115
stefano@22245 3116 do {
stefano@22245 3117 wait_secs--;
stefano@22245 3118 sleep(1);
stefano@22245 3119
stefano@22245 3120 rc = libxl_get_memory_target(ctx, domid, &target_memkb);
stefano@22245 3121 if (rc < 0)
stefano@22245 3122 goto out;
stefano@22245 3123
stefano@22245 3124 rc = libxl_domain_info(ctx, &info, domid);
stefano@22245 3125 if (rc < 0)
stefano@22245 3126 return rc;
stefano@22245 3127 } while (wait_secs > 0 && info.current_memkb > target_memkb);
stefano@22245 3128
stefano@22245 3129 if (info.current_memkb <= target_memkb)
stefano@22245 3130 rc = 0;
stefano@22245 3131 else
stefano@22245 3132 rc = ERROR_FAIL;
stefano@22245 3133
stefano@22245 3134 out:
stefano@22245 3135 return 0;
stefano@22245 3136 }
stefano@22245 3137
ian@21930 3138 int libxl_button_press(libxl_ctx *ctx, uint32_t domid, libxl_button button)
keir@20875 3139 {
keir@20875 3140 int rc = -1;
keir@20875 3141
keir@20875 3142 switch (button) {
keir@20875 3143 case POWER_BUTTON:
keir@20875 3144 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_POWER, 0);
keir@20875 3145 break;
keir@20875 3146 case SLEEP_BUTTON:
keir@20875 3147 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_SLEEP, 0);
keir@20875 3148 break;
keir@20875 3149 default:
keir@20875 3150 break;
keir@20875 3151 }
keir@20875 3152
keir@20875 3153 return rc;
keir@20875 3154 }
keir@21141 3155
ian@21930 3156 int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
keir@21141 3157 {
keir@21141 3158 xc_physinfo_t xcphysinfo = { 0 };
keir@21141 3159 int rc;
keir@21141 3160
keir@21141 3161 rc = xc_physinfo(ctx->xch, &xcphysinfo);
keir@21141 3162 if (rc != 0) {
ian@22165 3163 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting physinfo");
gianni@21892 3164 return ERROR_FAIL;
keir@21141 3165 }
keir@21141 3166 physinfo->threads_per_core = xcphysinfo.threads_per_core;
keir@21141 3167 physinfo->cores_per_socket = xcphysinfo.cores_per_socket;
keir@21142 3168 physinfo->max_cpu_id = xcphysinfo.max_cpu_id;
keir@21141 3169 physinfo->nr_cpus = xcphysinfo.nr_cpus;
keir@21141 3170 physinfo->cpu_khz = xcphysinfo.cpu_khz;
keir@21141 3171 physinfo->total_pages = xcphysinfo.total_pages;
keir@21141 3172 physinfo->free_pages = xcphysinfo.free_pages;
keir@21141 3173 physinfo->scrub_pages = xcphysinfo.scrub_pages;
keir@21264 3174 physinfo->nr_nodes = xcphysinfo.nr_nodes;
keir@21264 3175 memcpy(physinfo->hw_cap,xcphysinfo.hw_cap, sizeof(physinfo->hw_cap));
keir@21264 3176 physinfo->phys_cap = xcphysinfo.capabilities;
keir@21264 3177
keir@21141 3178 return 0;
keir@21141 3179 }
keir@21141 3180
ian@21930 3181 const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx)
keir@21266 3182 {
keir@21266 3183 union {
keir@21266 3184 xen_extraversion_t xen_extra;
keir@21266 3185 xen_compile_info_t xen_cc;
keir@21266 3186 xen_changeset_info_t xen_chgset;
keir@21266 3187 xen_capabilities_info_t xen_caps;
keir@21266 3188 xen_platform_parameters_t p_parms;
keir@21266 3189 xen_commandline_t xen_commandline;
keir@21266 3190 } u;
keir@21266 3191 long xen_version;
keir@21266 3192 libxl_version_info *info = &ctx->version_info;
keir@21266 3193
keir@21266 3194 if (info->xen_version_extra != NULL)
keir@21266 3195 return info;
keir@21266 3196
keir@21266 3197 xen_version = xc_version(ctx->xch, XENVER_version, NULL);
keir@21266 3198 info->xen_version_major = xen_version >> 16;
keir@21266 3199 info->xen_version_minor = xen_version & 0xFF;
gianni@22008 3200
keir@21266 3201 xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra);
gianni@22008 3202 info->xen_version_extra = strdup(u.xen_extra);
keir@21266 3203
keir@21266 3204 xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc);
gianni@22008 3205 info->compiler = strdup(u.xen_cc.compiler);
gianni@22008 3206 info->compile_by = strdup(u.xen_cc.compile_by);
gianni@22008 3207 info->compile_domain = strdup(u.xen_cc.compile_domain);
gianni@22008 3208 info->compile_date = strdup(u.xen_cc.compile_date);
keir@21266 3209
keir@21266 3210 xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps);
gianni@22008 3211 info->capabilities = strdup(u.xen_caps);
keir@21266 3212
keir@21266 3213 xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset);
gianni@22008 3214 info->changeset = strdup(u.xen_chgset);
keir@21266 3215
keir@21266 3216 xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms);
keir@21266 3217 info->virt_start = u.p_parms.virt_start;
keir@21266 3218
keir@21266 3219 info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL);
keir@21266 3220
keir@21266 3221 xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline);
gianni@22008 3222 info->commandline = strdup(u.xen_commandline);
keir@21266 3223
keir@21266 3224 return info;
keir@21266 3225 }
keir@21266 3226
ian@21930 3227 libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid,
sstabellini@22000 3228 int *nb_vcpu, int *nrcpus)
keir@21141 3229 {
ian@21930 3230 libxl_vcpuinfo *ptr, *ret;
keir@21141 3231 xc_domaininfo_t domaininfo;
keir@21141 3232 xc_vcpuinfo_t vcpuinfo;
keir@21141 3233
keir@21141 3234 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
ian@22165 3235 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting infolist");
keir@21141 3236 return NULL;
keir@21141 3237 }
juergen@22396 3238 *nrcpus = libxl_get_max_cpus(ctx);
gianni@22015 3239 ret = ptr = calloc(domaininfo.max_vcpu_id + 1, sizeof (libxl_vcpuinfo));
keir@21141 3240 if (!ptr) {
keir@21141 3241 return NULL;
keir@21141 3242 }
keir@21141 3243
keir@21141 3244 for (*nb_vcpu = 0; *nb_vcpu <= domaininfo.max_vcpu_id; ++*nb_vcpu, ++ptr) {
juergen@22396 3245 if (libxl_cpumap_alloc(ctx, &ptr->cpumap)) {
juergen@22319 3246 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating cpumap");
keir@21141 3247 return NULL;
keir@21141 3248 }
keir@21141 3249 if (xc_vcpu_getinfo(ctx->xch, domid, *nb_vcpu, &vcpuinfo) == -1) {
ian@22165 3250 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting vcpu info");
keir@21141 3251 return NULL;
keir@21141 3252 }
juergen@22396 3253 if (xc_vcpu_getaffinity(ctx->xch, domid, *nb_vcpu, ptr->cpumap.map) == -1) {
ian@22165 3254 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting vcpu affinity");
keir@21141 3255 return NULL;
keir@21141 3256 }
keir@21141 3257 ptr->vcpuid = *nb_vcpu;
keir@21141 3258 ptr->cpu = vcpuinfo.cpu;
keir@21141 3259 ptr->online = !!vcpuinfo.online;
keir@21141 3260 ptr->blocked = !!vcpuinfo.blocked;
keir@21141 3261 ptr->running = !!vcpuinfo.running;
keir@21141 3262 ptr->vcpu_time = vcpuinfo.cpu_time;
keir@21141 3263 }
keir@21141 3264 return ret;
keir@21141 3265 }
keir@21142 3266
ian@21930 3267 int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
juergen@22396 3268 libxl_cpumap *cpumap)
keir@21142 3269 {
juergen@22396