char *get_vm_name(int dom, int *target_dom) { struct xs_handle *xs; char buf[64]; char *name; char *target_dom_str; unsigned int len = 0; xs = xs_open(0); if (!xs) { perror("xs_daemon_open"); exit(1); } snprintf(buf, sizeof(buf), "/local/domain/%d/target", dom); target_dom_str = xs_read(xs, 0, buf, &len); if (target_dom_str) { errno = 0; *target_dom = strtol(target_dom_str, (char **) NULL, 10); if (errno != 0) { perror("strtol"); exit(1); } } else *target_dom = dom; snprintf(buf, sizeof(buf), "/local/domain/%d/name", *target_dom); name = xs_read(xs, 0, buf, &len); if (!name) { perror("xs_read domainname"); exit(1); } xs_close(xs); return name; }
char *xenstore_vm_read(int domid, char *key, unsigned int *len) { char *buf = NULL, *path = NULL, *value = NULL; if (xsh == NULL) goto out; path = xs_get_domain_path(xsh, domid); if (path == NULL) { fprintf(logfile, "xs_get_domain_path(%d): error\n", domid); goto out; } pasprintf(&buf, "%s/vm", path); free(path); path = xs_read(xsh, XBT_NULL, buf, NULL); if (path == NULL) { fprintf(logfile, "xs_read(%s): read error\n", buf); goto out; } pasprintf(&buf, "%s/%s", path, key); value = xs_read(xsh, XBT_NULL, buf, len); if (value == NULL) { fprintf(logfile, "xs_read(%s): read error\n", buf); goto out; } out: free(path); free(buf); return value; }
/* * xenStoreDomainGetDiskID: * @conn: pointer to the connection. * @id: the domain id * @dev: the virtual block device name * * Get the reference (i.e. the string number) for the device on that domain * which uses the given virtual block device name * * The caller must hold the lock on the privateData * associated with the 'conn' parameter. * * Returns the new string or NULL in case of error, the string must be * freed by the caller. */ char * xenStoreDomainGetDiskID(virConnectPtr conn, int id, const char *dev) { char dir[80], path[128], **list = NULL, *val = NULL; unsigned int devlen, len, num; size_t i; char *ret = NULL; xenUnifiedPrivatePtr priv = conn->privateData; if (id < 0 || priv->xshandle == NULL || dev == NULL) return NULL; devlen = strlen(dev); if (devlen <= 0) return NULL; snprintf(dir, sizeof(dir), "/local/domain/0/backend/vbd/%d", id); list = xs_directory(priv->xshandle, 0, dir, &num); if (list != NULL) { for (i = 0; i < num; i++) { snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev"); val = xs_read(priv->xshandle, 0, path, &len); if (val == NULL) break; if ((devlen != len) || memcmp(val, dev, len)) { VIR_FREE(val); } else { ignore_value(VIR_STRDUP(ret, list[i])); VIR_FREE(val); VIR_FREE(list); return ret; } } VIR_FREE(list); } snprintf(dir, sizeof(dir), "/local/domain/0/backend/tap/%d", id); list = xs_directory(priv->xshandle, 0, dir, &num); if (list != NULL) { for (i = 0; i < num; i++) { snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev"); val = xs_read(priv->xshandle, 0, path, &len); if (val == NULL) break; if ((devlen != len) || memcmp(val, dev, len)) { VIR_FREE(val); } else { ignore_value(VIR_STRDUP(ret, list[i])); VIR_FREE(val); VIR_FREE(list); return ret; } } VIR_FREE(list); } return NULL; }
static char* read_param(const char *paramname) { char keybuf[128]; unsigned int len; int my_domid; my_domid = atoi(xs_read(xsh, 0, "domid", &len)); snprintf(keybuf, sizeof(keybuf), "/local/domain/0/backend/audio/%d/%d/%s", my_domid, device_id, paramname); /* remember to free lvalue! */ return xs_read(xsh, 0, keybuf, &len); }
static int wait_for_backend_state_change() { char keybuf[128]; int my_domid; unsigned int len; int backend_state; int seconds; char *buf, **vec; int ret; int xs_fd; struct timeval tv; fd_set watch_fdset; int start, now; backend_state = STATE_UNDEFINED; xs_fd = xs_fileno(xsh); start = now = time(NULL); my_domid = atoi(xs_read(xsh, 0, "domid", &len)); snprintf(keybuf, sizeof(keybuf), "/local/domain/0/backend/audio/%d/%d/state", my_domid, device_id); /*XXX: hardcoded */ seconds = 10; do { tv.tv_usec = 0; tv.tv_sec = (start + seconds) - now; FD_ZERO(&watch_fdset); FD_SET(xs_fd, &watch_fdset); ret=select(xs_fd + 1, &watch_fdset, NULL, NULL, &tv); if (ret==-1) /* error */ return -1; else if (ret) { /* Read the watch to drain the buffer */ vec = xs_read_watch(xsh, &len); buf = xs_read(xsh, XBT_NULL, vec[0], &len); if (buf == 0) { /* usually means that the backend isn't there yet */ continue; }; backend_state = atoi(buf); free(buf); free(vec); } /* else: timeout */ } while (backend_state == STATE_UNDEFINED && \ (now = time(NULL)) < start + seconds); return backend_state; }
ivc_connection_t *makeConnection(libIVC_t *iface, char *name, ivc_contype_t type, float per) { char *key, *val, *rdomstr = NULL, *rrefstr = NULL, *rpstr = NULL; uint32_t me, other, num_refs, *grants; struct xs_permissions perms; ivc_connection_t *res; evtchn_port_t port; unsigned int len; void *buffer; /* me <- xsGetDomId */ me = getMyDomId(iface); /* removePath xs targetPath */ ASPRINTF(&key, "/rendezvous/%s", name); xs_rm(iface->xs, 0, key); /* xsMakeDirectory xs targetPath */ xs_mkdir(iface->xs, 0, key); /* xsSetPermissions xs targetPath [ReadWritePerm me] */ perms.id = me; perms.perms = XS_PERM_READ | XS_PERM_WRITE; xs_set_permissions(iface->xs, 0, key, &perms, 1); /* xsWrite xs (targetPath ++ "/LeftDomId") (show me) */ free(key), ASPRINTF(&key, "/rendezvous/%s/LeftDomId", name); ASPRINTF(&val, "dom%d", me); xs_write(iface->xs, 0, key, val, strlen(val)); /* other <- read <$> waitForKey xs (targetPAth ++ "/RightDomId") */ free(key), ASPRINTF(&key, "/rendezvous/%s/RightDomId", name); while(!rdomstr) { rdomstr = xs_read(iface->xs, 0, key, &len); }; sscanf(rdomstr, "dom%d", &other); /* grants <- read <$> waitForKey xs (targetPAth ++ "/RightGrantRefs") */ free(key), ASPRINTF(&key, "/rendezvous/%s/RightGrantRefs", name); while(!rrefstr) { rrefstr = xs_read(iface->xs, 0, key, &len); } grants = parseRefs(rrefstr, &num_refs); buffer = xc_gnttab_map_domain_grant_refs(iface->gt, num_refs, other, grants, PROT_READWRITE); assert(buffer); /* ports <- read <$> waitForKey xs (targetPAth ++ "/RightPorts") */ free(key), ASPRINTF(&key, "/rendezvous/%s/RightPorts", name); while(!rpstr) { rpstr = xs_read(iface->xs, 0, key, &len); } sscanf(rpstr, "[echan:%d]", &port); port = xc_evtchn_bind_interdomain(iface->ec, other, port); assert(port >= 0); /* res <- acceptConnection other grants ports extra */ res = buildChannel(iface, other, type, port, buffer, num_refs * 4096, per, 0); /* xsWrite xs (targetPath ++ "/LeftConnectionConfirmed") "True" */ free(key), ASPRINTF(&key, "/rendezvous/%s/LeftConnectionConfirmed", name); free(val), ASPRINTF(&val, "True"); xs_write(iface->xs, 0, key, val, strlen(val)); /* return res */ return res; }
int xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen) { char *buf = NULL, *path, *uuid = NULL, *passwd = NULL; unsigned int i, len, rc = 0; if (xsh == NULL) { return -1; } path = xs_get_domain_path(xsh, domid); if (path == NULL) { fprintf(logfile, "xs_get_domain_path() error. domid %d.\n", domid); return -1; } pasprintf(&buf, "%s/vm", path); uuid = xs_read(xsh, XBT_NULL, buf, &len); if (uuid == NULL) { fprintf(logfile, "xs_read(): uuid get error. %s.\n", buf); free(path); return -1; } pasprintf(&buf, "%s/vncpasswd", uuid); passwd = xs_read(xsh, XBT_NULL, buf, &len); if (passwd == NULL) { fprintf(logfile, "xs_read(): vncpasswd get error. %s.\n", buf); pwbuf[0] = '\0'; free(uuid); free(path); return rc; } for (i=0; i<len && i<pwbuflen; i++) { pwbuf[i] = passwd[i]; } pwbuf[len < (pwbuflen-1) ? len : (pwbuflen-1)] = '\0'; passwd[0] = '\0'; pasprintf(&buf, "%s/vncpasswd", uuid); if (xs_write(xsh, XBT_NULL, buf, passwd, len) == 0) { fprintf(logfile, "xs_write() vncpasswd failed.\n"); rc = -1; } free(passwd); free(uuid); free(path); return rc; }
/* wrapper around xs_read */ static char* do_read (xs_handle_t *xsh, char* path) { char *val = NULL, *san_val = NULL, *tmp = NULL; static struct expanding_buffer ebuf = { 0, }; unsigned len = 0; val = xs_read (xsh, 0, path, &len); if (val == NULL) { syslog (LOG_WARNING, "xs_read on %s returned null", path); return NULL; } san_val = sanitise_value (&ebuf, val, len); if (san_val == NULL) { syslog (LOG_CRIT, "sanitise_value returned NULL"); free (val); return NULL; } tmp = strdup (san_val); /* don't free san_val */ free (val); return tmp; }
/* * The caller must hold the lock on the privateData * associated with the 'conn' parameter. */ int xenStoreDomainGetUUID(virConnectPtr conn, int id, unsigned char *uuid) { char prop[200]; xenUnifiedPrivatePtr priv = conn->privateData; unsigned int len; char *uuidstr; int ret = 0; if (priv->xshandle == NULL) return -1; snprintf(prop, 199, "/local/domain/%d/vm", id); prop[199] = 0; /* This will return something like * /vm/00000000-0000-0000-0000-000000000000[-*] */ uuidstr = xs_read(priv->xshandle, 0, prop, &len); /* Strip optional version suffix when VM was renamed */ if (len > 40) /* strlen('/vm/') + VIR_UUID_STRING_BUFLEN - sizeof('\0') */ uuidstr[40] = '\0'; /* remove "/vm/" */ ret = virUUIDParse(uuidstr + 4, uuid); VIR_FREE(uuidstr); return ret; }
/* This function initializes the mode of the power management. */ static int32_t xen_battery_init_mode(struct xen_battery_manager *xbm) { char dompath[XEN_BUFSIZE]; char *value = NULL; /* xen_extended_power_mgmt xenstore entry indicates whether or not extended * power management support is requested for the hvm guest. Extended power * management support includes power management support beyond S3, S4, S5. * A value of 1 indicates pass-through pm support where upon pm resources * are mapped to the guest as appropriate where as a value of 2 as set in * non pass-through mode, requires qemu to take the onus of responding to * relevant pm port reads/writes. */ if (0 > snprintf(dompath, sizeof(dompath), "/local/domain/0/device-model/%d/xen_extended_power_mgmt", xen_domid)) { XBM_ERROR_MSG("snprintf failed\n"); return -1; } value = xs_read(xenstore, XBT_NULL, dompath, NULL); if (NULL == value) { XBM_ERROR_MSG("unable to read the content of \"%s\"\n", dompath); return -1; } xbm->mode = strtoull(value, NULL, 10); free(value); return 0; }
/* * xenStoreDomainGetPCIID: * @conn: pointer to the connection. * @id: the domain id * @bdf: the PCI BDF * * Get the reference (i.e. the string number) for the device on that domain * which uses the given PCI address * * The caller must hold the lock on the privateData * associated with the 'conn' parameter. * * Returns the new string or NULL in case of error, the string must be * freed by the caller. */ char * xenStoreDomainGetPCIID(virConnectPtr conn, int id, const char *bdf) { char dir[80], path[128], **list = NULL, *val = NULL; unsigned int len, num; size_t i; char *ret = NULL; xenUnifiedPrivatePtr priv = conn->privateData; if (id < 0 || priv->xshandle == NULL || bdf == NULL) return NULL; snprintf(dir, sizeof(dir), "/local/domain/0/backend/pci/%d", id); list = xs_directory(priv->xshandle, 0, dir, &num); if (list == NULL) return NULL; for (i = 0; i < num; i++) { snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev-0"); if ((val = xs_read(priv->xshandle, 0, path, &len)) == NULL) break; bool match = STREQ(val, bdf); VIR_FREE(val); if (match) { ignore_value(VIR_STRDUP(ret, list[i])); break; } } VIR_FREE(list); return ret; }
/* In Xenstore, /local/domain/0/backend/vbd/<domid>/<device>/state, * if available, must be XenbusStateConnected (= 4), otherwise there * is no connected device. */ static int check_bd_connected (xenUnifiedPrivatePtr priv, int device, int domid) { char s[256], *rs; int r; unsigned len = 0; /* This code assumes we're connected if we can't get to * xenstore, etc. */ if (!priv->xshandle) return 1; snprintf (s, sizeof s, "/local/domain/0/backend/vbd/%d/%d/state", domid, device); s[sizeof s - 1] = '\0'; rs = xs_read (priv->xshandle, 0, s, &len); if (!rs) return 1; if (len == 0) { /* Hmmm ... we can get to xenstore but it returns an empty * string instead of an error. Assume it's not connected * in this case. */ VIR_FREE(rs); return 0; } r = STREQ (rs, "4"); VIR_FREE(rs); return r; }
static int get_pty_fd(struct xs_handle *xs, char *path, int seconds) /* Check for a pty in xenstore, open it and return its fd. * Assumes there is already a watch set in the store for this path. */ { struct timeval tv; fd_set watch_fdset; int xs_fd = xs_fileno(xs), pty_fd = -1; int start, now; unsigned int len = 0; char *pty_path, **watch_paths;; start = now = time(NULL); do { tv.tv_usec = 0; tv.tv_sec = (start + seconds) - now; FD_ZERO(&watch_fdset); FD_SET(xs_fd, &watch_fdset); if (select(xs_fd + 1, &watch_fdset, NULL, NULL, &tv)) { /* Read the watch to drain the buffer */ watch_paths = xs_read_watch(xs, &len); free(watch_paths); /* We only watch for one thing, so no need to * disambiguate: just read the pty path */ pty_path = xs_read(xs, XBT_NULL, path, &len); if (pty_path != NULL) { pty_fd = open(pty_path, O_RDWR | O_NOCTTY); if (pty_fd == -1) err(errno, "Could not open tty `%s'", pty_path); free(pty_path); } } } while (pty_fd == -1 && (now = time(NULL)) < start + seconds); return pty_fd; }
static int get_pty_fd(struct xs_handle *xs, char *path, int seconds) /* Check for a pty in xenstore, open it and return its fd. * Assumes there is already a watch set in the store for this path. */ { struct timeval tv; fd_set watch_fdset; int xs_fd = xs_fileno(xs), pty_fd = -1; int start, now; unsigned int len = 0; char *pty_path, **watch_paths; start = now = time(NULL); do { tv.tv_usec = 0; tv.tv_sec = (start + seconds) - now; FD_ZERO(&watch_fdset); FD_SET(xs_fd, &watch_fdset); if (select(xs_fd + 1, &watch_fdset, NULL, NULL, &tv)) { /* Read the watch to drain the buffer */ watch_paths = xs_read_watch(xs, &len); free(watch_paths); /* We only watch for one thing, so no need to * disambiguate: just read the pty path */ pty_path = xs_read(xs, XBT_NULL, path, &len); if (pty_path != NULL) { if (access(pty_path, R_OK|W_OK) != 0) continue; pty_fd = open(pty_path, O_RDWR | O_NOCTTY); if (pty_fd == -1) err(errno, "Could not open tty `%s'", pty_path); free(pty_path); } } } while (pty_fd == -1 && (now = time(NULL)) < start + seconds); #ifdef __sun__ if (pty_fd != -1) { struct termios term; /* * The pty may come from either xend (with pygrub) or * xenconsoled. It may have tty semantics set up, or not. * While it isn't strictly necessary to have those * semantics here, it is good to have a consistent * state that is the same as under Linux. * * If tcgetattr fails, they have not been set up, * so go ahead and set them up now, by pushing the * ptem and ldterm streams modules. */ if (tcgetattr(pty_fd, &term) < 0) { ioctl(pty_fd, I_PUSH, "ptem"); ioctl(pty_fd, I_PUSH, "ldterm"); } } #endif return pty_fd; }
static int suspend_qemu(checkpoint_state *s) { char path[128]; fprintf(stderr, "pausing QEMU\n"); sprintf(path, "/local/domain/0/device-model/%d/command", s->domid); if (!xs_write(s->xsh, XBT_NULL, path, "save", 4)) { fprintf(stderr, "error signalling QEMU to save\n"); return -1; } sprintf(path, "/local/domain/0/device-model/%d/state", s->domid); do { char* state; unsigned int len; state = xs_read(s->xsh, XBT_NULL, path, &len); if (!state) { s->errstr = "error reading QEMU state"; return -1; } if (!strcmp(state, "paused")) { free(state); return 0; } free(state); usleep(1000); } while(1); return -1; }
char *xs_get_keyval(char *path, char *key) { char tmppath[256]; int len; snprintf(tmppath, sizeof(tmppath), "%s/%s", path, key); return xs_read(xs_handle, XBT_NULL, tmppath, &len); }
char * device_backend(struct xs_handle *xsh, char *buf, int domid) { char *backend, *resu; char path[256]; char device[256]; unsigned int len; int i; if(buf == NULL || xsh == NULL) return NULL; backend = malloc(256); if(backend == NULL) { DEBUG("error to alloc memory\n"); return NULL; } for( i = 0; buf[i] != 0x20; i++) { device[i] = buf[i]; } device[i] = '\0'; DEBUG(" device:%s \n", device); sprintf(path, "/local/domain/%d/device/%s/0/backend",domid, device); resu = xs_read(xsh, XBT_NULL, path, &len); if(!resu) { return NULL; } strcpy(backend,&resu[11]); free(resu); backend[len-1] = '\0'; DEBUG("dev:%s, backend :%s\n", device, backend); return backend; }
int xenstore_vm_write(int domid, char *key, char *value) { char *buf = NULL, *path = NULL; int rc = -1; if (xsh == NULL) goto out; path = xs_get_domain_path(xsh, domid); if (path == NULL) { fprintf(logfile, "xs_get_domain_path: error\n"); goto out; } pasprintf(&buf, "%s/vm", path); free(path); path = xs_read(xsh, XBT_NULL, buf, NULL); if (path == NULL) { fprintf(logfile, "xs_read(%s): read error\n", buf); goto out; } pasprintf(&buf, "%s/%s", path, key); rc = xs_write(xsh, XBT_NULL, buf, value, strlen(value)); if (rc == 0) { fprintf(logfile, "xs_write(%s, %s): write error\n", buf, key); goto out; } out: free(path); free(buf); return rc; }
/* Accept state change commands from the control tools */ static void xenstore_process_dm_command_event(void) { char *path = NULL, *command = NULL; unsigned int len; extern int suspend_requested; if (pasprintf(&path, "/local/domain/0/device-model/%u/command", domid) == -1) { fprintf(logfile, "out of memory reading dm command\n"); goto out; } command = xs_read(xsh, XBT_NULL, path, &len); if (!command) goto out; if (!strncmp(command, "save", len)) { fprintf(logfile, "dm-command: pause and save state\n"); suspend_requested = 1; } else if (!strncmp(command, "continue", len)) { fprintf(logfile, "dm-command: continue after state save\n"); suspend_requested = 0; } else { fprintf(logfile, "dm-command: unknown command\"%*s\"\n", len, command); } out: free(path); free(command); }
static void test_write_sizes(size_t max_size) { size_t s; char *buf, *b2; size_t l; buf = malloc(max_size); if (!buf) { printf("no memory"); exit(1); } for (s = 0; s < max_size; s++) { buf[s] = 0; if (!xs_write(xs_handle, "data/test/key1", buf)) break; b2 = xs_read(xs_handle, "data/test/key1", &l); if (!b2) { fail_test(__LINE__, "failed to read in size %d", s); } else if (l != s) { fail_test(__LINE__, "read wrong size %d != %d", s, l); } else if (strcmp(b2, buf)) { fail_test(__LINE__, "read wrong data size %d %s ! = %s", s, b2, buf); } if (b2) free(b2); buf[s] = 'X'; } /* Experimentally, 2027 is the maximum key size we can write before we hit xenstore quota limits. */ if (s < 2027) fail_test(__LINE__, "Could only write %d bytes to xenstore", s); free(buf); }
/*------------------------------ Event Reception -----------------------------*/ static void xctrl_on_watch_event(struct xs_watch *watch, const char **vec, unsigned int len) { const struct xctrl_shutdown_reason *reason; const struct xctrl_shutdown_reason *last_reason; char *result; int error; int result_len; error = xs_read(XST_NIL, "control", "shutdown", &result_len, (void **)&result); if (error != 0) return; reason = xctrl_shutdown_reasons; last_reason = reason + nitems(xctrl_shutdown_reasons); while (reason < last_reason) { if (!strcmp(result, reason->name)) { reason->handler(); break; } reason++; } free(result, M_XENSTORE); }
static char * xenstore_getsv(int domid, const char *fmt, va_list ap) { char *path = NULL, *s; uint64_t value = 0; struct xs_handle *xsh = NULL; int n, m; char key[1024]; bzero(key, sizeof(key)); xsh = xs_daemon_open(); if (xsh == NULL) return 0; path = xs_get_domain_path(xsh, domid); if (path == NULL) goto out; n = snprintf(key, sizeof(key), "%s/", path); if (n < 0) goto out; m = vsnprintf(key + n, sizeof(key) - n, fmt, ap); if (m < 0) goto out; s = xs_read(xsh, XBT_NULL, key, NULL); out: xs_daemon_close(xsh); free(path); return s; }
int xs_node_vscanf(struct xs_handle *xsh, xs_transaction_t tid, const char *node, const char *key, Error **errp, const char *fmt, va_list ap) { char *path, *value; int rc; path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : g_strdup(key); value = xs_read(xsh, tid, path, NULL); trace_xs_node_vscanf(path, value); if (value) { rc = vsscanf(value, fmt, ap); } else { error_setg_errno(errp, errno, "failed to read from '%s'", path); rc = EOF; } free(value); g_free(path); return rc; }
static int xenfb_xs_scanf1(struct xs_handle *xsh, const char *dir, const char *node, const char *fmt, void *dest) { char buf[1024]; char *p; int ret; if (snprintf(buf, sizeof(buf), "%s/%s", dir, node) >= sizeof(buf)) { errno = ENOENT; return -1; } p = xs_read(xsh, XBT_NULL, buf, NULL); if (!p) { errno = ENOENT; return -1; } ret = sscanf(p, fmt, dest); free(p); if (ret != 1) { errno = EDOM; return -1; } return ret; }
/* Get qemu to change buffers. */ static void qemu_flip_buffer(int domid, int next_active) { char digit = '0' + next_active; unsigned int len; char *active_str, **watch; struct timeval tv; fd_set fdset; /* Tell qemu that we want it to start writing log-dirty bits to the * other buffer */ if (!xs_write(xs, XBT_NULL, qemu_next_active_path, &digit, 1)) errx(1, "can't write next-active to store path (%s)\n", qemu_next_active_path); /* Wait a while for qemu to signal that it has switched to the new * active buffer */ read_again: tv.tv_sec = 5; tv.tv_usec = 0; FD_ZERO(&fdset); FD_SET(xs_fileno(xs), &fdset); if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1) errx(1, "timed out waiting for qemu to switch buffers\n"); watch = xs_read_watch(xs, &len); free(watch); active_str = xs_read(xs, XBT_NULL, qemu_active_path, &len); if (active_str == NULL || active_str[0] - '0' != next_active) /* Watch fired but value is not yet right */ goto read_again; }
ivc_connection_t *acceptConnection(libIVC_t *iface, char *name, ivc_contype_t type, uint32_t num_pages, float per) { char *key, *val, *domStr = NULL; uint32_t me, other, *gs, ps; unsigned int len; void *buffer; /* we can only do this if we create grant references */ if(!iface->gs) return NULL; /* other <- read `fmap` waitForKey xs (targetPath ++ "/LeftDomId) */ ASPRINTF(&key, "/rendezvous/%s/LeftDomId", name); while(!domStr) { domStr = xs_read(iface->xs, 0, key, &len); } sscanf(domStr, "dom%d", &other); /* me <- xsGetDomId */ me = getMyDomId(iface); /* (gs, ps, confirm) <- makeConnection other extra */ gs = calloc(num_pages, sizeof(uint32_t)); buffer = xc_gntshr_share_pages(iface->gs, other, num_pages, gs, 1); assert(buffer); ps = xc_evtchn_bind_unbound_port(iface->ec, other); assert(ps); /* xsWrite xs (targetPath ++ "/RightDomId") (show me) */ free(key), ASPRINTF(&key, "/rendezvous/%s/RightDomId", name); free(val), ASPRINTF(&val, "dom%d", me); xs_write(iface->xs, 0, key, val, strlen(val)); /* xsWrite xs (targetPath ++ "/RightGrantRefs") (show gs) */ free(key), ASPRINTF(&key, "/rendezvous/%s/RightGrantRefs", name); free(val), val = showGrantRefList(gs, num_pages); xs_write(iface->xs, 0, key, val, strlen(val)); /* xsWrite xs (targetPath ++ "/RightPorts") (show ps) */ free(key), ASPRINTF(&key, "/rendezvous/%s/RightPorts", name); free(val), ASPRINTF(&val, "[echan:%d]", ps); xs_write(iface->xs, 0, key, val, strlen(val)); /* _ <- waitForKey xs (targetPath ++ "/LeftConnectionConfirmed") */ free(key), ASPRINTF(&key, "/rendezvous/%s/LeftConnectionConfirmed", name); free(val), val = NULL; while(!val) { val = xs_read(iface->xs, 0, key, &len); } /* removePath xs targetPath */ free(key), ASPRINTF(&key, "/rendezvous/%s", name); xs_rm(iface->xs, 0, key); /* confirm */ return buildChannel(iface, other, type, ps, buffer, 4096 * num_pages, per, 1); }
/* * Returns val str in xenstore. * @param path * Full path string for key * @return * Pointer to Val str, NULL on failure */ static char * xen_read_node(char *path, uint32_t *len) { char *buf; buf = xs_read(xs, XBT_NULL, path, len); return buf; }
static int suspend_evtchn_init(int xc, int domid) { struct xs_handle *xs; char path[128]; char *portstr; unsigned int plen; int port; int rc; si.xce = -1; si.suspend_evtchn = -1; xs = xs_daemon_open(); if (!xs) { warnx("failed to get xenstore handle"); return -1; } sprintf(path, "/local/domain/%d/device/suspend/event-channel", domid); portstr = xs_read(xs, XBT_NULL, path, &plen); xs_daemon_close(xs); if (!portstr || !plen) { warnx("could not read suspend event channel"); return -1; } port = atoi(portstr); free(portstr); si.xce = xc_evtchn_open(); if (si.xce < 0) { warnx("failed to open event channel handle"); goto cleanup; } si.suspend_evtchn = xc_evtchn_bind_interdomain(si.xce, domid, port); if (si.suspend_evtchn < 0) { warnx("failed to bind suspend event channel: %d", si.suspend_evtchn); goto cleanup; } rc = xc_domain_subscribe_for_suspend(xc, domid, port); if (rc < 0) { warnx("failed to subscribe to domain: %d", rc); goto cleanup; } /* event channel is pending immediately after binding */ await_suspend(); return 0; cleanup: suspend_evtchn_release(); return -1; }
char *libxl_domid_to_name(libxl_ctx *ctx, uint32_t domid) { unsigned int len; char path[strlen("/local/domain") + 12]; char *s; snprintf(path, sizeof(path), "/local/domain/%d/name", domid); s = xs_read(ctx->xsh, XBT_NULL, path, &len); return s; }
/* Small utility function to figure out our domain id */ static int get_self_id(void) { char *dom_id; int ret; assert(xsh != NULL); dom_id = xs_read(xsh, XBT_NULL, "domid", NULL); sscanf(dom_id, "%d", &ret); return ret; }