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