23
#include "standard-headers/linux/virtio_pmem.h"
24
#include "system/hostmem.h"
25
#include "block/thread-pool.h"
26
+#include "qemu/aio-wait.h"
27
#include "trace.h"
28
29
typedef struct VirtIODeviceRequest {
55
static void done_cb(void *opaque, int ret)
56
{
57
VirtIODeviceRequest *req_data = opaque;
58
+ VirtIOPMEM *pmem = req_data->pmem;
59
int len = iov_from_buf(req_data->elem.in_sg, req_data->elem.in_num, 0,
60
&req_data->resp, sizeof(struct virtio_pmem_resp));
61
62
/* Callbacks are serialized, so no need to use atomic ops. */
61
- virtqueue_push(req_data->pmem->rq_vq, &req_data->elem, len);
62
- virtio_notify((VirtIODevice *)req_data->pmem, req_data->pmem->rq_vq);
63
+ virtqueue_push(pmem->rq_vq, &req_data->elem, len);
64
+ virtio_notify((VirtIODevice *)pmem, pmem->rq_vq);
65
trace_virtio_pmem_response();
66
g_free(req_data);
67
+
68
+ pmem->inflight--;
69
+ if (!pmem->inflight) {
70
+ aio_wait_kick();
71
+ }
72
}
73
74
static void virtio_pmem_flush(VirtIODevice *vdev, VirtQueue *vq)
92
req_data->fd = memory_region_get_fd(&backend->mr);
93
req_data->pmem = pmem;
94
req_data->vdev = vdev;
95
+ pmem->inflight++;
96
thread_pool_submit_aio(worker_cb, req_data, done_cb, req_data);
97
}
98
130
host_memory_backend_set_mapped(pmem->memdev, true);
131
virtio_init(vdev, VIRTIO_ID_PMEM, sizeof(struct virtio_pmem_config));
132
pmem->rq_vq = virtio_add_queue(vdev, 128, virtio_pmem_flush);
133
+ pmem->inflight = 1;
134
}
135
136
static void virtio_pmem_unrealize(DeviceState *dev)
138
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
139
VirtIOPMEM *pmem = VIRTIO_PMEM(dev);
140
141
+ /* Release the device's own reference and wait for in-flight flushes */
142
+ pmem->inflight--;
143
+ AIO_WAIT_WHILE(NULL, pmem->inflight > 0);
144
+
145
host_memory_backend_set_mapped(pmem->memdev, false);
146
virtio_delete_queue(pmem->rq_vq);
147
virtio_cleanup(vdev);