debuggers.hg

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

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

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

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

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