vmbus: add infrastructure to save/load vmbus requests

This can be allow to include controller-specific data while
saving/loading in-flight scsi requests of the vmbus scsi controller.

Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
Signed-off-by: Jon Doron <arilou@gmail.com>
Message-Id: <20200424123444.3481728-7-arilou@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Jon Doron 2020-04-24 15:34:44 +03:00 committed by Paolo Bonzini
parent 6775d15de1
commit 4dd8a7064b
2 changed files with 102 additions and 0 deletions

View File

@ -1272,6 +1272,105 @@ void vmbus_free_req(void *req)
g_free(req);
}
static const VMStateDescription vmstate_sgent = {
.name = "vmbus/sgentry",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_UINT64(base, ScatterGatherEntry),
VMSTATE_UINT64(len, ScatterGatherEntry),
VMSTATE_END_OF_LIST()
}
};
typedef struct VMBusChanReqSave {
uint16_t chan_idx;
uint16_t pkt_type;
uint32_t msglen;
void *msg;
uint64_t transaction_id;
bool need_comp;
uint32_t num;
ScatterGatherEntry *sgl;
} VMBusChanReqSave;
static const VMStateDescription vmstate_vmbus_chan_req = {
.name = "vmbus/vmbus_chan_req",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_UINT16(chan_idx, VMBusChanReqSave),
VMSTATE_UINT16(pkt_type, VMBusChanReqSave),
VMSTATE_UINT32(msglen, VMBusChanReqSave),
VMSTATE_VBUFFER_ALLOC_UINT32(msg, VMBusChanReqSave, 0, NULL, msglen),
VMSTATE_UINT64(transaction_id, VMBusChanReqSave),
VMSTATE_BOOL(need_comp, VMBusChanReqSave),
VMSTATE_UINT32(num, VMBusChanReqSave),
VMSTATE_STRUCT_VARRAY_POINTER_UINT32(sgl, VMBusChanReqSave, num,
vmstate_sgent, ScatterGatherEntry),
VMSTATE_END_OF_LIST()
}
};
void vmbus_save_req(QEMUFile *f, VMBusChanReq *req)
{
VMBusChanReqSave req_save;
req_save.chan_idx = req->chan->subchan_idx;
req_save.pkt_type = req->pkt_type;
req_save.msglen = req->msglen;
req_save.msg = req->msg;
req_save.transaction_id = req->transaction_id;
req_save.need_comp = req->need_comp;
req_save.num = req->sgl.nsg;
req_save.sgl = g_memdup(req->sgl.sg,
req_save.num * sizeof(ScatterGatherEntry));
vmstate_save_state(f, &vmstate_vmbus_chan_req, &req_save, NULL);
g_free(req_save.sgl);
}
void *vmbus_load_req(QEMUFile *f, VMBusDevice *dev, uint32_t size)
{
VMBusChanReqSave req_save;
VMBusChanReq *req = NULL;
VMBusChannel *chan = NULL;
uint32_t i;
vmstate_load_state(f, &vmstate_vmbus_chan_req, &req_save, 0);
if (req_save.chan_idx >= dev->num_channels) {
error_report("%s: %u(chan_idx) > %u(num_channels)", __func__,
req_save.chan_idx, dev->num_channels);
goto out;
}
chan = &dev->channels[req_save.chan_idx];
if (vmbus_channel_reserve(chan, 0, req_save.msglen)) {
goto out;
}
req = vmbus_alloc_req(chan, size, req_save.pkt_type, req_save.msglen,
req_save.transaction_id, req_save.need_comp);
if (req_save.msglen) {
memcpy(req->msg, req_save.msg, req_save.msglen);
}
for (i = 0; i < req_save.num; i++) {
qemu_sglist_add(&req->sgl, req_save.sgl[i].base, req_save.sgl[i].len);
}
out:
if (req_save.msglen) {
g_free(req_save.msg);
}
if (req_save.num) {
g_free(req_save.sgl);
}
return req;
}
static void channel_event_cb(EventNotifier *e)
{
VMBusChannel *chan = container_of(e, VMBusChannel, notifier);

View File

@ -224,4 +224,7 @@ int vmbus_map_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov,
void vmbus_unmap_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov,
unsigned iov_cnt, size_t accessed);
void vmbus_save_req(QEMUFile *f, VMBusChanReq *req);
void *vmbus_load_req(QEMUFile *f, VMBusDevice *dev, uint32_t size);
#endif