+static int virtio_blk_handle_write(VirtIOBlockReq *req)
+{
+ if (!req->buffer) {
+ size_t offset = 0;
+ int i;
+
+ for (i = 1; i < req->elem.out_num; i++)
+ req->size += req->elem.out_sg[i].iov_len;
+
+ req->buffer = qemu_memalign(512, req->size);
+ if (req->buffer == NULL) {
+ qemu_free(req);
+ return -1;
+ }
+
+ /* We copy the data from the SG list to avoid splitting up the request.
+ This helps performance a lot until we can pass full sg lists as AIO
+ operations */
+ for (i = 1; i < req->elem.out_num; i++) {
+ size_t len;
+
+ len = MIN(req->elem.out_sg[i].iov_len,
+ req->size - offset);
+ memcpy(req->buffer + offset,
+ req->elem.out_sg[i].iov_base,
+ len);
+ offset += len;
+ }
+ }
+
+ bdrv_aio_write(req->dev->bs, req->out->sector, req->buffer, req->size / 512,
+ virtio_blk_rw_complete, req);
+ return 0;
+}
+