/** * \brief XenStore watch callback for the root node of the XenStore * subtree representing a XenBus. * * This callback performs, or delegates to the xbs_probe_children task, * all processing necessary to handle dynmaic device arrival and departure * events from a XenBus. * * \param watch The XenStore watch object associated with this callback. * \param vec The XenStore watch event data. * \param len The number of fields in the event data stream. */ static void xenbusb_devices_changed(struct xs_watch *watch, const char **vec, unsigned int len) { struct xenbusb_softc *xbs; device_t dev; char *node; char *bus; char *type; char *id; char *p; u_int component; xbs = (struct xenbusb_softc *)watch->callback_data; dev = xbs->xbs_dev; if (len <= XS_WATCH_PATH) { device_printf(dev, "xenbusb_devices_changed: " "Short Event Data.\n"); return; } node = strdup(vec[XS_WATCH_PATH], M_XENBUS); p = strchr(node, '/'); if (p == NULL) goto out; bus = node; *p = 0; type = p + 1; p = strchr(type, '/'); if (p == NULL) goto out; *p++ = 0; /* * Extract the device ID. A device ID has one or more path * components separated by the '/' character. * * e.g. "<frontend vm id>/<frontend dev id>" for backend devices. */ id = p; for (component = 0; component < xbs->xbs_id_components; component++) { p = strchr(p, '/'); if (p == NULL) break; p++; } if (p != NULL) *p = 0; if (*id != 0 && component >= xbs->xbs_id_components - 1) { xenbusb_add_device(xbs->xbs_dev, type, id); taskqueue_enqueue(taskqueue_thread, &xbs->xbs_probe_children); } out: free(node, M_XENBUS); }
/** * \brief Enumerate all devices of the given type on this bus. * * \param dev NewBus device_t for this XenBus backend bus instance. * \param type String indicating the device sub-tree (e.g. "vfb", "vif") * to enumerate. * * \return On success, 0. Otherwise an errno value indicating the * type of failure. * * Devices that are found are entered into the NewBus hierarchy via * xenbusb_add_device(). xenbusb_add_device() ignores duplicate detects * and ignores duplicate devices, so it can be called unconditionally * for any device found in the XenStore. * * The backend XenStore hierarchy has the following format: * * backend/<device type>/<frontend vm id>/<device id> * */ static int xenbusb_back_enumerate_type(device_t dev, const char *type) { struct xenbusb_softc *xbs; const char **vms; u_int vm_idx; u_int vm_count; int error; xbs = device_get_softc(dev); error = xs_directory(XST_NIL, xbs->xbs_node, type, &vm_count, &vms); if (error) return (error); for (vm_idx = 0; vm_idx < vm_count; vm_idx++) { struct sbuf *vm_path; const char *vm; const char **devs; u_int dev_idx; u_int dev_count; vm = vms[vm_idx]; vm_path = xs_join(type, vm); error = xs_directory(XST_NIL, xbs->xbs_node, sbuf_data(vm_path), &dev_count, &devs); sbuf_delete(vm_path); if (error) break; for (dev_idx = 0; dev_idx < dev_count; dev_idx++) { const char *dev_num; struct sbuf *id; dev_num = devs[dev_idx]; id = xs_join(vm, dev_num); xenbusb_add_device(dev, type, sbuf_data(id)); sbuf_delete(id); } free(devs, M_XENSTORE); } free(vms, M_XENSTORE); return (0); }
/** * \brief Enumerate all devices of the given type on this bus. * * \param dev NewBus device_t for this XenBus front bus instance. * \param type String indicating the device sub-tree (e.g. "vfb", "vif") * to enumerate. * * \return On success, 0. Otherwise an errno value indicating the * type of failure. * * Devices that are found are entered into the NewBus hierarchy via * xenbusb_add_device(). xenbusb_add_device() ignores duplicate detects * and ignores duplicate devices, so it can be called unconditionally * for any device found in the XenStore. */ int xenbusb_front_enumerate_type(device_t dev, const char *type) { struct xenbusb_softc *xbs; const char **dir; unsigned int i, count; int error; xbs = device_get_softc(dev); error = xs_directory(XST_NIL, xbs->xbs_node, type, &count, &dir); if (error) return (error); for (i = 0; i < count; i++) xenbusb_add_device(dev, type, dir[i]); free(dir, M_XENSTORE); return (0); }