]> Git Repo - qemu.git/blob - hw/virtio-blk.c
Add virtio disk identification support
[qemu.git] / hw / virtio-blk.c
1 /*
2  * Virtio Block Device
3  *
4  * Copyright IBM, Corp. 2007
5  *
6  * Authors:
7  *  Anthony Liguori   <[email protected]>
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
14 #include <qemu-common.h>
15 #include "virtio-blk.h"
16 #ifdef __linux__
17 # include <scsi/sg.h>
18 #endif
19
20 typedef struct VirtIOBlock
21 {
22     VirtIODevice vdev;
23     BlockDriverState *bs;
24     VirtQueue *vq;
25     void *rq;
26     QEMUBH *bh;
27     BlockConf *conf;
28     unsigned short sector_mask;
29     char sn[BLOCK_SERIAL_STRLEN];
30 } VirtIOBlock;
31
32 static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
33 {
34     return (VirtIOBlock *)vdev;
35 }
36
37 typedef struct VirtIOBlockReq
38 {
39     VirtIOBlock *dev;
40     VirtQueueElement elem;
41     struct virtio_blk_inhdr *in;
42     struct virtio_blk_outhdr *out;
43     struct virtio_scsi_inhdr *scsi;
44     QEMUIOVector qiov;
45     struct VirtIOBlockReq *next;
46 } VirtIOBlockReq;
47
48 static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
49 {
50     VirtIOBlock *s = req->dev;
51
52     req->in->status = status;
53     virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in));
54     virtio_notify(&s->vdev, s->vq);
55
56     qemu_free(req);
57 }
58
59 static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
60     int is_read)
61 {
62     BlockErrorAction action = bdrv_get_on_error(req->dev->bs, is_read);
63     VirtIOBlock *s = req->dev;
64
65     if (action == BLOCK_ERR_IGNORE) {
66         bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read);
67         return 0;
68     }
69
70     if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
71             || action == BLOCK_ERR_STOP_ANY) {
72         req->next = s->rq;
73         s->rq = req;
74         bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
75         vm_stop(0);
76     } else {
77         virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
78         bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
79     }
80
81     return 1;
82 }
83
84 static void virtio_blk_rw_complete(void *opaque, int ret)
85 {
86     VirtIOBlockReq *req = opaque;
87
88     if (ret) {
89         int is_read = !(req->out->type & VIRTIO_BLK_T_OUT);
90         if (virtio_blk_handle_rw_error(req, -ret, is_read))
91             return;
92     }
93
94     virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
95 }
96
97 static void virtio_blk_flush_complete(void *opaque, int ret)
98 {
99     VirtIOBlockReq *req = opaque;
100
101     virtio_blk_req_complete(req, ret ? VIRTIO_BLK_S_IOERR : VIRTIO_BLK_S_OK);
102 }
103
104 static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
105 {
106     VirtIOBlockReq *req = qemu_malloc(sizeof(*req));
107     req->dev = s;
108     req->qiov.size = 0;
109     req->next = NULL;
110     return req;
111 }
112
113 static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
114 {
115     VirtIOBlockReq *req = virtio_blk_alloc_request(s);
116
117     if (req != NULL) {
118         if (!virtqueue_pop(s->vq, &req->elem)) {
119             qemu_free(req);
120             return NULL;
121         }
122     }
123
124     return req;
125 }
126
127 #ifdef __linux__
128 static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
129 {
130     struct sg_io_hdr hdr;
131     int ret;
132     int status;
133     int i;
134
135     /*
136      * We require at least one output segment each for the virtio_blk_outhdr
137      * and the SCSI command block.
138      *
139      * We also at least require the virtio_blk_inhdr, the virtio_scsi_inhdr
140      * and the sense buffer pointer in the input segments.
141      */
142     if (req->elem.out_num < 2 || req->elem.in_num < 3) {
143         virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
144         return;
145     }
146
147     /*
148      * No support for bidirection commands yet.
149      */
150     if (req->elem.out_num > 2 && req->elem.in_num > 3) {
151         virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
152         return;
153     }
154
155     /*
156      * The scsi inhdr is placed in the second-to-last input segment, just
157      * before the regular inhdr.
158      */
159     req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
160
161     memset(&hdr, 0, sizeof(struct sg_io_hdr));
162     hdr.interface_id = 'S';
163     hdr.cmd_len = req->elem.out_sg[1].iov_len;
164     hdr.cmdp = req->elem.out_sg[1].iov_base;
165     hdr.dxfer_len = 0;
166
167     if (req->elem.out_num > 2) {
168         /*
169          * If there are more than the minimally required 2 output segments
170          * there is write payload starting from the third iovec.
171          */
172         hdr.dxfer_direction = SG_DXFER_TO_DEV;
173         hdr.iovec_count = req->elem.out_num - 2;
174
175         for (i = 0; i < hdr.iovec_count; i++)
176             hdr.dxfer_len += req->elem.out_sg[i + 2].iov_len;
177
178         hdr.dxferp = req->elem.out_sg + 2;
179
180     } else if (req->elem.in_num > 3) {
181         /*
182          * If we have more than 3 input segments the guest wants to actually
183          * read data.
184          */
185         hdr.dxfer_direction = SG_DXFER_FROM_DEV;
186         hdr.iovec_count = req->elem.in_num - 3;
187         for (i = 0; i < hdr.iovec_count; i++)
188             hdr.dxfer_len += req->elem.in_sg[i].iov_len;
189
190         hdr.dxferp = req->elem.in_sg;
191     } else {
192         /*
193          * Some SCSI commands don't actually transfer any data.
194          */
195         hdr.dxfer_direction = SG_DXFER_NONE;
196     }
197
198     hdr.sbp = req->elem.in_sg[req->elem.in_num - 3].iov_base;
199     hdr.mx_sb_len = req->elem.in_sg[req->elem.in_num - 3].iov_len;
200
201     ret = bdrv_ioctl(req->dev->bs, SG_IO, &hdr);
202     if (ret) {
203         status = VIRTIO_BLK_S_UNSUPP;
204         hdr.status = ret;
205         hdr.resid = hdr.dxfer_len;
206     } else if (hdr.status) {
207         status = VIRTIO_BLK_S_IOERR;
208     } else {
209         status = VIRTIO_BLK_S_OK;
210     }
211
212     req->scsi->errors = hdr.status;
213     req->scsi->residual = hdr.resid;
214     req->scsi->sense_len = hdr.sb_len_wr;
215     req->scsi->data_len = hdr.dxfer_len;
216
217     virtio_blk_req_complete(req, status);
218 }
219 #else
220 static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
221 {
222     virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
223 }
224 #endif /* __linux__ */
225
226 typedef struct MultiReqBuffer {
227     BlockRequest        blkreq[32];
228     unsigned int        num_writes;
229 } MultiReqBuffer;
230
231 static void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb)
232 {
233     int i, ret;
234
235     if (!mrb->num_writes) {
236         return;
237     }
238
239     ret = bdrv_aio_multiwrite(bs, mrb->blkreq, mrb->num_writes);
240     if (ret != 0) {
241         for (i = 0; i < mrb->num_writes; i++) {
242             if (mrb->blkreq[i].error) {
243                 virtio_blk_rw_complete(mrb->blkreq[i].opaque, -EIO);
244             }
245         }
246     }
247
248     mrb->num_writes = 0;
249 }
250
251 static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
252 {
253     BlockDriverAIOCB *acb;
254
255     /*
256      * Make sure all outstanding writes are posted to the backing device.
257      */
258     virtio_submit_multiwrite(req->dev->bs, mrb);
259
260     acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
261     if (!acb) {
262         virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
263     }
264 }
265
266 static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
267 {
268     BlockRequest *blkreq;
269
270     if (req->out->sector & req->dev->sector_mask) {
271         virtio_blk_rw_complete(req, -EIO);
272         return;
273     }
274
275     if (mrb->num_writes == 32) {
276         virtio_submit_multiwrite(req->dev->bs, mrb);
277     }
278
279     blkreq = &mrb->blkreq[mrb->num_writes];
280     blkreq->sector = req->out->sector;
281     blkreq->nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;
282     blkreq->qiov = &req->qiov;
283     blkreq->cb = virtio_blk_rw_complete;
284     blkreq->opaque = req;
285     blkreq->error = 0;
286
287     mrb->num_writes++;
288 }
289
290 static void virtio_blk_handle_read(VirtIOBlockReq *req)
291 {
292     BlockDriverAIOCB *acb;
293
294     if (req->out->sector & req->dev->sector_mask) {
295         virtio_blk_rw_complete(req, -EIO);
296         return;
297     }
298
299     acb = bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov,
300                          req->qiov.size / BDRV_SECTOR_SIZE,
301                          virtio_blk_rw_complete, req);
302     if (!acb) {
303         virtio_blk_rw_complete(req, -EIO);
304     }
305 }
306
307 static void virtio_blk_handle_request(VirtIOBlockReq *req,
308     MultiReqBuffer *mrb)
309 {
310     if (req->elem.out_num < 1 || req->elem.in_num < 1) {
311         fprintf(stderr, "virtio-blk missing headers\n");
312         exit(1);
313     }
314
315     if (req->elem.out_sg[0].iov_len < sizeof(*req->out) ||
316         req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) {
317         fprintf(stderr, "virtio-blk header not in correct element\n");
318         exit(1);
319     }
320
321     req->out = (void *)req->elem.out_sg[0].iov_base;
322     req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
323
324     if (req->out->type & VIRTIO_BLK_T_FLUSH) {
325         virtio_blk_handle_flush(req, mrb);
326     } else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
327         virtio_blk_handle_scsi(req);
328     } else if (req->out->type & VIRTIO_BLK_T_GET_ID) {
329         VirtIOBlock *s = req->dev;
330
331         memcpy(req->elem.in_sg[0].iov_base, s->sn,
332                MIN(req->elem.in_sg[0].iov_len, sizeof(s->sn)));
333         virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
334     } else if (req->out->type & VIRTIO_BLK_T_OUT) {
335         qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
336                                  req->elem.out_num - 1);
337         virtio_blk_handle_write(req, mrb);
338     } else {
339         qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
340                                  req->elem.in_num - 1);
341         virtio_blk_handle_read(req);
342     }
343 }
344
345 static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
346 {
347     VirtIOBlock *s = to_virtio_blk(vdev);
348     VirtIOBlockReq *req;
349     MultiReqBuffer mrb = {
350         .num_writes = 0,
351     };
352
353     while ((req = virtio_blk_get_request(s))) {
354         virtio_blk_handle_request(req, &mrb);
355     }
356
357     virtio_submit_multiwrite(s->bs, &mrb);
358
359     /*
360      * FIXME: Want to check for completions before returning to guest mode,
361      * so cached reads and writes are reported as quickly as possible. But
362      * that should be done in the generic block layer.
363      */
364 }
365
366 static void virtio_blk_dma_restart_bh(void *opaque)
367 {
368     VirtIOBlock *s = opaque;
369     VirtIOBlockReq *req = s->rq;
370     MultiReqBuffer mrb = {
371         .num_writes = 0,
372     };
373
374     qemu_bh_delete(s->bh);
375     s->bh = NULL;
376
377     s->rq = NULL;
378
379     while (req) {
380         virtio_blk_handle_request(req, &mrb);
381         req = req->next;
382     }
383
384     virtio_submit_multiwrite(s->bs, &mrb);
385 }
386
387 static void virtio_blk_dma_restart_cb(void *opaque, int running, int reason)
388 {
389     VirtIOBlock *s = opaque;
390
391     if (!running)
392         return;
393
394     if (!s->bh) {
395         s->bh = qemu_bh_new(virtio_blk_dma_restart_bh, s);
396         qemu_bh_schedule(s->bh);
397     }
398 }
399
400 static void virtio_blk_reset(VirtIODevice *vdev)
401 {
402     /*
403      * This should cancel pending requests, but can't do nicely until there
404      * are per-device request lists.
405      */
406     qemu_aio_flush();
407 }
408
409 /* coalesce internal state, copy to pci i/o region 0
410  */
411 static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
412 {
413     VirtIOBlock *s = to_virtio_blk(vdev);
414     struct virtio_blk_config blkcfg;
415     uint64_t capacity;
416     int cylinders, heads, secs;
417
418     bdrv_get_geometry(s->bs, &capacity);
419     bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
420     memset(&blkcfg, 0, sizeof(blkcfg));
421     stq_raw(&blkcfg.capacity, capacity);
422     stl_raw(&blkcfg.seg_max, 128 - 2);
423     stw_raw(&blkcfg.cylinders, cylinders);
424     blkcfg.heads = heads;
425     blkcfg.sectors = secs & ~s->sector_mask;
426     blkcfg.blk_size = s->conf->logical_block_size;
427     blkcfg.size_max = 0;
428     blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
429     blkcfg.alignment_offset = 0;
430     blkcfg.min_io_size = s->conf->min_io_size / blkcfg.blk_size;
431     blkcfg.opt_io_size = s->conf->opt_io_size / blkcfg.blk_size;
432     memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
433 }
434
435 static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
436 {
437     VirtIOBlock *s = to_virtio_blk(vdev);
438
439     features |= (1 << VIRTIO_BLK_F_SEG_MAX);
440     features |= (1 << VIRTIO_BLK_F_GEOMETRY);
441     features |= (1 << VIRTIO_BLK_F_TOPOLOGY);
442     features |= (1 << VIRTIO_BLK_F_BLK_SIZE);
443
444     if (bdrv_enable_write_cache(s->bs))
445         features |= (1 << VIRTIO_BLK_F_WCACHE);
446     
447     if (bdrv_is_read_only(s->bs))
448         features |= 1 << VIRTIO_BLK_F_RO;
449
450     return features;
451 }
452
453 static void virtio_blk_save(QEMUFile *f, void *opaque)
454 {
455     VirtIOBlock *s = opaque;
456     VirtIOBlockReq *req = s->rq;
457
458     virtio_save(&s->vdev, f);
459     
460     while (req) {
461         qemu_put_sbyte(f, 1);
462         qemu_put_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
463         req = req->next;
464     }
465     qemu_put_sbyte(f, 0);
466 }
467
468 static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
469 {
470     VirtIOBlock *s = opaque;
471
472     if (version_id != 2)
473         return -EINVAL;
474
475     virtio_load(&s->vdev, f);
476     while (qemu_get_sbyte(f)) {
477         VirtIOBlockReq *req = virtio_blk_alloc_request(s);
478         qemu_get_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
479         req->next = s->rq;
480         s->rq = req;
481     }
482
483     return 0;
484 }
485
486 VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
487 {
488     VirtIOBlock *s;
489     int cylinders, heads, secs;
490     static int virtio_blk_id;
491     DriveInfo *dinfo;
492
493     s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
494                                           sizeof(struct virtio_blk_config),
495                                           sizeof(VirtIOBlock));
496
497     s->vdev.get_config = virtio_blk_update_config;
498     s->vdev.get_features = virtio_blk_get_features;
499     s->vdev.reset = virtio_blk_reset;
500     s->bs = conf->bs;
501     s->conf = conf;
502     s->rq = NULL;
503     s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
504     bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
505
506     /* NB: per existing s/n string convention the string is terminated
507      * by '\0' only when less than sizeof (s->sn)
508      */
509     dinfo = drive_get_by_blockdev(s->bs);
510     strncpy(s->sn, dinfo->serial, sizeof (s->sn));
511
512     s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
513
514     qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
515     register_savevm("virtio-blk", virtio_blk_id++, 2,
516                     virtio_blk_save, virtio_blk_load, s);
517     bdrv_set_removable(s->bs, 0);
518
519     return &s->vdev;
520 }
This page took 0.057525 seconds and 4 git commands to generate.