debuggers.hg

annotate tools/libxl/libxl.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents 6ec61438713a
children 00e1fd80e1f7
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;
stefano@22854 649 disk->physpath = strdup("");
stefano@22854 650 disk->phystype = PHYSTYPE_EMPTY;
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);
gianni@22853 665 libxl_dominfo dominfo;
keir@20801 666 char *dom_path;
ian@21894 667 char *vm_path;
keir@20628 668 int rc, dm_present;
keir@20628 669
gianni@22853 670 rc = libxl_domain_info(ctx, &dominfo, domid);
gianni@22853 671 switch(rc) {
gianni@22853 672 case 0:
gianni@22853 673 break;
gianni@22853 674 case ERROR_INVAL:
gianni@22853 675 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "non-existant domain %d", domid);
gianni@22853 676 default:
gianni@22853 677 return rc;
gianni@22853 678 }
gianni@22853 679
ian@22165 680 if (libxl__domain_is_hvm(ctx, domid)) {
keir@20628 681 dm_present = 1;
keir@20628 682 } else {
keir@20628 683 char *pid;
ian@22164 684 pid = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/image/device-model-pid", domid));
keir@20628 685 dm_present = (pid != NULL);
keir@20628 686 }
keir@20462 687
ian@22164 688 dom_path = libxl__xs_get_dompath(&gc, domid);
gianni@22023 689 if (!dom_path) {
gianni@22023 690 rc = ERROR_FAIL;
gianni@22023 691 goto out;
gianni@22023 692 }
keir@20512 693
keir@20482 694 if (libxl_device_pci_shutdown(ctx, domid) < 0)
ian@22165 695 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "pci shutdown failed for domid %d", domid);
keir@20512 696 rc = xc_domain_pause(ctx->xch, domid);
keir@20512 697 if (rc < 0) {
ian@22165 698 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_domain_pause failed for %d", domid);
keir@20462 699 }
keir@20628 700 if (dm_present) {
gianni@22725 701 if (libxl__destroy_device_model(ctx, domid) < 0)
gianni@22725 702 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "libxl__destroy_device_model failed for %d", domid);
keir@20628 703 }
ian@22164 704 if (libxl__devices_destroy(ctx, domid, force) < 0)
ian@22165 705 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "libxl_destroy_devices failed for %d", domid);
ian@21891 706
ian@22164 707 vm_path = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/vm", dom_path));
keir@20823 708 if (vm_path)
keir@20823 709 if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
ian@22165 710 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xs_rm failed for %s", vm_path);
keir@20779 711
ian@21891 712 if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
ian@22165 713 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xs_rm failed for %s", dom_path);
ian@21891 714
keir@21190 715 libxl__userdata_destroyall(ctx, domid);
keir@21190 716
keir@20545 717 rc = xc_domain_destroy(ctx->xch, domid);
keir@20545 718 if (rc < 0) {
ian@22165 719 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid);
gianni@22023 720 rc = ERROR_FAIL;
gianni@22023 721 goto out;
keir@20545 722 }
gianni@22023 723 rc = 0;
gianni@22023 724 out:
ian@22164 725 libxl__free_all(&gc);
keir@20462 726 return 0;
keir@20462 727 }
keir@20462 728
stefano@22040 729 int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num, libxl_console_constype type)
keir@20564 730 {
ian@22167 731 libxl__gc gc = LIBXL_INIT_GC(ctx);
ian@22164 732 char *p = libxl__sprintf(&gc, "%s/xenconsole", libxl_private_bindir_path());
ian@22164 733 char *domid_s = libxl__sprintf(&gc, "%d", domid);
ian@22164 734 char *cons_num_s = libxl__sprintf(&gc, "%d", cons_num);
stefano@22040 735 char *cons_type_s;
stefano@22040 736
ian@22071 737 switch (type) {
ian@22071 738 case LIBXL_CONSTYPE_PV:
stefano@22040 739 cons_type_s = "pv";
ian@22071 740 break;
ian@22071 741 case LIBXL_CONSTYPE_SERIAL:
stefano@22040 742 cons_type_s = "serial";
ian@22071 743 break;
ian@22071 744 default:
ian@22071 745 goto out;
ian@22071 746 }
stefano@22040 747
stefano@22040 748 execl(p, p, domid_s, "--num", cons_num_s, "--type", cons_type_s, (void *)NULL);
ian@22071 749
ian@22071 750 out:
ian@22164 751 libxl__free_all(&gc);
gianni@22023 752 return ERROR_FAIL;
keir@20564 753 }
keir@20564 754
ian@21930 755 int libxl_primary_console_exec(libxl_ctx *ctx, uint32_t domid_vm)
sstabellini@21867 756 {
sstabellini@21867 757 uint32_t stubdomid = libxl_get_stubdom_id(ctx, domid_vm);
sstabellini@21867 758 if (stubdomid)
stefano@22845 759 return libxl_console_exec(ctx, stubdomid,
stefano@22845 760 STUBDOM_CONSOLE_SERIAL, LIBXL_CONSTYPE_PV);
stefano@22040 761 else {
ian@22165 762 if (libxl__domain_is_hvm(ctx, domid_vm))
stefano@22040 763 return libxl_console_exec(ctx, domid_vm, 0, LIBXL_CONSTYPE_SERIAL);
stefano@22040 764 else
stefano@22040 765 return libxl_console_exec(ctx, domid_vm, 0, LIBXL_CONSTYPE_PV);
stefano@22040 766 }
sstabellini@21867 767 }
sstabellini@21867 768
ian@21930 769 int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass)
sstabellini@21879 770 {
ian@22167 771 libxl__gc gc = LIBXL_INIT_GC(ctx);
sstabellini@21879 772 const char *vnc_port, *vfb_back;
sstabellini@21879 773 const char *vnc_listen = NULL, *vnc_pass = NULL;
sstabellini@21879 774 int port = 0, autopass_fd = -1;
sstabellini@21879 775 char *vnc_bin, *args[] = {
sstabellini@21879 776 "vncviewer",
sstabellini@21879 777 NULL, /* hostname:display */
sstabellini@21879 778 NULL, /* -autopass */
sstabellini@21879 779 NULL,
sstabellini@21879 780 };
sstabellini@21879 781
ian@22164 782 vnc_port = libxl__xs_read(&gc, XBT_NULL,
ian@22164 783 libxl__sprintf(&gc,
sstabellini@21879 784 "/local/domain/%d/console/vnc-port", domid));
sstabellini@21879 785 if ( vnc_port )
sstabellini@21879 786 port = atoi(vnc_port) - 5900;
sstabellini@21879 787
ian@22164 788 vfb_back = libxl__xs_read(&gc, XBT_NULL,
ian@22164 789 libxl__sprintf(&gc,
sstabellini@21879 790 "/local/domain/%d/device/vfb/0/backend", domid));
sstabellini@21879 791 if ( vfb_back ) {
ian@22164 792 vnc_listen = libxl__xs_read(&gc, XBT_NULL,
ian@22164 793 libxl__sprintf(&gc,
sstabellini@21879 794 "/local/domain/%d/console/vnc-listen", domid));
sstabellini@21879 795 if ( autopass )
ian@22164 796 vnc_pass = libxl__xs_read(&gc, XBT_NULL,
ian@22164 797 libxl__sprintf(&gc,
sstabellini@21879 798 "/local/domain/%d/console/vnc-pass", domid));
sstabellini@21879 799 }
sstabellini@21879 800
sstabellini@21879 801 if ( NULL == vnc_listen )
sstabellini@21879 802 vnc_listen = "localhost";
sstabellini@21879 803
sstabellini@21879 804 if ( (vnc_bin = getenv("VNCVIEWER")) )
sstabellini@21879 805 args[0] = vnc_bin;
sstabellini@21879 806
ian@22164 807 args[1] = libxl__sprintf(&gc, "%s:%d", vnc_listen, port);
sstabellini@21879 808
sstabellini@21879 809 if ( vnc_pass ) {
sstabellini@21879 810 char tmpname[] = "/tmp/vncautopass.XXXXXX";
sstabellini@21879 811 autopass_fd = mkstemp(tmpname);
sstabellini@21879 812 if ( autopass_fd < 0 )
sstabellini@21879 813 goto skip_autopass;
sstabellini@21879 814
sstabellini@21879 815 if ( unlink(tmpname) )
sstabellini@21879 816 /* should never happen */
ian@22165 817 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unlink %s failed", tmpname);
sstabellini@21879 818
sstabellini@21879 819 if ( libxl_write_exactly(ctx, autopass_fd, vnc_pass, strlen(vnc_pass),
sstabellini@21879 820 tmpname, "vnc password") ) {
sstabellini@21879 821 do { close(autopass_fd); } while(errno == EINTR);
sstabellini@21879 822 goto skip_autopass;
sstabellini@21879 823 }
sstabellini@21879 824
sstabellini@21879 825 args[2] = "-autopass";
sstabellini@21879 826 }
sstabellini@21879 827
sstabellini@21879 828 skip_autopass:
ian@22164 829 libxl__free_all(&gc);
ian@22164 830 libxl__exec(autopass_fd, -1, -1, args[0], args);
sstabellini@21879 831 return 0;
sstabellini@21879 832 }
sstabellini@21879 833
keir@20462 834 /******************************************************************************/
keir@20566 835
kamala@22855 836 static int validate_virtual_disk(libxl_ctx *ctx, char *file_name, libxl_disk_phystype disk_type)
kamala@22855 837 {
kamala@22855 838 struct stat stat_buf;
kamala@22855 839
kamala@22855 840 if ( (file_name[0] == '\0') && (disk_type == PHYSTYPE_EMPTY) )
kamala@22855 841 return 0;
kamala@22855 842
kamala@22855 843 if ( stat(file_name, &stat_buf) != 0 ) {
kamala@22855 844 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "failed to stat %s", file_name);
kamala@22855 845 return ERROR_INVAL;
kamala@22855 846 }
kamala@22855 847 if ( disk_type == PHYSTYPE_PHY ) {
kamala@22855 848 if ( !(S_ISBLK(stat_buf.st_mode)) ) {
kamala@22855 849 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Virtual disk %s is not a block device!\n",
kamala@22855 850 file_name);
kamala@22855 851 return ERROR_INVAL;
kamala@22855 852 }
kamala@22855 853 } else if ( stat_buf.st_size == 0 ) {
kamala@22855 854 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Virtual disk %s size is 0!\n", file_name);
kamala@22855 855 return ERROR_INVAL;
kamala@22855 856 }
kamala@22855 857
kamala@22855 858 return 0;
kamala@22855 859 }
kamala@22855 860
ian@21930 861 int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20462 862 {
ian@22167 863 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@20462 864 flexarray_t *front;
keir@20462 865 flexarray_t *back;
keir@20462 866 char *backend_type;
keir@20462 867 int devid;
ian@22167 868 libxl__device device;
gianni@22023 869 int major, minor, rc;
keir@20462 870
kamala@22855 871 rc = validate_virtual_disk(ctx, disk->physpath, disk->phystype);
kamala@22855 872 if (rc)
kamala@22855 873 return rc;
kamala@22855 874
keir@20462 875 front = flexarray_make(16, 1);
gianni@22023 876 if (!front) {
gianni@22023 877 rc = ERROR_NOMEM;
gianni@22023 878 goto out;
gianni@22023 879 }
keir@20462 880 back = flexarray_make(16, 1);
gianni@22023 881 if (!back) {
gianni@22023 882 rc = ERROR_NOMEM;
gianni@22023 883 goto out_free;
gianni@22023 884 }
keir@20462 885
ian@22165 886 backend_type = libxl__device_disk_backend_type_of_phystype(disk->phystype);
ian@22165 887 devid = libxl__device_disk_dev_number(disk->virtpath);
keir@20947 888 if (devid==-1) {
ian@22165 889 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Invalid or unsupported"
keir@20947 890 " virtual disk identifier %s", disk->virtpath);
gianni@22023 891 rc = ERROR_INVAL;
gianni@22023 892 goto out_free;
keir@20947 893 }
keir@20462 894
keir@20462 895 device.backend_devid = devid;
keir@20462 896 device.backend_domid = disk->backend_domid;
keir@20462 897 device.devid = devid;
keir@20462 898 device.domid = disk->domid;
keir@20462 899 device.kind = DEVICE_VBD;
keir@20462 900
keir@20462 901 switch (disk->phystype) {
keir@20462 902 case PHYSTYPE_PHY: {
keir@20462 903
ian@22165 904 libxl__device_physdisk_major_minor(disk->physpath, &major, &minor);
gianni@22726 905 flexarray_append(back, "physical-device");
gianni@22726 906 flexarray_append(back, libxl__sprintf(&gc, "%x:%x", major, minor));
gianni@22726 907
gianni@22726 908 flexarray_append(back, "params");
gianni@22726 909 flexarray_append(back, disk->physpath);
keir@20462 910
keir@20462 911 device.backend_kind = DEVICE_VBD;
keir@20462 912 break;
keir@20462 913 }
stefano@22854 914 case PHYSTYPE_EMPTY:
stefano@22854 915 break;
keir@20566 916 case PHYSTYPE_FILE:
keir@20566 917 /* let's pretend is tap:aio for the moment */
keir@20566 918 disk->phystype = PHYSTYPE_AIO;
Christoph@22044 919 case PHYSTYPE_AIO:
Christoph@22044 920 case PHYSTYPE_QCOW:
Christoph@22044 921 case PHYSTYPE_QCOW2:
Christoph@22044 922 case PHYSTYPE_VHD:
ian@22165 923 if (libxl__blktap_enabled(&gc)) {
ian@22165 924 const char *dev = libxl__blktap_devpath(&gc,
Christoph@22044 925 disk->physpath, disk->phystype);
gianni@22023 926 if (!dev) {
gianni@22023 927 rc = ERROR_FAIL;
gianni@22023 928 goto out_free;
gianni@22023 929 }
gianni@22726 930 flexarray_append(back, "tapdisk-params");
gianni@22726 931 flexarray_append(back, libxl__sprintf(&gc, "%s:%s", libxl__device_disk_string_of_phystype(disk->phystype), disk->physpath));
gianni@22726 932 flexarray_append(back, "params");
gianni@22726 933 flexarray_append(back, libxl__strdup(&gc, dev));
keir@20566 934 backend_type = "phy";
ian@22165 935 libxl__device_physdisk_major_minor(dev, &major, &minor);
gianni@22726 936 flexarray_append(back, "physical-device");
gianni@22726 937 flexarray_append(back, libxl__sprintf(&gc, "%x:%x", major, minor));
keir@20566 938 device.backend_kind = DEVICE_VBD;
keir@20566 939
keir@20566 940 break;
keir@20566 941 }
gianni@22726 942 flexarray_append(back, "params");
gianni@22726 943 flexarray_append(back, libxl__sprintf(&gc, "%s:%s",
ian@22165 944 libxl__device_disk_string_of_phystype(disk->phystype), disk->physpath));
keir@20462 945
stefano@22468 946 if (libxl__blktap_enabled(&gc))
stefano@22468 947 device.backend_kind = DEVICE_TAP;
stefano@22468 948 else
stefano@22468 949 device.backend_kind = DEVICE_QDISK;
keir@20462 950 break;
Christoph@22044 951
keir@20846 952 default:
ian@22165 953 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk physical type: %d\n", disk->phystype);
gianni@22023 954 rc = ERROR_INVAL;
gianni@22023 955 goto out_free;
keir@20462 956 }
keir@20462 957
gianni@22726 958 flexarray_append(back, "frontend-id");
gianni@22726 959 flexarray_append(back, libxl__sprintf(&gc, "%d", disk->domid));
gianni@22726 960 flexarray_append(back, "online");
gianni@22726 961 flexarray_append(back, "1");
gianni@22726 962 flexarray_append(back, "removable");
gianni@22726 963 flexarray_append(back, libxl__sprintf(&gc, "%d", (disk->unpluggable) ? 1 : 0));
gianni@22726 964 flexarray_append(back, "bootable");
gianni@22726 965 flexarray_append(back, libxl__sprintf(&gc, "%d", 1));
gianni@22726 966 flexarray_append(back, "state");
gianni@22726 967 flexarray_append(back, libxl__sprintf(&gc, "%d", 1));
gianni@22726 968 flexarray_append(back, "dev");
gianni@22726 969 flexarray_append(back, disk->virtpath);
gianni@22726 970 flexarray_append(back, "type");
gianni@22726 971 flexarray_append(back, backend_type);
gianni@22726 972 flexarray_append(back, "mode");
gianni@22726 973 flexarray_append(back, disk->readwrite ? "w" : "r");
gianni@22726 974
gianni@22726 975 flexarray_append(front, "backend-id");
gianni@22726 976 flexarray_append(front, libxl__sprintf(&gc, "%d", disk->backend_domid));
gianni@22726 977 flexarray_append(front, "state");
gianni@22726 978 flexarray_append(front, libxl__sprintf(&gc, "%d", 1));
gianni@22726 979 flexarray_append(front, "virtual-device");
gianni@22726 980 flexarray_append(front, libxl__sprintf(&gc, "%d", devid));
gianni@22726 981 flexarray_append(front, "device-type");
gianni@22726 982 flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
keir@20462 983
keir@20462 984 if (0 /* protocol != native*/) {
gianni@22726 985 flexarray_append(front, "protocol");
gianni@22726 986 flexarray_append(front, "x86_32-abi"); /* hardcoded ! */
keir@20462 987 }
keir@20462 988
ian@22164 989 libxl__device_generic_add(ctx, &device,
gianni@22726 990 libxl__xs_kvs_of_flexarray(&gc, back, back->count),
gianni@22726 991 libxl__xs_kvs_of_flexarray(&gc, front, front->count));
gianni@22023 992
gianni@22023 993 rc = 0;
gianni@22023 994
gianni@22023 995 out_free:
keir@20516 996 flexarray_free(back);
keir@20516 997 flexarray_free(front);
gianni@22023 998 out:
ian@22164 999 libxl__free_all(&gc);
gianni@22023 1000 return rc;
keir@20462 1001 }
keir@20462 1002
ian@21930 1003 int libxl_device_disk_del(libxl_ctx *ctx,
keir@20626 1004 libxl_device_disk *disk, int wait)
keir@20462 1005 {
ian@22167 1006 libxl__device device;
keir@20626 1007 int devid;
keir@20462 1008
ian@22165 1009 devid = libxl__device_disk_dev_number(disk->virtpath);
keir@20626 1010 device.backend_domid = disk->backend_domid;
keir@20626 1011 device.backend_devid = devid;
keir@20626 1012 device.backend_kind =
keir@20626 1013 (disk->phystype == PHYSTYPE_PHY) ? DEVICE_VBD : DEVICE_TAP;
keir@20626 1014 device.domid = disk->domid;
keir@20626 1015 device.devid = devid;
keir@20626 1016 device.kind = DEVICE_VBD;
ian@22164 1017 return libxl__device_del(ctx, &device, wait);
keir@20462 1018 }
keir@20462 1019
gianni@22023 1020 char * libxl_device_disk_local_attach(libxl_ctx *ctx, libxl_device_disk *disk)
Ian@21849 1021 {
ian@22167 1022 libxl__gc gc = LIBXL_INIT_GC(ctx);
Christoph@22044 1023 const char *dev = NULL;
Christoph@22044 1024 char *ret;
Ian@21849 1025 int phystype = disk->phystype;
Ian@21849 1026 switch (phystype) {
Ian@21849 1027 case PHYSTYPE_PHY: {
Ian@21849 1028 fprintf(stderr, "attaching PHY disk %s to domain 0\n", disk->physpath);
Ian@21849 1029 dev = disk->physpath;
Ian@21849 1030 break;
Ian@21849 1031 }
Ian@21849 1032 case PHYSTYPE_FILE:
Ian@21849 1033 /* let's pretend is tap:aio for the moment */
Ian@21849 1034 phystype = PHYSTYPE_AIO;
Christoph@22044 1035 case PHYSTYPE_AIO:
Christoph@22044 1036 case PHYSTYPE_QCOW:
Christoph@22044 1037 case PHYSTYPE_QCOW2:
Christoph@22044 1038 case PHYSTYPE_VHD:
ian@22165 1039 if (libxl__blktap_enabled(&gc))
ian@22165 1040 dev = libxl__blktap_devpath(&gc, disk->physpath, phystype);
Ian@21849 1041 break;
Christoph@22044 1042
Ian@21849 1043 default:
ian@22165 1044 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk physical type: %d\n", phystype);
Ian@21849 1045 break;
Ian@21849 1046 }
gianni@22023 1047 ret = strdup(dev);
ian@22164 1048 libxl__free_all(&gc);
gianni@22023 1049 return ret;
Ian@21849 1050 }
Ian@21849 1051
ian@21930 1052 int libxl_device_disk_local_detach(libxl_ctx *ctx, libxl_device_disk *disk)
Ian@21849 1053 {
Ian@21849 1054 /* Nothing to do for PHYSTYPE_PHY. */
Ian@21849 1055
Ian@21849 1056 /*
Ian@21849 1057 * For other device types assume that the blktap2 process is
Ian@21849 1058 * needed by the soon to be started domain and do nothing.
Ian@21849 1059 */
Ian@21849 1060
Ian@21849 1061 return 0;
Ian@21849 1062 }
Ian@21849 1063
keir@20462 1064 /******************************************************************************/
gianni@22768 1065 int libxl_device_nic_init(libxl_device_nic *nic_info, int devnum)
gianni@22768 1066 {
gianni@22768 1067 const uint8_t *r;
gianni@22768 1068 libxl_uuid uuid;
gianni@22768 1069
gianni@22768 1070 libxl_uuid_generate(&uuid);
gianni@22768 1071 r = libxl_uuid_bytearray(&uuid);
gianni@22768 1072 memset(nic_info, '\0', sizeof(*nic_info));
gianni@22768 1073
gianni@22768 1074 nic_info->backend_domid = 0;
gianni@22768 1075 nic_info->domid = 0;
gianni@22768 1076 nic_info->devid = devnum;
gianni@22768 1077 nic_info->mtu = 1492;
gianni@22768 1078 nic_info->model = strdup("e1000");
gianni@22768 1079 nic_info->mac[0] = 0x00;
gianni@22768 1080 nic_info->mac[1] = 0x16;
gianni@22768 1081 nic_info->mac[2] = 0x3e;
gianni@22768 1082 nic_info->mac[3] = r[0] & 0x7f;
gianni@22768 1083 nic_info->mac[4] = r[1];
gianni@22768 1084 nic_info->mac[5] = r[2];
gianni@22768 1085 nic_info->ifname = NULL;
gianni@22768 1086 nic_info->bridge = strdup("xenbr0");
gianni@22768 1087 if ( asprintf(&nic_info->script, "%s/vif-bridge",
gianni@22768 1088 libxl_xen_script_dir_path()) < 0 )
gianni@22768 1089 return ERROR_FAIL;
gianni@22768 1090 nic_info->nictype = NICTYPE_IOEMU;
gianni@22768 1091 return 0;
gianni@22768 1092 }
gianni@22768 1093
ian@21930 1094 int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
keir@20462 1095 {
ian@22167 1096 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@20462 1097 flexarray_t *front;
keir@20462 1098 flexarray_t *back;
ian@22167 1099 libxl__device device;
keir@21407 1100 char *dompath, **l;
gianni@22023 1101 unsigned int nb, rc;
keir@20462 1102
keir@20462 1103 front = flexarray_make(16, 1);
gianni@22023 1104 if (!front) {
gianni@22023 1105 rc = ERROR_NOMEM;
gianni@22023 1106 goto out;
gianni@22023 1107 }
keir@20462 1108 back = flexarray_make(16, 1);
gianni@22023 1109 if (!back) {
gianni@22023 1110 rc = ERROR_NOMEM;
gianni@22023 1111 goto out_free;
gianni@22023 1112 }
keir@20462 1113
keir@21407 1114 if (nic->devid == -1) {
ian@22164 1115 if (!(dompath = libxl__xs_get_dompath(&gc, domid))) {
gianni@22023 1116 rc = ERROR_FAIL;
gianni@22023 1117 goto out_free;
keir@21407 1118 }
ian@22164 1119 if (!(l = libxl__xs_directory(&gc, XBT_NULL,
ian@22164 1120 libxl__sprintf(&gc, "%s/device/vif", dompath), &nb))) {
keir@21407 1121 nic->devid = 0;
keir@21407 1122 } else {
keir@21407 1123 nic->devid = strtoul(l[nb - 1], NULL, 10) + 1;
keir@21407 1124 }
keir@21407 1125 }
keir@21407 1126
keir@20462 1127 device.backend_devid = nic->devid;
keir@20462 1128 device.backend_domid = nic->backend_domid;
keir@20462 1129 device.backend_kind = DEVICE_VIF;
keir@20462 1130 device.devid = nic->devid;
keir@20462 1131 device.domid = nic->domid;
keir@20462 1132 device.kind = DEVICE_VIF;
keir@20462 1133
gianni@22726 1134 flexarray_append(back, "frontend-id");
gianni@22726 1135 flexarray_append(back, libxl__sprintf(&gc, "%d", nic->domid));
gianni@22726 1136 flexarray_append(back, "online");
gianni@22726 1137 flexarray_append(back, "1");
gianni@22726 1138 flexarray_append(back, "state");
gianni@22726 1139 flexarray_append(back, libxl__sprintf(&gc, "%d", 1));
gianni@22726 1140 flexarray_append(back, "script");
gianni@22726 1141 flexarray_append(back, nic->script);
gianni@22726 1142 flexarray_append(back, "mac");
gianni@22726 1143 flexarray_append(back, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 1144 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 1145 nic->mac[3], nic->mac[4], nic->mac[5]));
gianni@22726 1146 flexarray_append(back, "bridge");
gianni@22726 1147 flexarray_append(back, libxl__strdup(&gc, nic->bridge));
gianni@22726 1148 flexarray_append(back, "handle");
gianni@22726 1149 flexarray_append(back, libxl__sprintf(&gc, "%d", nic->devid));
gianni@22726 1150
gianni@22726 1151 flexarray_append(front, "backend-id");
gianni@22726 1152 flexarray_append(front, libxl__sprintf(&gc, "%d", nic->backend_domid));
gianni@22726 1153 flexarray_append(front, "state");
gianni@22726 1154 flexarray_append(front, libxl__sprintf(&gc, "%d", 1));
gianni@22726 1155 flexarray_append(front, "handle");
gianni@22726 1156 flexarray_append(front, libxl__sprintf(&gc, "%d", nic->devid));
gianni@22726 1157 flexarray_append(front, "mac");
gianni@22726 1158 flexarray_append(front, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 1159 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 1160 nic->mac[3], nic->mac[4], nic->mac[5]));
keir@20462 1161 if (0 /* protocol != native*/) {
gianni@22726 1162 flexarray_append(front, "protocol");
gianni@22726 1163 flexarray_append(front, "x86_32-abi"); /* hardcoded ! */
keir@20462 1164 }
keir@20462 1165
ian@22164 1166 libxl__device_generic_add(ctx, &device,
gianni@22726 1167 libxl__xs_kvs_of_flexarray(&gc, back, back->count),
gianni@22726 1168 libxl__xs_kvs_of_flexarray(&gc, front, front->count));
keir@20462 1169
keir@20462 1170 /* FIXME: wait for plug */
gianni@22023 1171 rc = 0;
gianni@22023 1172 out_free:
keir@20516 1173 flexarray_free(back);
keir@20516 1174 flexarray_free(front);
gianni@22023 1175 out:
ian@22164 1176 libxl__free_all(&gc);
gianni@22023 1177 return rc;
keir@20462 1178 }
keir@20462 1179
ian@21930 1180 int libxl_device_nic_del(libxl_ctx *ctx,
keir@20626 1181 libxl_device_nic *nic, int wait)
keir@20462 1182 {
ian@22167 1183 libxl__device device;
keir@20462 1184
keir@20626 1185 device.backend_devid = nic->devid;
keir@20626 1186 device.backend_domid = nic->backend_domid;
keir@20626 1187 device.backend_kind = DEVICE_VIF;
keir@20626 1188 device.devid = nic->devid;
keir@20626 1189 device.domid = nic->domid;
keir@20626 1190 device.kind = DEVICE_VIF;
keir@20626 1191
ian@22164 1192 return libxl__device_del(ctx, &device, wait);
keir@20462 1193 }
keir@20462 1194
ian@21930 1195 libxl_nicinfo *libxl_list_nics(libxl_ctx *ctx, uint32_t domid, unsigned int *nb)
keir@21408 1196 {
ian@22167 1197 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@21408 1198 char *dompath, *nic_path_fe;
gianni@22009 1199 char **l, **list;
keir@21408 1200 char *val, *tok;
keir@21408 1201 unsigned int nb_nics, i;
keir@21408 1202 libxl_nicinfo *res, *nics;
keir@21408 1203
ian@22164 1204 dompath = libxl__xs_get_dompath(&gc, domid);
gianni@22023 1205 if (!dompath)
gianni@22023 1206 goto err;
ian@22164 1207 list = l = libxl__xs_directory(&gc, XBT_NULL,
ian@22164 1208 libxl__sprintf(&gc, "%s/device/vif", dompath), &nb_nics);
gianni@22023 1209 if (!l)
gianni@22023 1210 goto err;
gianni@22009 1211 nics = res = calloc(nb_nics, sizeof (libxl_device_nic));
gianni@22023 1212 if (!res)
gianni@22023 1213 goto err;
keir@21408 1214 for (*nb = nb_nics; nb_nics > 0; --nb_nics, ++l, ++nics) {
ian@22164 1215 nic_path_fe = libxl__sprintf(&gc, "%s/device/vif/%s", dompath, *l);
keir@21408 1216
gianni@22009 1217 nics->backend = xs_read(ctx->xsh, XBT_NULL,
ian@22164 1218 libxl__sprintf(&gc, "%s/backend", nic_path_fe), NULL);
ian@22164 1219 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/backend-id", nic_path_fe));
keir@21408 1220 nics->backend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21408 1221
keir@21408 1222 nics->devid = strtoul(*l, NULL, 10);
ian@22164 1223 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/state", nic_path_fe));
keir@21408 1224 nics->state = val ? strtoul(val, NULL, 10) : -1;
ian@22164 1225 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/mac", nic_path_fe));
keir@21408 1226 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21408 1227 ++i, tok = strtok(NULL, ":")) {
keir@21408 1228 nics->mac[i] = strtoul(tok, NULL, 16);
keir@21408 1229 }
ian@22164 1230 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/event-channel", nic_path_fe));
keir@21408 1231 nics->evtch = val ? strtol(val, NULL, 10) : -1;
ian@22164 1232 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/tx-ring-ref", nic_path_fe));
keir@21408 1233 nics->rref_tx = val ? strtol(val, NULL, 10) : -1;
ian@22164 1234 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/rx-ring-ref", nic_path_fe));
keir@21408 1235 nics->rref_rx = val ? strtol(val, NULL, 10) : -1;
gianni@22009 1236 nics->frontend = xs_read(ctx->xsh, XBT_NULL,
ian@22164 1237 libxl__sprintf(&gc, "%s/frontend", nics->backend), NULL);
ian@22164 1238 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/frontend-id", nics->backend));
keir@21408 1239 nics->frontend_id = val ? strtoul(val, NULL, 10) : -1;
gianni@22009 1240 nics->script = xs_read(ctx->xsh, XBT_NULL,
ian@22164 1241 libxl__sprintf(&gc, "%s/script", nics->backend), NULL);
keir@21408 1242 }
keir@21408 1243
ian@22164 1244 libxl__free_all(&gc);
keir@21408 1245 return res;
gianni@22023 1246 err:
ian@22164 1247 libxl__free_all(&gc);
gianni@22023 1248 return NULL;
keir@21408 1249 }
keir@21408 1250
keir@21580 1251 /******************************************************************************/
gianni@22768 1252 void libxl_device_net2_init(libxl_device_net2 *net2_info, int devnum)
gianni@22768 1253 {
gianni@22768 1254 const uint8_t *r;
gianni@22768 1255 libxl_uuid uuid;
gianni@22768 1256
gianni@22768 1257 libxl_uuid_generate(&uuid);
gianni@22768 1258 r = libxl_uuid_bytearray(&uuid);
gianni@22768 1259 memset(net2_info, '\0', sizeof(*net2_info));
gianni@22768 1260
gianni@22768 1261 net2_info->devid = devnum;
gianni@22768 1262 net2_info->front_mac[0] = 0x00;
gianni@22768 1263 net2_info->front_mac[1] = 0x16;
gianni@22768 1264 net2_info->front_mac[2] = 0x3e;;
gianni@22768 1265 net2_info->front_mac[3] = 0x7f & r[0];
gianni@22768 1266 net2_info->front_mac[4] = r[1];
gianni@22768 1267 net2_info->front_mac[5] = r[2];
gianni@22768 1268 net2_info->back_mac[0] = 0x00;
gianni@22768 1269 net2_info->back_mac[1] = 0x16;
gianni@22768 1270 net2_info->back_mac[2] = 0x3e;
gianni@22768 1271 net2_info->back_mac[3] = 0x7f & r[3];
gianni@22768 1272 net2_info->back_mac[4] = r[4];
gianni@22768 1273 net2_info->back_mac[5] = r[5];
gianni@22768 1274 net2_info->back_trusted = 1;
gianni@22768 1275 net2_info->filter_mac = 1;
gianni@22768 1276 net2_info->max_bypasses = 5;
gianni@22768 1277 net2_info->bridge = strdup("xenbr0");
gianni@22768 1278 }
gianni@22768 1279
ian@21930 1280 int libxl_device_net2_add(libxl_ctx *ctx, uint32_t domid, libxl_device_net2 *net2)
keir@21580 1281 {
ian@22167 1282 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@21580 1283 flexarray_t *front, *back;
ian@22167 1284 libxl__device device;
keir@21580 1285 char *dompath, *dom, **l;
keir@21580 1286 unsigned int nb;
gianni@22023 1287 int rc;
keir@21580 1288
keir@21580 1289 front = flexarray_make(16, 1);
gianni@22023 1290 if (!front) {
gianni@22023 1291 rc = ERROR_NOMEM;
gianni@22023 1292 goto err;
gianni@22023 1293 }
keir@21580 1294 back = flexarray_make(16, 1);
gianni@22023 1295 if (!back) {
gianni@22023 1296 rc = ERROR_NOMEM;
gianni@22023 1297 goto err_free;
keir@21580 1298 }
gianni@22023 1299
ian@22164 1300 if (!(dompath = libxl__xs_get_dompath(&gc, domid))) {
gianni@22023 1301 rc = ERROR_FAIL;
gianni@22023 1302 goto err_free;
gianni@22023 1303 }
ian@22164 1304 dom = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/name", dompath));
keir@21580 1305
keir@21580 1306 if (net2->devid == -1) {
ian@22164 1307 if (!(l = libxl__xs_directory(&gc, XBT_NULL,
ian@22164 1308 libxl__sprintf(&gc, "%s/device/vif2", dompath), &nb))) {
keir@21580 1309 net2->devid = 0;
keir@21580 1310 } else {
keir@21580 1311 net2->devid = strtoul(l[nb - 1], NULL, 10) + 1;
keir@21580 1312 }
keir@21580 1313 }
keir@21580 1314
keir@21580 1315 device.backend_devid = net2->devid;
keir@21580 1316 device.backend_domid = net2->backend_domid;
keir@21580 1317 device.backend_kind = DEVICE_VIF2;
keir@21580 1318 device.devid = net2->devid;
keir@21580 1319 device.domid = net2->domid;
keir@21580 1320 device.kind = DEVICE_VIF2;
keir@21580 1321
gianni@22726 1322 flexarray_append(back, "domain");
gianni@22726 1323 flexarray_append(back, dom);
gianni@22726 1324 flexarray_append(back, "frontend-id");
gianni@22726 1325 flexarray_append(back, libxl__sprintf(&gc, "%d", net2->domid));
gianni@22726 1326
gianni@22726 1327 flexarray_append(back, "local-trusted");
gianni@22726 1328 flexarray_append(back, libxl__sprintf(&gc, "%d", net2->back_trusted));
gianni@22726 1329 flexarray_append(back, "mac");
gianni@22726 1330 flexarray_append(back, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 1331 net2->back_mac[0], net2->back_mac[1],
keir@21580 1332 net2->back_mac[2], net2->back_mac[3],
keir@21580 1333 net2->back_mac[4], net2->back_mac[5]));
keir@21580 1334
gianni@22726 1335 flexarray_append(back, "remote-trusted");
gianni@22726 1336 flexarray_append(back, libxl__sprintf(&gc, "%d", net2->trusted));
gianni@22726 1337 flexarray_append(back, "remote-mac");
gianni@22726 1338 flexarray_append(back, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 1339 net2->front_mac[0], net2->front_mac[1],
keir@21580 1340 net2->front_mac[2], net2->front_mac[3],
keir@21580 1341 net2->front_mac[4], net2->front_mac[5]));
keir@21580 1342
gianni@22726 1343 flexarray_append(back, "max-bypasses");
gianni@22726 1344 flexarray_append(back, libxl__sprintf(&gc, "%d", net2->max_bypasses));
gianni@22726 1345 flexarray_append(back, "filter-mac");
gianni@22726 1346 flexarray_append(back, libxl__sprintf(&gc, "%d", !!(net2->filter_mac)));
gianni@22726 1347 flexarray_append(back, "handle");
gianni@22726 1348 flexarray_append(back, libxl__sprintf(&gc, "%d", net2->devid));
gianni@22726 1349 flexarray_append(back, "online");
gianni@22726 1350 flexarray_append(back, "1");
gianni@22726 1351 flexarray_append(back, "state");
gianni@22726 1352 flexarray_append(back, "1");
gianni@22726 1353
gianni@22726 1354 flexarray_append(front, "backend-id");
gianni@22726 1355 flexarray_append(front, libxl__sprintf(&gc, "%d", net2->backend_domid));
gianni@22726 1356
gianni@22726 1357 flexarray_append(front, "local-trusted");
gianni@22726 1358 flexarray_append(front, libxl__sprintf(&gc, "%d", net2->trusted));
gianni@22726 1359 flexarray_append(front, "mac");
gianni@22726 1360 flexarray_append(front, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 1361 net2->front_mac[0], net2->front_mac[1],
keir@21580 1362 net2->front_mac[2], net2->front_mac[3],
keir@21580 1363 net2->front_mac[4], net2->front_mac[5]));
keir@21580 1364
gianni@22726 1365 flexarray_append(front, "remote-trusted");
gianni@22726 1366 flexarray_append(front, libxl__sprintf(&gc, "%d", net2->back_trusted));
gianni@22726 1367 flexarray_append(front, "remote-mac");
gianni@22726 1368 flexarray_append(front, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 1369 net2->back_mac[0], net2->back_mac[1],
keir@21580 1370 net2->back_mac[2], net2->back_mac[3],
keir@21580 1371 net2->back_mac[4], net2->back_mac[5]));
keir@21580 1372
gianni@22726 1373 flexarray_append(front, "filter-mac");
gianni@22726 1374 flexarray_append(front, libxl__sprintf(&gc, "%d", !!(net2->filter_mac)));
gianni@22726 1375 flexarray_append(front, "state");
gianni@22726 1376 flexarray_append(front, "1");
keir@21580 1377
ian@22164 1378 libxl__device_generic_add(ctx, &device,
gianni@22726 1379 libxl__xs_kvs_of_flexarray(&gc, back, back->count),
gianni@22726 1380 libxl__xs_kvs_of_flexarray(&gc, front, front->count));
keir@21580 1381
keir@21580 1382 /* FIXME: wait for plug */
gianni@22023 1383 rc = 0;
gianni@22023 1384 err_free:
keir@21580 1385 flexarray_free(back);
keir@21580 1386 flexarray_free(front);
gianni@22023 1387 err:
ian@22164 1388 libxl__free_all(&gc);
gianni@22023 1389 return rc;
keir@21580 1390 }
keir@21408 1391
ian@21930 1392 libxl_net2info *libxl_device_net2_list(libxl_ctx *ctx, uint32_t domid, unsigned int *nb)
keir@21581 1393 {
ian@22167 1394 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@21581 1395 char *dompath, *net2_path_fe;
keir@21581 1396 char **l;
keir@21581 1397 char *val, *tok;
keir@21581 1398 unsigned int nb_net2s, i;
keir@21581 1399 libxl_net2info *res, *net2s;
keir@21581 1400
ian@22164 1401 dompath = libxl__xs_get_dompath(&gc, domid);
gianni@22023 1402 if (!dompath)
gianni@22023 1403 goto err;
ian@22164 1404 l = libxl__xs_directory(&gc, XBT_NULL,
ian@22164 1405 libxl__sprintf(&gc, "%s/device/vif2", dompath), &nb_net2s);
gianni@22023 1406 if (!l)
gianni@22023 1407 goto err;
gianni@22023 1408 res = calloc(nb_net2s, sizeof (libxl_net2info));
gianni@22023 1409 if (!res)
gianni@22023 1410 goto err;
keir@21581 1411 net2s = res;
keir@21581 1412 for (*nb = nb_net2s; nb_net2s > 0; --nb_net2s, ++l, ++net2s) {
ian@22164 1413 net2_path_fe = libxl__sprintf(&gc, "%s/device/vif2/%s", dompath, *l);
ian@22164 1414
ian@22164 1415 net2s->backend = libxl__xs_read(&gc, XBT_NULL,
ian@22164 1416 libxl__sprintf(&gc, "%s/backend", net2_path_fe));
ian@22164 1417 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/backend-id", net2_path_fe));
keir@21581 1418 net2s->backend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1419
keir@21581 1420 net2s->devid = strtoul(*l, NULL, 10);
ian@22164 1421 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/state", net2_path_fe));
keir@21581 1422 net2s->state = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1423
ian@22164 1424 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/mac", net2_path_fe));
keir@21581 1425 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21581 1426 ++i, tok = strtok(NULL, ":")) {
keir@21581 1427 net2s->mac[i] = strtoul(tok, NULL, 16);
keir@21581 1428 }
ian@22164 1429 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/remote-trusted", net2_path_fe));
keir@21581 1430 net2s->trusted = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1431
ian@22164 1432 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/remote-mac", net2_path_fe));
keir@21581 1433 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21581 1434 ++i, tok = strtok(NULL, ":")) {
keir@21581 1435 net2s->back_mac[i] = strtoul(tok, NULL, 16);
keir@21581 1436 }
ian@22164 1437 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/filter-mac", net2_path_fe));
keir@21581 1438 net2s->filter_mac = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1439
ian@22164 1440 net2s->frontend = libxl__xs_read(&gc, XBT_NULL,
ian@22164 1441 libxl__sprintf(&gc, "%s/frontend", net2s->backend));
ian@22164 1442 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/frontend-id", net2s->backend));
keir@21581 1443 net2s->frontend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1444 }
keir@21581 1445
ian@22164 1446 libxl__free_all(&gc);
keir@21581 1447 return res;
gianni@22023 1448 err:
ian@22164 1449 libxl__free_all(&gc);
gianni@22023 1450 return NULL;
keir@21581 1451 }
keir@21581 1452
ian@21930 1453 int libxl_device_net2_del(libxl_ctx *ctx, libxl_device_net2 *net2, int wait)
keir@21582 1454 {
ian@22167 1455 libxl__device device;
keir@21582 1456
keir@21582 1457 device.backend_devid = net2->devid;
keir@21582 1458 device.backend_domid = net2->backend_domid;
keir@21582 1459 device.backend_kind = DEVICE_VIF2;
keir@21582 1460 device.devid = net2->devid;
keir@21582 1461 device.domid = net2->domid;
keir@21582 1462 device.kind = DEVICE_VIF2;
keir@21582 1463
ian@22164 1464 return libxl__device_del(ctx, &device, wait);
keir@21582 1465 }
keir@21582 1466
keir@21581 1467
keir@20462 1468 /******************************************************************************/
ian@21930 1469 int libxl_device_console_add(libxl_ctx *ctx, uint32_t domid, libxl_device_console *console)
keir@20462 1470 {
ian@22167 1471 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@20509 1472 flexarray_t *front;
keir@20509 1473 flexarray_t *back;
ian@22167 1474 libxl__device device;
gianni@22023 1475 int rc;
keir@20509 1476
keir@20509 1477 front = flexarray_make(16, 1);
gianni@22023 1478 if (!front) {
gianni@22023 1479 rc = ERROR_NOMEM;
gianni@22023 1480 goto out;
gianni@22023 1481 }
keir@20509 1482 back = flexarray_make(16, 1);
gianni@22023 1483 if (!back) {
gianni@22023 1484 rc = ERROR_NOMEM;
gianni@22023 1485 goto out_free;
gianni@22023 1486 }
keir@20509 1487
keir@20509 1488 device.backend_devid = console->devid;
keir@20509 1489 device.backend_domid = console->backend_domid;
keir@20509 1490 device.backend_kind = DEVICE_CONSOLE;
keir@20509 1491 device.devid = console->devid;
keir@20509 1492 device.domid = console->domid;
keir@20509 1493 device.kind = DEVICE_CONSOLE;
keir@20509 1494
gianni@22726 1495 flexarray_append(back, "frontend-id");
gianni@22726 1496 flexarray_append(back, libxl__sprintf(&gc, "%d", console->domid));
gianni@22726 1497 flexarray_append(back, "online");
gianni@22726 1498 flexarray_append(back, "1");
gianni@22726 1499 flexarray_append(back, "state");
gianni@22726 1500 flexarray_append(back, libxl__sprintf(&gc, "%d", 1));
gianni@22726 1501 flexarray_append(back, "domain");
gianni@22726 1502 flexarray_append(back, libxl__domid_to_name(&gc, domid));
gianni@22726 1503 flexarray_append(back, "protocol");
gianni@22726 1504 flexarray_append(back, LIBXL_XENCONSOLE_PROTOCOL);
gianni@22726 1505
gianni@22726 1506 flexarray_append(front, "backend-id");
gianni@22726 1507 flexarray_append(front, libxl__sprintf(&gc, "%d", console->backend_domid));
gianni@22726 1508 flexarray_append(front, "limit");
gianni@22726 1509 flexarray_append(front, libxl__sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT));
gianni@22726 1510 flexarray_append(front, "type");
ian@22273 1511 if (console->consback == LIBXL_CONSBACK_XENCONSOLED)
gianni@22726 1512 flexarray_append(front, "xenconsoled");
ian@22273 1513 else
gianni@22726 1514 flexarray_append(front, "ioemu");
gianni@22726 1515 flexarray_append(front, "output");
gianni@22726 1516 flexarray_append(front, console->output);
ian@22273 1517
ian@22273 1518 if (device.devid == 0) {
ian@22273 1519 if (console->build_state == NULL) {
ian@22273 1520 rc = ERROR_INVAL;
ian@22273 1521 goto out_free;
ian@22273 1522 }
gianni@22726 1523 flexarray_append(front, "port");
gianni@22726 1524 flexarray_append(front, libxl__sprintf(&gc, "%"PRIu32, console->build_state->console_port));
gianni@22726 1525 flexarray_append(front, "ring-ref");
gianni@22726 1526 flexarray_append(front, libxl__sprintf(&gc, "%lu", console->build_state->console_mfn));
ian@22273 1527 } else {
gianni@22726 1528 flexarray_append(front, "state");
gianni@22726 1529 flexarray_append(front, libxl__sprintf(&gc, "%d", 1));
gianni@22726 1530 flexarray_append(front, "protocol");
gianni@22726 1531 flexarray_append(front, LIBXL_XENCONSOLE_PROTOCOL);
stefano@22040 1532 }
keir@20509 1533
ian@22164 1534 libxl__device_generic_add(ctx, &device,
gianni@22726 1535 libxl__xs_kvs_of_flexarray(&gc, back, back->count),
gianni@22726 1536 libxl__xs_kvs_of_flexarray(&gc, front, front->count));
gianni@22023 1537 rc = 0;
gianni@22023 1538 out_free:
keir@20516 1539 flexarray_free(back);
keir@20516 1540 flexarray_free(front);
gianni@22023 1541 out:
ian@22164 1542 libxl__free_all(&gc);
gianni@22023 1543 return rc;
keir@20509 1544 }
keir@20509 1545
keir@20509 1546 /******************************************************************************/
gianni@22768 1547 void libxl_device_vkb_init(libxl_device_vkb *vkb, int dev_num)
gianni@22768 1548 {
gianni@22768 1549 memset(vkb, 0x00, sizeof(libxl_device_vkb));
gianni@22768 1550 vkb->devid = dev_num;
gianni@22768 1551 }
gianni@22768 1552
ian@21930 1553 int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb)
keir@20509 1554 {
ian@22167 1555 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@20509 1556 flexarray_t *front;
keir@20509 1557 flexarray_t *back;
ian@22167 1558 libxl__device device;
gianni@22023 1559 int rc;
keir@20509 1560
keir@20509 1561 front = flexarray_make(16, 1);
gianni@22023 1562 if (!front) {
gianni@22023 1563 rc = ERROR_NOMEM;
gianni@22023 1564 goto out;
gianni@22023 1565 }
keir@20509 1566 back = flexarray_make(16, 1);
gianni@22023 1567 if (!back) {
gianni@22023 1568 rc = ERROR_NOMEM;
gianni@22023 1569 goto out_free;
gianni@22023 1570 }
keir@20509 1571
keir@20509 1572 device.backend_devid = vkb->devid;
keir@20509 1573 device.backend_domid = vkb->backend_domid;
keir@20509 1574 device.backend_kind = DEVICE_VKBD;
keir@20509 1575 device.devid = vkb->devid;
keir@20509 1576 device.domid = vkb->domid;
keir@20509 1577 device.kind = DEVICE_VKBD;
keir@20509 1578
gianni@22726 1579 flexarray_append(back, "frontend-id");
gianni@22726 1580 flexarray_append(back, libxl__sprintf(&gc, "%d", vkb->domid));
gianni@22726 1581 flexarray_append(back, "online");
gianni@22726 1582 flexarray_append(back, "1");
gianni@22726 1583 flexarray_append(back, "state");
gianni@22726 1584 flexarray_append(back, libxl__sprintf(&gc, "%d", 1));
gianni@22726 1585 flexarray_append(back, "domain");
gianni@22726 1586 flexarray_append(back, libxl__domid_to_name(&gc, domid));
gianni@22726 1587
gianni@22726 1588 flexarray_append(front, "backend-id");
gianni@22726 1589 flexarray_append(front, libxl__sprintf(&gc, "%d", vkb->backend_domid));
gianni@22726 1590 flexarray_append(front, "state");
gianni@22726 1591 flexarray_append(front, libxl__sprintf(&gc, "%d", 1));
ian@22164 1592
ian@22164 1593 libxl__device_generic_add(ctx, &device,
gianni@22726 1594 libxl__xs_kvs_of_flexarray(&gc, back, back->count),
gianni@22726 1595 libxl__xs_kvs_of_flexarray(&gc, front, front->count));
gianni@22023 1596 rc = 0;
gianni@22023 1597 out_free:
keir@20516 1598 flexarray_free(back);
keir@20516 1599 flexarray_free(front);
gianni@22023 1600 out:
ian@22164 1601 libxl__free_all(&gc);
gianni@22023 1602 return rc;
keir@20462 1603 }
keir@20462 1604
ian@21930 1605 int libxl_device_vkb_clean_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 1606 {
keir@20462 1607 return ERROR_NI;
keir@20462 1608 }
keir@20462 1609
ian@21930 1610 int libxl_device_vkb_hard_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 1611 {
keir@20462 1612 return ERROR_NI;
keir@20462 1613 }
keir@20462 1614
anthony@22710 1615 static unsigned int libxl_append_disk_list_of_type(libxl_ctx *ctx,
anthony@22710 1616 uint32_t domid,
anthony@22710 1617 const char *type,
anthony@22710 1618 libxl_device_disk **disks,
anthony@22710 1619 unsigned int *ndisks)
keir@20637 1620 {
ian@22167 1621 libxl__gc gc = LIBXL_INIT_GC(ctx);
anthony@22710 1622 char *be_path = NULL;
anthony@22710 1623 char **dir = NULL;
anthony@22710 1624 unsigned int n = 0, len = 0;
anthony@22710 1625 libxl_device_disk *pdisk = NULL, *pdisk_end = NULL;
anthony@22710 1626 char *physpath_tmp = NULL;
anthony@22710 1627
anthony@22710 1628 be_path = libxl__sprintf(&gc, "%s/backend/%s/%d",
anthony@22710 1629 libxl__xs_get_dompath(&gc, 0), type, domid);
anthony@22710 1630 dir = libxl__xs_directory(&gc, XBT_NULL, be_path, &n);
anthony@22710 1631 if (dir) {
anthony@22710 1632 *disks = realloc(*disks, sizeof (libxl_device_disk) * (*ndisks + n));
anthony@22710 1633 pdisk = *disks + *ndisks;
anthony@22710 1634 *ndisks += n;
anthony@22710 1635 pdisk_end = *disks + *ndisks;
anthony@22710 1636 for (; pdisk < pdisk_end; pdisk++, dir++) {
anthony@22710 1637 pdisk->backend_domid = 0;
anthony@22710 1638 pdisk->domid = domid;
anthony@22710 1639 physpath_tmp = xs_read(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "%s/%s/params", be_path, *dir), &len);
stefano@22854 1640 if (physpath_tmp && strchr(physpath_tmp, ':')) {
anthony@22710 1641 pdisk->physpath = strdup(strchr(physpath_tmp, ':') + 1);
anthony@22710 1642 free(physpath_tmp);
anthony@22710 1643 } else {
anthony@22710 1644 pdisk->physpath = physpath_tmp;
anthony@22710 1645 }
anthony@22710 1646 libxl_string_to_phystype(ctx, libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/type", be_path, *dir)), &(pdisk->phystype));
anthony@22710 1647 pdisk->virtpath = xs_read(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "%s/%s/dev", be_path, *dir), &len);
anthony@22710 1648 pdisk->unpluggable = atoi(libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/removable", be_path, *dir)));
anthony@22710 1649 if (!strcmp(libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/mode", be_path, *dir)), "w"))
anthony@22710 1650 pdisk->readwrite = 1;
keir@20637 1651 else
anthony@22710 1652 pdisk->readwrite = 0;
anthony@22710 1653 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 1654 pdisk->is_cdrom = !strcmp(type, "cdrom");
keir@20637 1655 }
keir@20637 1656 }
anthony@22710 1657
ian@22164 1658 libxl__free_all(&gc);
anthony@22710 1659 return n;
anthony@22710 1660 }
anthony@22710 1661
anthony@22710 1662 libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *num)
anthony@22710 1663 {
anthony@22710 1664 libxl_device_disk *disks = NULL;
anthony@22710 1665 unsigned int ndisks = 0;
anthony@22710 1666
anthony@22710 1667 *num = libxl_append_disk_list_of_type(ctx, domid, "vbd", &disks, &ndisks);
anthony@22710 1668 *num += libxl_append_disk_list_of_type(ctx, domid, "tap", &disks, &ndisks);
anthony@22711 1669 *num += libxl_append_disk_list_of_type(ctx, domid, "qdisk", &disks, &ndisks);
anthony@22710 1670
anthony@22710 1671 return disks;
keir@21411 1672 }
keir@21411 1673
ian@21930 1674 int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
keir@21411 1675 libxl_device_disk *disk, libxl_diskinfo *diskinfo)
keir@21411 1676 {
ian@22167 1677 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@21411 1678 char *dompath, *diskpath;
keir@21411 1679 char *val;
keir@21411 1680
ian@22164 1681 dompath = libxl__xs_get_dompath(&gc, domid);
ian@22165 1682 diskinfo->devid = libxl__device_disk_dev_number(disk->virtpath);
keir@21411 1683
keir@21411 1684 /* tap devices entries in xenstore are written as vbd devices. */
ian@22164 1685 diskpath = libxl__sprintf(&gc, "%s/device/vbd/%d", dompath, diskinfo->devid);
ian@22059 1686 diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
ian@22164 1687 libxl__sprintf(&gc, "%s/backend", diskpath), NULL);
keir@21411 1688 if (!diskinfo->backend) {
ian@22164 1689 libxl__free_all(&gc);
keir@21411 1690 return ERROR_FAIL;
keir@21411 1691 }
ian@22164 1692 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/backend-id", diskpath));
keir@21411 1693 diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
ian@22164 1694 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/state", diskpath));
keir@21411 1695 diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
ian@22164 1696 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/event-channel", diskpath));
keir@21411 1697 diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
ian@22164 1698 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/ring-ref", diskpath));
keir@21411 1699 diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
ian@22059 1700 diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
ian@22164 1701 libxl__sprintf(&gc, "%s/frontend", diskinfo->backend), NULL);
ian@22164 1702 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/frontend-id", diskinfo->backend));
keir@21411 1703 diskinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21411 1704
ian@22164 1705 libxl__free_all(&gc);
keir@21411 1706 return 0;
keir@20637 1707 }
keir@20637 1708
ian@21930 1709 int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20637 1710 {
keir@20637 1711 int num, i;
keir@20637 1712 uint32_t stubdomid;
keir@20637 1713 libxl_device_disk *disks;
ian@22086 1714 int ret = ERROR_FAIL;
keir@20637 1715
keir@20637 1716 if (!disk->physpath) {
kamala@22840 1717 disk->physpath = strdup("");
stefano@22854 1718 disk->phystype = PHYSTYPE_EMPTY;
keir@20637 1719 }
keir@20637 1720 disks = libxl_device_disk_list(ctx, domid, &num);
keir@20637 1721 for (i = 0; i < num; i++) {
keir@20637 1722 if (disks[i].is_cdrom && !strcmp(disk->virtpath, disks[i].virtpath))
keir@20637 1723 /* found */
keir@20637 1724 break;
keir@20637 1725 }
keir@20637 1726 if (i == num) {
ian@22165 1727 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Virtual device not found");
ian@22086 1728 goto out;
keir@20637 1729 }
ian@22086 1730
ian@22086 1731 ret = 0;
ian@22086 1732
keir@20637 1733 libxl_device_disk_del(ctx, disks + i, 1);
keir@20637 1734 libxl_device_disk_add(ctx, domid, disk);
keir@20637 1735 stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20637 1736 if (stubdomid) {
keir@20781 1737 disks[i].domid = stubdomid;
keir@20637 1738 libxl_device_disk_del(ctx, disks + i, 1);
keir@20781 1739 disk->domid = stubdomid;
keir@20637 1740 libxl_device_disk_add(ctx, stubdomid, disk);
keir@20781 1741 disk->domid = domid;
keir@20637 1742 }
ian@22086 1743 out:
ian@22086 1744 for (i = 0; i < num; i++)
ian@22086 1745 libxl_device_disk_destroy(&disks[i]);
gianni@22023 1746 free(disks);
ian@22086 1747 return ret;
keir@20637 1748 }
keir@20637 1749
keir@20462 1750 /******************************************************************************/
gianni@22768 1751 void libxl_device_vfb_init(libxl_device_vfb *vfb, int dev_num)
gianni@22768 1752 {
gianni@22768 1753 memset(vfb, 0x00, sizeof(libxl_device_vfb));
gianni@22768 1754 vfb->devid = dev_num;
gianni@22768 1755 vfb->display = NULL;
gianni@22768 1756 vfb->xauthority = NULL;
gianni@22768 1757 vfb->vnc = 1;
gianni@22768 1758 vfb->vncpasswd = NULL;
gianni@22768 1759 vfb->vnclisten = strdup("127.0.0.1");
gianni@22768 1760 vfb->vncdisplay = 0;
gianni@22768 1761 vfb->vncunused = 1;
gianni@22768 1762 vfb->keymap = NULL;
gianni@22768 1763 vfb->sdl = 0;
gianni@22768 1764 vfb->opengl = 0;
gianni@22768 1765 }
gianni@22768 1766
ian@21930 1767 int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
keir@20462 1768 {
ian@22167 1769 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@20509 1770 flexarray_t *front;
keir@20509 1771 flexarray_t *back;
ian@22167 1772 libxl__device device;
gianni@22023 1773 int rc;
keir@20509 1774
keir@20509 1775 front = flexarray_make(16, 1);
gianni@22023 1776 if (!front) {
gianni@22023 1777 rc = ERROR_NOMEM;
gianni@22023 1778 goto out;
gianni@22023 1779 }
keir@20509 1780 back = flexarray_make(16, 1);
gianni@22023 1781 if (!back) {
gianni@22023 1782 rc = ERROR_NOMEM;
gianni@22023 1783 goto out_free;
gianni@22023 1784 }
keir@20509 1785
keir@20509 1786 device.backend_devid = vfb->devid;
keir@20509 1787 device.backend_domid = vfb->backend_domid;
keir@20509 1788 device.backend_kind = DEVICE_VFB;
keir@20509 1789 device.devid = vfb->devid;
keir@20509 1790 device.domid = vfb->domid;
keir@20509 1791 device.kind = DEVICE_VFB;
keir@20509 1792
gianni@22726 1793 flexarray_vappend(back, "frontend-id", libxl__sprintf(&gc, "%d", vfb->domid), NULL);
gianni@22726 1794 flexarray_vappend(back, "online", "1", NULL);
gianni@22726 1795 flexarray_vappend(back, "state", libxl__sprintf(&gc, "%d", 1), NULL);
gianni@22726 1796 flexarray_vappend(back, "domain", libxl__domid_to_name(&gc, domid), NULL);
gianni@22726 1797 flexarray_vappend(back, "vnc", libxl__sprintf(&gc, "%d", vfb->vnc), NULL);
gianni@22726 1798 flexarray_vappend(back, "vnclisten", vfb->vnclisten, NULL);
gianni@22726 1799 flexarray_append(back, "vncpasswd");
gianni@22726 1800 flexarray_append(back, vfb->vncpasswd);
gianni@22726 1801 flexarray_vappend(back, "vncdisplay", libxl__sprintf(&gc, "%d", vfb->vncdisplay), NULL);
gianni@22726 1802 flexarray_vappend(back, "vncunused", libxl__sprintf(&gc, "%d", vfb->vncunused), NULL);
gianni@22726 1803 flexarray_vappend(back, "sdl", libxl__sprintf(&gc, "%d", vfb->sdl), NULL);
gianni@22726 1804 flexarray_vappend(back, "opengl", libxl__sprintf(&gc, "%d", vfb->opengl), NULL);
keir@20509 1805 if (vfb->xauthority) {
gianni@22726 1806 flexarray_vappend(back, "xauthority", vfb->xauthority, NULL);
keir@20509 1807 }
keir@20509 1808 if (vfb->display) {
gianni@22726 1809 flexarray_vappend(back, "display", vfb->display, NULL);
keir@20509 1810 }
keir@20509 1811
gianni@22726 1812 flexarray_vappend(front, "backend-id", libxl__sprintf(&gc, "%d", vfb->backend_domid), NULL);
gianni@22726 1813 flexarray_vappend(front, "state", libxl__sprintf(&gc, "%d", 1), NULL);
ian@22164 1814
ian@22164 1815 libxl__device_generic_add(ctx, &device,
gianni@22726 1816 libxl__xs_kvs_of_flexarray(&gc, back, back->count),
gianni@22726 1817 libxl__xs_kvs_of_flexarray(&gc, front, front->count));
gianni@22023 1818 rc = 0;
gianni@22023 1819 out_free:
keir@20509 1820 flexarray_free(front);
keir@20509 1821 flexarray_free(back);
gianni@22023 1822 out:
ian@22164 1823 libxl__free_all(&gc);
gianni@22023 1824 return rc;
keir@20462 1825 }
keir@20462 1826
ian@21930 1827 int libxl_device_vfb_clean_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 1828 {
keir@20462 1829 return ERROR_NI;
keir@20462 1830 }
keir@20462 1831
ian@21930 1832 int libxl_device_vfb_hard_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 1833 {
keir@20462 1834 return ERROR_NI;
keir@20462 1835 }
keir@20462 1836
keir@20462 1837 /******************************************************************************/
keir@20482 1838
ian@21930 1839 int libxl_domain_setmaxmem(libxl_ctx *ctx, uint32_t domid, uint32_t max_memkb)
keir@21404 1840 {
ian@22167 1841 libxl__gc gc = LIBXL_INIT_GC(ctx);
keir@21404 1842 char *mem, *endptr;
keir@21404 1843 uint32_t memorykb;
ian@22164 1844 char *dompath = libxl__xs_get_dompath(&gc, domid);
gianni@22023 1845 int rc = 1;
gianni@22023 1846
ian@22164 1847 mem = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/memory/target", dompath));
keir@21404 1848 if (!mem) {
ian@22165 1849 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot get memory info from %s/memory/target\n", dompath);
gianni@22023 1850 goto out;
keir@21404 1851 }
keir@21404 1852 memorykb = strtoul(mem, &endptr, 10);
keir@21404 1853 if (*endptr != '\0') {
ian@22165 1854 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "invalid memory %s from %s/memory/target\n", mem, dompath);
gianni@22023 1855 goto out;
keir@21404 1856 }
keir@21404 1857
keir@21404 1858 if (max_memkb < memorykb) {
ian@22165 1859 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "memory_static_max must be greater than or or equal to memory_dynamic_max\n");
gianni@22023 1860 goto out;
keir@21404 1861 }
keir@21404 1862
gianni@22023 1863 rc = 0;
gianni@22023 1864 out:
ian@22164 1865 libxl__free_all(&gc);
gianni@22023 1866 return rc;
keir@21404 1867 }
keir@21404 1868
stefano@22244 1869 static int libxl__fill_dom0_memory_info(libxl__gc *gc, uint32_t *target_memkb)
stefano@22244 1870 {
stefano@22244 1871 int rc;
stefano@22244 1872 libxl_dominfo info;
stefano@22245 1873 libxl_physinfo physinfo;
stefano@22567 1874 char *target = NULL, *staticmax = NULL, *freememslack = NULL, *endptr = NULL;
stefano@22244 1875 char *target_path = "/local/domain/0/memory/target";
stefano@22244 1876 char *max_path = "/local/domain/0/memory/static-max";
stefano@22245 1877 char *free_mem_slack_path = "/local/domain/0/memory/freemem-slack";
stefano@22244 1878 xs_transaction_t t;
stefano@22244 1879 libxl_ctx *ctx = libxl__gc_owner(gc);
stefano@22567 1880 uint32_t free_mem_slack_kb = 0;
stefano@22244 1881
stefano@22244 1882 retry_transaction:
stefano@22244 1883 t = xs_transaction_start(ctx->xsh);
stefano@22244 1884
stefano@22244 1885 target = libxl__xs_read(gc, t, target_path);
ewalsh@22705 1886 staticmax = libxl__xs_read(gc, t, max_path);
ewalsh@22705 1887 freememslack = libxl__xs_read(gc, t, free_mem_slack_path);
stefano@22567 1888 if (target && staticmax && freememslack) {
stefano@22567 1889 rc = 0;
stefano@22567 1890 goto out;
stefano@22567 1891 }
stefano@22567 1892
stefano@22244 1893 if (target) {
stefano@22244 1894 *target_memkb = strtoul(target, &endptr, 10);
stefano@22244 1895 if (*endptr != '\0') {
stefano@22244 1896 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 1897 "invalid memory target %s from %s\n", target, target_path);
stefano@22244 1898 rc = ERROR_FAIL;
stefano@22244 1899 goto out;
stefano@22244 1900 }
stefano@22244 1901 }
stefano@22244 1902
stefano@22244 1903 rc = libxl_domain_info(ctx, &info, 0);
stefano@22244 1904 if (rc < 0)
stefano@22567 1905 goto out;
stefano@22244 1906
stefano@22245 1907 rc = libxl_get_physinfo(ctx, &physinfo);
stefano@22245 1908 if (rc < 0)
stefano@22567 1909 goto out;
stefano@22567 1910
stefano@22567 1911 if (target == NULL) {
stefano@22567 1912 libxl__xs_write(gc, t, target_path, "%"PRIu32,
stefano@22567 1913 (uint32_t) info.current_memkb);
stefano@22567 1914 *target_memkb = (uint32_t) info.current_memkb;
stefano@22567 1915 }
stefano@22567 1916 if (staticmax == NULL)
stefano@22567 1917 libxl__xs_write(gc, t, max_path, "%"PRIu32,
stefano@22567 1918 (uint32_t) info.max_memkb);
stefano@22567 1919
stefano@22567 1920 if (freememslack == NULL) {
stefano@22567 1921 free_mem_slack_kb = (uint32_t) (PAGE_TO_MEMKB(physinfo.total_pages) -
stefano@22567 1922 info.current_memkb);
stefano@22567 1923 /* From empirical measurements the free_mem_slack shouldn't be more
stefano@22567 1924 * than 15% of the total memory present on the system. */
stefano@22567 1925 if (free_mem_slack_kb > PAGE_TO_MEMKB(physinfo.total_pages) * 0.15)
stefano@22567 1926 free_mem_slack_kb = PAGE_TO_MEMKB(physinfo.total_pages) * 0.15;
stefano@22567 1927 libxl__xs_write(gc, t, free_mem_slack_path, "%"PRIu32, free_mem_slack_kb);
stefano@22567 1928 }
stefano@22244 1929 rc = 0;
stefano@22244 1930
stefano@22244 1931 out:
stefano@22567 1932 if (!xs_transaction_end(ctx->xsh, t, 0)) {
stefano@22244 1933 if (errno == EAGAIN)
stefano@22244 1934 goto retry_transaction;
stefano@22567 1935 else
stefano@22567 1936 rc = ERROR_FAIL;
stefano@22567 1937 }
stefano@22244 1938
stefano@22244 1939
stefano@22244 1940 return rc;
stefano@22244 1941 }
stefano@22244 1942
stefano@22245 1943 /* returns how much memory should be left free in the system */
stefano@22245 1944 static int libxl__get_free_memory_slack(libxl__gc *gc, uint32_t *free_mem_slack)
stefano@22245 1945 {
stefano@22245 1946 int rc;
stefano@22245 1947 char *free_mem_slack_path = "/local/domain/0/memory/freemem-slack";
stefano@22245 1948 char *free_mem_slack_s, *endptr;
stefano@22245 1949 uint32_t target_memkb;
stefano@22245 1950
stefano@22245 1951 retry:
stefano@22245 1952 free_mem_slack_s = libxl__xs_read(gc, XBT_NULL, free_mem_slack_path);
stefano@22245 1953 if (!free_mem_slack_s) {
stefano@22245 1954 rc = libxl__fill_dom0_memory_info(gc, &target_memkb);
stefano@22245 1955 if (rc < 0)
stefano@22245 1956 return rc;
stefano@22245 1957 goto retry;
stefano@22245 1958 } else {
stefano@22245 1959 *free_mem_slack = strtoul(free_mem_slack_s, &endptr, 10);
stefano@22245 1960 if (*endptr != '\0') {
stefano@22245 1961 LIBXL__LOG_ERRNO(gc->owner, LIBXL__LOG_ERROR,
stefano@22245 1962 "invalid free_mem_slack %s from %s\n",
stefano@22245 1963 free_mem_slack_s, free_mem_slack_path);
stefano@22245 1964 return ERROR_FAIL;
stefano@22245 1965 }
stefano@22245 1966 }
stefano@22245 1967 return 0;
stefano@22245 1968 }
stefano@22245 1969
stefano@22244 1970 int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid,
stefano@22244 1971 int32_t target_memkb, int relative, int enforce)
keir@20647 1972 {
ian@22167 1973 libxl__gc gc = LIBXL_INIT_GC(ctx);
stefano@22243 1974 int rc = 1, abort = 0;
stefano@22244 1975 uint32_t memorykb = 0, videoram = 0;
stefano@22244 1976 uint32_t current_target_memkb = 0, new_target_memkb = 0;
stefano@22244 1977 char *memmax, *endptr, *videoram_s = NULL, *target = NULL;
ian@22164 1978 char *dompath = libxl__xs_get_dompath(&gc, domid);
keir@21374 1979 xc_domaininfo_t info;
ian@21930 1980 libxl_dominfo ptr;
keir@21374 1981 char *uuid;
stefano@22243 1982 xs_transaction_t t;
stefano@22243 1983
stefano@22243 1984 retry_transaction:
stefano@22243 1985 t = xs_transaction_start(ctx->xsh);
stefano@22243 1986
stefano@22244 1987 target = libxl__xs_read(&gc, t, libxl__sprintf(&gc,
stefano@22244 1988 "%s/memory/target", dompath));
stefano@22244 1989 if (!target && !domid) {
stefano@22244 1990 xs_transaction_end(ctx->xsh, t, 1);
stefano@22244 1991 rc = libxl__fill_dom0_memory_info(&gc, &current_target_memkb);
stefano@22244 1992 if (rc < 0) {
stefano@22244 1993 abort = 1;
stefano@22244 1994 goto out;
stefano@22244 1995 }
stefano@22244 1996 goto retry_transaction;
stefano@22244 1997 } else if (!target) {
stefano@22244 1998 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 1999 "cannot get target memory info from %s/memory/target\n",
stefano@22244 2000 dompath);
stefano@22244 2001 abort = 1;
stefano@22244 2002 goto out;
stefano@22244 2003 } else {
stefano@22244 2004 current_target_memkb = strtoul(target, &endptr, 10);
stefano@22244 2005 if (*endptr != '\0') {
ian@22165 2006 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 2007 "invalid memory target %s from %s/memory/target\n",
stefano@22244 2008 target, dompath);
stefano@22243 2009 abort = 1;
gianni@22023 2010 goto out;
keir@21405 2011 }
keir@21405 2012 }
stefano@22244 2013 memmax = libxl__xs_read(&gc, t, libxl__sprintf(&gc,
stefano@22244 2014 "%s/memory/static-max", dompath));
stefano@22244 2015 if (!memmax) {
stefano@22244 2016 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 2017 "cannot get memory info from %s/memory/static-max\n",
stefano@22244 2018 dompath);
stefano@22244 2019 abort = 1;
stefano@22244 2020 goto out;
stefano@22244 2021 }
stefano@22244 2022 memorykb = strtoul(memmax, &endptr, 10);
stefano@22244 2023 if (*endptr != '\0') {
stefano@22244 2024 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 2025 "invalid max memory %s from %s/memory/static-max\n",
stefano@22244 2026 memmax, dompath);
stefano@22244 2027 abort = 1;
stefano@22244 2028 goto out;
stefano@22244 2029 }
stefano@22244 2030
stefano@22244 2031 if (relative)
stefano@22244 2032 new_target_memkb = current_target_memkb + target_memkb;
stefano@22244 2033 else
stefano@22244 2034 new_target_memkb = target_memkb;
stefano@22244 2035 if (new_target_memkb > memorykb) {
stefano@22244 2036 LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
stefano@22244 2037 "memory_dynamic_max must be less than or equal to"
stefano@22244 2038 " memory_static_max\n");
stefano@22244 2039 abort = 1;
stefano@22244 2040 goto out;
stefano@22244 2041 }
stefano@22244 2042
gianni@22367 2043 if (!domid && new_target_memkb < LIBXL_MIN_DOM0_MEM) {
gianni@22367 2044 LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
gianni@22367 2045 "new target %d for dom0 is below the minimum threshold\n",
gianni@22367 2046 new_target_memkb);
gianni@22367 2047 abort = 1;
gianni@22367 2048 goto out;
gianni@22367 2049 }
stefano@22244 2050 videoram_s = libxl__xs_read(&gc, t, libxl__sprintf(&gc,
stefano@22244 2051 "%s/memory/videoram", dompath));
stefano@22244 2052 videoram = videoram_s ? atoi(videoram_s) : 0;
stefano@22244 2053
stefano@22244 2054 if (enforce) {
stefano@22244 2055 memorykb = new_target_memkb;
stefano@22244 2056 rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb +
stefano@22244 2057 LIBXL_MAXMEM_CONSTANT);
stefano@22244 2058 if (rc != 0) {
stefano@22244 2059 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 2060 "xc_domain_setmaxmem domid=%d memkb=%d failed "
stefano@22244 2061 "rc=%d\n", domid, memorykb + LIBXL_MAXMEM_CONSTANT, rc);
stefano@22244 2062 abort = 1;
stefano@22244 2063 goto out;
stefano@22244 2064 }
stefano@22244 2065 }
stefano@22244 2066
stefano@22251 2067 new_target_memkb -= videoram;
ian@22294 2068 rc = xc_domain_set_pod_target(ctx->xch, domid,
stefano@22251 2069 new_target_memkb / 4, NULL, NULL, NULL);
stefano@22243 2070 if (rc != 0) {
stefano@22243 2071 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
ian@22294 2072 "xc_domain_set_pod_target domid=%d, memkb=%d "
stefano@22251 2073 "failed rc=%d\n", domid, new_target_memkb / 4,
stefano@22243 2074 rc);
stefano@22243 2075 abort = 1;
stefano@22243 2076 goto out;
stefano@22243 2077 }
stefano@22243 2078
stefano@22244 2079 libxl__xs_write(&gc, t, libxl__sprintf(&gc, "%s/memory/target",
stefano@22244 2080 dompath), "%"PRIu32, new_target_memkb);
keir@21374 2081 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &info);
stefano@22243 2082 if (rc != 1 || info.domain != domid) {
stefano@22243 2083 abort = 1;
gianni@22023 2084 goto out;
stefano@22243 2085 }
keir@21374 2086 xcinfo2xlinfo(&info, &ptr);
ian@22164 2087 uuid = libxl__uuid2string(&gc, ptr.uuid);
stefano@22244 2088 libxl__xs_write(&gc, t, libxl__sprintf(&gc, "/vm/%s/memory", uuid),
stefano@22244 2089 "%"PRIu32, new_target_memkb / 1024);
gianni@22023 2090
gianni@22023 2091 out:
stefano@22243 2092 if (!xs_transaction_end(ctx->xsh, t, abort) && !abort)
stefano@22243 2093 if (errno == EAGAIN)
stefano@22243 2094 goto retry_transaction;
stefano@22243 2095
ian@22164 2096 libxl__free_all(&gc);
keir@20647 2097 return rc;
keir@20647 2098 }
keir@20875 2099
stefano@22244 2100 int libxl_get_memory_target(libxl_ctx *ctx, uint32_t domid, uint32_t *out_target)
stefano@22244 2101 {
stefano@22244 2102 libxl__gc gc = LIBXL_INIT_GC(ctx);
stefano@22244 2103 int rc = 1;
stefano@22244 2104 char *target = NULL, *endptr = NULL;
stefano@22244 2105 char *dompath = libxl__xs_get_dompath(&gc, domid);
stefano@22244 2106 uint32_t target_memkb;
stefano@22244 2107
stefano@22244 2108 target = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc,
stefano@22244 2109 "%s/memory/target", dompath));
stefano@22244 2110 if (!target && !domid) {
stefano@22244 2111 rc = libxl__fill_dom0_memory_info(&gc, &target_memkb);
stefano@22244 2112 if (rc < 0)
stefano@22244 2113 goto out;
stefano@22244 2114 } else if (!target) {
stefano@22244 2115 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 2116 "cannot get target memory info from %s/memory/target\n",
stefano@22244 2117 dompath);
stefano@22244 2118 goto out;
stefano@22244 2119 } else {
stefano@22244 2120 target_memkb = strtoul(target, &endptr, 10);
stefano@22244 2121 if (*endptr != '\0') {
stefano@22244 2122 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
stefano@22244 2123 "invalid memory target %s from %s/memory/target\n",
stefano@22244 2124 target, dompath);
stefano@22244 2125 goto out;
stefano@22244 2126 }
stefano@22244 2127 }
stefano@22244 2128 *out_target = target_memkb;
stefano@22244 2129 rc = 0;
stefano@22244 2130
stefano@22244 2131 out:
stefano@22244 2132 libxl__free_all(&gc);
stefano@22244 2133 return rc;
stefano@22244 2134 }
stefano@22244 2135
stefano@22245 2136 int libxl_domain_need_memory(libxl_ctx *ctx, libxl_domain_build_info *b_info,
stefano@22245 2137 libxl_device_model_info *dm_info, uint32_t *need_memkb)
stefano@22245 2138 {
stefano@22245 2139 *need_memkb = b_info->target_memkb;
stefano@22245 2140 if (b_info->hvm) {
stefano@22245 2141 *need_memkb += b_info->shadow_memkb + LIBXL_HVM_EXTRA_MEMORY;
stefano@22245 2142 if (strstr(dm_info->device_model, "stubdom-dm"))
stefano@22245 2143 *need_memkb += 32 * 1024;
stefano@22245 2144 } else
stefano@22469 2145 *need_memkb += b_info->shadow_memkb + LIBXL_PV_EXTRA_MEMORY;
stefano@22245 2146 if (*need_memkb % (2 * 1024))
stefano@22245 2147 *need_memkb += (2 * 1024) - (*need_memkb % (2 * 1024));
stefano@22245 2148 return 0;
stefano@22245 2149 }
stefano@22245 2150
stefano@22245 2151 int libxl_get_free_memory(libxl_ctx *ctx, uint32_t *memkb)
stefano@22245 2152 {
stefano@22245 2153 int rc = 0;
stefano@22245 2154 libxl_physinfo info;
stefano@22245 2155 uint32_t freemem_slack;
stefano@22245 2156 libxl__gc gc = LIBXL_INIT_GC(ctx);
stefano@22245 2157
stefano@22245 2158 rc = libxl_get_physinfo(ctx, &info);
stefano@22245 2159 if (rc < 0)
stefano@22245 2160 goto out;
stefano@22245 2161 rc = libxl__get_free_memory_slack(&gc, &freemem_slack);
stefano@22245 2162 if (rc < 0)
stefano@22245 2163 goto out;
stefano@22245 2164
stefano@22245 2165 if ((info.free_pages + info.scrub_pages) * 4 > freemem_slack)
stefano@22245 2166 *memkb = (info.free_pages + info.scrub_pages) * 4 - freemem_slack;
stefano@22245 2167 else
stefano@22245 2168 *memkb = 0;
stefano@22245 2169
stefano@22245 2170 out:
stefano@22245 2171 libxl__free_all(&gc);
stefano@22245 2172 return rc;
stefano@22245 2173 }
stefano@22245 2174
stefano@22245 2175 int libxl_wait_for_free_memory(libxl_ctx *ctx, uint32_t domid, uint32_t
stefano@22245 2176 memory_kb, int wait_secs)
stefano@22245 2177 {
stefano@22245 2178 int rc = 0;
stefano@22245 2179 libxl_physinfo info;
stefano@22245 2180 uint32_t freemem_slack;
stefano@22245 2181 libxl__gc gc = LIBXL_INIT_GC(ctx);
stefano@22245 2182
stefano@22245 2183 rc = libxl__get_free_memory_slack(&gc, &freemem_slack);
stefano@22245 2184 if (rc < 0)
stefano@22245 2185 goto out;
stefano@22245 2186 while (wait_secs > 0) {
stefano@22245 2187 rc = libxl_get_physinfo(ctx, &info);
stefano@22245 2188 if (rc < 0)
stefano@22245 2189 goto out;
stefano@22245 2190 if (info.free_pages * 4 - freemem_slack >= memory_kb) {
stefano@22245 2191 rc = 0;
stefano@22245 2192 goto out;
stefano@22245 2193 }
stefano@22245 2194 wait_secs--;
stefano@22245 2195 sleep(1);
stefano@22245 2196 }
stefano@22245 2197 rc = ERROR_NOMEM;
stefano@22245 2198
stefano@22245 2199 out:
stefano@22245 2200 libxl__free_all(&gc);
stefano@22245 2201 return rc;
stefano@22245 2202 }
stefano@22245 2203
stefano@22245 2204 int libxl_wait_for_memory_target(libxl_ctx *ctx, uint32_t domid, int wait_secs)
stefano@22245 2205 {
stefano@22245 2206 int rc = 0;
stefano@22245 2207 uint32_t target_memkb = 0;
stefano@22245 2208 libxl_dominfo info;
stefano@22245 2209
stefano@22245 2210 do {
stefano@22245 2211 wait_secs--;
stefano@22245 2212 sleep(1);
stefano@22245 2213
stefano@22245 2214 rc = libxl_get_memory_target(ctx, domid, &target_memkb);
stefano@22245 2215 if (rc < 0)
stefano@22245 2216 goto out;
stefano@22245 2217
stefano@22245 2218 rc = libxl_domain_info(ctx, &info, domid);
stefano@22245 2219 if (rc < 0)
stefano@22245 2220 return rc;
stefano@22245 2221 } while (wait_secs > 0 && info.current_memkb > target_memkb);
stefano@22245 2222
stefano@22245 2223 if (info.current_memkb <= target_memkb)
stefano@22245 2224 rc = 0;
stefano@22245 2225 else
stefano@22245 2226 rc = ERROR_FAIL;
stefano@22245 2227
stefano@22245 2228 out:
stefano@22245 2229 return 0;
stefano@22245 2230 }
stefano@22245 2231
ian@21930 2232 int libxl_button_press(libxl_ctx *ctx, uint32_t domid, libxl_button button)
keir@20875 2233 {
keir@20875 2234 int rc = -1;
keir@20875 2235
keir@20875 2236 switch (button) {
keir@20875 2237 case POWER_BUTTON:
keir@20875 2238 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_POWER, 0);
keir@20875 2239 break;
keir@20875 2240 case SLEEP_BUTTON:
keir@20875 2241 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_SLEEP, 0);
keir@20875 2242 break;
keir@20875 2243 default:
keir@20875 2244 break;
keir@20875 2245 }
keir@20875 2246
keir@20875 2247 return rc;
keir@20875 2248 }
keir@21141 2249
ian@21930 2250 int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
keir@21141 2251 {
keir@21141 2252 xc_physinfo_t xcphysinfo = { 0 };
keir@21141 2253 int rc;
keir@21141 2254
keir@21141 2255 rc = xc_physinfo(ctx->xch, &xcphysinfo);
keir@21141 2256 if (rc != 0) {
ian@22165 2257 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting physinfo");
gianni@21892 2258 return ERROR_FAIL;
keir@21141 2259 }
keir@21141 2260 physinfo->threads_per_core = xcphysinfo.threads_per_core;
keir@21141 2261 physinfo->cores_per_socket = xcphysinfo.cores_per_socket;
keir@21142 2262 physinfo->max_cpu_id = xcphysinfo.max_cpu_id;
keir@21141 2263 physinfo->nr_cpus = xcphysinfo.nr_cpus;
keir@21141 2264 physinfo->cpu_khz = xcphysinfo.cpu_khz;
keir@21141 2265 physinfo->total_pages = xcphysinfo.total_pages;
keir@21141 2266 physinfo->free_pages = xcphysinfo.free_pages;
keir@21141 2267 physinfo->scrub_pages = xcphysinfo.scrub_pages;
keir@21264 2268 physinfo->nr_nodes = xcphysinfo.nr_nodes;
keir@21264 2269 memcpy(physinfo->hw_cap,xcphysinfo.hw_cap, sizeof(physinfo->hw_cap));
keir@21264 2270 physinfo->phys_cap = xcphysinfo.capabilities;
keir@21264 2271
keir@21141 2272 return 0;
keir@21141 2273 }
keir@21141 2274
juergen@22648 2275 int libxl_get_topologyinfo(libxl_ctx *ctx, libxl_topologyinfo *info)
juergen@22648 2276 {
juergen@22648 2277 xc_topologyinfo_t tinfo;
juergen@22648 2278 DECLARE_HYPERCALL_BUFFER(xc_cpu_to_core_t, coremap);
juergen@22648 2279 DECLARE_HYPERCALL_BUFFER(xc_cpu_to_socket_t, socketmap);
juergen@22648 2280 DECLARE_HYPERCALL_BUFFER(xc_cpu_to_node_t, nodemap);
juergen@22648 2281 int i;
juergen@22648 2282 int rc = 0;
juergen@22648 2283
juergen@22648 2284 rc += libxl_cpuarray_alloc(ctx, &info->coremap);
juergen@22648 2285 rc += libxl_cpuarray_alloc(ctx, &info->socketmap);
juergen@22648 2286 rc += libxl_cpuarray_alloc(ctx, &info->nodemap);
juergen@22648 2287 if (rc)
juergen@22648 2288 goto fail;
juergen@22648 2289
juergen@22648 2290 coremap = xc_hypercall_buffer_alloc(ctx->xch, coremap, sizeof(*coremap) * info->coremap.entries);
juergen@22648 2291 socketmap = xc_hypercall_buffer_alloc(ctx->xch, socketmap, sizeof(*socketmap) * info->socketmap.entries);
juergen@22648 2292 nodemap = xc_hypercall_buffer_alloc(ctx->xch, nodemap, sizeof(*nodemap) * info->nodemap.entries);
juergen@22648 2293 if ((coremap == NULL) || (socketmap == NULL) || (nodemap == NULL))
juergen@22648 2294 goto fail;
juergen@22648 2295
juergen@22648 2296 set_xen_guest_handle(tinfo.cpu_to_core, coremap);
juergen@22648 2297 set_xen_guest_handle(tinfo.cpu_to_socket, socketmap);
juergen@22648 2298 set_xen_guest_handle(tinfo.cpu_to_node, nodemap);
juergen@22648 2299 tinfo.max_cpu_index = info->coremap.entries - 1;
juergen@22648 2300 if (xc_topologyinfo(ctx->xch, &tinfo) != 0)
juergen@22648 2301 goto fail;
juergen@22648 2302
juergen@22648 2303 for (i = 0; i <= tinfo.max_cpu_index; i++) {
juergen@22648 2304 if (i < info->coremap.entries)
juergen@22648 2305 info->coremap.array[i] = (coremap[i] == INVALID_TOPOLOGY_ID) ?
juergen@22648 2306 LIBXL_CPUARRAY_INVALID_ENTRY : coremap[i];
juergen@22648 2307 if (i < info->socketmap.entries)
juergen@22648 2308 info->socketmap.array[i] = (socketmap[i] == INVALID_TOPOLOGY_ID) ?
juergen@22648 2309 LIBXL_CPUARRAY_INVALID_ENTRY : socketmap[i];
juergen@22648 2310 if (i < info->nodemap.entries)
juergen@22648 2311 info->nodemap.array[i] = (nodemap[i] == INVALID_TOPOLOGY_ID) ?
juergen@22648 2312 LIBXL_CPUARRAY_INVALID_ENTRY : nodemap[i];
juergen@22648 2313 }
juergen@22648 2314
juergen@22648 2315 xc_hypercall_buffer_free(ctx->xch, coremap);
juergen@22648 2316 xc_hypercall_buffer_free(ctx->xch, socketmap);
juergen@22648 2317 xc_hypercall_buffer_free(ctx->xch, nodemap);
juergen@22648 2318 return 0;
juergen@22648 2319
juergen@22648 2320 fail:
juergen@22648 2321 xc_hypercall_buffer_free(ctx->xch, coremap);
juergen@22648 2322 xc_hypercall_buffer_free(ctx->xch, socketmap);
juergen@22648 2323 xc_hypercall_buffer_free(ctx->xch, nodemap);
juergen@22648 2324 libxl_topologyinfo_destroy(info);
juergen@22648 2325 return ERROR_FAIL;
juergen@22648 2326 }
juergen@22648 2327
ian@21930 2328 const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx)
keir@21266 2329 {
keir@21266 2330 union {
keir@21266 2331 xen_extraversion_t xen_extra;
keir@21266 2332 xen_compile_info_t xen_cc;
keir@21266 2333 xen_changeset_info_t xen_chgset;
keir@21266 2334 xen_capabilities_info_t xen_caps;
keir@21266 2335 xen_platform_parameters_t p_parms;
keir@21266 2336 xen_commandline_t xen_commandline;
keir@21266 2337 } u;
keir@21266 2338 long xen_version;
keir@21266 2339 libxl_version_info *info = &ctx->version_info;
keir@21266 2340
keir@21266 2341 if (info->xen_version_extra != NULL)
keir@21266 2342 return info;
keir@21266 2343
keir@21266 2344 xen_version = xc_version(ctx->xch, XENVER_version, NULL);
keir@21266 2345 info->xen_version_major = xen_version >> 16;
keir@21266 2346 info->xen_version_minor = xen_version & 0xFF;
gianni@22008 2347
keir@21266 2348 xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra);
gianni@22008 2349 info->xen_version_extra = strdup(u.xen_extra);
keir@21266 2350
keir@21266 2351 xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc);
gianni@22008 2352 info->compiler = strdup(u.xen_cc.compiler);
gianni@22008 2353 info->compile_by = strdup(u.xen_cc.compile_by);
gianni@22008 2354 info->compile_domain = strdup(u.xen_cc.compile_domain);
gianni@22008 2355 info->compile_date = strdup(u.xen_cc.compile_date);
keir@21266 2356
keir@21266 2357 xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps);
gianni@22008 2358 info->capabilities = strdup(u.xen_caps);
keir@21266 2359
keir@21266 2360 xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset);
gianni@22008 2361 info->changeset = strdup(u.xen_chgset);
keir@21266 2362
keir@21266 2363 xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms);
keir@21266 2364 info->virt_start = u.p_parms.virt_start;
keir@21266 2365
keir@21266 2366 info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL);
keir@21266 2367
keir@21266 2368 xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline);
gianni@22008 2369 info->commandline = strdup(u.xen_commandline);
keir@21266 2370
keir@21266 2371 return info;
keir@21266 2372 }
keir@21266 2373
ian@21930 2374 libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid,
sstabellini@22000 2375 int *nb_vcpu, int *nrcpus)
keir@21141 2376 {
ian@21930 2377 libxl_vcpuinfo *ptr, *ret;
keir@21141 2378 xc_domaininfo_t domaininfo;
keir@21141 2379 xc_vcpuinfo_t vcpuinfo;
keir@21141 2380
keir@21141 2381 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
ian@22165 2382 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting infolist");
keir@21141 2383 return NULL;
keir@21141 2384 }
juergen@22396 2385 *nrcpus = libxl_get_max_cpus(ctx);
gianni@22015 2386 ret = ptr = calloc(domaininfo.max_vcpu_id + 1, sizeof (libxl_vcpuinfo));
keir@21141 2387 if (!ptr) {
keir@21141 2388 return NULL;
keir@21141 2389 }
keir@21141 2390
keir@21141 2391 for (*nb_vcpu = 0; *nb_vcpu <= domaininfo.max_vcpu_id; ++*nb_vcpu, ++ptr) {
juergen@22396 2392 if (libxl_cpumap_alloc(ctx, &ptr->cpumap)) {
juergen@22319 2393 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating cpumap");
keir@21141 2394 return NULL;
keir@21141 2395 }
keir@21141 2396 if (xc_vcpu_getinfo(ctx->xch, domid, *nb_vcpu, &vcpuinfo) == -1) {
ian@22165 2397 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting vcpu info");
keir@21141 2398 return NULL;
keir@21141 2399 }
juergen@22396 2400 if (xc_vcpu_getaffinity(ctx->xch, domid, *nb_vcpu, ptr->cpumap.map) == -1) {
ian@22165 2401 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting vcpu affinity");
keir@21141 2402 return NULL;
keir@21141 2403 }
keir@21141 2404 ptr->vcpuid = *nb_vcpu;
keir@21141 2405 ptr->cpu = vcpuinfo.cpu;
keir@21141 2406 ptr->online = !!vcpuinfo.online;
keir@21141 2407 ptr->blocked = !!vcpuinfo.blocked;
keir@21141 2408 ptr->running = !!vcpuinfo.running;
keir@21141 2409 ptr->vcpu_time = vcpuinfo.cpu_time;
keir@21141 2410 }
keir@21141 2411 return ret;
keir@21141 2412 }
keir@21142 2413
ian@21930 2414 int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
juergen@22396 2415 libxl_cpumap *cpumap)
keir@21142 2416 {
juergen@22396 2417 if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, cpumap->map)) {
ian@22165 2418 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting vcpu affinity");
gianni@21892 2419 return ERROR_FAIL;
gianni@21892 2420 }
gianni@21892 2421 return 0;
keir@21142 2422 }
keir@21143 2423
stefano@22121 2424 int libxl_set_vcpuonline(libxl_ctx *ctx, uint32_t domid, uint32_t bitmask)
keir@21143 2425 {
ian@22167 2426 libxl__gc gc = LIBXL_INIT_GC(ctx);
stefano@22121 2427 libxl_dominfo info;
keir@21143 2428 char *dompath;
stefano@22121 2429 xs_transaction_t t;
gianni@22023 2430 int i, rc = ERROR_FAIL;
keir@21143 2431
stefano@22121 2432 if (libxl_domain_info(ctx, &info, domid) < 0) {
ian@22165 2433 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting domain info list");
gianni@22023 2434 goto out;
keir@21143 2435 }
ian@22164 2436 if (!(dompath = libxl__xs_get_dompath(&gc, domid)))
gianni@22023 2437 goto out;
keir@21143 2438
stefano@22121 2439 retry_transaction:
stefano@22121 2440 t = xs_transaction_start(ctx->xsh);
stefano@22121 2441 for (i = 0; i <= info.vcpu_max_id; i++)
ian@22164 2442 libxl__xs_write(&gc, t,
ian@22164 2443 libxl__sprintf(&gc, "%s/cpu/%u/availability", dompath, i),
stefano@22121 2444 "%s", ((1 << i) & bitmask) ? "online" : "offline");
stefano@22121 2445 if (!xs_transaction_end(ctx->xsh, t, 0)) {
stefano@22121 2446 if (errno == EAGAIN)
stefano@22121 2447 goto retry_transaction;
stefano@22121 2448 } else
stefano@22121 2449 rc = 0;
gianni@22023 2450 out:
ian@22164 2451 libxl__free_all(&gc);
gianni@22023 2452 return rc;
keir@21143 2453 }
keir@21265 2454
keir@21265 2455 /*
keir@21265 2456 * returns one of the XEN_SCHEDULER_* constants from public/domctl.h
keir@21265 2457 */
ian@21930 2458 int libxl_get_sched_id(libxl_ctx *ctx)
keir@21265 2459 {
keir@21265 2460 int sched, ret;
keir@21265 2461
gianni@21892 2462 if ((ret = xc_sched_id(ctx->xch, &sched)) != 0) {
ian@22165 2463 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting domain info list");
gianni@21892 2464 return ERROR_FAIL;
gianni@21892 2465 }
keir@21265 2466 return sched;
keir@21265 2467 }
keir@21292 2468
ian@21930 2469 int libxl_sched_credit_domain_get(libxl_ctx *ctx, uint32_t domid, libxl_sched_credit *scinfo)
keir@21292 2470 {
keir@21292 2471 struct xen_domctl_sched_credit sdom;
keir@21292 2472 int rc;
keir@21292 2473
keir@21292 2474 rc = xc_sched_credit_domain_get(ctx->xch, domid, &sdom);
gianni@21892 2475 if (rc != 0) {
ian@22165 2476 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting domain sched credit");
gianni@21892 2477 return ERROR_FAIL;
gianni@21892 2478 }
keir@21292 2479
keir@21292 2480 scinfo->weight = sdom.weight;
keir@21292 2481 scinfo->cap = sdom.cap;
keir@21292 2482
keir@21292 2483 return 0;
keir@21292 2484 }
keir@21292 2485
ian@21930 2486 int libxl_sched_credit_domain_set(libxl_ctx *ctx, uint32_t domid, libxl_sched_credit *scinfo)
keir@21292 2487 {
keir@21292 2488 struct xen_domctl_sched_credit sdom;
keir@21292 2489 xc_domaininfo_t domaininfo;
keir@21292 2490 int rc;
keir@21292 2491
keir@21292 2492 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo);
gianni@21892 2493 if (rc < 0) {
ian@22165 2494 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting domain info list");
gianni@21892 2495 return ERROR_FAIL;
gianni@21892 2496 }
keir@21292 2497 if (rc != 1 || domaininfo.domain != domid)
gianni@21892 2498 return ERROR_INVAL;
keir@21292 2499
keir@21292 2500
keir@21292 2501 if (scinfo->weight < 1 || scinfo->weight > 65535) {
ian@22165 2502 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
keir@21292 2503 "Cpu weight out of range, valid values are within range from 1 to 65535");
gianni@21892 2504 return ERROR_INVAL;
keir@21292 2505 }
keir@21292 2506
keir@21292 2507 if (scinfo->cap < 0 || scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) {
ian@22165 2508 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
keir@21292 2509 "Cpu cap out of range, valid range is from 0 to %d for specified number of vcpus",
keir@21292 2510 ((domaininfo.max_vcpu_id + 1) * 100));
gianni@21892 2511 return ERROR_INVAL;
keir@21292 2512 }
keir@21292 2513
keir@21292 2514 sdom.weight = scinfo->weight;
keir@21292 2515 sdom.cap = scinfo->cap;
keir@21292 2516
keir@21292 2517 rc = xc_sched_credit_domain_set(ctx->xch, domid, &sdom);
gianni@21892 2518 if ( rc < 0 ) {
ian@22165 2519 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting domain sched credit");
gianni@21892 2520 return ERROR_FAIL;
gianni@21892 2521 }
keir@21292 2522
keir@21292 2523 return 0;
keir@21292 2524 }
keir@21292 2525
keir@21393 2526 static int trigger_type_from_string(char *trigger_name)
keir@21393 2527 {
keir@21393 2528 if (!strcmp(trigger_name, "nmi"))
keir@21393 2529 return XEN_DOMCTL_SENDTRIGGER_NMI;
keir@21393 2530 else if (!strcmp(trigger_name, "reset"))
keir@21393 2531 return XEN_DOMCTL_SENDTRIGGER_RESET;
keir@21393 2532 else if (!strcmp(trigger_name, "init"))
keir@21393 2533 return XEN_DOMCTL_SENDTRIGGER_INIT;
keir@21393 2534 else if (!strcmp(trigger_name, "power"))
keir@21393 2535 return XEN_DOMCTL_SENDTRIGGER_POWER;
keir@21393 2536 else if (!strcmp(trigger_name, "sleep"))
keir@21393 2537 return XEN_DOMCTL_SENDTRIGGER_SLEEP;
keir@21393 2538 else
keir@21393 2539 return -1;
keir@21393 2540 }
keir@21393 2541
ian@21930 2542 int libxl_send_trigger(libxl_ctx *ctx, uint32_t domid, char *trigger_name, uint32_t vcpuid)
keir@21393 2543 {
keir@21393 2544 int rc = -1;
keir@21393 2545 int trigger_type = trigger_type_from_string(trigger_name);
keir@21393 2546
keir@21393 2547 if (trigger_type == -1) {
ian@22165 2548 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, -1,
keir@21393 2549 "Invalid trigger, valid triggers are <nmi|reset|init|power|sleep>");
gianni@21892 2550 return ERROR_INVAL;
keir@21393 2551 }
keir@21393 2552
keir@21393 2553 rc = xc_domain_send_trigger(ctx->xch, domid, trigger_type, vcpuid);
gianni@21892 2554 if (rc != 0) {
ian@22165 2555 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
keir@21393 2556 "Send trigger '%s' failed", trigger_name);
gianni@21892 2557 return ERROR_FAIL;
gianni@21892 2558 }
gianni@21892 2559
gianni@21892 2560 return 0;
keir@21393 2561 }
keir@21402 2562
ian@21930 2563 int libxl_send_sysrq(libxl_ctx *ctx, uint32_t domid, char sysrq)
keir@21402 2564 {
ian@22167 2565 libxl__gc gc = LIBXL_INIT_GC(ctx);
ian@22164 2566 char *dompath = libxl__xs_get_dompath(&gc, domid);
ian@22164 2567
ian@22164 2568 libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/control/sysrq", dompath), "%c", sysrq);
ian@22164 2569
ian@22164 2570 libxl__free_all(&gc);
keir@21402 2571 return 0;
keir@21402 2572 }
keir@21402 2573
ian@21930 2574 int libxl_send_debug_keys(libxl_ctx *ctx, char *keys)
keir@21472 2575 {
gianni@21892 2576 int ret;
gianni@21892 2577 ret = xc_send_debug_keys(ctx->xch, keys);
gianni@21892 2578 if ( ret < 0 ) {
ian@22165 2579 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "sending debug keys");
gianni@21892 2580 return ERROR_FAIL;
gianni@21892 2581 }
gianni@21892 2582 return 0;
keir@21472 2583 }
keir@21472 2584
ian@21930 2585 libxl_xen_console_reader *
ian@21930 2586 libxl_xen_console_read_start(libxl_ctx *ctx, int clear)
keir@21496 2587 {
ian@21930 2588 libxl_xen_console_reader *cr;
keir@21496 2589 unsigned int size = 16384;
keir@21496 2590 char *buf = malloc(size);
keir@21496 2591
keir@21496 2592 if (!buf) {
ian@22165 2593 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot malloc buffer for libxl_xen_console_reader,"
keir@21496 2594 " size is %u", size);
keir@21496 2595 return NULL;
keir@21496 2596 }
keir@21496 2597
ian@21930 2598 cr = malloc(sizeof(libxl_xen_console_reader));
keir@21496 2599 if (!cr) {
ian@22165 2600 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot malloc libxl_xen_console_reader");
keir@21496 2601 return NULL;
keir@21496 2602 }
keir@21496 2603
ian@21930 2604 memset(cr, 0, sizeof(libxl_xen_console_reader));
keir@21496 2605 cr->buffer = buf;
keir@21496 2606 cr->size = size;
keir@21496 2607 cr->count = size;
keir@21496 2608 cr->clear = clear;
keir@21496 2609 cr->incremental = 1;
keir@21496 2610
keir@21496 2611 return cr;
keir@21496 2612 }
keir@21496 2613
keir@21496 2614 /* return values: *line_r
keir@21496 2615 * 1 success, whole line obtained from buffer non-0
keir@21496 2616 * 0 no more lines available right now 0
keir@21496 2617 * negative error code ERROR_* 0
keir@21496 2618 * On success *line_r is updated to point to a nul-terminated
keir@21496 2619 * string which is valid until the next call on the same console
keir@21496 2620 * reader. The libxl caller may overwrite parts of the string
keir@21496 2621 * if it wishes. */
ian@21930 2622 int libxl_xen_console_read_line(libxl_ctx *ctx,
ian@21930 2623 libxl_xen_console_reader *cr,
keir@21496 2624 char **line_r)
keir@21496 2625 {
keir@21496 2626 int ret;
keir@21496 2627
keir@21496 2628 memset(cr->buffer, 0, cr->size);
ian@22292 2629 ret = xc_readconsolering(ctx->xch, cr->buffer, &cr->count,
keir@21496 2630 cr->clear, cr->incremental, &cr->index);
gianni@21892 2631 if (ret < 0) {
ian@22165 2632 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "reading console ring buffer");
gianni@21892 2633 return ERROR_FAIL;
gianni@21892 2634 }
keir@21496 2635 if (!ret) {
keir@21496 2636 if (cr->count) {
keir@21496 2637 *line_r = cr->buffer;
keir@21496 2638 ret = 1;
keir@21496 2639 } else {
keir@21496 2640 *line_r = NULL;
keir@21496 2641 ret = 0;
keir@21496 2642 }
keir@21496 2643 }
keir@21496 2644
keir@21496 2645 return ret;
keir@21496 2646 }
keir@21496 2647
ian@21930 2648 void libxl_xen_console_read_finish(libxl_ctx *ctx,
ian@21930 2649 libxl_xen_console_reader *cr)
keir@21496 2650 {
keir@21496 2651 free(cr->buffer);
keir@21496 2652 free(cr);
keir@21496 2653 }
keir@21496 2654
ian@21930 2655 uint32_t libxl_vm_get_start_time(libxl_ctx *ctx, uint32_t domid)
keir@21425 2656 {
ian@22167 2657 libxl__gc gc = LIBXL_INIT_GC(ctx);
ian@22164 2658 char *dompath = libxl__xs_get_dompath(&gc, domid);
keir@21425 2659 char *vm_path, *start_time;
gianni@22023 2660 uint32_t ret;
keir@21425 2661
ian@22164 2662 vm_path = libxl__xs_read(
ian@22164 2663 &gc, XBT_NULL, libxl__sprintf(&gc, "%s/vm", dompath));
ian@22164 2664 start_time = libxl__xs_read(
ian@22164 2665 &gc, XBT_NULL, libxl__sprintf(&gc, "%s/start_time", vm_path));
keir@21425 2666 if (start_time == NULL) {
ian@22165 2667 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, -1,
keir@21425 2668 "Can't get start time of domain '%d'", domid);
gianni@22023 2669 ret = -1;
gianni@22023 2670 }else{
gianni@22023 2671 ret = strtoul(start_time, NULL, 10);
keir@21425 2672 }
ian@22164 2673 libxl__free_all(&gc);
gianni@22023 2674 return ret;
keir@21425 2675 }
keir@21425 2676
ian@21930 2677 char *libxl_tmem_list(libxl_ctx *ctx, uint32_t domid, int use_long)
keir@21471 2678 {
keir@21471 2679 int rc;
keir@21471 2680 char _buf[32768];
keir@21471 2681
keir@21471 2682 rc = xc_tmem_control(ctx->xch, -1, TMEMC_LIST, domid, 32768, use_long,
keir@21471 2683 0, _buf);
keir@21471 2684 if (rc < 0) {
ian@22165 2685 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
keir@21471 2686 "Can not get tmem list");
keir@21471 2687 return NULL;
keir@21471 2688 }
keir@21471 2689
keir@21471 2690 return strdup(_buf);
keir@21471 2691 }
keir@21471 2692
ian@21930 2693 int libxl_tmem_freeze(libxl_ctx *ctx, uint32_t domid)
keir@21471 2694 {
keir@21471 2695 int rc;
keir@21471 2696
keir@21471 2697 rc = xc_tmem_control(ctx->xch, -1, TMEMC_FREEZE, domid, 0, 0,
keir@21471 2698 0, NULL);
keir@21471 2699 if (rc < 0) {
ian@22165 2700 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
keir@21471 2701 "Can not freeze tmem pools");
gianni@21892 2702 return ERROR_FAIL;
keir@21471 2703 }
keir@21471 2704
keir@21471 2705 return rc;
keir@21471 2706 }
keir@21471 2707
ian@21930 2708 int libxl_tmem_destroy(libxl_ctx *ctx, uint32_t domid)
keir@21471 2709 {
keir@21471 2710 int rc;
keir@21471 2711
keir@21471 2712 rc = xc_tmem_control(ctx->xch, -1, TMEMC_DESTROY, domid, 0, 0,
keir@21471 2713 0, NULL);
keir@21471 2714 if (rc < 0) {
ian@22165 2715 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
keir@21471 2716 "Can not destroy tmem pools");
gianni@21892 2717 return ERROR_FAIL;
keir@21471 2718 }
keir@21471 2719
keir@21471 2720 return rc;
keir@21471 2721 }
keir@21471 2722
ian@21930 2723 int libxl_tmem_thaw(libxl_ctx *ctx, uint32_t domid)
keir@21471 2724 {
keir@21471 2725 int rc;
keir@21471 2726
keir@21471 2727 rc = xc_tmem_control(ctx->xch, -1, TMEMC_THAW, domid, 0, 0,
keir@21471 2728 0, NULL);
keir@21471 2729 if (rc < 0) {
ian@22165 2730 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
keir@21471 2731 "Can not thaw tmem pools");
gianni@21892 2732 return ERROR_FAIL;
keir@21471 2733 }
keir@21471 2734
keir@21471 2735 return rc;
keir@21471 2736 }
keir@21471 2737
keir@21471 2738 static int32_t tmem_setop_from_string(char *set_name)
keir@21471 2739 {
keir@21471 2740 if (!strcmp(set_name, "weight"))
keir@21471 2741 return TMEMC_SET_WEIGHT;
keir@21471 2742 else if (!strcmp(set_name, "cap"))
keir@21471 2743 return TMEMC_SET_CAP;
keir@21471 2744 else if (!strcmp(set_name, "compress"))
keir@21471 2745 return TMEMC_SET_COMPRESS;
keir@21471 2746 else
keir@21471 2747 return -1;
keir@21471 2748 }
keir@21471 2749
ian@21930 2750 int libxl_tmem_set(libxl_ctx *ctx, uint32_t domid, char* name, uint32_t set)
keir@21471 2751 {
keir@21471 2752 int rc;
keir@21471 2753 int32_t subop = tmem_setop_from_string(name);
keir@21471 2754
keir@21471 2755 if (subop == -1) {
ian@22165 2756 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, -1,
keir@21471 2757 "Invalid set, valid sets are <weight|cap|compress>");
gianni@21892 2758 return ERROR_INVAL;
keir@21471 2759 }
keir@21471 2760 rc = xc_tmem_control(ctx->xch, -1, subop, domid, set, 0, 0, NULL);
keir@21471 2761 if (rc < 0) {
ian@22165 2762 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
keir@21471 2763 "Can not set tmem %s", name);
gianni@21892 2764 return ERROR_FAIL;
keir@21471 2765 }
keir@21471 2766
keir@21471 2767 return rc;
keir@21471 2768 }
keir@21471 2769
ian@21930 2770 int libxl_tmem_shared_auth(libxl_ctx *ctx, uint32_t domid,
keir@21471 2771 char* uuid, int auth)
keir@21471 2772 {
keir@21471 2773 int rc;
keir@21471 2774
keir@21471 2775 rc = xc_tmem_auth(ctx->xch, domid, uuid, auth);
keir@21471 2776 if (rc < 0) {
ian@22165 2777 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
keir@21471 2778 "Can not set tmem shared auth");
gianni@21892 2779 return ERROR_FAIL;
keir@21471 2780 }
keir@21471 2781
keir@21471 2782 return rc;
keir@21471 2783 }
keir@21471 2784
ian@21930 2785 int libxl_tmem_freeable(libxl_ctx *ctx)
sstabellini@21863 2786 {
sstabellini@21863 2787 int rc;
sstabellini@21863 2788
sstabellini@21863 2789 rc = xc_tmem_control(ctx->xch, -1, TMEMC_QUERY_FREEABLE_MB, -1, 0, 0, 0, 0);
sstabellini@21863 2790 if (rc < 0) {
ian@22165 2791 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
sstabellini@21863 2792 "Can not get tmem freeable memory");
gianni@21892 2793 return ERROR_FAIL;
sstabellini@21863 2794 }
sstabellini@21863 2795
sstabellini@21863 2796 return rc;
sstabellini@21863 2797 }
sstabellini@21863 2798
ian@22082 2799 void libxl_file_reference_destroy(libxl_file_reference *f)
Ian@21848 2800 {
ian@22082 2801 libxl__file_reference_unmap(f);
ian@22082 2802 free(f->path);
Ian@21848 2803 }
juergen@22319 2804
juergen@22319 2805 int libxl_get_freecpus(libxl_ctx *ctx, libxl_cpumap *cpumap)
juergen@22319 2806 {
juergen@22319 2807 int ncpus;
juergen@22319 2808
juergen@22396 2809 ncpus = libxl_get_max_cpus(ctx);
juergen@22396 2810 if (ncpus == 0)
juergen@22396 2811 return ERROR_FAIL;
juergen@22396 2812
juergen@22396 2813 cpumap->map = xc_cpupool_freeinfo(ctx->xch);
juergen@22319 2814 if (cpumap->map == NULL)
juergen@22319 2815 return ERROR_FAIL;
juergen@22319 2816
juergen@22319 2817 cpumap->size = (ncpus + 7) / 8;
juergen@22319 2818
juergen@22319 2819 return 0;
juergen@22319 2820 }
juergen@22319 2821
Christoph@22602 2822 int libxl_create_cpupool(libxl_ctx *ctx, const char *name, int schedid,
juergen@22319 2823 libxl_cpumap cpumap, libxl_uuid *uuid,
juergen@22319 2824 uint32_t *poolid)
juergen@22319 2825 {
juergen@22319 2826 libxl__gc gc = LIBXL_INIT_GC(ctx);
juergen@22319 2827 int rc;
juergen@22319 2828 int i;
juergen@22319 2829 xs_transaction_t t;
juergen@22319 2830 char *uuid_string;
juergen@22319 2831
juergen@22319 2832 uuid_string = libxl__uuid2string(&gc, *uuid);
juergen@22549 2833 if (!uuid_string) {
juergen@22549 2834 libxl__free_all(&gc);
juergen@22319 2835 return ERROR_NOMEM;
juergen@22549 2836 }
juergen@22319 2837
juergen@22319 2838 rc = xc_cpupool_create(ctx->xch, poolid, schedid);
juergen@22319 2839 if (rc) {
juergen@22319 2840 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
juergen@22319 2841 "Could not create cpupool");
juergen@22549 2842 libxl__free_all(&gc);
juergen@22319 2843 return ERROR_FAIL;
juergen@22319 2844 }
juergen@22319 2845
juergen@22396 2846 libxl_for_each_cpu(i, cpumap)
juergen@22396 2847 if (libxl_cpumap_test(&cpumap, i)) {
juergen@22319 2848 rc = xc_cpupool_addcpu(ctx->xch, *poolid, i);
juergen@22319 2849 if (rc) {
juergen@22319 2850 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
juergen@22319 2851 "Error moving cpu to cpupool");
juergen@22319 2852 libxl_destroy_cpupool(ctx, *poolid);
juergen@22549 2853 libxl__free_all(&gc);
juergen@22319 2854 return ERROR_FAIL;
juergen@22319 2855 }
juergen@22319 2856 }
juergen@22319 2857
juergen@22319 2858 for (;;) {
juergen@22319 2859 t = xs_transaction_start(ctx->xsh);
juergen@22319 2860
juergen@22319 2861 xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/pool/%d", *poolid));
Ian@22368 2862 libxl__xs_write(&gc, t,
Ian@22368 2863 libxl__sprintf(&gc, "/local/pool/%d/uuid", *poolid),
Ian@22368 2864 "%s", uuid_string);
Ian@22368 2865 libxl__xs_write(&gc, t,
Ian@22368 2866 libxl__sprintf(&gc, "/local/pool/%d/name", *poolid),
Ian@22368 2867 "%s", name);
juergen@22319 2868
juergen@22549 2869 if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN)) {
juergen@22549 2870 libxl__free_all(&gc);
juergen@22319 2871 return 0;
juergen@22549 2872 }
juergen@22319 2873 }
juergen@22319 2874 }
juergen@22319 2875
juergen@22319 2876 int libxl_destroy_cpupool(libxl_ctx *ctx, uint32_t poolid)
juergen@22319 2877 {
juergen@22319 2878 libxl__gc gc = LIBXL_INIT_GC(ctx);
juergen@22319 2879 int rc, i;
juergen@22319 2880 xc_cpupoolinfo_t *info;
juergen@22319 2881 xs_transaction_t t;
juergen@22396 2882 libxl_cpumap cpumap;
juergen@22319 2883
juergen@22319 2884 info = xc_cpupool_getinfo(ctx->xch, poolid);
juergen@22549 2885 if (info == NULL) {
juergen@22549 2886 libxl__free_all(&gc);
juergen@22319 2887 return ERROR_NOMEM;
juergen@22549 2888 }
juergen@22319 2889
juergen@22319 2890 rc = ERROR_INVAL;
juergen@22319 2891 if ((info->cpupool_id != poolid) || (info->n_dom))
juergen@22319 2892 goto out;
juergen@22319 2893
juergen@22396 2894 rc = ERROR_NOMEM;
juergen@22396 2895 if (libxl_cpumap_alloc(ctx, &cpumap))
juergen@22396 2896 goto out;
juergen@22396 2897
juergen@22396 2898 memcpy(cpumap.map, info->cpumap, cpumap.size);
juergen@22396 2899 libxl_for_each_cpu(i, cpumap)
juergen@22396 2900 if (libxl_cpumap_test(&cpumap, i)) {
juergen@22319 2901 rc = xc_cpupool_removecpu(ctx->xch, poolid, i);
juergen@22319 2902 if (rc) {
juergen@22319 2903 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
juergen@22319 2904 "Error removing cpu from cpupool");
juergen@22319 2905 rc = ERROR_FAIL;
juergen@22396 2906 goto out1;
juergen@22319 2907 }
juergen@22319 2908 }
juergen@22319 2909
juergen@22319 2910 rc = xc_cpupool_destroy(ctx->xch, poolid);
juergen@22319 2911 if (rc) {
juergen@22319 2912 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "Could not destroy cpupool");
juergen@22319 2913 rc = ERROR_FAIL;
juergen@22396 2914 goto out1;
juergen@22319 2915 }
juergen@22319 2916
juergen@22319 2917 for (;;) {
juergen@22319 2918 t = xs_transaction_start(ctx->xsh);
juergen@22319 2919
juergen@22319 2920 xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "/local/pool/%d", poolid));
juergen@22319 2921
juergen@22319 2922 if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN))
juergen@22319 2923 break;
juergen@22319 2924 }
juergen@22319 2925
juergen@22319 2926 rc = 0;
juergen@22319 2927
juergen@22396 2928 out1:
juergen@22396 2929 libxl_cpumap_destroy(&cpumap);
juergen@22319 2930 out:
juergen@22396 2931 xc_cpupool_infofree(ctx->xch, info);
juergen@22549 2932 libxl__free_all(&gc);
juergen@22319 2933
juergen@22319 2934 return rc;
juergen@22319 2935 }
juergen@22319 2936
juergen@22651 2937 int libxl_cpupool_rename(libxl_ctx *ctx, const char *name, uint32_t poolid)
juergen@22651 2938 {
juergen@22651 2939 libxl__gc gc = LIBXL_INIT_GC(ctx);
juergen@22651 2940 xs_transaction_t t;
juergen@22651 2941 xc_cpupoolinfo_t *info;
juergen@22651 2942 int rc;
juergen@22651 2943
juergen@22651 2944 info = xc_cpupool_getinfo(ctx->xch, poolid);
juergen@22651 2945 if (info == NULL) {
juergen@22651 2946 libxl__free_all(&gc);
juergen@22651 2947 return ERROR_NOMEM;
juergen@22651 2948 }
juergen@22651 2949
juergen@22651 2950 rc = ERROR_INVAL;
juergen@22651 2951 if (info->cpupool_id != poolid)
juergen@22651 2952 goto out;
juergen@22651 2953
juergen@22651 2954 rc = 0;
juergen@22651 2955
juergen@22651 2956 for (;;) {
juergen@22651 2957 t = xs_transaction_start(ctx->xsh);
juergen@22651 2958
juergen@22651 2959 libxl__xs_write(&gc, t,
juergen@22651 2960 libxl__sprintf(&gc, "/local/pool/%d/name", poolid),
juergen@22651 2961 "%s", name);
juergen@22651 2962
juergen@22651 2963 if (xs_transaction_end(ctx->xsh, t, 0))
juergen@22651 2964 break;
juergen@22651 2965
juergen@22651 2966 if (errno == EAGAIN)
juergen@22651 2967 continue;
juergen@22651 2968
juergen@22651 2969 rc = ERROR_FAIL;
juergen@22651 2970 break;
juergen@22651 2971 }
juergen@22651 2972
juergen@22651 2973 out:
juergen@22651 2974 xc_cpupool_infofree(ctx->xch, info);
juergen@22651 2975 libxl__free_all(&gc);
juergen@22651 2976
juergen@22651 2977 return rc;
juergen@22651 2978 }
juergen@22651 2979
juergen@22319 2980 int libxl_cpupool_cpuadd(libxl_ctx *ctx, uint32_t poolid, int cpu)
juergen@22319 2981 {
juergen@22319 2982 int rc;
juergen@22319 2983
juergen@22319 2984 rc = xc_cpupool_addcpu(ctx->xch, poolid, cpu);
juergen@22319 2985 if (rc) {
juergen@22319 2986 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
juergen@22319 2987 "Error moving cpu to cpupool");
juergen@22319 2988 return ERROR_FAIL;
juergen@22319 2989 }
juergen@22319 2990 return 0;
juergen@22319 2991 }
juergen@22319 2992
juergen@22650 2993 int libxl_cpupool_cpuadd_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus)
juergen@22650 2994 {
juergen@22650 2995 int rc = 0;
juergen@22650 2996 int cpu;
juergen@22650 2997 libxl_cpumap freemap;
juergen@22650 2998 libxl_topologyinfo topology;
juergen@22650 2999
juergen@22650 3000 if (libxl_get_freecpus(ctx, &freemap)) {
juergen@22650 3001 return ERROR_FAIL;
juergen@22650 3002 }
juergen@22650 3003
juergen@22650 3004 if (libxl_get_topologyinfo(ctx, &topology)) {
juergen@22650 3005 rc = ERROR_FAIL;
juergen@22650 3006 goto out;
juergen@22650 3007 }
juergen@22650 3008
juergen@22650 3009 *cpus = 0;
juergen@22650 3010 for (cpu = 0; cpu < topology.nodemap.entries; cpu++) {
juergen@22650 3011 if (libxl_cpumap_test(&freemap, cpu) &&
juergen@22650 3012 (topology.nodemap.array[cpu] == node) &&
juergen@22650 3013 !libxl_cpupool_cpuadd(ctx, poolid, cpu)) {
juergen@22650 3014 (*cpus)++;
juergen@22650 3015 }
juergen@22650 3016 }
juergen@22650 3017
juergen@22650 3018 libxl_topologyinfo_destroy(&topology);
juergen@22650 3019
juergen@22650 3020 out:
juergen@22650 3021 libxl_cpumap_destroy(&freemap);
juergen@22650 3022 return rc;
juergen@22650 3023 }
juergen@22650 3024
juergen@22319 3025 int libxl_cpupool_cpuremove(libxl_ctx *ctx, uint32_t poolid, int cpu)
juergen@22319 3026 {
juergen@22319 3027 int rc;
juergen@22319 3028
juergen@22319 3029 rc = xc_cpupool_removecpu(ctx->xch, poolid, cpu);
juergen@22319 3030 if (rc) {
juergen@22319 3031 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
juergen@22319 3032 "Error removing cpu from cpupool");
juergen@22319 3033 return ERROR_FAIL;
juergen@22319 3034 }
juergen@22319 3035 return 0;
juergen@22319 3036 }
juergen@22319 3037
juergen@22650 3038 int libxl_cpupool_cpuremove_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus)
juergen@22650 3039 {
juergen@22650 3040 int ret = 0;
juergen@22650 3041 int n_pools;
juergen@22650 3042 int p;
juergen@22650 3043 int cpu;
juergen@22650 3044 libxl_topologyinfo topology;
juergen@22650 3045 libxl_cpupoolinfo *poolinfo;
juergen@22650 3046
juergen@22650 3047 poolinfo = libxl_list_cpupool(ctx, &n_pools);
juergen@22650 3048 if (!poolinfo) {
juergen@22650 3049 return ERROR_NOMEM;
juergen@22650 3050 }
juergen@22650 3051
juergen@22650 3052 if (libxl_get_topologyinfo(ctx, &topology)) {
juergen@22650 3053 ret = ERROR_FAIL;
juergen@22650 3054 goto out;
juergen@22650 3055 }
juergen@22650 3056
juergen@22650 3057 *cpus = 0;
juergen@22650 3058 for (p = 0; p < n_pools; p++) {
juergen@22650 3059 if (poolinfo[p].poolid == poolid) {
juergen@22650 3060 for (cpu = 0; cpu < topology.nodemap.entries; cpu++) {
juergen@22650 3061 if ((topology.nodemap.array[cpu] == node) &&
juergen@22650 3062 libxl_cpumap_test(&poolinfo[p].cpumap, cpu) &&
juergen@22650 3063 !libxl_cpupool_cpuremove(ctx, poolid, cpu)) {
juergen@22650 3064 (*cpus)++;
juergen@22650 3065 }
juergen@22650 3066 }
juergen@22650 3067 }
juergen@22650 3068 }
juergen@22650 3069
juergen@22650 3070 libxl_topologyinfo_destroy(&topology);
juergen@22650 3071
juergen@22650 3072 out:
juergen@22650 3073 for (p = 0; p < n_pools; p++) {
juergen@22650 3074 libxl_cpupoolinfo_destroy(poolinfo + p);
juergen@22650 3075 }
juergen@22650 3076
juergen@22650 3077 return ret;
juergen@22650 3078 }
juergen@22650 3079
juergen@22319 3080 int libxl_cpupool_movedomain(libxl_ctx *ctx, uint32_t poolid, uint32_t domid)
juergen@22319 3081 {
juergen@22319 3082 libxl__gc gc = LIBXL_INIT_GC(ctx);
juergen@22319 3083 int rc;
juergen@22319 3084 char *dom_path;
juergen@22319 3085 char *vm_path;
juergen@22319 3086 char *poolname;
juergen@22319 3087 xs_transaction_t t;
juergen@22319 3088
juergen@22319 3089 dom_path = libxl__xs_get_dompath(&gc, domid);
juergen@22319 3090 if (!dom_path) {
juergen@22549 3091 libxl__free_all(&gc);
juergen@22319 3092 return ERROR_FAIL;
juergen@22319 3093 }
juergen@22319 3094
juergen@22319 3095 rc = xc_cpupool_movedomain(ctx->xch, poolid, domid);
juergen@22319 3096 if (rc) {
juergen@22319 3097 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
juergen@22319 3098 "Error moving domain to cpupool");
juergen@22549 3099 libxl__free_all(&gc);
juergen@22319 3100 return ERROR_FAIL;
juergen@22319 3101 }
juergen@22319 3102
juergen@22319 3103 for (;;) {
juergen@22319 3104 t = xs_transaction_start(ctx->xsh);
juergen@22319 3105
juergen@22319 3106 poolname = libxl__cpupoolid_to_name(&gc, poolid);
juergen@22319 3107 vm_path = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/vm", dom_path));
juergen@22319 3108 if (!vm_path)
juergen@22319 3109 break;
juergen@22319 3110
Ian@22368 3111 libxl__xs_write(&gc, t, libxl__sprintf(&gc, "%s/pool_name", vm_path),
Ian@22368 3112 "%s", poolname);
juergen@22319 3113
juergen@22319 3114 if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN))
juergen@22319 3115 break;
juergen@22319 3116 }
juergen@22319 3117
juergen@22549 3118 libxl__free_all(&gc);
juergen@22319 3119 return 0;
juergen@22319 3120 }