static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) { V9fsVirtioState *v = (V9fsVirtioState *)vdev; V9fsState *s = &v->state; V9fsPDU *pdu; ssize_t len; VirtQueueElement *elem; while ((pdu = pdu_alloc(s))) { struct { uint32_t size_le; uint8_t id; uint16_t tag_le; } QEMU_PACKED out; elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); if (!elem) { goto out_free_pdu; } if (elem->in_num == 0) { virtio_error(vdev, "The guest sent a VirtFS request without space for " "the reply"); goto out_free_req; } QEMU_BUILD_BUG_ON(sizeof(out) != 7); v->elems[pdu->idx] = elem; len = iov_to_buf(elem->out_sg, elem->out_num, 0, &out, sizeof(out)); if (len != sizeof(out)) { virtio_error(vdev, "The guest sent a malformed VirtFS request: " "header size is %zd, should be 7", len); goto out_free_req; } pdu->size = le32_to_cpu(out.size_le); pdu->id = out.id; pdu->tag = le16_to_cpu(out.tag_le); qemu_co_queue_init(&pdu->complete); pdu_submit(pdu); } return; out_free_req: virtqueue_detach_element(vq, elem, 0); g_free(elem); out_free_pdu: pdu_free(pdu); }
static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) { V9fsVirtioState *v = (V9fsVirtioState *)vdev; V9fsState *s = &v->state; V9fsPDU *pdu; ssize_t len; VirtQueueElement *elem; while ((pdu = pdu_alloc(s))) { P9MsgHeader out; elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); if (!elem) { goto out_free_pdu; } if (elem->in_num == 0) { virtio_error(vdev, "The guest sent a VirtFS request without space for " "the reply"); goto out_free_req; } QEMU_BUILD_BUG_ON(sizeof(out) != 7); v->elems[pdu->idx] = elem; len = iov_to_buf(elem->out_sg, elem->out_num, 0, &out, sizeof(out)); if (len != sizeof(out)) { virtio_error(vdev, "The guest sent a malformed VirtFS request: " "header size is %zd, should be 7", len); goto out_free_req; } pdu_submit(pdu, &out); } return; out_free_req: virtqueue_detach_element(vq, elem, 0); g_free(elem); out_free_pdu: pdu_free(pdu); }
static int xen_9pfs_receive(Xen9pfsRing *ring) { P9MsgHeader h; RING_IDX cons, prod, masked_prod, masked_cons, queued; V9fsPDU *pdu; if (ring->inprogress) { return 0; } cons = ring->intf->out_cons; prod = ring->intf->out_prod; xen_rmb(); queued = xen_9pfs_queued(prod, cons, XEN_FLEX_RING_SIZE(ring->ring_order)); if (queued < sizeof(h)) { return 0; } ring->inprogress = true; masked_prod = xen_9pfs_mask(prod, XEN_FLEX_RING_SIZE(ring->ring_order)); masked_cons = xen_9pfs_mask(cons, XEN_FLEX_RING_SIZE(ring->ring_order)); xen_9pfs_read_packet((uint8_t *) &h, ring->ring.out, sizeof(h), masked_prod, &masked_cons, XEN_FLEX_RING_SIZE(ring->ring_order)); if (queued < le32_to_cpu(h.size_le)) { return 0; } /* cannot fail, because we only handle one request per ring at a time */ pdu = pdu_alloc(&ring->priv->state); ring->out_size = le32_to_cpu(h.size_le); ring->out_cons = cons + le32_to_cpu(h.size_le); pdu_submit(pdu, &h); return 0; }