blob: e25cc96477d0628d866c7735de15503bacb6c634 [file] [log] [blame]
aliguori6e02c382008-12-04 19:52:44 +00001/*
2 * Virtio Block Device
3 *
4 * Copyright IBM, Corp. 2007
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
11 *
12 */
13
Stefan Weil5a61cb62011-09-08 17:55:32 +020014#include "qemu-common.h"
Markus Armbrusterd75d25e2010-07-06 14:37:43 +020015#include "qemu-error.h"
Stefan Hajnoczi6d519a52010-05-22 18:15:08 +010016#include "trace.h"
Markus Armbruster9db1c0f2012-07-10 11:12:31 +020017#include "hw/block-common.h"
Blue Swirl24463332010-08-24 15:22:24 +000018#include "blockdev.h"
aliguori6e02c382008-12-04 19:52:44 +000019#include "virtio-blk.h"
Paolo Bonzini5bb23922011-11-02 13:19:40 +010020#include "scsi-defs.h"
Christoph Hellwig1063b8b2009-04-27 10:29:14 +020021#ifdef __linux__
22# include <scsi/sg.h>
23#endif
aliguori6e02c382008-12-04 19:52:44 +000024
25typedef struct VirtIOBlock
26{
27 VirtIODevice vdev;
28 BlockDriverState *bs;
29 VirtQueue *vq;
aliguori869a5c62009-01-22 19:52:25 +000030 void *rq;
Markus Armbruster213189a2009-07-28 14:33:41 -040031 QEMUBH *bh;
Christoph Hellwig9752c372010-02-10 23:37:25 +010032 BlockConf *conf;
Paolo Bonzini12c56742012-05-16 12:54:05 +020033 VirtIOBlkConf *blk;
Christoph Hellwig8cfacf02010-03-04 14:20:17 +010034 unsigned short sector_mask;
Alex Williamson9d0d3132010-07-20 11:14:22 -060035 DeviceState *qdev;
aliguori6e02c382008-12-04 19:52:44 +000036} VirtIOBlock;
37
38static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
39{
40 return (VirtIOBlock *)vdev;
41}
42
43typedef struct VirtIOBlockReq
44{
45 VirtIOBlock *dev;
46 VirtQueueElement elem;
47 struct virtio_blk_inhdr *in;
48 struct virtio_blk_outhdr *out;
Christoph Hellwig1063b8b2009-04-27 10:29:14 +020049 struct virtio_scsi_inhdr *scsi;
aliguorid28a1b62009-03-28 17:46:14 +000050 QEMUIOVector qiov;
aliguori869a5c62009-01-22 19:52:25 +000051 struct VirtIOBlockReq *next;
Christoph Hellwiga597e792011-08-25 08:26:01 +020052 BlockAcctCookie acct;
aliguori6e02c382008-12-04 19:52:44 +000053} VirtIOBlockReq;
54
aliguori869a5c62009-01-22 19:52:25 +000055static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
56{
57 VirtIOBlock *s = req->dev;
58
Stefan Hajnoczi6d519a52010-05-22 18:15:08 +010059 trace_virtio_blk_req_complete(req, status);
60
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +010061 stb_p(&req->in->status, status);
aliguorid28a1b62009-03-28 17:46:14 +000062 virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in));
aliguori869a5c62009-01-22 19:52:25 +000063 virtio_notify(&s->vdev, s->vq);
aliguori869a5c62009-01-22 19:52:25 +000064}
65
Kevin Wolff35d68f2009-11-27 13:25:39 +010066static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
Paolo Bonzini1ceee0d2012-09-28 17:22:56 +020067 bool is_read)
aliguori869a5c62009-01-22 19:52:25 +000068{
Paolo Bonzini3e1caa52012-09-28 17:22:57 +020069 BlockErrorAction action = bdrv_get_error_action(req->dev->bs, is_read, error);
aliguori869a5c62009-01-22 19:52:25 +000070 VirtIOBlock *s = req->dev;
71
Paolo Bonzini3e1caa52012-09-28 17:22:57 +020072 if (action == BDRV_ACTION_STOP) {
aliguori869a5c62009-01-22 19:52:25 +000073 req->next = s->rq;
74 s->rq = req;
Paolo Bonzini3e1caa52012-09-28 17:22:57 +020075 } else if (action == BDRV_ACTION_REPORT) {
aliguori869a5c62009-01-22 19:52:25 +000076 virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
Christoph Hellwiga597e792011-08-25 08:26:01 +020077 bdrv_acct_done(s->bs, &req->acct);
78 g_free(req);
aliguori869a5c62009-01-22 19:52:25 +000079 }
80
Paolo Bonzini3e1caa52012-09-28 17:22:57 +020081 bdrv_error_action(s->bs, action, is_read, error);
82 return action != BDRV_ACTION_IGNORE;
aliguori869a5c62009-01-22 19:52:25 +000083}
84
aliguori6e02c382008-12-04 19:52:44 +000085static void virtio_blk_rw_complete(void *opaque, int ret)
86{
87 VirtIOBlockReq *req = opaque;
aliguori6e02c382008-12-04 19:52:44 +000088
Stefan Hajnoczi6d519a52010-05-22 18:15:08 +010089 trace_virtio_blk_rw_complete(req, ret);
90
Kevin Wolff35d68f2009-11-27 13:25:39 +010091 if (ret) {
Paolo Bonzini1ceee0d2012-09-28 17:22:56 +020092 bool is_read = !(ldl_p(&req->out->type) & VIRTIO_BLK_T_OUT);
Kevin Wolff35d68f2009-11-27 13:25:39 +010093 if (virtio_blk_handle_rw_error(req, -ret, is_read))
aliguori869a5c62009-01-22 19:52:25 +000094 return;
aliguori6e02c382008-12-04 19:52:44 +000095 }
96
Kevin Wolff35d68f2009-11-27 13:25:39 +010097 virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
Christoph Hellwiga597e792011-08-25 08:26:01 +020098 bdrv_acct_done(req->dev->bs, &req->acct);
99 g_free(req);
aliguori869a5c62009-01-22 19:52:25 +0000100}
aliguori6e02c382008-12-04 19:52:44 +0000101
Christoph Hellwigaa659be2009-09-04 19:02:23 +0200102static void virtio_blk_flush_complete(void *opaque, int ret)
103{
104 VirtIOBlockReq *req = opaque;
105
Kevin Wolf8c269b52010-10-20 13:17:30 +0200106 if (ret) {
107 if (virtio_blk_handle_rw_error(req, -ret, 0)) {
108 return;
109 }
110 }
111
112 virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200113 bdrv_acct_done(req->dev->bs, &req->acct);
114 g_free(req);
Christoph Hellwigaa659be2009-09-04 19:02:23 +0200115}
116
aliguori869a5c62009-01-22 19:52:25 +0000117static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
118{
Anthony Liguori7267c092011-08-20 22:09:37 -0500119 VirtIOBlockReq *req = g_malloc(sizeof(*req));
aliguori487414f2009-02-05 22:06:05 +0000120 req->dev = s;
Stefan Hajnoczide6c8042010-05-14 22:52:30 +0100121 req->qiov.size = 0;
122 req->next = NULL;
aliguori869a5c62009-01-22 19:52:25 +0000123 return req;
aliguori6e02c382008-12-04 19:52:44 +0000124}
125
126static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
127{
aliguori869a5c62009-01-22 19:52:25 +0000128 VirtIOBlockReq *req = virtio_blk_alloc_request(s);
aliguori6e02c382008-12-04 19:52:44 +0000129
aliguori869a5c62009-01-22 19:52:25 +0000130 if (req != NULL) {
131 if (!virtqueue_pop(s->vq, &req->elem)) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500132 g_free(req);
aliguori869a5c62009-01-22 19:52:25 +0000133 return NULL;
134 }
aliguori6e02c382008-12-04 19:52:44 +0000135 }
136
137 return req;
138}
139
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200140static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
141{
Stefan Weil47ce9ef2012-05-22 23:23:32 +0200142#ifdef __linux__
Christoph Hellwig42779062010-01-13 13:30:32 +0100143 int ret;
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200144 int i;
Stefan Weil47ce9ef2012-05-22 23:23:32 +0200145#endif
146 int status = VIRTIO_BLK_S_OK;
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200147
148 /*
149 * We require at least one output segment each for the virtio_blk_outhdr
150 * and the SCSI command block.
151 *
152 * We also at least require the virtio_blk_inhdr, the virtio_scsi_inhdr
153 * and the sense buffer pointer in the input segments.
154 */
155 if (req->elem.out_num < 2 || req->elem.in_num < 3) {
156 virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200157 g_free(req);
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200158 return;
159 }
160
161 /*
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200162 * The scsi inhdr is placed in the second-to-last input segment, just
163 * before the regular inhdr.
164 */
165 req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200166
Paolo Bonzinia6c5c842012-05-16 12:54:06 +0200167 if (!req->dev->blk->scsi) {
Paolo Bonzinif34e73c2012-05-16 12:54:03 +0200168 status = VIRTIO_BLK_S_UNSUPP;
169 goto fail;
170 }
171
172 /*
173 * No support for bidirection commands yet.
174 */
175 if (req->elem.out_num > 2 && req->elem.in_num > 3) {
176 status = VIRTIO_BLK_S_UNSUPP;
177 goto fail;
178 }
179
180#ifdef __linux__
181 struct sg_io_hdr hdr;
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200182 memset(&hdr, 0, sizeof(struct sg_io_hdr));
183 hdr.interface_id = 'S';
184 hdr.cmd_len = req->elem.out_sg[1].iov_len;
185 hdr.cmdp = req->elem.out_sg[1].iov_base;
186 hdr.dxfer_len = 0;
187
188 if (req->elem.out_num > 2) {
189 /*
190 * If there are more than the minimally required 2 output segments
191 * there is write payload starting from the third iovec.
192 */
193 hdr.dxfer_direction = SG_DXFER_TO_DEV;
194 hdr.iovec_count = req->elem.out_num - 2;
195
196 for (i = 0; i < hdr.iovec_count; i++)
197 hdr.dxfer_len += req->elem.out_sg[i + 2].iov_len;
198
199 hdr.dxferp = req->elem.out_sg + 2;
200
201 } else if (req->elem.in_num > 3) {
202 /*
203 * If we have more than 3 input segments the guest wants to actually
204 * read data.
205 */
206 hdr.dxfer_direction = SG_DXFER_FROM_DEV;
207 hdr.iovec_count = req->elem.in_num - 3;
208 for (i = 0; i < hdr.iovec_count; i++)
209 hdr.dxfer_len += req->elem.in_sg[i].iov_len;
210
211 hdr.dxferp = req->elem.in_sg;
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200212 } else {
213 /*
214 * Some SCSI commands don't actually transfer any data.
215 */
216 hdr.dxfer_direction = SG_DXFER_NONE;
217 }
218
219 hdr.sbp = req->elem.in_sg[req->elem.in_num - 3].iov_base;
220 hdr.mx_sb_len = req->elem.in_sg[req->elem.in_num - 3].iov_len;
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200221
222 ret = bdrv_ioctl(req->dev->bs, SG_IO, &hdr);
223 if (ret) {
224 status = VIRTIO_BLK_S_UNSUPP;
Paolo Bonzinif34e73c2012-05-16 12:54:03 +0200225 goto fail;
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200226 }
227
Paolo Bonzini5bb23922011-11-02 13:19:40 +0100228 /*
229 * From SCSI-Generic-HOWTO: "Some lower level drivers (e.g. ide-scsi)
230 * clear the masked_status field [hence status gets cleared too, see
231 * block/scsi_ioctl.c] even when a CHECK_CONDITION or COMMAND_TERMINATED
232 * status has occurred. However they do set DRIVER_SENSE in driver_status
233 * field. Also a (sb_len_wr > 0) indicates there is a sense buffer.
234 */
235 if (hdr.status == 0 && hdr.sb_len_wr > 0) {
236 hdr.status = CHECK_CONDITION;
237 }
238
239 stl_p(&req->scsi->errors,
240 hdr.status | (hdr.msg_status << 8) |
241 (hdr.host_status << 16) | (hdr.driver_status << 24));
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100242 stl_p(&req->scsi->residual, hdr.resid);
243 stl_p(&req->scsi->sense_len, hdr.sb_len_wr);
244 stl_p(&req->scsi->data_len, hdr.dxfer_len);
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200245
246 virtio_blk_req_complete(req, status);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200247 g_free(req);
Avi Kivity730a9c52012-08-06 15:49:03 +0300248 return;
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200249#else
Paolo Bonzinif34e73c2012-05-16 12:54:03 +0200250 abort();
251#endif
252
253fail:
254 /* Just put anything nonzero so that the ioctl fails in the guest. */
255 stl_p(&req->scsi->errors, 255);
256 virtio_blk_req_complete(req, status);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200257 g_free(req);
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200258}
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200259
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200260typedef struct MultiReqBuffer {
261 BlockRequest blkreq[32];
262 unsigned int num_writes;
263} MultiReqBuffer;
264
265static void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb)
aliguori869a5c62009-01-22 19:52:25 +0000266{
Kevin Wolf91553dc2009-09-09 17:53:38 +0200267 int i, ret;
Christoph Hellwig87b245d2009-08-13 16:49:56 +0200268
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200269 if (!mrb->num_writes) {
270 return;
271 }
272
273 ret = bdrv_aio_multiwrite(bs, mrb->blkreq, mrb->num_writes);
Kevin Wolf91553dc2009-09-09 17:53:38 +0200274 if (ret != 0) {
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200275 for (i = 0; i < mrb->num_writes; i++) {
276 if (mrb->blkreq[i].error) {
277 virtio_blk_rw_complete(mrb->blkreq[i].opaque, -EIO);
Kevin Wolf91553dc2009-09-09 17:53:38 +0200278 }
279 }
Christoph Hellwig87b245d2009-08-13 16:49:56 +0200280 }
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200281
282 mrb->num_writes = 0;
aliguorid28a1b62009-03-28 17:46:14 +0000283}
aliguori869a5c62009-01-22 19:52:25 +0000284
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200285static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
Christoph Hellwigaa659be2009-09-04 19:02:23 +0200286{
Christoph Hellwiga597e792011-08-25 08:26:01 +0200287 bdrv_acct_start(req->dev->bs, &req->acct, 0, BDRV_ACCT_FLUSH);
288
Christoph Hellwig618fbb82010-05-19 12:40:09 +0200289 /*
290 * Make sure all outstanding writes are posted to the backing device.
291 */
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200292 virtio_submit_multiwrite(req->dev->bs, mrb);
Paolo Bonziniad54ae82011-11-30 09:12:30 +0100293 bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
Christoph Hellwigaa659be2009-09-04 19:02:23 +0200294}
295
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200296static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
Kevin Wolf91553dc2009-09-09 17:53:38 +0200297{
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200298 BlockRequest *blkreq;
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100299 uint64_t sector;
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200300
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100301 sector = ldq_p(&req->out->sector);
Stefan Hajnoczi6d519a52010-05-22 18:15:08 +0100302
Christoph Hellwiga597e792011-08-25 08:26:01 +0200303 bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_WRITE);
304
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100305 trace_virtio_blk_handle_write(req, sector, req->qiov.size / 512);
306
307 if (sector & req->dev->sector_mask) {
Christoph Hellwig8cfacf02010-03-04 14:20:17 +0100308 virtio_blk_rw_complete(req, -EIO);
309 return;
310 }
Christoph Hellwig52c05022011-04-06 20:28:34 +0200311 if (req->qiov.size % req->dev->conf->logical_block_size) {
312 virtio_blk_rw_complete(req, -EIO);
313 return;
314 }
Christoph Hellwig8cfacf02010-03-04 14:20:17 +0100315
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200316 if (mrb->num_writes == 32) {
317 virtio_submit_multiwrite(req->dev->bs, mrb);
Kevin Wolf91553dc2009-09-09 17:53:38 +0200318 }
319
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200320 blkreq = &mrb->blkreq[mrb->num_writes];
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100321 blkreq->sector = sector;
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200322 blkreq->nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;
323 blkreq->qiov = &req->qiov;
324 blkreq->cb = virtio_blk_rw_complete;
325 blkreq->opaque = req;
326 blkreq->error = 0;
Kevin Wolf91553dc2009-09-09 17:53:38 +0200327
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200328 mrb->num_writes++;
Kevin Wolf91553dc2009-09-09 17:53:38 +0200329}
330
aliguorid28a1b62009-03-28 17:46:14 +0000331static void virtio_blk_handle_read(VirtIOBlockReq *req)
332{
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100333 uint64_t sector;
Christoph Hellwig87b245d2009-08-13 16:49:56 +0200334
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100335 sector = ldq_p(&req->out->sector);
336
Christoph Hellwiga597e792011-08-25 08:26:01 +0200337 bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);
338
Stefan Hajnoczi81b6b9f2011-12-22 13:17:02 +0000339 trace_virtio_blk_handle_read(req, sector, req->qiov.size / 512);
340
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100341 if (sector & req->dev->sector_mask) {
Christoph Hellwig8cfacf02010-03-04 14:20:17 +0100342 virtio_blk_rw_complete(req, -EIO);
343 return;
344 }
Christoph Hellwig52c05022011-04-06 20:28:34 +0200345 if (req->qiov.size % req->dev->conf->logical_block_size) {
346 virtio_blk_rw_complete(req, -EIO);
347 return;
348 }
Paolo Bonziniad54ae82011-11-30 09:12:30 +0100349 bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
350 req->qiov.size / BDRV_SECTOR_SIZE,
351 virtio_blk_rw_complete, req);
aliguori869a5c62009-01-22 19:52:25 +0000352}
353
Kevin Wolfbc6694d2010-01-27 13:12:34 +0100354static void virtio_blk_handle_request(VirtIOBlockReq *req,
355 MultiReqBuffer *mrb)
356{
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100357 uint32_t type;
358
Kevin Wolfbc6694d2010-01-27 13:12:34 +0100359 if (req->elem.out_num < 1 || req->elem.in_num < 1) {
Stefan Hajnoczi870cef12010-11-15 20:44:35 +0000360 error_report("virtio-blk missing headers");
Kevin Wolfbc6694d2010-01-27 13:12:34 +0100361 exit(1);
362 }
363
364 if (req->elem.out_sg[0].iov_len < sizeof(*req->out) ||
365 req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) {
Stefan Hajnoczi870cef12010-11-15 20:44:35 +0000366 error_report("virtio-blk header not in correct element");
Kevin Wolfbc6694d2010-01-27 13:12:34 +0100367 exit(1);
368 }
369
370 req->out = (void *)req->elem.out_sg[0].iov_base;
371 req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
372
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100373 type = ldl_p(&req->out->type);
374
375 if (type & VIRTIO_BLK_T_FLUSH) {
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200376 virtio_blk_handle_flush(req, mrb);
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100377 } else if (type & VIRTIO_BLK_T_SCSI_CMD) {
Kevin Wolfbc6694d2010-01-27 13:12:34 +0100378 virtio_blk_handle_scsi(req);
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100379 } else if (type & VIRTIO_BLK_T_GET_ID) {
john cooper2930b312010-07-02 13:44:25 -0400380 VirtIOBlock *s = req->dev;
381
Markus Armbrustera8686a92011-06-20 11:35:18 +0200382 /*
383 * NB: per existing s/n string convention the string is
384 * terminated by '\0' only when shorter than buffer.
385 */
386 strncpy(req->elem.in_sg[0].iov_base,
Paolo Bonzini12c56742012-05-16 12:54:05 +0200387 s->blk->serial ? s->blk->serial : "",
Markus Armbrustera8686a92011-06-20 11:35:18 +0200388 MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
john cooper2930b312010-07-02 13:44:25 -0400389 virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
Christoph Hellwiga597e792011-08-25 08:26:01 +0200390 g_free(req);
Aurelien Jarno92e3c2a2011-01-25 11:55:14 +0100391 } else if (type & VIRTIO_BLK_T_OUT) {
Kevin Wolfbc6694d2010-01-27 13:12:34 +0100392 qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
393 req->elem.out_num - 1);
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200394 virtio_blk_handle_write(req, mrb);
Kevin Wolfbc6694d2010-01-27 13:12:34 +0100395 } else {
396 qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
397 req->elem.in_num - 1);
398 virtio_blk_handle_read(req);
399 }
400}
401
aliguori6e02c382008-12-04 19:52:44 +0000402static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
403{
404 VirtIOBlock *s = to_virtio_blk(vdev);
405 VirtIOBlockReq *req;
Kevin Wolfbc6694d2010-01-27 13:12:34 +0100406 MultiReqBuffer mrb = {
407 .num_writes = 0,
Kevin Wolfbc6694d2010-01-27 13:12:34 +0100408 };
aliguori6e02c382008-12-04 19:52:44 +0000409
410 while ((req = virtio_blk_get_request(s))) {
Kevin Wolfbc6694d2010-01-27 13:12:34 +0100411 virtio_blk_handle_request(req, &mrb);
aliguori6e02c382008-12-04 19:52:44 +0000412 }
Kevin Wolf91553dc2009-09-09 17:53:38 +0200413
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200414 virtio_submit_multiwrite(s->bs, &mrb);
Kevin Wolf91553dc2009-09-09 17:53:38 +0200415
aliguori6e02c382008-12-04 19:52:44 +0000416 /*
417 * FIXME: Want to check for completions before returning to guest mode,
418 * so cached reads and writes are reported as quickly as possible. But
419 * that should be done in the generic block layer.
420 */
421}
422
Markus Armbruster213189a2009-07-28 14:33:41 -0400423static void virtio_blk_dma_restart_bh(void *opaque)
aliguori869a5c62009-01-22 19:52:25 +0000424{
425 VirtIOBlock *s = opaque;
426 VirtIOBlockReq *req = s->rq;
Kevin Wolff1b52862010-01-27 13:12:35 +0100427 MultiReqBuffer mrb = {
428 .num_writes = 0,
Kevin Wolff1b52862010-01-27 13:12:35 +0100429 };
aliguori869a5c62009-01-22 19:52:25 +0000430
Markus Armbruster213189a2009-07-28 14:33:41 -0400431 qemu_bh_delete(s->bh);
432 s->bh = NULL;
aliguori869a5c62009-01-22 19:52:25 +0000433
434 s->rq = NULL;
435
436 while (req) {
Kevin Wolff1b52862010-01-27 13:12:35 +0100437 virtio_blk_handle_request(req, &mrb);
aliguori869a5c62009-01-22 19:52:25 +0000438 req = req->next;
439 }
Kevin Wolff1b52862010-01-27 13:12:35 +0100440
Christoph Hellwigc20fd872010-06-08 18:26:07 +0200441 virtio_submit_multiwrite(s->bs, &mrb);
aliguori869a5c62009-01-22 19:52:25 +0000442}
443
Luiz Capitulino1dfb4dd2011-07-29 14:26:33 -0300444static void virtio_blk_dma_restart_cb(void *opaque, int running,
445 RunState state)
Markus Armbruster213189a2009-07-28 14:33:41 -0400446{
447 VirtIOBlock *s = opaque;
448
449 if (!running)
450 return;
451
452 if (!s->bh) {
453 s->bh = qemu_bh_new(virtio_blk_dma_restart_bh, s);
454 qemu_bh_schedule(s->bh);
455 }
456}
457
aliguori6e02c382008-12-04 19:52:44 +0000458static void virtio_blk_reset(VirtIODevice *vdev)
459{
460 /*
461 * This should cancel pending requests, but can't do nicely until there
462 * are per-device request lists.
463 */
Stefan Hajnoczi922453b2011-11-30 12:23:43 +0000464 bdrv_drain_all();
aliguori6e02c382008-12-04 19:52:44 +0000465}
466
john cooperbf011292009-06-22 14:26:51 -0400467/* coalesce internal state, copy to pci i/o region 0
468 */
aliguori6e02c382008-12-04 19:52:44 +0000469static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
470{
471 VirtIOBlock *s = to_virtio_blk(vdev);
472 struct virtio_blk_config blkcfg;
473 uint64_t capacity;
Paolo Bonzini3a395142011-11-18 16:31:59 +0100474 int blk_size = s->conf->logical_block_size;
aliguori6e02c382008-12-04 19:52:44 +0000475
476 bdrv_get_geometry(s->bs, &capacity);
Gerd Hoffmann5c5dafd2009-06-12 09:50:18 +0200477 memset(&blkcfg, 0, sizeof(blkcfg));
aliguori6e02c382008-12-04 19:52:44 +0000478 stq_raw(&blkcfg.capacity, capacity);
479 stl_raw(&blkcfg.seg_max, 128 - 2);
Markus Armbrustere63e7fd2012-07-10 11:12:43 +0200480 stw_raw(&blkcfg.cylinders, s->conf->cyls);
Paolo Bonzini3a395142011-11-18 16:31:59 +0100481 stl_raw(&blkcfg.blk_size, blk_size);
482 stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
483 stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
Markus Armbrustere63e7fd2012-07-10 11:12:43 +0200484 blkcfg.heads = s->conf->heads;
Christian Borntraeger136be992012-05-24 13:22:55 +0200485 /*
486 * We must ensure that the block device capacity is a multiple of
487 * the logical block size. If that is not the case, lets use
488 * sector_mask to adopt the geometry to have a correct picture.
489 * For those devices where the capacity is ok for the given geometry
490 * we dont touch the sector value of the geometry, since some devices
491 * (like s390 dasd) need a specific value. Here the capacity is already
492 * cyls*heads*secs*blk_size and the sector value is not block size
493 * divided by 512 - instead it is the amount of blk_size blocks
494 * per track (cylinder).
495 */
Markus Armbrustere63e7fd2012-07-10 11:12:43 +0200496 if (bdrv_getlength(s->bs) / s->conf->heads / s->conf->secs % blk_size) {
497 blkcfg.sectors = s->conf->secs & ~s->sector_mask;
Christian Borntraeger136be992012-05-24 13:22:55 +0200498 } else {
Markus Armbrustere63e7fd2012-07-10 11:12:43 +0200499 blkcfg.sectors = s->conf->secs;
Christian Borntraeger136be992012-05-24 13:22:55 +0200500 }
Blue Swirlc7085da2009-06-13 13:20:25 +0000501 blkcfg.size_max = 0;
Christoph Hellwig9752c372010-02-10 23:37:25 +0100502 blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
503 blkcfg.alignment_offset = 0;
Paolo Bonzini13e3dce2012-08-09 16:07:19 +0200504 blkcfg.wce = bdrv_enable_write_cache(s->bs);
hch@lst.de37d5ddd2010-02-10 23:36:49 +0100505 memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
aliguori6e02c382008-12-04 19:52:44 +0000506}
507
Paolo Bonzini13e3dce2012-08-09 16:07:19 +0200508static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
509{
510 VirtIOBlock *s = to_virtio_blk(vdev);
511 struct virtio_blk_config blkcfg;
512
513 memcpy(&blkcfg, config, sizeof(blkcfg));
514 bdrv_set_enable_write_cache(s->bs, blkcfg.wce != 0);
515}
516
Michael S. Tsirkin81725392010-01-10 13:52:53 +0200517static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
aliguori6e02c382008-12-04 19:52:44 +0000518{
john cooperbf011292009-06-22 14:26:51 -0400519 VirtIOBlock *s = to_virtio_blk(vdev);
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200520
521 features |= (1 << VIRTIO_BLK_F_SEG_MAX);
522 features |= (1 << VIRTIO_BLK_F_GEOMETRY);
Christoph Hellwig9752c372010-02-10 23:37:25 +0100523 features |= (1 << VIRTIO_BLK_F_TOPOLOGY);
Christoph Hellwig8cfacf02010-03-04 14:20:17 +0100524 features |= (1 << VIRTIO_BLK_F_BLK_SIZE);
Paolo Bonzinia6c5c842012-05-16 12:54:06 +0200525 features |= (1 << VIRTIO_BLK_F_SCSI);
Christoph Hellwigaa659be2009-09-04 19:02:23 +0200526
527 if (bdrv_enable_write_cache(s->bs))
Paolo Bonzini13e3dce2012-08-09 16:07:19 +0200528 features |= (1 << VIRTIO_BLK_F_WCE);
529
Naphtali Spreic79662f2009-10-29 11:42:11 +0200530 if (bdrv_is_read_only(s->bs))
531 features |= 1 << VIRTIO_BLK_F_RO;
Christoph Hellwig1063b8b2009-04-27 10:29:14 +0200532
533 return features;
aliguori6e02c382008-12-04 19:52:44 +0000534}
535
Paolo Bonzini9315cbf2012-08-09 16:07:20 +0200536static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
537{
538 VirtIOBlock *s = to_virtio_blk(vdev);
539 uint32_t features;
540
541 if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
542 return;
543 }
544
545 features = vdev->guest_features;
546 bdrv_set_enable_write_cache(s->bs, !!(features & (1 << VIRTIO_BLK_F_WCE)));
547}
548
aliguori6e02c382008-12-04 19:52:44 +0000549static void virtio_blk_save(QEMUFile *f, void *opaque)
550{
551 VirtIOBlock *s = opaque;
aliguori869a5c62009-01-22 19:52:25 +0000552 VirtIOBlockReq *req = s->rq;
553
aliguori6e02c382008-12-04 19:52:44 +0000554 virtio_save(&s->vdev, f);
aliguori869a5c62009-01-22 19:52:25 +0000555
556 while (req) {
557 qemu_put_sbyte(f, 1);
558 qemu_put_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
559 req = req->next;
560 }
561 qemu_put_sbyte(f, 0);
aliguori6e02c382008-12-04 19:52:44 +0000562}
563
564static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
565{
566 VirtIOBlock *s = opaque;
Orit Wassermann2a633c42012-05-16 12:21:35 +0200567 int ret;
aliguori6e02c382008-12-04 19:52:44 +0000568
aliguori869a5c62009-01-22 19:52:25 +0000569 if (version_id != 2)
aliguori6e02c382008-12-04 19:52:44 +0000570 return -EINVAL;
571
Orit Wassermann2a633c42012-05-16 12:21:35 +0200572 ret = virtio_load(&s->vdev, f);
573 if (ret) {
574 return ret;
575 }
576
aliguori869a5c62009-01-22 19:52:25 +0000577 while (qemu_get_sbyte(f)) {
578 VirtIOBlockReq *req = virtio_blk_alloc_request(s);
579 qemu_get_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
580 req->next = s->rq;
Yoshiaki Tamura20a81e42010-06-21 17:50:01 +0900581 s->rq = req;
Kevin Wolfb6a48052010-08-03 16:57:02 +0200582
583 virtqueue_map_sg(req->elem.in_sg, req->elem.in_addr,
584 req->elem.in_num, 1);
585 virtqueue_map_sg(req->elem.out_sg, req->elem.out_addr,
586 req->elem.out_num, 0);
aliguori869a5c62009-01-22 19:52:25 +0000587 }
aliguori6e02c382008-12-04 19:52:44 +0000588
589 return 0;
590}
591
Markus Armbruster145feb12011-08-03 15:07:42 +0200592static void virtio_blk_resize(void *opaque)
Christoph Hellwige5051fc2011-01-24 13:32:51 +0100593{
594 VirtIOBlock *s = opaque;
595
Markus Armbruster145feb12011-08-03 15:07:42 +0200596 virtio_notify_config(&s->vdev);
Christoph Hellwige5051fc2011-01-24 13:32:51 +0100597}
598
Markus Armbruster0e49de52011-08-03 15:07:41 +0200599static const BlockDevOps virtio_block_ops = {
Markus Armbruster145feb12011-08-03 15:07:42 +0200600 .resize_cb = virtio_blk_resize,
Markus Armbruster0e49de52011-08-03 15:07:41 +0200601};
602
Paolo Bonzini12c56742012-05-16 12:54:05 +0200603VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
aliguori6e02c382008-12-04 19:52:44 +0000604{
605 VirtIOBlock *s;
aliguori6e02c382008-12-04 19:52:44 +0000606 static int virtio_blk_id;
607
Paolo Bonzini12c56742012-05-16 12:54:05 +0200608 if (!blk->conf.bs) {
Markus Armbruster6a84cb12011-12-21 11:37:57 +0100609 error_report("drive property not set");
Markus Armbrusterd75d25e2010-07-06 14:37:43 +0200610 return NULL;
611 }
Paolo Bonzini12c56742012-05-16 12:54:05 +0200612 if (!bdrv_is_inserted(blk->conf.bs)) {
Markus Armbruster98f28ad2010-07-06 14:37:44 +0200613 error_report("Device needs media, but drive is empty");
614 return NULL;
615 }
Markus Armbrusterd75d25e2010-07-06 14:37:43 +0200616
Markus Armbruster911525d2012-07-11 15:08:37 +0200617 blkconf_serial(&blk->conf, &blk->serial);
Markus Armbrusterb7eb0c92012-07-11 15:08:39 +0200618 if (blkconf_geometry(&blk->conf, NULL, 65535, 255, 255) < 0) {
619 return NULL;
620 }
Markus Armbrustera8686a92011-06-20 11:35:18 +0200621
Paul Brook53c25ce2009-05-18 14:51:59 +0100622 s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
hch@lst.de37d5ddd2010-02-10 23:36:49 +0100623 sizeof(struct virtio_blk_config),
Paul Brook53c25ce2009-05-18 14:51:59 +0100624 sizeof(VirtIOBlock));
aliguori6e02c382008-12-04 19:52:44 +0000625
626 s->vdev.get_config = virtio_blk_update_config;
Paolo Bonzini13e3dce2012-08-09 16:07:19 +0200627 s->vdev.set_config = virtio_blk_set_config;
aliguori6e02c382008-12-04 19:52:44 +0000628 s->vdev.get_features = virtio_blk_get_features;
Paolo Bonzini9315cbf2012-08-09 16:07:20 +0200629 s->vdev.set_status = virtio_blk_set_status;
aliguori6e02c382008-12-04 19:52:44 +0000630 s->vdev.reset = virtio_blk_reset;
Paolo Bonzini12c56742012-05-16 12:54:05 +0200631 s->bs = blk->conf.bs;
632 s->conf = &blk->conf;
633 s->blk = blk;
aliguori869a5c62009-01-22 19:52:25 +0000634 s->rq = NULL;
Jes Sorensen1573a352010-05-27 16:20:33 +0200635 s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
Markus Armbrustere63e7fd2012-07-10 11:12:43 +0200636
aliguori6e02c382008-12-04 19:52:44 +0000637 s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
638
aliguori869a5c62009-01-22 19:52:25 +0000639 qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
Alex Williamson9d0d3132010-07-20 11:14:22 -0600640 s->qdev = dev;
Alex Williamson0be71e32010-06-25 11:09:07 -0600641 register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
aliguori6e02c382008-12-04 19:52:44 +0000642 virtio_blk_save, virtio_blk_load, s);
Markus Armbruster0e49de52011-08-03 15:07:41 +0200643 bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
Paolo Bonzini12c56742012-05-16 12:54:05 +0200644 bdrv_set_buffer_alignment(s->bs, s->conf->logical_block_size);
Paul Brook07e3af92009-05-14 22:35:08 +0100645
Luiz Capitulinoaf239a62011-09-26 17:43:51 -0300646 bdrv_iostatus_enable(s->bs);
Paolo Bonzini12c56742012-05-16 12:54:05 +0200647 add_boot_device_path(s->conf->bootindex, dev, "/disk@0,0");
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200648
Paul Brook53c25ce2009-05-18 14:51:59 +0100649 return &s->vdev;
Paul Brook07e3af92009-05-14 22:35:08 +0100650}
Alex Williamson9d0d3132010-07-20 11:14:22 -0600651
652void virtio_blk_exit(VirtIODevice *vdev)
653{
654 VirtIOBlock *s = to_virtio_blk(vdev);
655 unregister_savevm(s->qdev, "virtio-blk", s);
Paolo Bonzini0e479312012-05-16 12:54:04 +0200656 blockdev_mark_auto_del(s->bs);
Amit Shahd92551f2011-07-27 14:00:30 +0530657 virtio_cleanup(vdev);
Alex Williamson9d0d3132010-07-20 11:14:22 -0600658}