/* * Try to initialise xendev. Depends on the frontend being ready * for it (shared ring and evtchn info in xenstore, state being * Initialised or Connected). * * Goes to Connected on success. */ static int xen_be_try_initialise(struct XenDevice *xendev) { int rc = 0; if (xendev->fe_state != XenbusStateInitialised && xendev->fe_state != XenbusStateConnected) { if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) { xen_be_printf(xendev, 2, "frontend not ready, ignoring\n"); } else { xen_be_printf(xendev, 2, "frontend not ready (yet)\n"); return -1; } } if (xendev->ops->initialise) { rc = xendev->ops->initialise(xendev); } if (rc != 0) { xen_be_printf(xendev, 0, "initialise() failed\n"); return rc; } xen_be_set_state(xendev, XenbusStateConnected); return 0; }
/* * Initial xendev setup. Read frontend path, register watch for it. * Should succeed once xend finished setting up the backend device. * * Also sets initial state (-> Initializing) when done. Which * only affects the xendev->be_state variable as xenbus should * already be put into that state by xend. */ static int xen_be_try_setup(struct XenDevice *xendev) { char token[XEN_BUFSIZE]; int be_state; if (xenstore_read_be_int(xendev, "state", &be_state) == -1) { xen_be_printf(xendev, 0, "reading backend state failed\n"); return -1; } if (be_state != XenbusStateInitialising) { xen_be_printf(xendev, 0, "initial backend state is wrong (%s)\n", xenbus_strstate(be_state)); return -1; } xendev->fe = xenstore_read_be_str(xendev, "frontend"); if (xendev->fe == NULL) { xen_be_printf(xendev, 0, "reading frontend path failed\n"); return -1; } /* setup frontend watch */ snprintf(token, sizeof(token), "fe:%p", xendev); if (!xs_watch(xenstore, xendev->fe, token)) { xen_be_printf(xendev, 0, "watching frontend path (%s) failed\n", xendev->fe); return -1; } xen_be_set_state(xendev, XenbusStateInitialising); xen_be_backend_changed(xendev, NULL); xen_be_frontend_changed(xendev, NULL); return 0; }
static void xen_9pfs_init_in_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov, unsigned int *pniov, size_t size) { Xen9pfsDev *xen_9pfs = container_of(pdu->s, Xen9pfsDev, state); Xen9pfsRing *ring = &xen_9pfs->rings[pdu->tag % xen_9pfs->num_rings]; int num; size_t buf_size; g_free(ring->sg); ring->sg = g_new0(struct iovec, 2); xen_9pfs_in_sg(ring, ring->sg, &num, pdu->idx, size); buf_size = iov_size(ring->sg, num); if (buf_size < size) { xen_pv_printf(&xen_9pfs->xendev, 0, "Xen 9pfs request type %d" "needs %zu bytes, buffer has %zu\n", pdu->id, size, buf_size); xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing); xen_9pfs_disconnect(&xen_9pfs->xendev); } *piov = ring->sg; *pniov = num; }
/* * Try to reset xendev, for reconnection by another frontend instance. */ static int xen_be_try_reset(struct XenDevice *xendev) { if (xendev->fe_state != XenbusStateInitialising) { return -1; } xen_be_printf(xendev, 1, "device reset (for re-connect)\n"); xen_be_set_state(xendev, XenbusStateInitialising); return 0; }
/* * Teardown connection. * * Goes to Closed when done. */ static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state) { if (xendev->be_state != XenbusStateClosing && xendev->be_state != XenbusStateClosed && xendev->ops->disconnect) { xendev->ops->disconnect(xendev); } if (xendev->be_state != state) { xen_be_set_state(xendev, state); } }
static void fb_frontend_changed(struct XenDevice *xendev, const char *node) { struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev); /* * Set state to Connected *again* once the frontend switched * to connected. We must trigger the watch a second time to * workaround a frontend bug. */ if (fb->bug_trigger == 0 && strcmp(node, "state") == 0 && xendev->fe_state == XenbusStateConnected && xendev->be_state == XenbusStateConnected) { xen_be_printf(xendev, 2, "re-trigger connected (frontend bug)\n"); xen_be_set_state(xendev, XenbusStateConnected); fb->bug_trigger = 1; /* only once */ } }
/* * Try initialize xendev. Prepare everything the backend can do * without synchronizing with the frontend. Fakes hotplug-status. No * hotplug involved here because this is about userspace drivers, thus * there are kernel backend devices which could invoke hotplug. * * Goes to InitWait on success. */ static int xen_be_try_init(struct XenDevice *xendev) { int rc = 0; if (!xendev->online) { xen_be_printf(xendev, 1, "not online\n"); return -1; } if (xendev->ops->init) { rc = xendev->ops->init(xendev); } if (rc != 0) { xen_be_printf(xendev, 1, "init() failed\n"); return rc; } xenstore_write_be_str(xendev, "hotplug-status", "connected"); xen_be_set_state(xendev, XenbusStateInitWait); return 0; }
static ssize_t xen_9pfs_pdu_vunmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, va_list ap) { Xen9pfsDev *xen_9pfs = container_of(pdu->s, Xen9pfsDev, state); struct iovec out_sg[2]; int num; ssize_t ret; xen_9pfs_out_sg(&xen_9pfs->rings[pdu->tag % xen_9pfs->num_rings], out_sg, &num, pdu->idx); ret = v9fs_iov_vunmarshal(out_sg, num, offset, 0, fmt, ap); if (ret < 0) { xen_pv_printf(&xen_9pfs->xendev, 0, "Failed to decode VirtFS request type %d\n", pdu->id); xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing); xen_9pfs_disconnect(&xen_9pfs->xendev); } return ret; }