XenbusState xenbus_read_driver_state(const char *path) { XenbusState result; int error; error = xs_gather(XST_NIL, path, "state", "%d", &result, NULL); if (error) result = XenbusStateClosed; return (result); }
int xenbus_dev_is_online(device_t dev) { const char *path; int error; int value; path = xenbus_get_node(dev); error = xs_gather(XST_NIL, path, "online", "%d", &value, NULL); if (error != 0) { /* Default to not online. */ value = 0; } return (value); }
/** * \brief Determine and store the XenStore path for the other end of * a split device whose local end is represented by ivars. * * If successful, the xd_otherend_path field of the child's instance * variables will be updated. * * \param dev NewBus device_t for this XenBus front bus instance. * \param ivars Instance variables from the XenBus child device for * which to perform this function. * * \return On success, 0. Otherwise an errno value indicating the * type of failure. */ int xenbusb_front_get_otherend_node(device_t dev, struct xenbus_device_ivars *ivars) { char *otherend_path; int error; if (ivars->xd_otherend_path != NULL) { free(ivars->xd_otherend_path, M_XENBUS); ivars->xd_otherend_path = NULL; } error = xs_gather(XST_NIL, ivars->xd_node, "backend-id", "%i", &ivars->xd_otherend_id, "backend", NULL, &otherend_path, NULL); if (error == 0) { ivars->xd_otherend_path = strdup(otherend_path, M_XENBUS); ivars->xd_otherend_path_len = strlen(otherend_path); free(otherend_path, M_XENSTORE); } return (error); }
/** * Xenstore watch callback entry point. This code replaces the hotplug scripts, * and as soon as the xenstore backend driver entries are created, this script * gets called. */ static void ueblktap_probe(struct xs_handle *h, struct xenbus_watch *w, const char *bepath_im) { struct backend_info *be = NULL; char *frontend = NULL, *bepath = NULL, *p; int er, len; blkif_t *blkif; bepath = strdup(bepath_im); if (!bepath) { DPRINTF("No path\n"); return; } /* *asserts that xenstore structure is always 7 levels deep *e.g. /local/domain/0/backend/vbd/1/2049 */ len = strsep_len(bepath, '/', 7); if (len < 0) goto free_be; if (bepath[len] != '\0') goto free_be; be = malloc(sizeof(*be)); if (!be) { DPRINTF("ERROR: allocating backend structure\n"); goto free_be; } memset(be, 0, sizeof(*be)); frontend = NULL; er = xs_gather(h, bepath, "frontend-id", "%li", &be->frontend_id, "frontend", NULL, &frontend, NULL); if (er) { /* *Unable to find frontend entries, *bus-id is no longer valid */ DPRINTF("ERROR: Frontend-id check failed, removing backend: " "[%s]\n",bepath); /** * BE info should already exist, * free new mem and find old entry */ free(be); be = be_lookup_be(bepath); if ( (be != NULL) && (be->blkif != NULL) ) backend_remove(h, be); else goto free_be; if (bepath) free(bepath); return; } /* Are we already tracking this device? */ if (be_exists_be(bepath)) goto free_be; be->backpath = bepath; be->frontpath = frontend; list_add(&be->list, &belist); DPRINTF("[PROBE]\tADDED NEW DEVICE (%s)\n", bepath); DPRINTF("\tFRONTEND (%s),(%ld)\n", frontend,be->frontend_id); ueblktap_setup(h, bepath); return; free_be: if (frontend) free(frontend); if (bepath) free(bepath); if (be) free(be); }
static void ueblktap_setup(struct xs_handle *h, char *bepath) { struct backend_info *be; char *path = NULL, *p,*dev; int len, er, deverr; long int pdev = 0, handle; blkif_info_t *blk; const char* errmsg = NULL; be = be_lookup_be(bepath); if (be == NULL) { DPRINTF("ERROR: backend changed called for nonexistent " "backend! (%s)\n", bepath); goto fail; } deverr = xs_gather(h, bepath, "physical-device", "%li", &pdev, NULL); if (!deverr) { DPRINTF("pdev set to %ld\n",pdev); if (be->pdev && be->pdev != pdev) { DPRINTF("changing physical-device not supported"); goto fail; } be->pdev = pdev; } /* Check to see if device is to be opened read-only. */ deverr = xs_gather(h, bepath, "mode", NULL, &path, NULL); if (deverr) { DPRINTF("ERROR: could not find read/write mode\n"); goto fail; } else if (path[0] == 'r') be->readonly = 1; if (be->blkif == NULL) { /* Front end dir is a number, which is used as the handle. */ p = strrchr(be->frontpath, '/') + 1; handle = strtoul(p, NULL, 0); be->blkif = alloc_blkif(be->frontend_id); if (be->blkif == NULL) goto fail; be->blkif->be_id = get_be_id(bepath); /* Insert device specific info, */ blk = malloc(sizeof(blkif_info_t)); if (!blk) { DPRINTF("Out of memory - blkif_info_t\n"); goto fail; } er = xs_gather(h, bepath, "params", NULL, &blk->params, NULL); if (er) goto fail; be->blkif->info = blk; if (deverr) { /*Dev number was not available, try to set manually*/ pdev = convert_dev_name_to_num(blk->params); be->pdev = pdev; } if (check_image(h, be, &errmsg)) goto fail; er = blkif_init(be->blkif, handle, be->pdev, be->readonly); if (er != 0) { DPRINTF("Unable to open device %s\n",blk->params); goto fail; } DPRINTF("[BECHG]: ADDED A NEW BLKIF (%s)\n", bepath); } /* Supply the information about the device to xenstore */ er = xs_printf(h, be->backpath, "sectors", "%llu", be->blkif->ops->get_size(be->blkif)); if (er == 0) { DPRINTF("ERROR: Failed writing sectors"); goto fail; } er = xs_printf(h, be->backpath, "sector-size", "%lu", be->blkif->ops->get_secsize(be->blkif)); if (er == 0) { DPRINTF("ERROR: Failed writing sector-size"); goto fail; } er = xs_printf(h, be->backpath, "info", "%u", be->blkif->ops->get_info(be->blkif)); if (er == 0) { DPRINTF("ERROR: Failed writing info"); goto fail; } be->blkif->state = CONNECTED; xs_printf(h, be->backpath, "hotplug-status", "connected"); DPRINTF("[SETUP] Complete\n\n"); goto close; fail: if (be) { if (errmsg == NULL) errmsg = "Setting up the backend failed. See the log " "files in /var/log/xen/ for details."; xs_printf(h, be->backpath, "hotplug-error", errmsg); xs_printf(h, be->backpath, "hotplug-status", "error"); backend_remove(h, be); } close: if (path) free(path); return; }
static int check_sharing(struct xs_handle *h, struct backend_info *be) { char *dom_uuid; char *cur_dom_uuid; char *path; char *mode; char *params; char **domains; char **devices; int i, j; unsigned int num_dom, num_dev; blkif_info_t *info = be->blkif->info; int ret = 0; const char *image_path[2]; int be_domid = get_be_domid(be->backpath); image_path[0] = get_image_path(info->params); /* If the mode contains '!' or doesn't contain 'w' don't check anything */ xs_gather(h, be->backpath, "mode", NULL, &mode, NULL); if (strchr(mode, '!')) goto out; if (strchr(mode, 'w') == NULL) goto out; /* Get the UUID of the domain we want to attach to */ if (asprintf(&path, "/local/domain/%ld", be->frontend_id) == -1) goto fail; xs_gather(h, path, "vm", NULL, &dom_uuid, NULL); free(path); /* Iterate through the devices of all VMs */ if (asprintf(&path, "/local/domain/%d/backend/tap", be_domid) == -1) goto fail; domains = xs_directory(h, XBT_NULL, path, &num_dom); free(path); if (domains == NULL) num_dom = 0; for (i = 0; !ret && (i < num_dom); i++) { /* If it's the same VM, no action needed */ if (asprintf(&path, "/local/domain/%s", domains[i]) == -1) { ret = -1; break; } cur_dom_uuid = NULL; xs_gather(h, path, "vm", NULL, &cur_dom_uuid, NULL); free(path); if (!cur_dom_uuid) continue; if (!strcmp(cur_dom_uuid, dom_uuid)) { free(cur_dom_uuid); continue; } /* Check the devices */ if (asprintf(&path, "/local/domain/%d/backend/tap/%s", be_domid, domains[i]) == -1) { ret = -1; free(cur_dom_uuid); break; } devices = xs_directory(h, XBT_NULL, path, &num_dev); if (devices == NULL) num_dev = 0; free(path); for (j = 0; !ret && (j < num_dev); j++) { if (asprintf(&path, "/local/domain/%d/backend/tap/%s/%s", be_domid, domains[i], devices[j]) == -1) { ret = -1; break; } params = NULL; xs_gather(h, path, "params", NULL, ¶ms, NULL); free(path); if (!params) continue; image_path[1] = get_image_path(params); if (!strcmp(image_path[0], image_path[1])) { ret = -1; } free(params); } free(cur_dom_uuid); free(devices); } free(domains); free(dom_uuid); goto out; fail: ret = -1; out: free(mode); return ret; }