keir@20462: /* keir@20462: * Copyright (C) 2009 Citrix Ltd. keir@20462: * Author Vincent Hanquez keir@20462: * Author Stefano Stabellini keir@20462: * keir@20462: * This program is free software; you can redistribute it and/or modify keir@20462: * it under the terms of the GNU Lesser General Public License as published keir@20462: * by the Free Software Foundation; version 2.1 only. with the special keir@20462: * exception on linking described in file LICENSE. keir@20462: * keir@20462: * This program is distributed in the hope that it will be useful, keir@20462: * but WITHOUT ANY WARRANTY; without even the implied warranty of keir@20462: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the keir@20462: * GNU Lesser General Public License for more details. keir@20462: */ keir@20462: keir@20513: #include "libxl_osdeps.h" keir@20513: keir@20462: #include keir@20462: #include keir@20462: #include keir@20462: #include zhigang@21941: #include keir@20462: #include keir@20462: #include keir@20514: #include ian@22032: #include keir@20462: #include keir@20468: #include /* for write, unlink and close */ keir@20509: #include keir@20509: #include keir@20514: #include keir@20513: keir@20462: #include "libxl.h" keir@20462: #include "libxl_utils.h" keir@20462: #include "libxl_internal.h" keir@20462: #include "flexarray.h" keir@20462: keir@20860: #define PAGE_TO_MEMKB(pages) ((pages) * 4) keir@20860: ian@21930: int libxl_ctx_init(libxl_ctx *ctx, int version, xentoollog_logger *lg) keir@20462: { keir@20788: if (version != LIBXL_VERSION) keir@20788: return ERROR_VERSION; ian@21930: memset(ctx, 0, sizeof(libxl_ctx)); keir@21532: ctx->lg = lg; keir@21266: memset(&ctx->version_info, 0, sizeof(libxl_version_info)); keir@20462: keir@21532: ctx->xch = xc_interface_open(lg,lg,0); keir@21529: if (!ctx->xch) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, errno, keir@21681: "cannot open libxc handle"); keir@20819: return ERROR_FAIL; keir@20819: } keir@20819: keir@20462: ctx->xsh = xs_daemon_open(); dgdegra@22118: if (!ctx->xsh) dgdegra@22118: ctx->xsh = xs_domain_open(); keir@20819: if (!ctx->xsh) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, errno, keir@21681: "cannot connect to xenstore"); keir@20819: xc_interface_close(ctx->xch); keir@20819: return ERROR_FAIL; keir@20819: } keir@20462: return 0; keir@20462: } keir@20462: ian@21930: int libxl_ctx_free(libxl_ctx *ctx) keir@20462: { gianni@22156: if (ctx->xch) xc_interface_close(ctx->xch); ian@22084: libxl_version_info_destroy(&ctx->version_info); keir@21186: if (ctx->xsh) xs_daemon_close(ctx->xsh); keir@20462: return 0; keir@20462: } keir@20462: ian@22124: void libxl_string_list_destroy(libxl_string_list *psl) ian@22078: { ian@22078: int i; ian@22124: libxl_string_list sl = *psl; ian@22078: ian@22078: if (!sl) ian@22078: return; ian@22078: ian@22078: for (i = 0; sl[i] != NULL; i++) ian@22078: free(sl[i]); ian@22078: free(sl); ian@22078: } ian@22078: ian@22124: void libxl_key_value_list_destroy(libxl_key_value_list *pkvl) ian@22078: { ian@22078: int i; ian@22124: libxl_key_value_list kvl = *pkvl; ian@22078: ian@22078: if (!kvl) ian@22078: return; ian@22078: ian@22078: for (i = 0; kvl[i] != NULL; i += 2) { ian@22078: free(kvl[i]); ian@22078: if (kvl[i + 1]) ian@22078: free(kvl[i + 1]); ian@22078: } ian@22078: free(kvl); ian@22078: } ian@22078: keir@20462: /******************************************************************************/ keir@20462: ian@21930: int libxl_domain_make(libxl_ctx *ctx, libxl_domain_create_info *info, keir@20462: uint32_t *domid) keir@20462: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@21184: int flags, ret, i, rc; keir@20468: char *uuid_string; keir@20646: char *rw_paths[] = { "device", "device/suspend/event-channel" , "data"}; keir@20462: char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers", keir@20646: "control", "attr", "messages" }; ian@21894: char *dom_path, *vm_path; keir@20462: struct xs_permissions roperm[2]; keir@20462: struct xs_permissions rwperm[1]; keir@20462: xs_transaction_t t; keir@20468: xen_domain_handle_t handle; keir@20462: ian@22164: uuid_string = libxl__uuid2string(&gc, info->uuid); gianni@22023: if (!uuid_string) { ian@22164: libxl__free_all(&gc); gianni@22023: return ERROR_NOMEM; gianni@22023: } keir@20462: keir@20462: flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0; keir@20462: flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0; keir@21274: flags |= info->oos ? 0 : XEN_DOMCTL_CDF_oos_off; keir@20824: *domid = -1; keir@20462: keir@20580: /* Ultimately, handle is an array of 16 uint8_t, same as uuid */ gianni@22143: libxl_uuid_copy((libxl_uuid *)handle, &info->uuid); keir@20468: keir@20468: ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid); keir@20462: if (ret < 0) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain creation fail"); ian@22164: libxl__free_all(&gc); keir@20462: return ERROR_FAIL; keir@20462: } keir@20462: keir@21368: ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid); keir@21368: if (ret < 0) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain move fail"); ian@22164: libxl__free_all(&gc); keir@21368: return ERROR_FAIL; keir@21368: } keir@21368: ian@22164: dom_path = libxl__xs_get_dompath(&gc, *domid); gianni@22023: if (!dom_path) { ian@22164: libxl__free_all(&gc); keir@20512: return ERROR_FAIL; gianni@22023: } gianni@22023: ian@22164: vm_path = libxl__sprintf(&gc, "/vm/%s", uuid_string); ian@21894: if (!vm_path) { ian@22165: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "cannot allocate create paths"); ian@22164: libxl__free_all(&gc); keir@20462: return ERROR_FAIL; keir@20462: } keir@20462: keir@20462: roperm[0].id = 0; keir@20462: roperm[0].perms = XS_PERM_NONE; keir@20462: roperm[1].id = *domid; keir@20462: roperm[1].perms = XS_PERM_READ; keir@20462: rwperm[0].id = *domid; keir@20462: rwperm[0].perms = XS_PERM_NONE; keir@20462: keir@20462: retry_transaction: keir@20462: t = xs_transaction_start(ctx->xsh); keir@20462: xs_rm(ctx->xsh, t, dom_path); keir@20462: xs_mkdir(ctx->xsh, t, dom_path); keir@20462: xs_set_permissions(ctx->xsh, t, dom_path, roperm, ARRAY_SIZE(roperm)); keir@20462: keir@20462: xs_rm(ctx->xsh, t, vm_path); keir@20462: xs_mkdir(ctx->xsh, t, vm_path); keir@20462: xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm)); keir@20462: ian@22164: xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/vm", dom_path), vm_path, strlen(vm_path)); keir@21184: rc = libxl_domain_rename(ctx, *domid, 0, info->name, t); gianni@22023: if (rc) { ian@22164: libxl__free_all(&gc); gianni@22023: return rc; gianni@22023: } keir@20462: keir@20462: for (i = 0; i < ARRAY_SIZE(rw_paths); i++) { ian@22164: char *path = libxl__sprintf(&gc, "%s/%s", dom_path, rw_paths[i]); keir@20462: xs_mkdir(ctx->xsh, t, path); keir@20462: xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm)); keir@20462: } keir@20462: for (i = 0; i < ARRAY_SIZE(ro_paths); i++) { ian@22164: char *path = libxl__sprintf(&gc, "%s/%s", dom_path, ro_paths[i]); keir@20462: xs_mkdir(ctx->xsh, t, path); keir@20462: xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm)); keir@20462: } keir@20462: ian@22164: xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/uuid", vm_path), uuid_string, strlen(uuid_string)); ian@22164: xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/name", vm_path), info->name, strlen(info->name)); keir@21389: if (info->poolname) ian@22164: xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/pool_name", vm_path), info->poolname, strlen(info->poolname)); ian@22164: ian@22164: libxl__xs_writev(&gc, t, dom_path, info->xsdata); ian@22164: libxl__xs_writev(&gc, t, libxl__sprintf(&gc, "%s/platform", dom_path), info->platformdata); ian@22164: ian@22164: xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1); keir@20462: keir@20462: if (!xs_transaction_end(ctx->xsh, t, 0)) keir@20462: if (errno == EAGAIN) keir@20462: goto retry_transaction; gianni@22023: ian@22164: libxl__free_all(&gc); keir@20462: return 0; keir@20462: } keir@20462: ian@21930: int libxl_domain_rename(libxl_ctx *ctx, uint32_t domid, keir@21184: const char *old_name, const char *new_name, gianni@22023: xs_transaction_t trans) gianni@22023: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@21184: char *dom_path = 0; keir@21184: const char *name_path; keir@21184: char *got_old_name; keir@21184: unsigned int got_old_len; keir@21184: xs_transaction_t our_trans = 0; keir@21184: int rc; keir@21184: ian@22164: dom_path = libxl__xs_get_dompath(&gc, domid); keir@21184: if (!dom_path) goto x_nomem; keir@21184: ian@22164: name_path= libxl__sprintf(&gc, "%s/name", dom_path); keir@21184: if (!name_path) goto x_nomem; keir@21184: keir@21184: retry_transaction: keir@21184: if (!trans) { keir@21184: trans = our_trans = xs_transaction_start(ctx->xsh); keir@21184: if (!our_trans) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, errno, keir@21184: "create xs transaction for domain (re)name"); keir@21184: goto x_fail; keir@21184: } keir@21184: } keir@21184: keir@21184: if (old_name) { keir@21184: got_old_name = xs_read(ctx->xsh, trans, name_path, &got_old_len); keir@21184: if (!got_old_name) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, errno, "check old name" keir@21184: " for domain %"PRIu32" allegedly named `%s'", keir@21184: domid, old_name); keir@21184: goto x_fail; keir@21184: } keir@21184: if (strcmp(old_name, got_old_name)) { ian@22165: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "domain %"PRIu32" allegedly named " keir@21184: "`%s' is actually named `%s' - racing ?", keir@21184: domid, old_name, got_old_name); keir@21184: free(got_old_name); keir@21184: goto x_fail; keir@21184: } keir@21184: free(got_old_name); keir@21184: } keir@21184: if (!xs_write(ctx->xsh, trans, name_path, keir@21184: new_name, strlen(new_name))) { ian@22165: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "failed to write new name `%s'" keir@21184: " for domain %"PRIu32" previously named `%s'", keir@21531: new_name, domid, old_name); keir@21184: goto x_fail; keir@21184: } keir@21184: keir@21184: if (our_trans) { keir@21184: if (!xs_transaction_end(ctx->xsh, our_trans, 0)) { keir@21184: trans = our_trans = 0; keir@21184: if (errno != EAGAIN) { ian@22165: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "failed to commit new name `%s'" keir@21184: " for domain %"PRIu32" previously named `%s'", keir@21531: new_name, domid, old_name); keir@21184: goto x_fail; keir@21184: } ian@22165: LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "need to retry rename transaction" keir@21184: " for domain %"PRIu32" (name_path=\"%s\", new_name=\"%s\")", keir@21184: domid, name_path, new_name); keir@21184: goto retry_transaction; keir@21184: } keir@21184: our_trans = 0; keir@21184: } keir@21184: keir@21184: rc = 0; keir@21184: x_rc: keir@21184: if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1); ian@22164: libxl__free_all(&gc); keir@21184: return rc; keir@21184: keir@21184: x_fail: rc = ERROR_FAIL; goto x_rc; keir@21184: x_nomem: rc = ERROR_NOMEM; goto x_rc; keir@21184: } keir@21184: ian@21930: int libxl_domain_build(libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid, libxl_domain_build_state *state) keir@20462: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@20462: char **vments = NULL, **localents = NULL; keir@21438: struct timeval start_time; keir@20829: int i, ret; keir@20829: ian@22165: ret = libxl__build_pre(ctx, domid, info, state); gianni@22023: if (ret) gianni@22023: goto out; keir@20462: keir@21438: gettimeofday(&start_time, NULL); keir@21438: keir@20462: if (info->hvm) { ian@22165: ret = libxl__build_hvm(ctx, domid, info, state); gianni@22023: if (ret) gianni@22023: goto out; gianni@22023: ian@22164: vments = libxl__calloc(&gc, 7, sizeof(char *)); keir@20516: vments[0] = "rtc/timeoffset"; keir@20516: vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : ""; keir@20516: vments[2] = "image/ostype"; keir@20516: vments[3] = "hvm"; keir@21438: vments[4] = "start_time"; ian@22164: vments[5] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); keir@20462: } else { ian@22165: ret = libxl__build_pv(ctx, domid, info, state); gianni@22023: if (ret) gianni@22023: goto out; gianni@22023: ian@22164: vments = libxl__calloc(&gc, 11, sizeof(char *)); keir@20578: i = 0; keir@20578: vments[i++] = "image/ostype"; keir@20578: vments[i++] = "linux"; keir@20578: vments[i++] = "image/kernel"; Ian@21848: vments[i++] = (char*) info->kernel.path; keir@21438: vments[i++] = "start_time"; ian@22164: vments[i++] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); Ian@21848: if (info->u.pv.ramdisk.path) { keir@20578: vments[i++] = "image/ramdisk"; Ian@21848: vments[i++] = (char*) info->u.pv.ramdisk.path; keir@20578: } keir@20578: if (info->u.pv.cmdline) { keir@20578: vments[i++] = "image/cmdline"; keir@20578: vments[i++] = (char*) info->u.pv.cmdline; keir@20578: } keir@20462: } ian@22165: ret = libxl__build_post(ctx, domid, info, state, vments, localents); keir@20829: out: ian@22082: libxl__file_reference_unmap(&info->kernel); Ian@21848: if (!info->hvm) ian@22082: libxl__file_reference_unmap(&info->u.pv.ramdisk); Ian@21848: ian@22164: libxl__free_all(&gc); keir@20829: return ret; keir@20462: } keir@20462: ian@21930: int libxl_domain_restore(libxl_ctx *ctx, libxl_domain_build_info *info, keir@20565: uint32_t domid, int fd, libxl_domain_build_state *state, keir@20565: libxl_device_model_info *dm_info) keir@20462: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@20462: char **vments = NULL, **localents = NULL; keir@21438: struct timeval start_time; keir@21183: int i, ret, esave, flags; keir@20462: ian@22165: ret = libxl__build_pre(ctx, domid, info, state); gianni@22023: if (ret) gianni@22023: goto out; keir@20829: ian@22165: ret = libxl__domain_restore_common(ctx, domid, info, state, fd); gianni@22023: if (ret) gianni@22023: goto out; keir@20829: keir@21438: gettimeofday(&start_time, NULL); keir@21438: keir@20462: if (info->hvm) { ian@22164: vments = libxl__calloc(&gc, 7, sizeof(char *)); keir@20516: vments[0] = "rtc/timeoffset"; keir@20516: vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : ""; keir@20565: vments[2] = "image/ostype"; keir@20565: vments[3] = "hvm"; keir@21438: vments[4] = "start_time"; ian@22164: vments[5] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); keir@20462: } else { ian@22164: vments = libxl__calloc(&gc, 11, sizeof(char *)); keir@20627: i = 0; keir@20627: vments[i++] = "image/ostype"; keir@20627: vments[i++] = "linux"; keir@20627: vments[i++] = "image/kernel"; Ian@21848: vments[i++] = (char*) info->kernel.path; keir@21438: vments[i++] = "start_time"; ian@22164: vments[i++] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); Ian@21848: if (info->u.pv.ramdisk.path) { keir@20627: vments[i++] = "image/ramdisk"; Ian@21848: vments[i++] = (char*) info->u.pv.ramdisk.path; keir@20627: } keir@20627: if (info->u.pv.cmdline) { keir@20627: vments[i++] = "image/cmdline"; keir@20627: vments[i++] = (char*) info->u.pv.cmdline; keir@20627: } keir@20462: } ian@22165: ret = libxl__build_post(ctx, domid, info, state, vments, localents); gianni@22023: if (ret) gianni@22023: goto out; keir@20829: keir@21417: dm_info->saved_state = NULL; keir@21417: if (info->hvm) { keir@21417: ret = asprintf(&dm_info->saved_state, keir@21417: "/var/lib/xen/qemu-save.%d", domid); keir@21417: ret = (ret < 0) ? ERROR_FAIL : 0; keir@21417: } keir@21417: keir@20829: out: ian@22082: libxl__file_reference_unmap(&info->kernel); Ian@21848: if (!info->hvm) ian@22082: libxl__file_reference_unmap(&info->u.pv.ramdisk); Ian@21848: keir@21183: esave = errno; keir@21183: keir@21183: flags = fcntl(fd, F_GETFL); keir@21183: if (flags == -1) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to get flags on restore fd"); keir@21183: } else { keir@21183: flags &= ~O_NONBLOCK; keir@21183: if (fcntl(fd, F_SETFL, flags) == -1) ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to put restore fd" keir@21183: " back to blocking mode"); keir@21183: } keir@21183: keir@21183: errno = esave; ian@22164: libxl__free_all(&gc); keir@20829: return ret; keir@20462: } keir@20462: ian@21930: int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid) keir@20629: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); gianni@22023: int rc = 0; gianni@22023: ian@22165: if (libxl__domain_is_hvm(ctx, domid)) { ian@22165: LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Called domain_resume on " keir@20629: "non-cooperative hvm domain %u", domid); gianni@22023: rc = ERROR_NI; gianni@22023: goto out; keir@20629: } keir@20629: if (xc_domain_resume(ctx->xch, domid, 1)) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, keir@20629: "xc_domain_resume failed for domain %u", keir@20629: domid); gianni@22023: rc = ERROR_FAIL; gianni@22023: goto out; keir@20629: } keir@20629: if (!xs_resume_domain(ctx->xsh, domid)) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, keir@20629: "xs_resume_domain failed for domain %u", keir@20629: domid); gianni@22023: rc = ERROR_FAIL; keir@20629: } gianni@22023: out: ian@22164: libxl__free_all(&gc); keir@20629: return 0; keir@20629: } keir@20629: ian@21920: /* ian@21920: * Preserves a domain but rewrites xenstore etc to make it unique so ian@21920: * that the domain can be restarted. ian@21920: * ian@21920: * Does not modify info so that it may be reused. ian@21920: */ ian@21930: int libxl_domain_preserve(libxl_ctx *ctx, uint32_t domid, Ian@21969: libxl_domain_create_info *info, const char *name_suffix, libxl_uuid new_uuid) ian@21920: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); ian@21920: struct xs_permissions roperm[2]; ian@21920: xs_transaction_t t; ian@21920: char *preserved_name; ian@21920: char *uuid_string; ian@21920: char *vm_path; ian@21920: char *dom_path; ian@21920: ian@21920: int rc; ian@21920: ian@22164: preserved_name = libxl__sprintf(&gc, "%s%s", info->name, name_suffix); gianni@22023: if (!preserved_name) { ian@22164: libxl__free_all(&gc); gianni@22023: return ERROR_NOMEM; gianni@22023: } ian@21920: ian@22164: uuid_string = libxl__uuid2string(&gc, new_uuid); gianni@22023: if (!uuid_string) { ian@22164: libxl__free_all(&gc); gianni@22023: return ERROR_NOMEM; gianni@22023: } gianni@22023: ian@22164: dom_path = libxl__xs_get_dompath(&gc, domid); gianni@22023: if (!dom_path) { ian@22164: libxl__free_all(&gc); gianni@22023: return ERROR_FAIL; gianni@22023: } gianni@22023: ian@22164: vm_path = libxl__sprintf(&gc, "/vm/%s", uuid_string); gianni@22023: if (!vm_path) { ian@22164: libxl__free_all(&gc); gianni@22023: return ERROR_FAIL; gianni@22023: } ian@21920: ian@21920: roperm[0].id = 0; ian@21920: roperm[0].perms = XS_PERM_NONE; ian@21920: roperm[1].id = domid; ian@21920: roperm[1].perms = XS_PERM_READ; ian@21920: ian@21920: retry_transaction: ian@21920: t = xs_transaction_start(ctx->xsh); ian@21920: ian@21920: xs_rm(ctx->xsh, t, vm_path); ian@21920: xs_mkdir(ctx->xsh, t, vm_path); ian@21920: xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm)); ian@21920: ian@22164: xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/vm", dom_path), vm_path, strlen(vm_path)); ian@21920: rc = libxl_domain_rename(ctx, domid, info->name, preserved_name, t); juergen@22549: if (rc) { juergen@22549: libxl__free_all(&gc); juergen@22549: return rc; juergen@22549: } ian@21920: ian@22164: xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/uuid", vm_path), uuid_string, strlen(uuid_string)); ian@21920: ian@21920: if (!xs_transaction_end(ctx->xsh, t, 0)) ian@21920: if (errno == EAGAIN) ian@21920: goto retry_transaction; ian@21920: ian@22164: libxl__free_all(&gc); ian@21920: return 0; ian@21920: } ian@21920: keir@21189: static void xcinfo2xlinfo(const xc_domaininfo_t *xcinfo, ian@21930: libxl_dominfo *xlinfo) ian@21895: { keir@21189: memcpy(&(xlinfo->uuid), xcinfo->handle, sizeof(xen_domain_handle_t)); keir@21189: xlinfo->domid = xcinfo->domain; keir@21189: ian@21895: xlinfo->dying = !!(xcinfo->flags&XEN_DOMINF_dying); ian@21895: xlinfo->shutdown = !!(xcinfo->flags&XEN_DOMINF_shutdown); ian@21895: xlinfo->paused = !!(xcinfo->flags&XEN_DOMINF_paused); ian@21895: xlinfo->blocked = !!(xcinfo->flags&XEN_DOMINF_blocked); ian@21895: xlinfo->running = !!(xcinfo->flags&XEN_DOMINF_running); ian@21914: ian@21914: if (xlinfo->shutdown || xlinfo->dying) ian@21914: xlinfo->shutdown_reason = (xcinfo->flags>>XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask; ian@21914: else ian@21914: xlinfo->shutdown_reason = ~0; ian@21895: stefano@22241: xlinfo->current_memkb = PAGE_TO_MEMKB(xcinfo->tot_pages); stefano@22241: xlinfo->max_memkb = PAGE_TO_MEMKB(xcinfo->max_pages); keir@21189: xlinfo->cpu_time = xcinfo->cpu_time; keir@21189: xlinfo->vcpu_max_id = xcinfo->max_vcpu_id; keir@21189: xlinfo->vcpu_online = xcinfo->nr_online_vcpus; keir@21189: } keir@21189: ian@21930: libxl_dominfo * libxl_list_domain(libxl_ctx *ctx, int *nb_domain) keir@20462: { ian@21930: libxl_dominfo *ptr; keir@20867: int i, ret; keir@20822: xc_domaininfo_t info[1024]; keir@20822: int size = 1024; keir@20462: ian@21930: ptr = calloc(size, sizeof(libxl_dominfo)); gianni@21892: if (!ptr) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating domain info"); gianni@21892: return NULL; gianni@21892: } keir@20822: keir@20860: ret = xc_domain_getinfolist(ctx->xch, 0, 1024, info); gianni@21892: if (ret<0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "geting domain info list"); gianni@21892: return NULL; gianni@21892: } keir@20784: keir@21189: for (i = 0; i < ret; i++) { keir@21189: xcinfo2xlinfo(&info[i], &ptr[i]); keir@20462: } keir@20867: *nb_domain = ret; keir@20462: return ptr; keir@20462: } keir@20462: ian@21930: int libxl_domain_info(libxl_ctx *ctx, libxl_dominfo *info_r, keir@21189: uint32_t domid) { keir@21189: xc_domaininfo_t xcinfo; keir@21189: int ret; keir@21189: keir@21189: ret = xc_domain_getinfolist(ctx->xch, domid, 1, &xcinfo); gianni@21892: if (ret<0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "geting domain info list"); gianni@21892: return ERROR_FAIL; gianni@21892: } keir@21189: if (ret==0 || xcinfo.domain != domid) return ERROR_INVAL; keir@21189: keir@21189: xcinfo2xlinfo(&xcinfo, info_r); keir@21189: return 0; keir@21189: } keir@21189: juergen@22319: libxl_cpupoolinfo * libxl_list_cpupool(libxl_ctx *ctx, int *nb_pool) keir@21368: { juergen@22319: libxl_cpupoolinfo *ptr, *tmp; juergen@22396: int i; juergen@22317: xc_cpupoolinfo_t *info; juergen@22317: uint32_t poolid; juergen@22317: juergen@22317: ptr = NULL; juergen@22317: juergen@22317: poolid = 0; juergen@22317: for (i = 0;; i++) { juergen@22317: info = xc_cpupool_getinfo(ctx->xch, poolid); juergen@22317: if (info == NULL) juergen@22317: break; juergen@22319: tmp = realloc(ptr, (i + 1) * sizeof(libxl_cpupoolinfo)); juergen@22317: if (!tmp) { juergen@22317: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating cpupool info"); juergen@22317: free(ptr); juergen@22396: xc_cpupool_infofree(ctx->xch, info); juergen@22317: return NULL; juergen@22317: } juergen@22317: ptr = tmp; juergen@22317: ptr[i].poolid = info->cpupool_id; juergen@22319: ptr[i].sched_id = info->sched_id; juergen@22319: ptr[i].n_dom = info->n_dom; juergen@22396: if (libxl_cpumap_alloc(ctx, &ptr[i].cpumap)) { juergen@22396: xc_cpupool_infofree(ctx->xch, info); juergen@22319: break; juergen@22396: } juergen@22396: memcpy(ptr[i].cpumap.map, info->cpumap, ptr[i].cpumap.size); juergen@22317: poolid = info->cpupool_id + 1; juergen@22396: xc_cpupool_infofree(ctx->xch, info); gianni@21892: } keir@21368: juergen@22317: *nb_pool = i; keir@21368: return ptr; keir@21368: } keir@21368: keir@20860: /* this API call only list VM running on this host. a VM can be an aggregate of multiple domains. */ ian@21930: libxl_vminfo * libxl_list_vm(libxl_ctx *ctx, int *nb_vm) keir@20860: { ian@21930: libxl_vminfo *ptr; keir@20860: int index, i, ret; keir@20860: xc_domaininfo_t info[1024]; keir@20860: int size = 1024; keir@20860: ian@21930: ptr = calloc(size, sizeof(libxl_dominfo)); keir@20860: if (!ptr) keir@20860: return NULL; keir@20860: keir@20860: ret = xc_domain_getinfolist(ctx->xch, 1, 1024, info); gianni@21892: if (ret<0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "geting domain info list"); gianni@21892: return NULL; gianni@21892: } keir@20860: for (index = i = 0; i < ret; i++) { keir@20860: if (libxl_is_stubdom(ctx, info[i].domain, NULL)) keir@20860: continue; keir@20860: memcpy(&(ptr[index].uuid), info[i].handle, sizeof(xen_domain_handle_t)); keir@20860: ptr[index].domid = info[i].domain; keir@20860: keir@20860: index++; keir@20860: } keir@20860: *nb_vm = index; keir@20860: return ptr; keir@20860: } keir@20860: ian@21930: int libxl_domain_suspend(libxl_ctx *ctx, libxl_domain_suspend_info *info, keir@20462: uint32_t domid, int fd) keir@20462: { ian@22165: int hvm = libxl__domain_is_hvm(ctx, domid); keir@20565: int live = info != NULL && info->flags & XL_SUSPEND_LIVE; keir@21543: int debug = info != NULL && info->flags & XL_SUSPEND_DEBUG; gianni@22023: int rc = 0; keir@20462: ian@22371: rc = libxl__domain_suspend_common(ctx, domid, fd, hvm, live, debug); ian@22371: if (!rc && hvm) ian@22165: rc = libxl__domain_save_device_model(ctx, domid, fd); gianni@22023: return rc; keir@20462: } keir@20462: ian@21930: int libxl_domain_pause(libxl_ctx *ctx, uint32_t domid) keir@20462: { gianni@21892: int ret; gianni@21892: ret = xc_domain_pause(ctx->xch, domid); gianni@21892: if (ret<0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "pausing domain %d", domid); gianni@21892: return ERROR_FAIL; gianni@21892: } Ian@21888: return 0; keir@20462: } keir@20462: ian@21930: int libxl_domain_core_dump(libxl_ctx *ctx, uint32_t domid, gianni@21892: const char *filename) sstabellini@21870: { gianni@21892: int ret; gianni@21892: ret = xc_domain_dumpcore(ctx->xch, domid, filename); gianni@21892: if (ret<0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "core dumping domain %d to %s", gianni@21892: domid, filename); Ian@21888: return ERROR_FAIL; gianni@21892: } Ian@21888: return 0; sstabellini@21870: } sstabellini@21870: ian@21930: int libxl_domain_unpause(libxl_ctx *ctx, uint32_t domid) keir@20462: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@20779: char *path; keir@20565: char *state; gianni@22023: int ret, rc = 0; keir@20565: ian@22165: if (libxl__domain_is_hvm(ctx, domid)) { ian@22164: path = libxl__sprintf(&gc, "/local/domain/0/device-model/%d/state", domid); ian@22164: state = libxl__xs_read(&gc, XBT_NULL, path); keir@20565: if (state != NULL && !strcmp(state, "paused")) { ian@22164: libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/0/device-model/%d/command", domid), "continue"); ian@22164: libxl__wait_for_device_model(ctx, domid, "running", NULL, NULL); keir@20565: } keir@20565: } gianni@21892: ret = xc_domain_unpause(ctx->xch, domid); gianni@21892: if (ret<0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unpausing domain %d", domid); gianni@22023: rc = ERROR_FAIL; gianni@21892: } ian@22164: libxl__free_all(&gc); gianni@22023: return rc; keir@20462: } keir@20462: keir@20462: static char *req_table[] = { keir@20462: [0] = "poweroff", keir@20462: [1] = "reboot", keir@20462: [2] = "suspend", keir@20462: [3] = "crash", keir@20462: [4] = "halt", keir@20462: }; keir@20462: ian@21930: int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid, int req) keir@20462: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@20462: char *shutdown_path; keir@20462: char *dom_path; keir@20462: gianni@22023: if (req > ARRAY_SIZE(req_table)) { ian@22164: libxl__free_all(&gc); keir@20462: return ERROR_INVAL; gianni@22023: } gianni@22023: ian@22164: dom_path = libxl__xs_get_dompath(&gc, domid); gianni@22023: if (!dom_path) { ian@22164: libxl__free_all(&gc); keir@20512: return ERROR_FAIL; gianni@22023: } gianni@22023: ian@22164: shutdown_path = libxl__sprintf(&gc, "%s/control/shutdown", dom_path); keir@20462: keir@20462: xs_write(ctx->xsh, XBT_NULL, shutdown_path, req_table[req], strlen(req_table[req])); ian@22165: if (libxl__domain_is_hvm(ctx,domid)) { keir@20462: unsigned long acpi_s_state = 0; keir@20462: unsigned long pvdriver = 0; gianni@21892: int ret; gianni@21892: ret = xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_ACPI_S_STATE, &acpi_s_state); gianni@21892: if (ret<0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting ACPI S-state"); juergen@22549: libxl__free_all(&gc); gianni@21892: return ERROR_FAIL; gianni@21892: } gianni@21892: ret = xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver); gianni@21892: if (ret<0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting HVM callback IRQ"); juergen@22549: libxl__free_all(&gc); gianni@21892: return ERROR_FAIL; gianni@21892: } gianni@21892: if (!pvdriver || acpi_s_state != 0) { gianni@21892: ret = xc_domain_shutdown(ctx->xch, domid, req); gianni@21892: if (ret<0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unpausing domain"); juergen@22549: libxl__free_all(&gc); gianni@21892: return ERROR_FAIL; gianni@21892: } gianni@21892: } keir@20462: } ian@22164: libxl__free_all(&gc); Ian@21888: return 0; keir@20462: } keir@20462: ian@21930: int libxl_get_wait_fd(libxl_ctx *ctx, int *fd) keir@20545: { keir@20545: *fd = xs_fileno(ctx->xsh); keir@20545: return 0; keir@20545: } keir@20545: ian@21930: int libxl_wait_for_domain_death(libxl_ctx *ctx, uint32_t domid, libxl_waiter *waiter) keir@20637: { keir@20637: waiter->path = strdup("@releaseDomain"); ian@21913: if (asprintf(&(waiter->token), "%d", LIBXL_EVENT_DOMAIN_DEATH) < 0) keir@21417: return -1; keir@20637: if (!xs_watch(ctx->xsh, waiter->path, waiter->token)) keir@20637: return -1; keir@20637: return 0; keir@20637: } keir@20637: ian@21930: 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: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); gianni@22023: int i, rc = -1; keir@20637: uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid); keir@20637: keir@20637: if (!domid) keir@20637: domid = guest_domid; keir@20637: keir@20637: for (i = 0; i < num_disks; i++) { keir@21417: if (asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject", ian@22164: libxl__xs_get_dompath(&gc, domid), ian@22165: libxl__device_disk_dev_number(disks[i].virtpath)) < 0) gianni@22023: goto out; ian@21913: if (asprintf(&(waiter[i].token), "%d", LIBXL_EVENT_DISK_EJECT) < 0) gianni@22023: goto out; keir@20637: xs_watch(ctx->xsh, waiter->path, waiter->token); keir@20637: } gianni@22023: rc = 0; gianni@22023: out: ian@22164: libxl__free_all(&gc); gianni@22023: return rc; keir@20637: } keir@20637: ian@21930: int libxl_get_event(libxl_ctx *ctx, libxl_event *event) keir@20545: { keir@20545: unsigned int num; keir@20637: char **events = xs_read_watch(ctx->xsh, &num); keir@20637: if (num != 2) { keir@20637: free(events); gianni@21892: return ERROR_FAIL; keir@20637: } keir@20637: event->path = strdup(events[XS_WATCH_PATH]); keir@20637: event->token = strdup(events[XS_WATCH_TOKEN]); keir@20637: event->type = atoi(event->token); keir@20637: free(events); keir@20637: return 0; keir@20637: } keir@20637: ian@21930: int libxl_stop_waiting(libxl_ctx *ctx, libxl_waiter *waiter) keir@20637: { keir@20637: if (!xs_unwatch(ctx->xsh, waiter->path, waiter->token)) gianni@21892: return ERROR_FAIL; keir@20637: else keir@20637: return 0; keir@20637: } keir@20637: keir@20637: int libxl_free_event(libxl_event *event) keir@20637: { keir@20637: free(event->path); keir@20637: free(event->token); keir@20637: return 0; keir@20637: } keir@20637: keir@20637: int libxl_free_waiter(libxl_waiter *waiter) keir@20637: { keir@20637: free(waiter->path); keir@20637: free(waiter->token); keir@20637: return 0; keir@20637: } keir@20637: ian@21930: int libxl_event_get_domain_death_info(libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_dominfo *info) keir@20637: { ian@21916: if (libxl_domain_info(ctx, info, domid) < 0) ian@21916: return 0; ian@21916: ian@21916: if (info->running || (!info->shutdown && !info->dying)) ian@21916: return ERROR_INVAL; ian@21916: ian@21916: return 1; keir@20545: } keir@20545: ian@21930: int libxl_event_get_disk_eject_info(libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_device_disk *disk) keir@20637: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); ian@21916: char *path; ian@21916: char *backend; ian@21916: char *value; ian@21916: ian@22164: value = libxl__xs_read(&gc, XBT_NULL, event->path); gianni@22023: gianni@22023: if (!value || strcmp(value, "eject")) { ian@22164: libxl__free_all(&gc); ian@21916: return 0; gianni@22023: } ian@21916: ian@21916: path = strdup(event->path); ian@21916: path[strlen(path) - 6] = '\0'; ian@22164: backend = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/backend", path)); ian@21916: ian@21916: disk->backend_domid = 0; ian@21916: disk->domid = domid; ian@21916: disk->physpath = NULL; ian@21916: disk->phystype = 0; ian@21916: /* this value is returned to the user: do not free right away */ ian@22164: disk->virtpath = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/dev", backend)); ian@21916: disk->unpluggable = 1; ian@21916: disk->readwrite = 0; ian@21916: disk->is_cdrom = 1; ian@21916: ian@21916: free(path); ian@22164: libxl__free_all(&gc); ian@21916: return 1; keir@20637: } keir@20637: ian@21930: int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid, int force) keir@20462: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@20801: char *dom_path; ian@21894: char *vm_path; keir@20628: int rc, dm_present; keir@20628: ian@22165: if (libxl__domain_is_hvm(ctx, domid)) { keir@20628: dm_present = 1; keir@20628: } else { keir@20628: char *pid; ian@22164: pid = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/image/device-model-pid", domid)); keir@20628: dm_present = (pid != NULL); keir@20628: } keir@20462: ian@22164: dom_path = libxl__xs_get_dompath(&gc, domid); gianni@22023: if (!dom_path) { gianni@22023: rc = ERROR_FAIL; gianni@22023: goto out; gianni@22023: } keir@20512: keir@20482: if (libxl_device_pci_shutdown(ctx, domid) < 0) ian@22165: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "pci shutdown failed for domid %d", domid); keir@20628: if (dm_present) { keir@20628: xs_write(ctx->xsh, XBT_NULL, ian@22164: libxl__sprintf(&gc, "/local/domain/0/device-model/%d/command", domid), keir@20628: "shutdown", strlen("shutdown")); keir@20628: } keir@20512: rc = xc_domain_pause(ctx->xch, domid); keir@20512: if (rc < 0) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_domain_pause failed for %d", domid); keir@20462: } keir@20628: if (dm_present) { gianni@22725: if (libxl__destroy_device_model(ctx, domid) < 0) gianni@22725: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "libxl__destroy_device_model failed for %d", domid); keir@20628: } ian@22164: if (libxl__devices_destroy(ctx, domid, force) < 0) ian@22165: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "libxl_destroy_devices failed for %d", domid); ian@21891: ian@22164: vm_path = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/vm", dom_path)); keir@20823: if (vm_path) keir@20823: if (!xs_rm(ctx->xsh, XBT_NULL, vm_path)) ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xs_rm failed for %s", vm_path); keir@20779: ian@21891: if (!xs_rm(ctx->xsh, XBT_NULL, dom_path)) ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xs_rm failed for %s", dom_path); ian@21891: keir@21190: libxl__userdata_destroyall(ctx, domid); keir@21190: keir@20545: rc = xc_domain_destroy(ctx->xch, domid); keir@20545: if (rc < 0) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid); gianni@22023: rc = ERROR_FAIL; gianni@22023: goto out; keir@20545: } gianni@22023: rc = 0; gianni@22023: out: ian@22164: libxl__free_all(&gc); keir@20462: return 0; keir@20462: } keir@20462: stefano@22040: int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num, libxl_console_constype type) keir@20564: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); ian@22164: char *p = libxl__sprintf(&gc, "%s/xenconsole", libxl_private_bindir_path()); ian@22164: char *domid_s = libxl__sprintf(&gc, "%d", domid); ian@22164: char *cons_num_s = libxl__sprintf(&gc, "%d", cons_num); stefano@22040: char *cons_type_s; stefano@22040: ian@22071: switch (type) { ian@22071: case LIBXL_CONSTYPE_PV: stefano@22040: cons_type_s = "pv"; ian@22071: break; ian@22071: case LIBXL_CONSTYPE_SERIAL: stefano@22040: cons_type_s = "serial"; ian@22071: break; ian@22071: default: ian@22071: goto out; ian@22071: } stefano@22040: stefano@22040: execl(p, p, domid_s, "--num", cons_num_s, "--type", cons_type_s, (void *)NULL); ian@22071: ian@22071: out: ian@22164: libxl__free_all(&gc); gianni@22023: return ERROR_FAIL; keir@20564: } keir@20564: ian@21930: int libxl_primary_console_exec(libxl_ctx *ctx, uint32_t domid_vm) sstabellini@21867: { sstabellini@21867: uint32_t stubdomid = libxl_get_stubdom_id(ctx, domid_vm); sstabellini@21867: if (stubdomid) stefano@22040: return libxl_console_exec(ctx, stubdomid, 1, LIBXL_CONSTYPE_PV); stefano@22040: else { ian@22165: if (libxl__domain_is_hvm(ctx, domid_vm)) stefano@22040: return libxl_console_exec(ctx, domid_vm, 0, LIBXL_CONSTYPE_SERIAL); stefano@22040: else stefano@22040: return libxl_console_exec(ctx, domid_vm, 0, LIBXL_CONSTYPE_PV); stefano@22040: } sstabellini@21867: } sstabellini@21867: ian@21930: int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass) sstabellini@21879: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); sstabellini@21879: const char *vnc_port, *vfb_back; sstabellini@21879: const char *vnc_listen = NULL, *vnc_pass = NULL; sstabellini@21879: int port = 0, autopass_fd = -1; sstabellini@21879: char *vnc_bin, *args[] = { sstabellini@21879: "vncviewer", sstabellini@21879: NULL, /* hostname:display */ sstabellini@21879: NULL, /* -autopass */ sstabellini@21879: NULL, sstabellini@21879: }; sstabellini@21879: ian@22164: vnc_port = libxl__xs_read(&gc, XBT_NULL, ian@22164: libxl__sprintf(&gc, sstabellini@21879: "/local/domain/%d/console/vnc-port", domid)); sstabellini@21879: if ( vnc_port ) sstabellini@21879: port = atoi(vnc_port) - 5900; sstabellini@21879: ian@22164: vfb_back = libxl__xs_read(&gc, XBT_NULL, ian@22164: libxl__sprintf(&gc, sstabellini@21879: "/local/domain/%d/device/vfb/0/backend", domid)); sstabellini@21879: if ( vfb_back ) { ian@22164: vnc_listen = libxl__xs_read(&gc, XBT_NULL, ian@22164: libxl__sprintf(&gc, sstabellini@21879: "/local/domain/%d/console/vnc-listen", domid)); sstabellini@21879: if ( autopass ) ian@22164: vnc_pass = libxl__xs_read(&gc, XBT_NULL, ian@22164: libxl__sprintf(&gc, sstabellini@21879: "/local/domain/%d/console/vnc-pass", domid)); sstabellini@21879: } sstabellini@21879: sstabellini@21879: if ( NULL == vnc_listen ) sstabellini@21879: vnc_listen = "localhost"; sstabellini@21879: sstabellini@21879: if ( (vnc_bin = getenv("VNCVIEWER")) ) sstabellini@21879: args[0] = vnc_bin; sstabellini@21879: ian@22164: args[1] = libxl__sprintf(&gc, "%s:%d", vnc_listen, port); sstabellini@21879: sstabellini@21879: if ( vnc_pass ) { sstabellini@21879: char tmpname[] = "/tmp/vncautopass.XXXXXX"; sstabellini@21879: autopass_fd = mkstemp(tmpname); sstabellini@21879: if ( autopass_fd < 0 ) sstabellini@21879: goto skip_autopass; sstabellini@21879: sstabellini@21879: if ( unlink(tmpname) ) sstabellini@21879: /* should never happen */ ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unlink %s failed", tmpname); sstabellini@21879: sstabellini@21879: if ( libxl_write_exactly(ctx, autopass_fd, vnc_pass, strlen(vnc_pass), sstabellini@21879: tmpname, "vnc password") ) { sstabellini@21879: do { close(autopass_fd); } while(errno == EINTR); sstabellini@21879: goto skip_autopass; sstabellini@21879: } sstabellini@21879: sstabellini@21879: args[2] = "-autopass"; sstabellini@21879: } sstabellini@21879: sstabellini@21879: skip_autopass: ian@22164: libxl__free_all(&gc); ian@22164: libxl__exec(autopass_fd, -1, -1, args[0], args); sstabellini@21879: return 0; sstabellini@21879: } sstabellini@21879: keir@20462: /******************************************************************************/ keir@20566: ian@21930: int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk) keir@20462: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@20462: flexarray_t *front; keir@20462: flexarray_t *back; keir@20462: char *backend_type; keir@20462: int devid; ian@22167: libxl__device device; gianni@22023: int major, minor, rc; keir@20462: keir@20462: front = flexarray_make(16, 1); gianni@22023: if (!front) { gianni@22023: rc = ERROR_NOMEM; gianni@22023: goto out; gianni@22023: } keir@20462: back = flexarray_make(16, 1); gianni@22023: if (!back) { gianni@22023: rc = ERROR_NOMEM; gianni@22023: goto out_free; gianni@22023: } keir@20462: ian@22165: backend_type = libxl__device_disk_backend_type_of_phystype(disk->phystype); ian@22165: devid = libxl__device_disk_dev_number(disk->virtpath); keir@20947: if (devid==-1) { ian@22165: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Invalid or unsupported" keir@20947: " virtual disk identifier %s", disk->virtpath); gianni@22023: rc = ERROR_INVAL; gianni@22023: goto out_free; keir@20947: } keir@20462: keir@20462: device.backend_devid = devid; keir@20462: device.backend_domid = disk->backend_domid; keir@20462: device.devid = devid; keir@20462: device.domid = disk->domid; keir@20462: device.kind = DEVICE_VBD; keir@20462: keir@20462: switch (disk->phystype) { keir@20462: case PHYSTYPE_PHY: { keir@20462: ian@22165: libxl__device_physdisk_major_minor(disk->physpath, &major, &minor); gianni@22726: flexarray_append(back, "physical-device"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%x:%x", major, minor)); gianni@22726: gianni@22726: flexarray_append(back, "params"); gianni@22726: flexarray_append(back, disk->physpath); keir@20462: keir@20462: device.backend_kind = DEVICE_VBD; keir@20462: break; keir@20462: } keir@20566: case PHYSTYPE_FILE: keir@20566: /* let's pretend is tap:aio for the moment */ keir@20566: disk->phystype = PHYSTYPE_AIO; Christoph@22044: case PHYSTYPE_AIO: Christoph@22044: case PHYSTYPE_QCOW: Christoph@22044: case PHYSTYPE_QCOW2: Christoph@22044: case PHYSTYPE_VHD: ian@22165: if (libxl__blktap_enabled(&gc)) { ian@22165: const char *dev = libxl__blktap_devpath(&gc, Christoph@22044: disk->physpath, disk->phystype); gianni@22023: if (!dev) { gianni@22023: rc = ERROR_FAIL; gianni@22023: goto out_free; gianni@22023: } gianni@22726: flexarray_append(back, "tapdisk-params"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%s:%s", libxl__device_disk_string_of_phystype(disk->phystype), disk->physpath)); gianni@22726: flexarray_append(back, "params"); gianni@22726: flexarray_append(back, libxl__strdup(&gc, dev)); keir@20566: backend_type = "phy"; ian@22165: libxl__device_physdisk_major_minor(dev, &major, &minor); gianni@22726: flexarray_append(back, "physical-device"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%x:%x", major, minor)); keir@20566: device.backend_kind = DEVICE_VBD; keir@20566: keir@20566: break; keir@20566: } gianni@22726: flexarray_append(back, "params"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%s:%s", ian@22165: libxl__device_disk_string_of_phystype(disk->phystype), disk->physpath)); keir@20462: stefano@22468: if (libxl__blktap_enabled(&gc)) stefano@22468: device.backend_kind = DEVICE_TAP; stefano@22468: else stefano@22468: device.backend_kind = DEVICE_QDISK; keir@20462: break; Christoph@22044: keir@20846: default: ian@22165: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk physical type: %d\n", disk->phystype); gianni@22023: rc = ERROR_INVAL; gianni@22023: goto out_free; keir@20462: } keir@20462: gianni@22726: flexarray_append(back, "frontend-id"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", disk->domid)); gianni@22726: flexarray_append(back, "online"); gianni@22726: flexarray_append(back, "1"); gianni@22726: flexarray_append(back, "removable"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", (disk->unpluggable) ? 1 : 0)); gianni@22726: flexarray_append(back, "bootable"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", 1)); gianni@22726: flexarray_append(back, "state"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", 1)); gianni@22726: flexarray_append(back, "dev"); gianni@22726: flexarray_append(back, disk->virtpath); gianni@22726: flexarray_append(back, "type"); gianni@22726: flexarray_append(back, backend_type); gianni@22726: flexarray_append(back, "mode"); gianni@22726: flexarray_append(back, disk->readwrite ? "w" : "r"); gianni@22726: gianni@22726: flexarray_append(front, "backend-id"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", disk->backend_domid)); gianni@22726: flexarray_append(front, "state"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", 1)); gianni@22726: flexarray_append(front, "virtual-device"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", devid)); gianni@22726: flexarray_append(front, "device-type"); gianni@22726: flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk"); keir@20462: keir@20462: if (0 /* protocol != native*/) { gianni@22726: flexarray_append(front, "protocol"); gianni@22726: flexarray_append(front, "x86_32-abi"); /* hardcoded ! */ keir@20462: } keir@20462: ian@22164: libxl__device_generic_add(ctx, &device, gianni@22726: libxl__xs_kvs_of_flexarray(&gc, back, back->count), gianni@22726: libxl__xs_kvs_of_flexarray(&gc, front, front->count)); gianni@22023: gianni@22023: rc = 0; gianni@22023: gianni@22023: out_free: keir@20516: flexarray_free(back); keir@20516: flexarray_free(front); gianni@22023: out: ian@22164: libxl__free_all(&gc); gianni@22023: return rc; keir@20462: } keir@20462: ian@21930: int libxl_device_disk_del(libxl_ctx *ctx, keir@20626: libxl_device_disk *disk, int wait) keir@20462: { ian@22167: libxl__device device; keir@20626: int devid; keir@20462: ian@22165: devid = libxl__device_disk_dev_number(disk->virtpath); keir@20626: device.backend_domid = disk->backend_domid; keir@20626: device.backend_devid = devid; keir@20626: device.backend_kind = keir@20626: (disk->phystype == PHYSTYPE_PHY) ? DEVICE_VBD : DEVICE_TAP; keir@20626: device.domid = disk->domid; keir@20626: device.devid = devid; keir@20626: device.kind = DEVICE_VBD; ian@22164: return libxl__device_del(ctx, &device, wait); keir@20462: } keir@20462: gianni@22023: char * libxl_device_disk_local_attach(libxl_ctx *ctx, libxl_device_disk *disk) Ian@21849: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); Christoph@22044: const char *dev = NULL; Christoph@22044: char *ret; Ian@21849: int phystype = disk->phystype; Ian@21849: switch (phystype) { Ian@21849: case PHYSTYPE_PHY: { Ian@21849: fprintf(stderr, "attaching PHY disk %s to domain 0\n", disk->physpath); Ian@21849: dev = disk->physpath; Ian@21849: break; Ian@21849: } Ian@21849: case PHYSTYPE_FILE: Ian@21849: /* let's pretend is tap:aio for the moment */ Ian@21849: phystype = PHYSTYPE_AIO; Christoph@22044: case PHYSTYPE_AIO: Christoph@22044: case PHYSTYPE_QCOW: Christoph@22044: case PHYSTYPE_QCOW2: Christoph@22044: case PHYSTYPE_VHD: ian@22165: if (libxl__blktap_enabled(&gc)) ian@22165: dev = libxl__blktap_devpath(&gc, disk->physpath, phystype); Ian@21849: break; Christoph@22044: Ian@21849: default: ian@22165: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk physical type: %d\n", phystype); Ian@21849: break; Ian@21849: } gianni@22023: ret = strdup(dev); ian@22164: libxl__free_all(&gc); gianni@22023: return ret; Ian@21849: } Ian@21849: ian@21930: int libxl_device_disk_local_detach(libxl_ctx *ctx, libxl_device_disk *disk) Ian@21849: { Ian@21849: /* Nothing to do for PHYSTYPE_PHY. */ Ian@21849: Ian@21849: /* Ian@21849: * For other device types assume that the blktap2 process is Ian@21849: * needed by the soon to be started domain and do nothing. Ian@21849: */ Ian@21849: Ian@21849: return 0; Ian@21849: } Ian@21849: keir@20462: /******************************************************************************/ ian@21930: int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic) keir@20462: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@20462: flexarray_t *front; keir@20462: flexarray_t *back; ian@22167: libxl__device device; keir@21407: char *dompath, **l; gianni@22023: unsigned int nb, rc; keir@20462: keir@20462: front = flexarray_make(16, 1); gianni@22023: if (!front) { gianni@22023: rc = ERROR_NOMEM; gianni@22023: goto out; gianni@22023: } keir@20462: back = flexarray_make(16, 1); gianni@22023: if (!back) { gianni@22023: rc = ERROR_NOMEM; gianni@22023: goto out_free; gianni@22023: } keir@20462: keir@21407: if (nic->devid == -1) { ian@22164: if (!(dompath = libxl__xs_get_dompath(&gc, domid))) { gianni@22023: rc = ERROR_FAIL; gianni@22023: goto out_free; keir@21407: } ian@22164: if (!(l = libxl__xs_directory(&gc, XBT_NULL, ian@22164: libxl__sprintf(&gc, "%s/device/vif", dompath), &nb))) { keir@21407: nic->devid = 0; keir@21407: } else { keir@21407: nic->devid = strtoul(l[nb - 1], NULL, 10) + 1; keir@21407: } keir@21407: } keir@21407: keir@20462: device.backend_devid = nic->devid; keir@20462: device.backend_domid = nic->backend_domid; keir@20462: device.backend_kind = DEVICE_VIF; keir@20462: device.devid = nic->devid; keir@20462: device.domid = nic->domid; keir@20462: device.kind = DEVICE_VIF; keir@20462: gianni@22726: flexarray_append(back, "frontend-id"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", nic->domid)); gianni@22726: flexarray_append(back, "online"); gianni@22726: flexarray_append(back, "1"); gianni@22726: flexarray_append(back, "state"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", 1)); gianni@22726: flexarray_append(back, "script"); gianni@22726: flexarray_append(back, nic->script); gianni@22726: flexarray_append(back, "mac"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x", keir@20462: nic->mac[0], nic->mac[1], nic->mac[2], keir@20462: nic->mac[3], nic->mac[4], nic->mac[5])); gianni@22726: flexarray_append(back, "bridge"); gianni@22726: flexarray_append(back, libxl__strdup(&gc, nic->bridge)); gianni@22726: flexarray_append(back, "handle"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", nic->devid)); gianni@22726: gianni@22726: flexarray_append(front, "backend-id"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", nic->backend_domid)); gianni@22726: flexarray_append(front, "state"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", 1)); gianni@22726: flexarray_append(front, "handle"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", nic->devid)); gianni@22726: flexarray_append(front, "mac"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x", keir@20462: nic->mac[0], nic->mac[1], nic->mac[2], keir@20462: nic->mac[3], nic->mac[4], nic->mac[5])); keir@20462: if (0 /* protocol != native*/) { gianni@22726: flexarray_append(front, "protocol"); gianni@22726: flexarray_append(front, "x86_32-abi"); /* hardcoded ! */ keir@20462: } keir@20462: ian@22164: libxl__device_generic_add(ctx, &device, gianni@22726: libxl__xs_kvs_of_flexarray(&gc, back, back->count), gianni@22726: libxl__xs_kvs_of_flexarray(&gc, front, front->count)); keir@20462: keir@20462: /* FIXME: wait for plug */ gianni@22023: rc = 0; gianni@22023: out_free: keir@20516: flexarray_free(back); keir@20516: flexarray_free(front); gianni@22023: out: ian@22164: libxl__free_all(&gc); gianni@22023: return rc; keir@20462: } keir@20462: ian@21930: int libxl_device_nic_del(libxl_ctx *ctx, keir@20626: libxl_device_nic *nic, int wait) keir@20462: { ian@22167: libxl__device device; keir@20462: keir@20626: device.backend_devid = nic->devid; keir@20626: device.backend_domid = nic->backend_domid; keir@20626: device.backend_kind = DEVICE_VIF; keir@20626: device.devid = nic->devid; keir@20626: device.domid = nic->domid; keir@20626: device.kind = DEVICE_VIF; keir@20626: ian@22164: return libxl__device_del(ctx, &device, wait); keir@20462: } keir@20462: ian@21930: libxl_nicinfo *libxl_list_nics(libxl_ctx *ctx, uint32_t domid, unsigned int *nb) keir@21408: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@21408: char *dompath, *nic_path_fe; gianni@22009: char **l, **list; keir@21408: char *val, *tok; keir@21408: unsigned int nb_nics, i; keir@21408: libxl_nicinfo *res, *nics; keir@21408: ian@22164: dompath = libxl__xs_get_dompath(&gc, domid); gianni@22023: if (!dompath) gianni@22023: goto err; ian@22164: list = l = libxl__xs_directory(&gc, XBT_NULL, ian@22164: libxl__sprintf(&gc, "%s/device/vif", dompath), &nb_nics); gianni@22023: if (!l) gianni@22023: goto err; gianni@22009: nics = res = calloc(nb_nics, sizeof (libxl_device_nic)); gianni@22023: if (!res) gianni@22023: goto err; keir@21408: for (*nb = nb_nics; nb_nics > 0; --nb_nics, ++l, ++nics) { ian@22164: nic_path_fe = libxl__sprintf(&gc, "%s/device/vif/%s", dompath, *l); keir@21408: gianni@22009: nics->backend = xs_read(ctx->xsh, XBT_NULL, ian@22164: libxl__sprintf(&gc, "%s/backend", nic_path_fe), NULL); ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/backend-id", nic_path_fe)); keir@21408: nics->backend_id = val ? strtoul(val, NULL, 10) : -1; keir@21408: keir@21408: nics->devid = strtoul(*l, NULL, 10); ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/state", nic_path_fe)); keir@21408: nics->state = val ? strtoul(val, NULL, 10) : -1; ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/mac", nic_path_fe)); keir@21408: for (i = 0, tok = strtok(val, ":"); tok && (i < 6); keir@21408: ++i, tok = strtok(NULL, ":")) { keir@21408: nics->mac[i] = strtoul(tok, NULL, 16); keir@21408: } ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/event-channel", nic_path_fe)); keir@21408: nics->evtch = val ? strtol(val, NULL, 10) : -1; ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/tx-ring-ref", nic_path_fe)); keir@21408: nics->rref_tx = val ? strtol(val, NULL, 10) : -1; ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/rx-ring-ref", nic_path_fe)); keir@21408: nics->rref_rx = val ? strtol(val, NULL, 10) : -1; gianni@22009: nics->frontend = xs_read(ctx->xsh, XBT_NULL, ian@22164: libxl__sprintf(&gc, "%s/frontend", nics->backend), NULL); ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/frontend-id", nics->backend)); keir@21408: nics->frontend_id = val ? strtoul(val, NULL, 10) : -1; gianni@22009: nics->script = xs_read(ctx->xsh, XBT_NULL, ian@22164: libxl__sprintf(&gc, "%s/script", nics->backend), NULL); keir@21408: } keir@21408: ian@22164: libxl__free_all(&gc); keir@21408: return res; gianni@22023: err: ian@22164: libxl__free_all(&gc); gianni@22023: return NULL; keir@21408: } keir@21408: keir@21580: /******************************************************************************/ ian@21930: int libxl_device_net2_add(libxl_ctx *ctx, uint32_t domid, libxl_device_net2 *net2) keir@21580: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@21580: flexarray_t *front, *back; ian@22167: libxl__device device; keir@21580: char *dompath, *dom, **l; keir@21580: unsigned int nb; gianni@22023: int rc; keir@21580: keir@21580: front = flexarray_make(16, 1); gianni@22023: if (!front) { gianni@22023: rc = ERROR_NOMEM; gianni@22023: goto err; gianni@22023: } keir@21580: back = flexarray_make(16, 1); gianni@22023: if (!back) { gianni@22023: rc = ERROR_NOMEM; gianni@22023: goto err_free; keir@21580: } gianni@22023: ian@22164: if (!(dompath = libxl__xs_get_dompath(&gc, domid))) { gianni@22023: rc = ERROR_FAIL; gianni@22023: goto err_free; gianni@22023: } ian@22164: dom = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/name", dompath)); keir@21580: keir@21580: if (net2->devid == -1) { ian@22164: if (!(l = libxl__xs_directory(&gc, XBT_NULL, ian@22164: libxl__sprintf(&gc, "%s/device/vif2", dompath), &nb))) { keir@21580: net2->devid = 0; keir@21580: } else { keir@21580: net2->devid = strtoul(l[nb - 1], NULL, 10) + 1; keir@21580: } keir@21580: } keir@21580: keir@21580: device.backend_devid = net2->devid; keir@21580: device.backend_domid = net2->backend_domid; keir@21580: device.backend_kind = DEVICE_VIF2; keir@21580: device.devid = net2->devid; keir@21580: device.domid = net2->domid; keir@21580: device.kind = DEVICE_VIF2; keir@21580: gianni@22726: flexarray_append(back, "domain"); gianni@22726: flexarray_append(back, dom); gianni@22726: flexarray_append(back, "frontend-id"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", net2->domid)); gianni@22726: gianni@22726: flexarray_append(back, "local-trusted"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", net2->back_trusted)); gianni@22726: flexarray_append(back, "mac"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x", keir@21580: net2->back_mac[0], net2->back_mac[1], keir@21580: net2->back_mac[2], net2->back_mac[3], keir@21580: net2->back_mac[4], net2->back_mac[5])); keir@21580: gianni@22726: flexarray_append(back, "remote-trusted"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", net2->trusted)); gianni@22726: flexarray_append(back, "remote-mac"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x", keir@21580: net2->front_mac[0], net2->front_mac[1], keir@21580: net2->front_mac[2], net2->front_mac[3], keir@21580: net2->front_mac[4], net2->front_mac[5])); keir@21580: gianni@22726: flexarray_append(back, "max-bypasses"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", net2->max_bypasses)); gianni@22726: flexarray_append(back, "filter-mac"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", !!(net2->filter_mac))); gianni@22726: flexarray_append(back, "handle"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", net2->devid)); gianni@22726: flexarray_append(back, "online"); gianni@22726: flexarray_append(back, "1"); gianni@22726: flexarray_append(back, "state"); gianni@22726: flexarray_append(back, "1"); gianni@22726: gianni@22726: flexarray_append(front, "backend-id"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", net2->backend_domid)); gianni@22726: gianni@22726: flexarray_append(front, "local-trusted"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", net2->trusted)); gianni@22726: flexarray_append(front, "mac"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x", keir@21580: net2->front_mac[0], net2->front_mac[1], keir@21580: net2->front_mac[2], net2->front_mac[3], keir@21580: net2->front_mac[4], net2->front_mac[5])); keir@21580: gianni@22726: flexarray_append(front, "remote-trusted"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", net2->back_trusted)); gianni@22726: flexarray_append(front, "remote-mac"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x", keir@21580: net2->back_mac[0], net2->back_mac[1], keir@21580: net2->back_mac[2], net2->back_mac[3], keir@21580: net2->back_mac[4], net2->back_mac[5])); keir@21580: gianni@22726: flexarray_append(front, "filter-mac"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", !!(net2->filter_mac))); gianni@22726: flexarray_append(front, "state"); gianni@22726: flexarray_append(front, "1"); keir@21580: ian@22164: libxl__device_generic_add(ctx, &device, gianni@22726: libxl__xs_kvs_of_flexarray(&gc, back, back->count), gianni@22726: libxl__xs_kvs_of_flexarray(&gc, front, front->count)); keir@21580: keir@21580: /* FIXME: wait for plug */ gianni@22023: rc = 0; gianni@22023: err_free: keir@21580: flexarray_free(back); keir@21580: flexarray_free(front); gianni@22023: err: ian@22164: libxl__free_all(&gc); gianni@22023: return rc; keir@21580: } keir@21408: ian@21930: libxl_net2info *libxl_device_net2_list(libxl_ctx *ctx, uint32_t domid, unsigned int *nb) keir@21581: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@21581: char *dompath, *net2_path_fe; keir@21581: char **l; keir@21581: char *val, *tok; keir@21581: unsigned int nb_net2s, i; keir@21581: libxl_net2info *res, *net2s; keir@21581: ian@22164: dompath = libxl__xs_get_dompath(&gc, domid); gianni@22023: if (!dompath) gianni@22023: goto err; ian@22164: l = libxl__xs_directory(&gc, XBT_NULL, ian@22164: libxl__sprintf(&gc, "%s/device/vif2", dompath), &nb_net2s); gianni@22023: if (!l) gianni@22023: goto err; gianni@22023: res = calloc(nb_net2s, sizeof (libxl_net2info)); gianni@22023: if (!res) gianni@22023: goto err; keir@21581: net2s = res; keir@21581: for (*nb = nb_net2s; nb_net2s > 0; --nb_net2s, ++l, ++net2s) { ian@22164: net2_path_fe = libxl__sprintf(&gc, "%s/device/vif2/%s", dompath, *l); ian@22164: ian@22164: net2s->backend = libxl__xs_read(&gc, XBT_NULL, ian@22164: libxl__sprintf(&gc, "%s/backend", net2_path_fe)); ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/backend-id", net2_path_fe)); keir@21581: net2s->backend_id = val ? strtoul(val, NULL, 10) : -1; keir@21581: keir@21581: net2s->devid = strtoul(*l, NULL, 10); ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/state", net2_path_fe)); keir@21581: net2s->state = val ? strtoul(val, NULL, 10) : -1; keir@21581: ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/mac", net2_path_fe)); keir@21581: for (i = 0, tok = strtok(val, ":"); tok && (i < 6); keir@21581: ++i, tok = strtok(NULL, ":")) { keir@21581: net2s->mac[i] = strtoul(tok, NULL, 16); keir@21581: } ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/remote-trusted", net2_path_fe)); keir@21581: net2s->trusted = val ? strtoul(val, NULL, 10) : -1; keir@21581: ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/remote-mac", net2_path_fe)); keir@21581: for (i = 0, tok = strtok(val, ":"); tok && (i < 6); keir@21581: ++i, tok = strtok(NULL, ":")) { keir@21581: net2s->back_mac[i] = strtoul(tok, NULL, 16); keir@21581: } ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/filter-mac", net2_path_fe)); keir@21581: net2s->filter_mac = val ? strtoul(val, NULL, 10) : -1; keir@21581: ian@22164: net2s->frontend = libxl__xs_read(&gc, XBT_NULL, ian@22164: libxl__sprintf(&gc, "%s/frontend", net2s->backend)); ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/frontend-id", net2s->backend)); keir@21581: net2s->frontend_id = val ? strtoul(val, NULL, 10) : -1; keir@21581: } keir@21581: ian@22164: libxl__free_all(&gc); keir@21581: return res; gianni@22023: err: ian@22164: libxl__free_all(&gc); gianni@22023: return NULL; keir@21581: } keir@21581: ian@21930: int libxl_device_net2_del(libxl_ctx *ctx, libxl_device_net2 *net2, int wait) keir@21582: { ian@22167: libxl__device device; keir@21582: keir@21582: device.backend_devid = net2->devid; keir@21582: device.backend_domid = net2->backend_domid; keir@21582: device.backend_kind = DEVICE_VIF2; keir@21582: device.devid = net2->devid; keir@21582: device.domid = net2->domid; keir@21582: device.kind = DEVICE_VIF2; keir@21582: ian@22164: return libxl__device_del(ctx, &device, wait); keir@21582: } keir@21582: keir@21581: keir@20462: /******************************************************************************/ ian@21930: int libxl_device_console_add(libxl_ctx *ctx, uint32_t domid, libxl_device_console *console) keir@20462: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@20509: flexarray_t *front; keir@20509: flexarray_t *back; ian@22167: libxl__device device; gianni@22023: int rc; keir@20509: keir@20509: front = flexarray_make(16, 1); gianni@22023: if (!front) { gianni@22023: rc = ERROR_NOMEM; gianni@22023: goto out; gianni@22023: } keir@20509: back = flexarray_make(16, 1); gianni@22023: if (!back) { gianni@22023: rc = ERROR_NOMEM; gianni@22023: goto out_free; gianni@22023: } keir@20509: keir@20509: device.backend_devid = console->devid; keir@20509: device.backend_domid = console->backend_domid; keir@20509: device.backend_kind = DEVICE_CONSOLE; keir@20509: device.devid = console->devid; keir@20509: device.domid = console->domid; keir@20509: device.kind = DEVICE_CONSOLE; keir@20509: gianni@22726: flexarray_append(back, "frontend-id"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", console->domid)); gianni@22726: flexarray_append(back, "online"); gianni@22726: flexarray_append(back, "1"); gianni@22726: flexarray_append(back, "state"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", 1)); gianni@22726: flexarray_append(back, "domain"); gianni@22726: flexarray_append(back, libxl__domid_to_name(&gc, domid)); gianni@22726: flexarray_append(back, "protocol"); gianni@22726: flexarray_append(back, LIBXL_XENCONSOLE_PROTOCOL); gianni@22726: gianni@22726: flexarray_append(front, "backend-id"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", console->backend_domid)); gianni@22726: flexarray_append(front, "limit"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT)); gianni@22726: flexarray_append(front, "type"); ian@22273: if (console->consback == LIBXL_CONSBACK_XENCONSOLED) gianni@22726: flexarray_append(front, "xenconsoled"); ian@22273: else gianni@22726: flexarray_append(front, "ioemu"); gianni@22726: flexarray_append(front, "output"); gianni@22726: flexarray_append(front, console->output); ian@22273: ian@22273: if (device.devid == 0) { ian@22273: if (console->build_state == NULL) { ian@22273: rc = ERROR_INVAL; ian@22273: goto out_free; ian@22273: } gianni@22726: flexarray_append(front, "port"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%"PRIu32, console->build_state->console_port)); gianni@22726: flexarray_append(front, "ring-ref"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%lu", console->build_state->console_mfn)); ian@22273: } else { gianni@22726: flexarray_append(front, "state"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", 1)); gianni@22726: flexarray_append(front, "protocol"); gianni@22726: flexarray_append(front, LIBXL_XENCONSOLE_PROTOCOL); stefano@22040: } keir@20509: ian@22164: libxl__device_generic_add(ctx, &device, gianni@22726: libxl__xs_kvs_of_flexarray(&gc, back, back->count), gianni@22726: libxl__xs_kvs_of_flexarray(&gc, front, front->count)); gianni@22023: rc = 0; gianni@22023: out_free: keir@20516: flexarray_free(back); keir@20516: flexarray_free(front); gianni@22023: out: ian@22164: libxl__free_all(&gc); gianni@22023: return rc; keir@20509: } keir@20509: keir@20509: /******************************************************************************/ ian@21930: int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb) keir@20509: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@20509: flexarray_t *front; keir@20509: flexarray_t *back; ian@22167: libxl__device device; gianni@22023: int rc; keir@20509: keir@20509: front = flexarray_make(16, 1); gianni@22023: if (!front) { gianni@22023: rc = ERROR_NOMEM; gianni@22023: goto out; gianni@22023: } keir@20509: back = flexarray_make(16, 1); gianni@22023: if (!back) { gianni@22023: rc = ERROR_NOMEM; gianni@22023: goto out_free; gianni@22023: } keir@20509: keir@20509: device.backend_devid = vkb->devid; keir@20509: device.backend_domid = vkb->backend_domid; keir@20509: device.backend_kind = DEVICE_VKBD; keir@20509: device.devid = vkb->devid; keir@20509: device.domid = vkb->domid; keir@20509: device.kind = DEVICE_VKBD; keir@20509: gianni@22726: flexarray_append(back, "frontend-id"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", vkb->domid)); gianni@22726: flexarray_append(back, "online"); gianni@22726: flexarray_append(back, "1"); gianni@22726: flexarray_append(back, "state"); gianni@22726: flexarray_append(back, libxl__sprintf(&gc, "%d", 1)); gianni@22726: flexarray_append(back, "domain"); gianni@22726: flexarray_append(back, libxl__domid_to_name(&gc, domid)); gianni@22726: gianni@22726: flexarray_append(front, "backend-id"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", vkb->backend_domid)); gianni@22726: flexarray_append(front, "state"); gianni@22726: flexarray_append(front, libxl__sprintf(&gc, "%d", 1)); ian@22164: ian@22164: libxl__device_generic_add(ctx, &device, gianni@22726: libxl__xs_kvs_of_flexarray(&gc, back, back->count), gianni@22726: libxl__xs_kvs_of_flexarray(&gc, front, front->count)); gianni@22023: rc = 0; gianni@22023: out_free: keir@20516: flexarray_free(back); keir@20516: flexarray_free(front); gianni@22023: out: ian@22164: libxl__free_all(&gc); gianni@22023: return rc; keir@20462: } keir@20462: ian@21930: int libxl_device_vkb_clean_shutdown(libxl_ctx *ctx, uint32_t domid) keir@20462: { keir@20462: return ERROR_NI; keir@20462: } keir@20462: ian@21930: int libxl_device_vkb_hard_shutdown(libxl_ctx *ctx, uint32_t domid) keir@20462: { keir@20462: return ERROR_NI; keir@20462: } keir@20462: anthony@22710: static unsigned int libxl_append_disk_list_of_type(libxl_ctx *ctx, anthony@22710: uint32_t domid, anthony@22710: const char *type, anthony@22710: libxl_device_disk **disks, anthony@22710: unsigned int *ndisks) keir@20637: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); anthony@22710: char *be_path = NULL; anthony@22710: char **dir = NULL; anthony@22710: unsigned int n = 0, len = 0; anthony@22710: libxl_device_disk *pdisk = NULL, *pdisk_end = NULL; anthony@22710: char *physpath_tmp = NULL; anthony@22710: anthony@22710: be_path = libxl__sprintf(&gc, "%s/backend/%s/%d", anthony@22710: libxl__xs_get_dompath(&gc, 0), type, domid); anthony@22710: dir = libxl__xs_directory(&gc, XBT_NULL, be_path, &n); anthony@22710: if (dir) { anthony@22710: *disks = realloc(*disks, sizeof (libxl_device_disk) * (*ndisks + n)); anthony@22710: pdisk = *disks + *ndisks; anthony@22710: *ndisks += n; anthony@22710: pdisk_end = *disks + *ndisks; anthony@22710: for (; pdisk < pdisk_end; pdisk++, dir++) { anthony@22710: pdisk->backend_domid = 0; anthony@22710: pdisk->domid = domid; anthony@22710: physpath_tmp = xs_read(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "%s/%s/params", be_path, *dir), &len); anthony@22710: if (strchr(physpath_tmp, ':')) { anthony@22710: pdisk->physpath = strdup(strchr(physpath_tmp, ':') + 1); anthony@22710: free(physpath_tmp); anthony@22710: } else { anthony@22710: pdisk->physpath = physpath_tmp; anthony@22710: } anthony@22710: libxl_string_to_phystype(ctx, libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/type", be_path, *dir)), &(pdisk->phystype)); anthony@22710: pdisk->virtpath = xs_read(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "%s/%s/dev", be_path, *dir), &len); anthony@22710: pdisk->unpluggable = atoi(libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/removable", be_path, *dir))); anthony@22710: if (!strcmp(libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/mode", be_path, *dir)), "w")) anthony@22710: pdisk->readwrite = 1; keir@20637: else anthony@22710: pdisk->readwrite = 0; anthony@22710: 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: pdisk->is_cdrom = !strcmp(type, "cdrom"); keir@20637: } keir@20637: } anthony@22710: ian@22164: libxl__free_all(&gc); anthony@22710: return n; anthony@22710: } anthony@22710: anthony@22710: libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *num) anthony@22710: { anthony@22710: libxl_device_disk *disks = NULL; anthony@22710: unsigned int ndisks = 0; anthony@22710: anthony@22710: *num = libxl_append_disk_list_of_type(ctx, domid, "vbd", &disks, &ndisks); anthony@22710: *num += libxl_append_disk_list_of_type(ctx, domid, "tap", &disks, &ndisks); anthony@22711: *num += libxl_append_disk_list_of_type(ctx, domid, "qdisk", &disks, &ndisks); anthony@22710: anthony@22710: return disks; keir@21411: } keir@21411: ian@21930: int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid, keir@21411: libxl_device_disk *disk, libxl_diskinfo *diskinfo) keir@21411: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@21411: char *dompath, *diskpath; keir@21411: char *val; keir@21411: ian@22164: dompath = libxl__xs_get_dompath(&gc, domid); ian@22165: diskinfo->devid = libxl__device_disk_dev_number(disk->virtpath); keir@21411: keir@21411: /* tap devices entries in xenstore are written as vbd devices. */ ian@22164: diskpath = libxl__sprintf(&gc, "%s/device/vbd/%d", dompath, diskinfo->devid); ian@22059: diskinfo->backend = xs_read(ctx->xsh, XBT_NULL, ian@22164: libxl__sprintf(&gc, "%s/backend", diskpath), NULL); keir@21411: if (!diskinfo->backend) { ian@22164: libxl__free_all(&gc); keir@21411: return ERROR_FAIL; keir@21411: } ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/backend-id", diskpath)); keir@21411: diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1; ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/state", diskpath)); keir@21411: diskinfo->state = val ? strtoul(val, NULL, 10) : -1; ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/event-channel", diskpath)); keir@21411: diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1; ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/ring-ref", diskpath)); keir@21411: diskinfo->rref = val ? strtoul(val, NULL, 10) : -1; ian@22059: diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL, ian@22164: libxl__sprintf(&gc, "%s/frontend", diskinfo->backend), NULL); ian@22164: val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/frontend-id", diskinfo->backend)); keir@21411: diskinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1; keir@21411: ian@22164: libxl__free_all(&gc); keir@21411: return 0; keir@20637: } keir@20637: ian@21930: int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk) keir@20637: { keir@20637: int num, i; keir@20637: uint32_t stubdomid; keir@20637: libxl_device_disk *disks; ian@22086: int ret = ERROR_FAIL; keir@20637: keir@20637: if (!disk->physpath) { keir@20637: disk->physpath = ""; keir@20637: disk->phystype = PHYSTYPE_PHY; keir@20637: } keir@20637: disks = libxl_device_disk_list(ctx, domid, &num); keir@20637: for (i = 0; i < num; i++) { keir@20637: if (disks[i].is_cdrom && !strcmp(disk->virtpath, disks[i].virtpath)) keir@20637: /* found */ keir@20637: break; keir@20637: } keir@20637: if (i == num) { ian@22165: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Virtual device not found"); ian@22086: goto out; keir@20637: } ian@22086: ian@22086: ret = 0; ian@22086: keir@20637: libxl_device_disk_del(ctx, disks + i, 1); keir@20637: libxl_device_disk_add(ctx, domid, disk); keir@20637: stubdomid = libxl_get_stubdom_id(ctx, domid); keir@20637: if (stubdomid) { keir@20781: disks[i].domid = stubdomid; keir@20637: libxl_device_disk_del(ctx, disks + i, 1); keir@20781: disk->domid = stubdomid; keir@20637: libxl_device_disk_add(ctx, stubdomid, disk); keir@20781: disk->domid = domid; keir@20637: } ian@22086: out: ian@22086: for (i = 0; i < num; i++) ian@22086: libxl_device_disk_destroy(&disks[i]); gianni@22023: free(disks); ian@22086: return ret; keir@20637: } keir@20637: keir@20462: /******************************************************************************/ ian@21930: int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb) keir@20462: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@20509: flexarray_t *front; keir@20509: flexarray_t *back; ian@22167: libxl__device device; gianni@22023: int rc; keir@20509: keir@20509: front = flexarray_make(16, 1); gianni@22023: if (!front) { gianni@22023: rc = ERROR_NOMEM; gianni@22023: goto out; gianni@22023: } keir@20509: back = flexarray_make(16, 1); gianni@22023: if (!back) { gianni@22023: rc = ERROR_NOMEM; gianni@22023: goto out_free; gianni@22023: } keir@20509: keir@20509: device.backend_devid = vfb->devid; keir@20509: device.backend_domid = vfb->backend_domid; keir@20509: device.backend_kind = DEVICE_VFB; keir@20509: device.devid = vfb->devid; keir@20509: device.domid = vfb->domid; keir@20509: device.kind = DEVICE_VFB; keir@20509: gianni@22726: flexarray_vappend(back, "frontend-id", libxl__sprintf(&gc, "%d", vfb->domid), NULL); gianni@22726: flexarray_vappend(back, "online", "1", NULL); gianni@22726: flexarray_vappend(back, "state", libxl__sprintf(&gc, "%d", 1), NULL); gianni@22726: flexarray_vappend(back, "domain", libxl__domid_to_name(&gc, domid), NULL); gianni@22726: flexarray_vappend(back, "vnc", libxl__sprintf(&gc, "%d", vfb->vnc), NULL); gianni@22726: flexarray_vappend(back, "vnclisten", vfb->vnclisten, NULL); gianni@22726: flexarray_append(back, "vncpasswd"); gianni@22726: flexarray_append(back, vfb->vncpasswd); gianni@22726: flexarray_vappend(back, "vncdisplay", libxl__sprintf(&gc, "%d", vfb->vncdisplay), NULL); gianni@22726: flexarray_vappend(back, "vncunused", libxl__sprintf(&gc, "%d", vfb->vncunused), NULL); gianni@22726: flexarray_vappend(back, "sdl", libxl__sprintf(&gc, "%d", vfb->sdl), NULL); gianni@22726: flexarray_vappend(back, "opengl", libxl__sprintf(&gc, "%d", vfb->opengl), NULL); keir@20509: if (vfb->xauthority) { gianni@22726: flexarray_vappend(back, "xauthority", vfb->xauthority, NULL); keir@20509: } keir@20509: if (vfb->display) { gianni@22726: flexarray_vappend(back, "display", vfb->display, NULL); keir@20509: } keir@20509: gianni@22726: flexarray_vappend(front, "backend-id", libxl__sprintf(&gc, "%d", vfb->backend_domid), NULL); gianni@22726: flexarray_vappend(front, "state", libxl__sprintf(&gc, "%d", 1), NULL); ian@22164: ian@22164: libxl__device_generic_add(ctx, &device, gianni@22726: libxl__xs_kvs_of_flexarray(&gc, back, back->count), gianni@22726: libxl__xs_kvs_of_flexarray(&gc, front, front->count)); gianni@22023: rc = 0; gianni@22023: out_free: keir@20509: flexarray_free(front); keir@20509: flexarray_free(back); gianni@22023: out: ian@22164: libxl__free_all(&gc); gianni@22023: return rc; keir@20462: } keir@20462: ian@21930: int libxl_device_vfb_clean_shutdown(libxl_ctx *ctx, uint32_t domid) keir@20462: { keir@20462: return ERROR_NI; keir@20462: } keir@20462: ian@21930: int libxl_device_vfb_hard_shutdown(libxl_ctx *ctx, uint32_t domid) keir@20462: { keir@20462: return ERROR_NI; keir@20462: } keir@20462: keir@20462: /******************************************************************************/ keir@20482: ian@21930: int libxl_domain_setmaxmem(libxl_ctx *ctx, uint32_t domid, uint32_t max_memkb) keir@21404: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); keir@21404: char *mem, *endptr; keir@21404: uint32_t memorykb; ian@22164: char *dompath = libxl__xs_get_dompath(&gc, domid); gianni@22023: int rc = 1; gianni@22023: ian@22164: mem = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/memory/target", dompath)); keir@21404: if (!mem) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot get memory info from %s/memory/target\n", dompath); gianni@22023: goto out; keir@21404: } keir@21404: memorykb = strtoul(mem, &endptr, 10); keir@21404: if (*endptr != '\0') { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "invalid memory %s from %s/memory/target\n", mem, dompath); gianni@22023: goto out; keir@21404: } keir@21404: keir@21404: if (max_memkb < memorykb) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "memory_static_max must be greater than or or equal to memory_dynamic_max\n"); gianni@22023: goto out; keir@21404: } keir@21404: gianni@22023: rc = 0; gianni@22023: out: ian@22164: libxl__free_all(&gc); gianni@22023: return rc; keir@21404: } keir@21404: stefano@22244: static int libxl__fill_dom0_memory_info(libxl__gc *gc, uint32_t *target_memkb) stefano@22244: { stefano@22244: int rc; stefano@22244: libxl_dominfo info; stefano@22245: libxl_physinfo physinfo; stefano@22567: char *target = NULL, *staticmax = NULL, *freememslack = NULL, *endptr = NULL; stefano@22244: char *target_path = "/local/domain/0/memory/target"; stefano@22244: char *max_path = "/local/domain/0/memory/static-max"; stefano@22245: char *free_mem_slack_path = "/local/domain/0/memory/freemem-slack"; stefano@22244: xs_transaction_t t; stefano@22244: libxl_ctx *ctx = libxl__gc_owner(gc); stefano@22567: uint32_t free_mem_slack_kb = 0; stefano@22244: stefano@22244: retry_transaction: stefano@22244: t = xs_transaction_start(ctx->xsh); stefano@22244: stefano@22244: target = libxl__xs_read(gc, t, target_path); ewalsh@22705: staticmax = libxl__xs_read(gc, t, max_path); ewalsh@22705: freememslack = libxl__xs_read(gc, t, free_mem_slack_path); stefano@22567: if (target && staticmax && freememslack) { stefano@22567: rc = 0; stefano@22567: goto out; stefano@22567: } stefano@22567: stefano@22244: if (target) { stefano@22244: *target_memkb = strtoul(target, &endptr, 10); stefano@22244: if (*endptr != '\0') { stefano@22244: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, stefano@22244: "invalid memory target %s from %s\n", target, target_path); stefano@22244: rc = ERROR_FAIL; stefano@22244: goto out; stefano@22244: } stefano@22244: } stefano@22244: stefano@22244: rc = libxl_domain_info(ctx, &info, 0); stefano@22244: if (rc < 0) stefano@22567: goto out; stefano@22244: stefano@22245: rc = libxl_get_physinfo(ctx, &physinfo); stefano@22245: if (rc < 0) stefano@22567: goto out; stefano@22567: stefano@22567: if (target == NULL) { stefano@22567: libxl__xs_write(gc, t, target_path, "%"PRIu32, stefano@22567: (uint32_t) info.current_memkb); stefano@22567: *target_memkb = (uint32_t) info.current_memkb; stefano@22567: } stefano@22567: if (staticmax == NULL) stefano@22567: libxl__xs_write(gc, t, max_path, "%"PRIu32, stefano@22567: (uint32_t) info.max_memkb); stefano@22567: stefano@22567: if (freememslack == NULL) { stefano@22567: free_mem_slack_kb = (uint32_t) (PAGE_TO_MEMKB(physinfo.total_pages) - stefano@22567: info.current_memkb); stefano@22567: /* From empirical measurements the free_mem_slack shouldn't be more stefano@22567: * than 15% of the total memory present on the system. */ stefano@22567: if (free_mem_slack_kb > PAGE_TO_MEMKB(physinfo.total_pages) * 0.15) stefano@22567: free_mem_slack_kb = PAGE_TO_MEMKB(physinfo.total_pages) * 0.15; stefano@22567: libxl__xs_write(gc, t, free_mem_slack_path, "%"PRIu32, free_mem_slack_kb); stefano@22567: } stefano@22244: rc = 0; stefano@22244: stefano@22244: out: stefano@22567: if (!xs_transaction_end(ctx->xsh, t, 0)) { stefano@22244: if (errno == EAGAIN) stefano@22244: goto retry_transaction; stefano@22567: else stefano@22567: rc = ERROR_FAIL; stefano@22567: } stefano@22244: stefano@22244: stefano@22244: return rc; stefano@22244: } stefano@22244: stefano@22245: /* returns how much memory should be left free in the system */ stefano@22245: static int libxl__get_free_memory_slack(libxl__gc *gc, uint32_t *free_mem_slack) stefano@22245: { stefano@22245: int rc; stefano@22245: char *free_mem_slack_path = "/local/domain/0/memory/freemem-slack"; stefano@22245: char *free_mem_slack_s, *endptr; stefano@22245: uint32_t target_memkb; stefano@22245: stefano@22245: retry: stefano@22245: free_mem_slack_s = libxl__xs_read(gc, XBT_NULL, free_mem_slack_path); stefano@22245: if (!free_mem_slack_s) { stefano@22245: rc = libxl__fill_dom0_memory_info(gc, &target_memkb); stefano@22245: if (rc < 0) stefano@22245: return rc; stefano@22245: goto retry; stefano@22245: } else { stefano@22245: *free_mem_slack = strtoul(free_mem_slack_s, &endptr, 10); stefano@22245: if (*endptr != '\0') { stefano@22245: LIBXL__LOG_ERRNO(gc->owner, LIBXL__LOG_ERROR, stefano@22245: "invalid free_mem_slack %s from %s\n", stefano@22245: free_mem_slack_s, free_mem_slack_path); stefano@22245: return ERROR_FAIL; stefano@22245: } stefano@22245: } stefano@22245: return 0; stefano@22245: } stefano@22245: stefano@22244: int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid, stefano@22244: int32_t target_memkb, int relative, int enforce) keir@20647: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); stefano@22243: int rc = 1, abort = 0; stefano@22244: uint32_t memorykb = 0, videoram = 0; stefano@22244: uint32_t current_target_memkb = 0, new_target_memkb = 0; stefano@22244: char *memmax, *endptr, *videoram_s = NULL, *target = NULL; ian@22164: char *dompath = libxl__xs_get_dompath(&gc, domid); keir@21374: xc_domaininfo_t info; ian@21930: libxl_dominfo ptr; keir@21374: char *uuid; stefano@22243: xs_transaction_t t; stefano@22243: stefano@22243: retry_transaction: stefano@22243: t = xs_transaction_start(ctx->xsh); stefano@22243: stefano@22244: target = libxl__xs_read(&gc, t, libxl__sprintf(&gc, stefano@22244: "%s/memory/target", dompath)); stefano@22244: if (!target && !domid) { stefano@22244: xs_transaction_end(ctx->xsh, t, 1); stefano@22244: rc = libxl__fill_dom0_memory_info(&gc, ¤t_target_memkb); stefano@22244: if (rc < 0) { stefano@22244: abort = 1; stefano@22244: goto out; stefano@22244: } stefano@22244: goto retry_transaction; stefano@22244: } else if (!target) { stefano@22244: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, stefano@22244: "cannot get target memory info from %s/memory/target\n", stefano@22244: dompath); stefano@22244: abort = 1; stefano@22244: goto out; stefano@22244: } else { stefano@22244: current_target_memkb = strtoul(target, &endptr, 10); stefano@22244: if (*endptr != '\0') { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, stefano@22244: "invalid memory target %s from %s/memory/target\n", stefano@22244: target, dompath); stefano@22243: abort = 1; gianni@22023: goto out; keir@21405: } keir@21405: } stefano@22244: memmax = libxl__xs_read(&gc, t, libxl__sprintf(&gc, stefano@22244: "%s/memory/static-max", dompath)); stefano@22244: if (!memmax) { stefano@22244: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, stefano@22244: "cannot get memory info from %s/memory/static-max\n", stefano@22244: dompath); stefano@22244: abort = 1; stefano@22244: goto out; stefano@22244: } stefano@22244: memorykb = strtoul(memmax, &endptr, 10); stefano@22244: if (*endptr != '\0') { stefano@22244: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, stefano@22244: "invalid max memory %s from %s/memory/static-max\n", stefano@22244: memmax, dompath); stefano@22244: abort = 1; stefano@22244: goto out; stefano@22244: } stefano@22244: stefano@22244: if (relative) stefano@22244: new_target_memkb = current_target_memkb + target_memkb; stefano@22244: else stefano@22244: new_target_memkb = target_memkb; stefano@22244: if (new_target_memkb > memorykb) { stefano@22244: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, stefano@22244: "memory_dynamic_max must be less than or equal to" stefano@22244: " memory_static_max\n"); stefano@22244: abort = 1; stefano@22244: goto out; stefano@22244: } stefano@22244: gianni@22367: if (!domid && new_target_memkb < LIBXL_MIN_DOM0_MEM) { gianni@22367: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, gianni@22367: "new target %d for dom0 is below the minimum threshold\n", gianni@22367: new_target_memkb); gianni@22367: abort = 1; gianni@22367: goto out; gianni@22367: } stefano@22244: videoram_s = libxl__xs_read(&gc, t, libxl__sprintf(&gc, stefano@22244: "%s/memory/videoram", dompath)); stefano@22244: videoram = videoram_s ? atoi(videoram_s) : 0; stefano@22244: stefano@22244: if (enforce) { stefano@22244: memorykb = new_target_memkb; stefano@22244: rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb + stefano@22244: LIBXL_MAXMEM_CONSTANT); stefano@22244: if (rc != 0) { stefano@22244: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, stefano@22244: "xc_domain_setmaxmem domid=%d memkb=%d failed " stefano@22244: "rc=%d\n", domid, memorykb + LIBXL_MAXMEM_CONSTANT, rc); stefano@22244: abort = 1; stefano@22244: goto out; stefano@22244: } stefano@22244: } stefano@22244: stefano@22251: new_target_memkb -= videoram; ian@22294: rc = xc_domain_set_pod_target(ctx->xch, domid, stefano@22251: new_target_memkb / 4, NULL, NULL, NULL); stefano@22243: if (rc != 0) { stefano@22243: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, ian@22294: "xc_domain_set_pod_target domid=%d, memkb=%d " stefano@22251: "failed rc=%d\n", domid, new_target_memkb / 4, stefano@22243: rc); stefano@22243: abort = 1; stefano@22243: goto out; stefano@22243: } stefano@22243: stefano@22244: libxl__xs_write(&gc, t, libxl__sprintf(&gc, "%s/memory/target", stefano@22244: dompath), "%"PRIu32, new_target_memkb); keir@21374: rc = xc_domain_getinfolist(ctx->xch, domid, 1, &info); stefano@22243: if (rc != 1 || info.domain != domid) { stefano@22243: abort = 1; gianni@22023: goto out; stefano@22243: } keir@21374: xcinfo2xlinfo(&info, &ptr); ian@22164: uuid = libxl__uuid2string(&gc, ptr.uuid); stefano@22244: libxl__xs_write(&gc, t, libxl__sprintf(&gc, "/vm/%s/memory", uuid), stefano@22244: "%"PRIu32, new_target_memkb / 1024); gianni@22023: gianni@22023: out: stefano@22243: if (!xs_transaction_end(ctx->xsh, t, abort) && !abort) stefano@22243: if (errno == EAGAIN) stefano@22243: goto retry_transaction; stefano@22243: ian@22164: libxl__free_all(&gc); keir@20647: return rc; keir@20647: } keir@20875: stefano@22244: int libxl_get_memory_target(libxl_ctx *ctx, uint32_t domid, uint32_t *out_target) stefano@22244: { stefano@22244: libxl__gc gc = LIBXL_INIT_GC(ctx); stefano@22244: int rc = 1; stefano@22244: char *target = NULL, *endptr = NULL; stefano@22244: char *dompath = libxl__xs_get_dompath(&gc, domid); stefano@22244: uint32_t target_memkb; stefano@22244: stefano@22244: target = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, stefano@22244: "%s/memory/target", dompath)); stefano@22244: if (!target && !domid) { stefano@22244: rc = libxl__fill_dom0_memory_info(&gc, &target_memkb); stefano@22244: if (rc < 0) stefano@22244: goto out; stefano@22244: } else if (!target) { stefano@22244: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, stefano@22244: "cannot get target memory info from %s/memory/target\n", stefano@22244: dompath); stefano@22244: goto out; stefano@22244: } else { stefano@22244: target_memkb = strtoul(target, &endptr, 10); stefano@22244: if (*endptr != '\0') { stefano@22244: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, stefano@22244: "invalid memory target %s from %s/memory/target\n", stefano@22244: target, dompath); stefano@22244: goto out; stefano@22244: } stefano@22244: } stefano@22244: *out_target = target_memkb; stefano@22244: rc = 0; stefano@22244: stefano@22244: out: stefano@22244: libxl__free_all(&gc); stefano@22244: return rc; stefano@22244: } stefano@22244: stefano@22245: int libxl_domain_need_memory(libxl_ctx *ctx, libxl_domain_build_info *b_info, stefano@22245: libxl_device_model_info *dm_info, uint32_t *need_memkb) stefano@22245: { stefano@22245: *need_memkb = b_info->target_memkb; stefano@22245: if (b_info->hvm) { stefano@22245: *need_memkb += b_info->shadow_memkb + LIBXL_HVM_EXTRA_MEMORY; stefano@22245: if (strstr(dm_info->device_model, "stubdom-dm")) stefano@22245: *need_memkb += 32 * 1024; stefano@22245: } else stefano@22469: *need_memkb += b_info->shadow_memkb + LIBXL_PV_EXTRA_MEMORY; stefano@22245: if (*need_memkb % (2 * 1024)) stefano@22245: *need_memkb += (2 * 1024) - (*need_memkb % (2 * 1024)); stefano@22245: return 0; stefano@22245: } stefano@22245: stefano@22245: int libxl_get_free_memory(libxl_ctx *ctx, uint32_t *memkb) stefano@22245: { stefano@22245: int rc = 0; stefano@22245: libxl_physinfo info; stefano@22245: uint32_t freemem_slack; stefano@22245: libxl__gc gc = LIBXL_INIT_GC(ctx); stefano@22245: stefano@22245: rc = libxl_get_physinfo(ctx, &info); stefano@22245: if (rc < 0) stefano@22245: goto out; stefano@22245: rc = libxl__get_free_memory_slack(&gc, &freemem_slack); stefano@22245: if (rc < 0) stefano@22245: goto out; stefano@22245: stefano@22245: if ((info.free_pages + info.scrub_pages) * 4 > freemem_slack) stefano@22245: *memkb = (info.free_pages + info.scrub_pages) * 4 - freemem_slack; stefano@22245: else stefano@22245: *memkb = 0; stefano@22245: stefano@22245: out: stefano@22245: libxl__free_all(&gc); stefano@22245: return rc; stefano@22245: } stefano@22245: stefano@22245: int libxl_wait_for_free_memory(libxl_ctx *ctx, uint32_t domid, uint32_t stefano@22245: memory_kb, int wait_secs) stefano@22245: { stefano@22245: int rc = 0; stefano@22245: libxl_physinfo info; stefano@22245: uint32_t freemem_slack; stefano@22245: libxl__gc gc = LIBXL_INIT_GC(ctx); stefano@22245: stefano@22245: rc = libxl__get_free_memory_slack(&gc, &freemem_slack); stefano@22245: if (rc < 0) stefano@22245: goto out; stefano@22245: while (wait_secs > 0) { stefano@22245: rc = libxl_get_physinfo(ctx, &info); stefano@22245: if (rc < 0) stefano@22245: goto out; stefano@22245: if (info.free_pages * 4 - freemem_slack >= memory_kb) { stefano@22245: rc = 0; stefano@22245: goto out; stefano@22245: } stefano@22245: wait_secs--; stefano@22245: sleep(1); stefano@22245: } stefano@22245: rc = ERROR_NOMEM; stefano@22245: stefano@22245: out: stefano@22245: libxl__free_all(&gc); stefano@22245: return rc; stefano@22245: } stefano@22245: stefano@22245: int libxl_wait_for_memory_target(libxl_ctx *ctx, uint32_t domid, int wait_secs) stefano@22245: { stefano@22245: int rc = 0; stefano@22245: uint32_t target_memkb = 0; stefano@22245: libxl_dominfo info; stefano@22245: stefano@22245: do { stefano@22245: wait_secs--; stefano@22245: sleep(1); stefano@22245: stefano@22245: rc = libxl_get_memory_target(ctx, domid, &target_memkb); stefano@22245: if (rc < 0) stefano@22245: goto out; stefano@22245: stefano@22245: rc = libxl_domain_info(ctx, &info, domid); stefano@22245: if (rc < 0) stefano@22245: return rc; stefano@22245: } while (wait_secs > 0 && info.current_memkb > target_memkb); stefano@22245: stefano@22245: if (info.current_memkb <= target_memkb) stefano@22245: rc = 0; stefano@22245: else stefano@22245: rc = ERROR_FAIL; stefano@22245: stefano@22245: out: stefano@22245: return 0; stefano@22245: } stefano@22245: ian@21930: int libxl_button_press(libxl_ctx *ctx, uint32_t domid, libxl_button button) keir@20875: { keir@20875: int rc = -1; keir@20875: keir@20875: switch (button) { keir@20875: case POWER_BUTTON: keir@20875: rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_POWER, 0); keir@20875: break; keir@20875: case SLEEP_BUTTON: keir@20875: rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_SLEEP, 0); keir@20875: break; keir@20875: default: keir@20875: break; keir@20875: } keir@20875: keir@20875: return rc; keir@20875: } keir@21141: ian@21930: int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo) keir@21141: { keir@21141: xc_physinfo_t xcphysinfo = { 0 }; keir@21141: int rc; keir@21141: keir@21141: rc = xc_physinfo(ctx->xch, &xcphysinfo); keir@21141: if (rc != 0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting physinfo"); gianni@21892: return ERROR_FAIL; keir@21141: } keir@21141: physinfo->threads_per_core = xcphysinfo.threads_per_core; keir@21141: physinfo->cores_per_socket = xcphysinfo.cores_per_socket; keir@21142: physinfo->max_cpu_id = xcphysinfo.max_cpu_id; keir@21141: physinfo->nr_cpus = xcphysinfo.nr_cpus; keir@21141: physinfo->cpu_khz = xcphysinfo.cpu_khz; keir@21141: physinfo->total_pages = xcphysinfo.total_pages; keir@21141: physinfo->free_pages = xcphysinfo.free_pages; keir@21141: physinfo->scrub_pages = xcphysinfo.scrub_pages; keir@21264: physinfo->nr_nodes = xcphysinfo.nr_nodes; keir@21264: memcpy(physinfo->hw_cap,xcphysinfo.hw_cap, sizeof(physinfo->hw_cap)); keir@21264: physinfo->phys_cap = xcphysinfo.capabilities; keir@21264: keir@21141: return 0; keir@21141: } keir@21141: juergen@22648: int libxl_get_topologyinfo(libxl_ctx *ctx, libxl_topologyinfo *info) juergen@22648: { juergen@22648: xc_topologyinfo_t tinfo; juergen@22648: DECLARE_HYPERCALL_BUFFER(xc_cpu_to_core_t, coremap); juergen@22648: DECLARE_HYPERCALL_BUFFER(xc_cpu_to_socket_t, socketmap); juergen@22648: DECLARE_HYPERCALL_BUFFER(xc_cpu_to_node_t, nodemap); juergen@22648: int i; juergen@22648: int rc = 0; juergen@22648: juergen@22648: rc += libxl_cpuarray_alloc(ctx, &info->coremap); juergen@22648: rc += libxl_cpuarray_alloc(ctx, &info->socketmap); juergen@22648: rc += libxl_cpuarray_alloc(ctx, &info->nodemap); juergen@22648: if (rc) juergen@22648: goto fail; juergen@22648: juergen@22648: coremap = xc_hypercall_buffer_alloc(ctx->xch, coremap, sizeof(*coremap) * info->coremap.entries); juergen@22648: socketmap = xc_hypercall_buffer_alloc(ctx->xch, socketmap, sizeof(*socketmap) * info->socketmap.entries); juergen@22648: nodemap = xc_hypercall_buffer_alloc(ctx->xch, nodemap, sizeof(*nodemap) * info->nodemap.entries); juergen@22648: if ((coremap == NULL) || (socketmap == NULL) || (nodemap == NULL)) juergen@22648: goto fail; juergen@22648: juergen@22648: set_xen_guest_handle(tinfo.cpu_to_core, coremap); juergen@22648: set_xen_guest_handle(tinfo.cpu_to_socket, socketmap); juergen@22648: set_xen_guest_handle(tinfo.cpu_to_node, nodemap); juergen@22648: tinfo.max_cpu_index = info->coremap.entries - 1; juergen@22648: if (xc_topologyinfo(ctx->xch, &tinfo) != 0) juergen@22648: goto fail; juergen@22648: juergen@22648: for (i = 0; i <= tinfo.max_cpu_index; i++) { juergen@22648: if (i < info->coremap.entries) juergen@22648: info->coremap.array[i] = (coremap[i] == INVALID_TOPOLOGY_ID) ? juergen@22648: LIBXL_CPUARRAY_INVALID_ENTRY : coremap[i]; juergen@22648: if (i < info->socketmap.entries) juergen@22648: info->socketmap.array[i] = (socketmap[i] == INVALID_TOPOLOGY_ID) ? juergen@22648: LIBXL_CPUARRAY_INVALID_ENTRY : socketmap[i]; juergen@22648: if (i < info->nodemap.entries) juergen@22648: info->nodemap.array[i] = (nodemap[i] == INVALID_TOPOLOGY_ID) ? juergen@22648: LIBXL_CPUARRAY_INVALID_ENTRY : nodemap[i]; juergen@22648: } juergen@22648: juergen@22648: xc_hypercall_buffer_free(ctx->xch, coremap); juergen@22648: xc_hypercall_buffer_free(ctx->xch, socketmap); juergen@22648: xc_hypercall_buffer_free(ctx->xch, nodemap); juergen@22648: return 0; juergen@22648: juergen@22648: fail: juergen@22648: xc_hypercall_buffer_free(ctx->xch, coremap); juergen@22648: xc_hypercall_buffer_free(ctx->xch, socketmap); juergen@22648: xc_hypercall_buffer_free(ctx->xch, nodemap); juergen@22648: libxl_topologyinfo_destroy(info); juergen@22648: return ERROR_FAIL; juergen@22648: } juergen@22648: ian@21930: const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx) keir@21266: { keir@21266: union { keir@21266: xen_extraversion_t xen_extra; keir@21266: xen_compile_info_t xen_cc; keir@21266: xen_changeset_info_t xen_chgset; keir@21266: xen_capabilities_info_t xen_caps; keir@21266: xen_platform_parameters_t p_parms; keir@21266: xen_commandline_t xen_commandline; keir@21266: } u; keir@21266: long xen_version; keir@21266: libxl_version_info *info = &ctx->version_info; keir@21266: keir@21266: if (info->xen_version_extra != NULL) keir@21266: return info; keir@21266: keir@21266: xen_version = xc_version(ctx->xch, XENVER_version, NULL); keir@21266: info->xen_version_major = xen_version >> 16; keir@21266: info->xen_version_minor = xen_version & 0xFF; gianni@22008: keir@21266: xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra); gianni@22008: info->xen_version_extra = strdup(u.xen_extra); keir@21266: keir@21266: xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc); gianni@22008: info->compiler = strdup(u.xen_cc.compiler); gianni@22008: info->compile_by = strdup(u.xen_cc.compile_by); gianni@22008: info->compile_domain = strdup(u.xen_cc.compile_domain); gianni@22008: info->compile_date = strdup(u.xen_cc.compile_date); keir@21266: keir@21266: xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps); gianni@22008: info->capabilities = strdup(u.xen_caps); keir@21266: keir@21266: xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset); gianni@22008: info->changeset = strdup(u.xen_chgset); keir@21266: keir@21266: xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms); keir@21266: info->virt_start = u.p_parms.virt_start; keir@21266: keir@21266: info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL); keir@21266: keir@21266: xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline); gianni@22008: info->commandline = strdup(u.xen_commandline); keir@21266: keir@21266: return info; keir@21266: } keir@21266: ian@21930: libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid, sstabellini@22000: int *nb_vcpu, int *nrcpus) keir@21141: { ian@21930: libxl_vcpuinfo *ptr, *ret; keir@21141: xc_domaininfo_t domaininfo; keir@21141: xc_vcpuinfo_t vcpuinfo; keir@21141: keir@21141: if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting infolist"); keir@21141: return NULL; keir@21141: } juergen@22396: *nrcpus = libxl_get_max_cpus(ctx); gianni@22015: ret = ptr = calloc(domaininfo.max_vcpu_id + 1, sizeof (libxl_vcpuinfo)); keir@21141: if (!ptr) { keir@21141: return NULL; keir@21141: } keir@21141: keir@21141: for (*nb_vcpu = 0; *nb_vcpu <= domaininfo.max_vcpu_id; ++*nb_vcpu, ++ptr) { juergen@22396: if (libxl_cpumap_alloc(ctx, &ptr->cpumap)) { juergen@22319: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating cpumap"); keir@21141: return NULL; keir@21141: } keir@21141: if (xc_vcpu_getinfo(ctx->xch, domid, *nb_vcpu, &vcpuinfo) == -1) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting vcpu info"); keir@21141: return NULL; keir@21141: } juergen@22396: if (xc_vcpu_getaffinity(ctx->xch, domid, *nb_vcpu, ptr->cpumap.map) == -1) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting vcpu affinity"); keir@21141: return NULL; keir@21141: } keir@21141: ptr->vcpuid = *nb_vcpu; keir@21141: ptr->cpu = vcpuinfo.cpu; keir@21141: ptr->online = !!vcpuinfo.online; keir@21141: ptr->blocked = !!vcpuinfo.blocked; keir@21141: ptr->running = !!vcpuinfo.running; keir@21141: ptr->vcpu_time = vcpuinfo.cpu_time; keir@21141: } keir@21141: return ret; keir@21141: } keir@21142: ian@21930: int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid, juergen@22396: libxl_cpumap *cpumap) keir@21142: { juergen@22396: if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, cpumap->map)) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting vcpu affinity"); gianni@21892: return ERROR_FAIL; gianni@21892: } gianni@21892: return 0; keir@21142: } keir@21143: stefano@22121: int libxl_set_vcpuonline(libxl_ctx *ctx, uint32_t domid, uint32_t bitmask) keir@21143: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); stefano@22121: libxl_dominfo info; keir@21143: char *dompath; stefano@22121: xs_transaction_t t; gianni@22023: int i, rc = ERROR_FAIL; keir@21143: stefano@22121: if (libxl_domain_info(ctx, &info, domid) < 0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting domain info list"); gianni@22023: goto out; keir@21143: } ian@22164: if (!(dompath = libxl__xs_get_dompath(&gc, domid))) gianni@22023: goto out; keir@21143: stefano@22121: retry_transaction: stefano@22121: t = xs_transaction_start(ctx->xsh); stefano@22121: for (i = 0; i <= info.vcpu_max_id; i++) ian@22164: libxl__xs_write(&gc, t, ian@22164: libxl__sprintf(&gc, "%s/cpu/%u/availability", dompath, i), stefano@22121: "%s", ((1 << i) & bitmask) ? "online" : "offline"); stefano@22121: if (!xs_transaction_end(ctx->xsh, t, 0)) { stefano@22121: if (errno == EAGAIN) stefano@22121: goto retry_transaction; stefano@22121: } else stefano@22121: rc = 0; gianni@22023: out: ian@22164: libxl__free_all(&gc); gianni@22023: return rc; keir@21143: } keir@21265: keir@21265: /* keir@21265: * returns one of the XEN_SCHEDULER_* constants from public/domctl.h keir@21265: */ ian@21930: int libxl_get_sched_id(libxl_ctx *ctx) keir@21265: { keir@21265: int sched, ret; keir@21265: gianni@21892: if ((ret = xc_sched_id(ctx->xch, &sched)) != 0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting domain info list"); gianni@21892: return ERROR_FAIL; gianni@21892: } keir@21265: return sched; keir@21265: } keir@21292: ian@21930: int libxl_sched_credit_domain_get(libxl_ctx *ctx, uint32_t domid, libxl_sched_credit *scinfo) keir@21292: { keir@21292: struct xen_domctl_sched_credit sdom; keir@21292: int rc; keir@21292: keir@21292: rc = xc_sched_credit_domain_get(ctx->xch, domid, &sdom); gianni@21892: if (rc != 0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting domain sched credit"); gianni@21892: return ERROR_FAIL; gianni@21892: } keir@21292: keir@21292: scinfo->weight = sdom.weight; keir@21292: scinfo->cap = sdom.cap; keir@21292: keir@21292: return 0; keir@21292: } keir@21292: ian@21930: int libxl_sched_credit_domain_set(libxl_ctx *ctx, uint32_t domid, libxl_sched_credit *scinfo) keir@21292: { keir@21292: struct xen_domctl_sched_credit sdom; keir@21292: xc_domaininfo_t domaininfo; keir@21292: int rc; keir@21292: keir@21292: rc = xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo); gianni@21892: if (rc < 0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting domain info list"); gianni@21892: return ERROR_FAIL; gianni@21892: } keir@21292: if (rc != 1 || domaininfo.domain != domid) gianni@21892: return ERROR_INVAL; keir@21292: keir@21292: keir@21292: if (scinfo->weight < 1 || scinfo->weight > 65535) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, keir@21292: "Cpu weight out of range, valid values are within range from 1 to 65535"); gianni@21892: return ERROR_INVAL; keir@21292: } keir@21292: keir@21292: if (scinfo->cap < 0 || scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, keir@21292: "Cpu cap out of range, valid range is from 0 to %d for specified number of vcpus", keir@21292: ((domaininfo.max_vcpu_id + 1) * 100)); gianni@21892: return ERROR_INVAL; keir@21292: } keir@21292: keir@21292: sdom.weight = scinfo->weight; keir@21292: sdom.cap = scinfo->cap; keir@21292: keir@21292: rc = xc_sched_credit_domain_set(ctx->xch, domid, &sdom); gianni@21892: if ( rc < 0 ) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting domain sched credit"); gianni@21892: return ERROR_FAIL; gianni@21892: } keir@21292: keir@21292: return 0; keir@21292: } keir@21292: keir@21393: static int trigger_type_from_string(char *trigger_name) keir@21393: { keir@21393: if (!strcmp(trigger_name, "nmi")) keir@21393: return XEN_DOMCTL_SENDTRIGGER_NMI; keir@21393: else if (!strcmp(trigger_name, "reset")) keir@21393: return XEN_DOMCTL_SENDTRIGGER_RESET; keir@21393: else if (!strcmp(trigger_name, "init")) keir@21393: return XEN_DOMCTL_SENDTRIGGER_INIT; keir@21393: else if (!strcmp(trigger_name, "power")) keir@21393: return XEN_DOMCTL_SENDTRIGGER_POWER; keir@21393: else if (!strcmp(trigger_name, "sleep")) keir@21393: return XEN_DOMCTL_SENDTRIGGER_SLEEP; keir@21393: else keir@21393: return -1; keir@21393: } keir@21393: ian@21930: int libxl_send_trigger(libxl_ctx *ctx, uint32_t domid, char *trigger_name, uint32_t vcpuid) keir@21393: { keir@21393: int rc = -1; keir@21393: int trigger_type = trigger_type_from_string(trigger_name); keir@21393: keir@21393: if (trigger_type == -1) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, -1, keir@21393: "Invalid trigger, valid triggers are "); gianni@21892: return ERROR_INVAL; keir@21393: } keir@21393: keir@21393: rc = xc_domain_send_trigger(ctx->xch, domid, trigger_type, vcpuid); gianni@21892: if (rc != 0) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, keir@21393: "Send trigger '%s' failed", trigger_name); gianni@21892: return ERROR_FAIL; gianni@21892: } gianni@21892: gianni@21892: return 0; keir@21393: } keir@21402: ian@21930: int libxl_send_sysrq(libxl_ctx *ctx, uint32_t domid, char sysrq) keir@21402: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); ian@22164: char *dompath = libxl__xs_get_dompath(&gc, domid); ian@22164: ian@22164: libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/control/sysrq", dompath), "%c", sysrq); ian@22164: ian@22164: libxl__free_all(&gc); keir@21402: return 0; keir@21402: } keir@21402: ian@21930: int libxl_send_debug_keys(libxl_ctx *ctx, char *keys) keir@21472: { gianni@21892: int ret; gianni@21892: ret = xc_send_debug_keys(ctx->xch, keys); gianni@21892: if ( ret < 0 ) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "sending debug keys"); gianni@21892: return ERROR_FAIL; gianni@21892: } gianni@21892: return 0; keir@21472: } keir@21472: ian@21930: libxl_xen_console_reader * ian@21930: libxl_xen_console_read_start(libxl_ctx *ctx, int clear) keir@21496: { ian@21930: libxl_xen_console_reader *cr; keir@21496: unsigned int size = 16384; keir@21496: char *buf = malloc(size); keir@21496: keir@21496: if (!buf) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot malloc buffer for libxl_xen_console_reader," keir@21496: " size is %u", size); keir@21496: return NULL; keir@21496: } keir@21496: ian@21930: cr = malloc(sizeof(libxl_xen_console_reader)); keir@21496: if (!cr) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot malloc libxl_xen_console_reader"); keir@21496: return NULL; keir@21496: } keir@21496: ian@21930: memset(cr, 0, sizeof(libxl_xen_console_reader)); keir@21496: cr->buffer = buf; keir@21496: cr->size = size; keir@21496: cr->count = size; keir@21496: cr->clear = clear; keir@21496: cr->incremental = 1; keir@21496: keir@21496: return cr; keir@21496: } keir@21496: keir@21496: /* return values: *line_r keir@21496: * 1 success, whole line obtained from buffer non-0 keir@21496: * 0 no more lines available right now 0 keir@21496: * negative error code ERROR_* 0 keir@21496: * On success *line_r is updated to point to a nul-terminated keir@21496: * string which is valid until the next call on the same console keir@21496: * reader. The libxl caller may overwrite parts of the string keir@21496: * if it wishes. */ ian@21930: int libxl_xen_console_read_line(libxl_ctx *ctx, ian@21930: libxl_xen_console_reader *cr, keir@21496: char **line_r) keir@21496: { keir@21496: int ret; keir@21496: keir@21496: memset(cr->buffer, 0, cr->size); ian@22292: ret = xc_readconsolering(ctx->xch, cr->buffer, &cr->count, keir@21496: cr->clear, cr->incremental, &cr->index); gianni@21892: if (ret < 0) { ian@22165: LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "reading console ring buffer"); gianni@21892: return ERROR_FAIL; gianni@21892: } keir@21496: if (!ret) { keir@21496: if (cr->count) { keir@21496: *line_r = cr->buffer; keir@21496: ret = 1; keir@21496: } else { keir@21496: *line_r = NULL; keir@21496: ret = 0; keir@21496: } keir@21496: } keir@21496: keir@21496: return ret; keir@21496: } keir@21496: ian@21930: void libxl_xen_console_read_finish(libxl_ctx *ctx, ian@21930: libxl_xen_console_reader *cr) keir@21496: { keir@21496: free(cr->buffer); keir@21496: free(cr); keir@21496: } keir@21496: ian@21930: uint32_t libxl_vm_get_start_time(libxl_ctx *ctx, uint32_t domid) keir@21425: { ian@22167: libxl__gc gc = LIBXL_INIT_GC(ctx); ian@22164: char *dompath = libxl__xs_get_dompath(&gc, domid); keir@21425: char *vm_path, *start_time; gianni@22023: uint32_t ret; keir@21425: ian@22164: vm_path = libxl__xs_read( ian@22164: &gc, XBT_NULL, libxl__sprintf(&gc, "%s/vm", dompath)); ian@22164: start_time = libxl__xs_read( ian@22164: &gc, XBT_NULL, libxl__sprintf(&gc, "%s/start_time", vm_path)); keir@21425: if (start_time == NULL) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, -1, keir@21425: "Can't get start time of domain '%d'", domid); gianni@22023: ret = -1; gianni@22023: }else{ gianni@22023: ret = strtoul(start_time, NULL, 10); keir@21425: } ian@22164: libxl__free_all(&gc); gianni@22023: return ret; keir@21425: } keir@21425: ian@21930: char *libxl_tmem_list(libxl_ctx *ctx, uint32_t domid, int use_long) keir@21471: { keir@21471: int rc; keir@21471: char _buf[32768]; keir@21471: keir@21471: rc = xc_tmem_control(ctx->xch, -1, TMEMC_LIST, domid, 32768, use_long, keir@21471: 0, _buf); keir@21471: if (rc < 0) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, keir@21471: "Can not get tmem list"); keir@21471: return NULL; keir@21471: } keir@21471: keir@21471: return strdup(_buf); keir@21471: } keir@21471: ian@21930: int libxl_tmem_freeze(libxl_ctx *ctx, uint32_t domid) keir@21471: { keir@21471: int rc; keir@21471: keir@21471: rc = xc_tmem_control(ctx->xch, -1, TMEMC_FREEZE, domid, 0, 0, keir@21471: 0, NULL); keir@21471: if (rc < 0) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, keir@21471: "Can not freeze tmem pools"); gianni@21892: return ERROR_FAIL; keir@21471: } keir@21471: keir@21471: return rc; keir@21471: } keir@21471: ian@21930: int libxl_tmem_destroy(libxl_ctx *ctx, uint32_t domid) keir@21471: { keir@21471: int rc; keir@21471: keir@21471: rc = xc_tmem_control(ctx->xch, -1, TMEMC_DESTROY, domid, 0, 0, keir@21471: 0, NULL); keir@21471: if (rc < 0) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, keir@21471: "Can not destroy tmem pools"); gianni@21892: return ERROR_FAIL; keir@21471: } keir@21471: keir@21471: return rc; keir@21471: } keir@21471: ian@21930: int libxl_tmem_thaw(libxl_ctx *ctx, uint32_t domid) keir@21471: { keir@21471: int rc; keir@21471: keir@21471: rc = xc_tmem_control(ctx->xch, -1, TMEMC_THAW, domid, 0, 0, keir@21471: 0, NULL); keir@21471: if (rc < 0) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, keir@21471: "Can not thaw tmem pools"); gianni@21892: return ERROR_FAIL; keir@21471: } keir@21471: keir@21471: return rc; keir@21471: } keir@21471: keir@21471: static int32_t tmem_setop_from_string(char *set_name) keir@21471: { keir@21471: if (!strcmp(set_name, "weight")) keir@21471: return TMEMC_SET_WEIGHT; keir@21471: else if (!strcmp(set_name, "cap")) keir@21471: return TMEMC_SET_CAP; keir@21471: else if (!strcmp(set_name, "compress")) keir@21471: return TMEMC_SET_COMPRESS; keir@21471: else keir@21471: return -1; keir@21471: } keir@21471: ian@21930: int libxl_tmem_set(libxl_ctx *ctx, uint32_t domid, char* name, uint32_t set) keir@21471: { keir@21471: int rc; keir@21471: int32_t subop = tmem_setop_from_string(name); keir@21471: keir@21471: if (subop == -1) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, -1, keir@21471: "Invalid set, valid sets are "); gianni@21892: return ERROR_INVAL; keir@21471: } keir@21471: rc = xc_tmem_control(ctx->xch, -1, subop, domid, set, 0, 0, NULL); keir@21471: if (rc < 0) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, keir@21471: "Can not set tmem %s", name); gianni@21892: return ERROR_FAIL; keir@21471: } keir@21471: keir@21471: return rc; keir@21471: } keir@21471: ian@21930: int libxl_tmem_shared_auth(libxl_ctx *ctx, uint32_t domid, keir@21471: char* uuid, int auth) keir@21471: { keir@21471: int rc; keir@21471: keir@21471: rc = xc_tmem_auth(ctx->xch, domid, uuid, auth); keir@21471: if (rc < 0) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, keir@21471: "Can not set tmem shared auth"); gianni@21892: return ERROR_FAIL; keir@21471: } keir@21471: keir@21471: return rc; keir@21471: } keir@21471: ian@21930: int libxl_tmem_freeable(libxl_ctx *ctx) sstabellini@21863: { sstabellini@21863: int rc; sstabellini@21863: sstabellini@21863: rc = xc_tmem_control(ctx->xch, -1, TMEMC_QUERY_FREEABLE_MB, -1, 0, 0, 0, 0); sstabellini@21863: if (rc < 0) { ian@22165: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, sstabellini@21863: "Can not get tmem freeable memory"); gianni@21892: return ERROR_FAIL; sstabellini@21863: } sstabellini@21863: sstabellini@21863: return rc; sstabellini@21863: } sstabellini@21863: ian@22082: void libxl_file_reference_destroy(libxl_file_reference *f) Ian@21848: { ian@22082: libxl__file_reference_unmap(f); ian@22082: free(f->path); Ian@21848: } juergen@22319: juergen@22319: int libxl_get_freecpus(libxl_ctx *ctx, libxl_cpumap *cpumap) juergen@22319: { juergen@22319: int ncpus; juergen@22319: juergen@22396: ncpus = libxl_get_max_cpus(ctx); juergen@22396: if (ncpus == 0) juergen@22396: return ERROR_FAIL; juergen@22396: juergen@22396: cpumap->map = xc_cpupool_freeinfo(ctx->xch); juergen@22319: if (cpumap->map == NULL) juergen@22319: return ERROR_FAIL; juergen@22319: juergen@22319: cpumap->size = (ncpus + 7) / 8; juergen@22319: juergen@22319: return 0; juergen@22319: } juergen@22319: Christoph@22602: int libxl_create_cpupool(libxl_ctx *ctx, const char *name, int schedid, juergen@22319: libxl_cpumap cpumap, libxl_uuid *uuid, juergen@22319: uint32_t *poolid) juergen@22319: { juergen@22319: libxl__gc gc = LIBXL_INIT_GC(ctx); juergen@22319: int rc; juergen@22319: int i; juergen@22319: xs_transaction_t t; juergen@22319: char *uuid_string; juergen@22319: juergen@22319: uuid_string = libxl__uuid2string(&gc, *uuid); juergen@22549: if (!uuid_string) { juergen@22549: libxl__free_all(&gc); juergen@22319: return ERROR_NOMEM; juergen@22549: } juergen@22319: juergen@22319: rc = xc_cpupool_create(ctx->xch, poolid, schedid); juergen@22319: if (rc) { juergen@22319: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, juergen@22319: "Could not create cpupool"); juergen@22549: libxl__free_all(&gc); juergen@22319: return ERROR_FAIL; juergen@22319: } juergen@22319: juergen@22396: libxl_for_each_cpu(i, cpumap) juergen@22396: if (libxl_cpumap_test(&cpumap, i)) { juergen@22319: rc = xc_cpupool_addcpu(ctx->xch, *poolid, i); juergen@22319: if (rc) { juergen@22319: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, juergen@22319: "Error moving cpu to cpupool"); juergen@22319: libxl_destroy_cpupool(ctx, *poolid); juergen@22549: libxl__free_all(&gc); juergen@22319: return ERROR_FAIL; juergen@22319: } juergen@22319: } juergen@22319: juergen@22319: for (;;) { juergen@22319: t = xs_transaction_start(ctx->xsh); juergen@22319: juergen@22319: xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/pool/%d", *poolid)); Ian@22368: libxl__xs_write(&gc, t, Ian@22368: libxl__sprintf(&gc, "/local/pool/%d/uuid", *poolid), Ian@22368: "%s", uuid_string); Ian@22368: libxl__xs_write(&gc, t, Ian@22368: libxl__sprintf(&gc, "/local/pool/%d/name", *poolid), Ian@22368: "%s", name); juergen@22319: juergen@22549: if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN)) { juergen@22549: libxl__free_all(&gc); juergen@22319: return 0; juergen@22549: } juergen@22319: } juergen@22319: } juergen@22319: juergen@22319: int libxl_destroy_cpupool(libxl_ctx *ctx, uint32_t poolid) juergen@22319: { juergen@22319: libxl__gc gc = LIBXL_INIT_GC(ctx); juergen@22319: int rc, i; juergen@22319: xc_cpupoolinfo_t *info; juergen@22319: xs_transaction_t t; juergen@22396: libxl_cpumap cpumap; juergen@22319: juergen@22319: info = xc_cpupool_getinfo(ctx->xch, poolid); juergen@22549: if (info == NULL) { juergen@22549: libxl__free_all(&gc); juergen@22319: return ERROR_NOMEM; juergen@22549: } juergen@22319: juergen@22319: rc = ERROR_INVAL; juergen@22319: if ((info->cpupool_id != poolid) || (info->n_dom)) juergen@22319: goto out; juergen@22319: juergen@22396: rc = ERROR_NOMEM; juergen@22396: if (libxl_cpumap_alloc(ctx, &cpumap)) juergen@22396: goto out; juergen@22396: juergen@22396: memcpy(cpumap.map, info->cpumap, cpumap.size); juergen@22396: libxl_for_each_cpu(i, cpumap) juergen@22396: if (libxl_cpumap_test(&cpumap, i)) { juergen@22319: rc = xc_cpupool_removecpu(ctx->xch, poolid, i); juergen@22319: if (rc) { juergen@22319: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, juergen@22319: "Error removing cpu from cpupool"); juergen@22319: rc = ERROR_FAIL; juergen@22396: goto out1; juergen@22319: } juergen@22319: } juergen@22319: juergen@22319: rc = xc_cpupool_destroy(ctx->xch, poolid); juergen@22319: if (rc) { juergen@22319: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "Could not destroy cpupool"); juergen@22319: rc = ERROR_FAIL; juergen@22396: goto out1; juergen@22319: } juergen@22319: juergen@22319: for (;;) { juergen@22319: t = xs_transaction_start(ctx->xsh); juergen@22319: juergen@22319: xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "/local/pool/%d", poolid)); juergen@22319: juergen@22319: if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN)) juergen@22319: break; juergen@22319: } juergen@22319: juergen@22319: rc = 0; juergen@22319: juergen@22396: out1: juergen@22396: libxl_cpumap_destroy(&cpumap); juergen@22319: out: juergen@22396: xc_cpupool_infofree(ctx->xch, info); juergen@22549: libxl__free_all(&gc); juergen@22319: juergen@22319: return rc; juergen@22319: } juergen@22319: juergen@22651: int libxl_cpupool_rename(libxl_ctx *ctx, const char *name, uint32_t poolid) juergen@22651: { juergen@22651: libxl__gc gc = LIBXL_INIT_GC(ctx); juergen@22651: xs_transaction_t t; juergen@22651: xc_cpupoolinfo_t *info; juergen@22651: int rc; juergen@22651: juergen@22651: info = xc_cpupool_getinfo(ctx->xch, poolid); juergen@22651: if (info == NULL) { juergen@22651: libxl__free_all(&gc); juergen@22651: return ERROR_NOMEM; juergen@22651: } juergen@22651: juergen@22651: rc = ERROR_INVAL; juergen@22651: if (info->cpupool_id != poolid) juergen@22651: goto out; juergen@22651: juergen@22651: rc = 0; juergen@22651: juergen@22651: for (;;) { juergen@22651: t = xs_transaction_start(ctx->xsh); juergen@22651: juergen@22651: libxl__xs_write(&gc, t, juergen@22651: libxl__sprintf(&gc, "/local/pool/%d/name", poolid), juergen@22651: "%s", name); juergen@22651: juergen@22651: if (xs_transaction_end(ctx->xsh, t, 0)) juergen@22651: break; juergen@22651: juergen@22651: if (errno == EAGAIN) juergen@22651: continue; juergen@22651: juergen@22651: rc = ERROR_FAIL; juergen@22651: break; juergen@22651: } juergen@22651: juergen@22651: out: juergen@22651: xc_cpupool_infofree(ctx->xch, info); juergen@22651: libxl__free_all(&gc); juergen@22651: juergen@22651: return rc; juergen@22651: } juergen@22651: juergen@22319: int libxl_cpupool_cpuadd(libxl_ctx *ctx, uint32_t poolid, int cpu) juergen@22319: { juergen@22319: int rc; juergen@22319: juergen@22319: rc = xc_cpupool_addcpu(ctx->xch, poolid, cpu); juergen@22319: if (rc) { juergen@22319: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, juergen@22319: "Error moving cpu to cpupool"); juergen@22319: return ERROR_FAIL; juergen@22319: } juergen@22319: return 0; juergen@22319: } juergen@22319: juergen@22650: int libxl_cpupool_cpuadd_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus) juergen@22650: { juergen@22650: int rc = 0; juergen@22650: int cpu; juergen@22650: libxl_cpumap freemap; juergen@22650: libxl_topologyinfo topology; juergen@22650: juergen@22650: if (libxl_get_freecpus(ctx, &freemap)) { juergen@22650: return ERROR_FAIL; juergen@22650: } juergen@22650: juergen@22650: if (libxl_get_topologyinfo(ctx, &topology)) { juergen@22650: rc = ERROR_FAIL; juergen@22650: goto out; juergen@22650: } juergen@22650: juergen@22650: *cpus = 0; juergen@22650: for (cpu = 0; cpu < topology.nodemap.entries; cpu++) { juergen@22650: if (libxl_cpumap_test(&freemap, cpu) && juergen@22650: (topology.nodemap.array[cpu] == node) && juergen@22650: !libxl_cpupool_cpuadd(ctx, poolid, cpu)) { juergen@22650: (*cpus)++; juergen@22650: } juergen@22650: } juergen@22650: juergen@22650: libxl_topologyinfo_destroy(&topology); juergen@22650: juergen@22650: out: juergen@22650: libxl_cpumap_destroy(&freemap); juergen@22650: return rc; juergen@22650: } juergen@22650: juergen@22319: int libxl_cpupool_cpuremove(libxl_ctx *ctx, uint32_t poolid, int cpu) juergen@22319: { juergen@22319: int rc; juergen@22319: juergen@22319: rc = xc_cpupool_removecpu(ctx->xch, poolid, cpu); juergen@22319: if (rc) { juergen@22319: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, juergen@22319: "Error removing cpu from cpupool"); juergen@22319: return ERROR_FAIL; juergen@22319: } juergen@22319: return 0; juergen@22319: } juergen@22319: juergen@22650: int libxl_cpupool_cpuremove_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus) juergen@22650: { juergen@22650: int ret = 0; juergen@22650: int n_pools; juergen@22650: int p; juergen@22650: int cpu; juergen@22650: libxl_topologyinfo topology; juergen@22650: libxl_cpupoolinfo *poolinfo; juergen@22650: juergen@22650: poolinfo = libxl_list_cpupool(ctx, &n_pools); juergen@22650: if (!poolinfo) { juergen@22650: return ERROR_NOMEM; juergen@22650: } juergen@22650: juergen@22650: if (libxl_get_topologyinfo(ctx, &topology)) { juergen@22650: ret = ERROR_FAIL; juergen@22650: goto out; juergen@22650: } juergen@22650: juergen@22650: *cpus = 0; juergen@22650: for (p = 0; p < n_pools; p++) { juergen@22650: if (poolinfo[p].poolid == poolid) { juergen@22650: for (cpu = 0; cpu < topology.nodemap.entries; cpu++) { juergen@22650: if ((topology.nodemap.array[cpu] == node) && juergen@22650: libxl_cpumap_test(&poolinfo[p].cpumap, cpu) && juergen@22650: !libxl_cpupool_cpuremove(ctx, poolid, cpu)) { juergen@22650: (*cpus)++; juergen@22650: } juergen@22650: } juergen@22650: } juergen@22650: } juergen@22650: juergen@22650: libxl_topologyinfo_destroy(&topology); juergen@22650: juergen@22650: out: juergen@22650: for (p = 0; p < n_pools; p++) { juergen@22650: libxl_cpupoolinfo_destroy(poolinfo + p); juergen@22650: } juergen@22650: juergen@22650: return ret; juergen@22650: } juergen@22650: juergen@22319: int libxl_cpupool_movedomain(libxl_ctx *ctx, uint32_t poolid, uint32_t domid) juergen@22319: { juergen@22319: libxl__gc gc = LIBXL_INIT_GC(ctx); juergen@22319: int rc; juergen@22319: char *dom_path; juergen@22319: char *vm_path; juergen@22319: char *poolname; juergen@22319: xs_transaction_t t; juergen@22319: juergen@22319: dom_path = libxl__xs_get_dompath(&gc, domid); juergen@22319: if (!dom_path) { juergen@22549: libxl__free_all(&gc); juergen@22319: return ERROR_FAIL; juergen@22319: } juergen@22319: juergen@22319: rc = xc_cpupool_movedomain(ctx->xch, poolid, domid); juergen@22319: if (rc) { juergen@22319: LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, juergen@22319: "Error moving domain to cpupool"); juergen@22549: libxl__free_all(&gc); juergen@22319: return ERROR_FAIL; juergen@22319: } juergen@22319: juergen@22319: for (;;) { juergen@22319: t = xs_transaction_start(ctx->xsh); juergen@22319: juergen@22319: poolname = libxl__cpupoolid_to_name(&gc, poolid); juergen@22319: vm_path = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/vm", dom_path)); juergen@22319: if (!vm_path) juergen@22319: break; juergen@22319: Ian@22368: libxl__xs_write(&gc, t, libxl__sprintf(&gc, "%s/pool_name", vm_path), Ian@22368: "%s", poolname); juergen@22319: juergen@22319: if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN)) juergen@22319: break; juergen@22319: } juergen@22319: juergen@22549: libxl__free_all(&gc); juergen@22319: return 0; juergen@22319: }