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