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