char * tapback_device_read(const vbd_t * const device, xs_transaction_t xst, const char * const path) { ASSERT(device); ASSERT(path); return tapback_xs_read(device->backend->xs, xst, "%s/%s/%s", device->backend->path, device->name, path); }
char * tapback_device_read_otherend(vbd_t * const device, xs_transaction_t xst, const char * const path) { ASSERT(device); ASSERT(path); ASSERT(device->frontend_path); return tapback_xs_read(device->backend->xs, xst, "%s/%s", device->frontend_path, path); }
int tapback_xs_exists(struct xs_handle * const xs, xs_transaction_t xst, char *path, const int *len) { int err = 0; char *s = NULL; bool exists = false; char c = '\0'; ASSERT(xs); ASSERT(path); if (len) { c = path[*len]; path[*len] = '\0'; } s = tapback_xs_read(xs, xst, "%s", path); if (s) exists = true; else { err = errno; ASSERT(err != 0); if (err == ENOENT) { err = 0; exists = false; } } free(s); if (len) path[*len] = c; if (!err) { if (exists) { return 1; } else { return 0; } } else { return -err; } }
int tapback_backend_handle_otherend_watch(backend_t *backend, const char * const path) { vbd_t *device = NULL; int err = 0, state = 0; char *s = NULL, *end = NULL, *_path = NULL; ASSERT(backend); ASSERT(path); /* * Find the device that has the same front-end state path. * * There should definitely be such a device in our list, otherwise this * function would not have executed at all, since we would not be waiting * on that XenStore path. The XenStore path we wait for is: * /local/domain/<domid>/device/vbd/<devname>/state. In order to watch this * path, it means that we have received a device create request, so the * device will be there. * * TODO Instead of this linear search we could do better (hash table etc). */ tapback_backend_find_device(backend, device, device->frontend_state_path && !strcmp(device->frontend_state_path, path)); if (!device) { WARN(NULL, "path \'%s\' does not correspond to a known device\n", path); return ENODEV; } /* * Read the new front-end's state. */ s = tapback_xs_read(device->backend->xs, XBT_NULL, "%s", device->frontend_state_path); if (!s) { err = errno; /* * If the front-end XenBus node is missing, the XenBus device has been * removed: remove the XenBus back-end node. */ if (err == ENOENT) { err = asprintf(&_path, "%s/%s/%d/%d", XENSTORE_BACKEND, device->backend->name, device->domid, device->devid); if (err == -1) { err = errno; WARN(device, "failed to asprintf for %d/%d: %s\n", strerror(err)); goto out; } err = 0; if (!xs_rm(device->backend->xs, XBT_NULL, _path)) { if (errno != ENOENT) { err = errno; WARN(device, "failed to remove %s: %s\n", path, strerror(err)); } } } } else { state = strtol(s, &end, 0); if (*end != 0 || end == s) { WARN(device, "invalid XenBus state '%s'\n", s); err = EINVAL; } else err = frontend_changed(device, state); } out: free(s); free(_path); return err; }