debuggers.hg

annotate tools/libxl/libxl.c @ 22852:eefb8e971be5

libxl: libxl_ctx_init checks for xenstored pid file

This is a proxy for whether xenstored is running. Otherwise the
failure modes are unfortunate (hangs, or mysterious error messages).
If and when we have a stubdom xenstored this will need to be
revisited, if not before.

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