int control_compose(void *ch, u_int16_t type, void *buf, size_t len) { struct pdu *pdu; struct ctrlmsghdr *cmh; void *ptr; if (PDU_LEN(len) > CONTROL_READ_SIZE - PDU_LEN(sizeof(*cmh))) return -1; if ((pdu = pdu_new()) == NULL) return -1; if ((cmh = pdu_alloc(sizeof(*cmh))) == NULL) goto fail; bzero(cmh, sizeof(*cmh)); cmh->type = type; cmh->len[0] = len; pdu_addbuf(pdu, cmh, sizeof(*cmh), 0); if (len > 0) { if ((ptr = pdu_alloc(len)) == NULL) goto fail; bcopy(buf, ptr, len); pdu_addbuf(pdu, ptr, len, 1); } return control_queue(ch, pdu); fail: pdu_free(pdu); return -1; }
/* | this is a kludge, | the jury is not back with a veredict, user or kernel */ static void _nop_out(isc_session_t *sp) { pduq_t *pq; nop_out_t *nop_out; debug_called(8); sdebug(4, "cws=%d", sp->cws); if(sp->cws == 0) { /* | only send a nop if window is closed. */ if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL) // I guess we ran out of resources return; nop_out = &pq->pdu.ipdu.nop_out; nop_out->opcode = ISCSI_NOP_OUT; nop_out->itt = htonl(sp->sn.itt); nop_out->ttt = -1; nop_out->I = 1; nop_out->F = 1; if(isc_qout(sp, pq) != 0) { sdebug(1, "failed"); pdu_free(sp->isc, pq); } } }
struct pdu * control_getpdu(char *buf, size_t len) { struct pdu *p; struct ctrlmsghdr *cmh; void *data; size_t n; int i; if (len < sizeof(*cmh)) return NULL; if (!(p = pdu_new())) return NULL; n = sizeof(*cmh); cmh = pdu_alloc(n); bcopy(buf, cmh, n); buf += n; len -= n; if (pdu_addbuf(p, cmh, n, 0)) { free(cmh); fail: pdu_free(p); return NULL; } for (i = 0; i < 3; i++) { n = cmh->len[i]; if (n == 0) continue; if (PDU_LEN(n) > len) goto fail; if (!(data = pdu_alloc(n))) goto fail; bcopy(buf, data, n); if (pdu_addbuf(p, data, n, i + 1)) { free(data); goto fail; } buf += PDU_LEN(n); len -= PDU_LEN(n); } return p; }
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); }
int control_build(void *ch, u_int16_t type, int argc, struct ctrldata *argv) { struct pdu *pdu; struct ctrlmsghdr *cmh; size_t size = 0; int i; if (argc > (int)nitems(cmh->len)) return -1; for (i = 0; i < argc; i++) size += argv[i].len; if (PDU_LEN(size) > CONTROL_READ_SIZE - PDU_LEN(sizeof(*cmh))) return -1; if ((pdu = pdu_new()) == NULL) return -1; if ((cmh = pdu_alloc(sizeof(*cmh))) == NULL) goto fail; bzero(cmh, sizeof(*cmh)); cmh->type = type; pdu_addbuf(pdu, cmh, sizeof(*cmh), 0); for (i = 0; i < argc; i++) if (argv[i].len > 0) { void *ptr; cmh->len[i] = argv[i].len; if ((ptr = pdu_alloc(argv[i].len)) == NULL) goto fail; memcpy(ptr, argv[i].buf, argv[i].len); pdu_addbuf(pdu, ptr, argv[i].len, i + 1); } control_queue(ch, pdu); return 0; fail: pdu_free(pdu); return -1; }
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; }