5 #include <qemu-common.h>
7 #include "qemu-vio-blk.h"
14 extern unsigned long int num_reads
;
15 extern unsigned long int num_writes
;
16 extern unsigned long int num_scsi_cmds
;
17 extern unsigned long int num_flushs
;
18 extern unsigned long int bytes_wrote
;
19 extern unsigned long int bytes_read
;
21 //#define trace() printf("qemu-vio-blk: %s-%s: %s(%d)\n",__TIME__, __FILE__,__func__, __LINE__)
25 static void qemu_vio_blk_req_complete(VirtIOBlockReq
*req
, int status
)
28 if (req
->out
->type
& VIRTIO_BLK_T_FLUSH
) {
29 bytes_wrote
+=req
->qiov
.size
;
30 } else if (req
->out
->type
& VIRTIO_BLK_T_SCSI_CMD
) {
31 bytes_wrote
+=req
->qiov
.size
;
32 } else if (req
->out
->type
& VIRTIO_BLK_T_OUT
) {
33 bytes_wrote
+=req
->qiov
.size
;
35 bytes_read
+=req
->qiov
.size
;
38 VirtIOBlock
*s
= req
->dev
;
40 req
->in
->status
= status
;
41 virtqueue_push(s
->vq
, &req
->elem
, req
->qiov
.size
+ sizeof(*req
->in
));
47 static void qemu_vio_blk_flush_complete(void *opaque
, int ret
)
49 VirtIOBlockReq
*req
= opaque
;
51 qemu_vio_blk_req_complete(req
, ret
? VIRTIO_BLK_S_IOERR
: VIRTIO_BLK_S_OK
);
55 static void qemu_vio_blk_handle_scsi(VirtIOBlockReq
*req
)
63 * We require at least one output segment each for the virtio_blk_outhdr
64 * and the SCSI command block.
66 * We also at least require the virtio_blk_inhdr, the virtio_scsi_inhdr
67 * and the sense buffer pointer in the input segments.
69 if (req
->elem
.out_num
< 2 || req
->elem
.in_num
< 3) {
70 qemu_vio_blk_req_complete(req
, VIRTIO_BLK_S_IOERR
);
75 * No support for bidirection commands yet.
77 if (req
->elem
.out_num
> 2 && req
->elem
.in_num
> 3) {
78 qemu_vio_blk_req_complete(req
, VIRTIO_BLK_S_UNSUPP
);
83 * The scsi inhdr is placed in the second-to-last input segment, just
84 * before the regular inhdr.
86 req
->scsi
= (void *)req
->elem
.in_sg
[req
->elem
.in_num
- 2].iov_base
;
87 size
= sizeof(*req
->in
) + sizeof(*req
->scsi
);
89 memset(&hdr
, 0, sizeof(struct sg_io_hdr
));
90 hdr
.interface_id
= 'S';
91 hdr
.cmd_len
= req
->elem
.out_sg
[1].iov_len
;
92 hdr
.cmdp
= req
->elem
.out_sg
[1].iov_base
;
95 if (req
->elem
.out_num
> 2) {
97 * If there are more than the minimally required 2 output segments
98 * there is write payload starting from the third iovec.
100 hdr
.dxfer_direction
= SG_DXFER_TO_DEV
;
101 hdr
.iovec_count
= req
->elem
.out_num
- 2;
103 for (i
= 0; i
< hdr
.iovec_count
; i
++)
104 hdr
.dxfer_len
+= req
->elem
.out_sg
[i
+ 2].iov_len
;
106 hdr
.dxferp
= req
->elem
.out_sg
+ 2;
108 } else if (req
->elem
.in_num
> 3) {
110 * If we have more than 3 input segments the guest wants to actually
113 hdr
.dxfer_direction
= SG_DXFER_FROM_DEV
;
114 hdr
.iovec_count
= req
->elem
.in_num
- 3;
115 for (i
= 0; i
< hdr
.iovec_count
; i
++)
116 hdr
.dxfer_len
+= req
->elem
.in_sg
[i
].iov_len
;
118 hdr
.dxferp
= req
->elem
.in_sg
;
119 size
+= hdr
.dxfer_len
;
122 * Some SCSI commands don't actually transfer any data.
124 hdr
.dxfer_direction
= SG_DXFER_NONE
;
127 hdr
.sbp
= req
->elem
.in_sg
[req
->elem
.in_num
- 3].iov_base
;
128 hdr
.mx_sb_len
= req
->elem
.in_sg
[req
->elem
.in_num
- 3].iov_len
;
129 size
+= hdr
.mx_sb_len
;
131 ret
= bdrv_ioctl(req
->dev
->bs
, SG_IO
, &hdr
);
133 status
= VIRTIO_BLK_S_UNSUPP
;
135 hdr
.resid
= hdr
.dxfer_len
;
136 } else if (hdr
.status
) {
137 status
= VIRTIO_BLK_S_IOERR
;
139 status
= VIRTIO_BLK_S_OK
;
142 req
->scsi
->errors
= hdr
.status
;
143 req
->scsi
->residual
= hdr
.resid
;
144 req
->scsi
->sense_len
= hdr
.sb_len_wr
;
145 req
->scsi
->data_len
= hdr
.dxfer_len
;
147 qemu_vio_blk_req_complete(req
, status
);
150 static void qemu_vio_blk_handle_scsi(VirtIOBlockReq
*req
)
152 qemu_vio_blk_req_complete(req
, VIRTIO_BLK_S_UNSUPP
);
154 #endif /* __linux__ */
156 BlockErrorAction
drive_get_on_error(
157 BlockDriverState
*bdrv
, int is_read
)
163 QTAILQ_FOREACH(dinfo, &drives, next) {
164 if (dinfo->bdrv == bdrv)
165 return is_read ? dinfo->on_read_error : dinfo->on_write_error;
168 return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
170 return BLOCK_ERR_REPORT
;
173 static void q_vm_stop(int reason
)
179 static int qemu_vio_blk_handle_rw_error(VirtIOBlockReq
*req
, int error
,
183 BlockErrorAction action
=
184 drive_get_on_error(req
->dev
->bs
, is_read
);
185 VirtIOBlock
*s
= req
->dev
;
188 if (action
== BLOCK_ERR_IGNORE
)
191 if ((error
== ENOSPC
&& action
== BLOCK_ERR_STOP_ENOSPC
)
192 || action
== BLOCK_ERR_STOP_ANY
) {
198 qemu_vio_blk_req_complete(req
, VIRTIO_BLK_S_IOERR
);
206 static void qemu_vio_blk_rw_complete(void *opaque
, int ret
)
208 VirtIOBlockReq
*req
= opaque
;
214 int is_read
= !(req
->out
->type
& VIRTIO_BLK_T_OUT
);
216 if (qemu_vio_blk_handle_rw_error(req
, -ret
, is_read
))
220 qemu_vio_blk_req_complete(req
, VIRTIO_BLK_S_OK
);
223 void do_multiwrite(BlockDriverState
*bs
, BlockRequest
*blkreq
,
229 for (i
= 0; i
< num_writes
; i
++) {
231 ret
= bdrv_write(bs
,blkreq
[i
].sector
,blkreq
[i
].qiov
->iov
->iov_base
,blkreq
[i
].nb_sectors
);
232 blkreq
[i
].cb(blkreq
[i
].opaque
,ret
);
237 //FIX: How to use bdrv_aio_multiwrite inside qemu-vio?
238 ret
= bdrv_aio_multiwrite(bs
, blkreq
, num_writes
);
242 for (i
= 0; i
< num_writes
; i
++) {
243 if (blkreq
[i
].error
) {
244 qemu_vio_blk_rw_complete(blkreq
[i
].opaque
, -EIO
);
250 static void qemu_vio_blk_handle_write(BlockRequest
*blkreq
, int *num_writes
,
251 VirtIOBlockReq
*req
, BlockDriverState
**old_bs
)
254 if (req
->dev
->bs
!= *old_bs
|| *num_writes
== 32) {
255 if (*old_bs
!= NULL
) {
256 do_multiwrite(*old_bs
, blkreq
, *num_writes
);
259 *old_bs
= req
->dev
->bs
;
263 blkreq
[*num_writes
].sector
= req
->out
->sector
;
264 blkreq
[*num_writes
].nb_sectors
= req
->qiov
.size
/ 512;
265 blkreq
[*num_writes
].qiov
= &req
->qiov
;
266 blkreq
[*num_writes
].cb
= qemu_vio_blk_rw_complete
;
267 blkreq
[*num_writes
].opaque
= req
;
268 blkreq
[*num_writes
].error
= 0;
273 static void qemu_vio_blk_handle_read(VirtIOBlockReq
*req
)
275 int ret
,i
, read_offset
=0, remaining
;
276 BlockDriverAIOCB
*acb
;
281 remaining
= req
->qiov
.size
;
283 for (i
= 0; i
<req
->qiov
.niov
;i
++) {
284 vec
= &req
->qiov
.iov
[i
];
285 ret
= bdrv_read(req
->dev
->bs
,req
->out
->sector
+read_offset
,
286 vec
->iov_base
,vec
->iov_len
/512);
288 read_offset
+= vec
->iov_len
/512;
290 remaining
= remaining
- vec
->iov_len
;
292 if (remaining
== 0) {
293 qemu_vio_blk_rw_complete(req
,ret
);
298 qemu_vio_blk_rw_complete(req
, -EIO
);
302 acb
= bdrv_aio_readv(req
->dev
->bs
, req
->out
->sector
, &req
->qiov
,
303 req
->qiov
.size
/ 512, qemu_vio_blk_rw_complete
, req
);
308 qemu_vio_blk_rw_complete(req
, -EIO
);
313 static void qemu_vio_blk_handle_flush(BlockRequest
*blkreq
, int *num_writes
,
314 VirtIOBlockReq
*req
, BlockDriverState
**old_bs
)
316 BlockDriverAIOCB
*acb
;
319 * Make sure all outstanding writes are posted to the backing device.
321 if (*old_bs
!= NULL
) {
323 do_multiwrite(*old_bs
, blkreq
, *num_writes
);
326 *old_bs
= req
->dev
->bs
;
328 acb
= bdrv_aio_flush(req
->dev
->bs
, qemu_vio_blk_flush_complete
, req
);
330 qemu_vio_blk_req_complete(req
, VIRTIO_BLK_S_IOERR
);
334 VirtIOBlockReq
*virtio_blk_get_request(VirtIOBlock
*s
)
337 VirtIOBlockReq
*req
= malloc(sizeof(VirtIOBlockReq
));
341 bzero(req
,sizeof(VirtIOBlockReq
));
344 req
->dev
->bs
= s
->bs
;
347 if (!virtqueue_pop(s
->vq
, &req
->elem
)) {
357 void virtio_blk_handle_request(VirtIOBlockReq
*req
,
362 if (req
->elem
.out_num
< 1 || req
->elem
.in_num
< 1) {
363 fprintf(stderr
, "qemu-vio-blk: missing headers\n");
367 if (req
->elem
.out_sg
[0].iov_len
< sizeof(*req
->out
) ||
368 req
->elem
.in_sg
[req
->elem
.in_num
- 1].iov_len
< sizeof(*req
->in
)) {
369 fprintf(stderr
, "qemu-vio-blk: header not in correct element\n");
373 req
->out
= (void *)req
->elem
.out_sg
[0].iov_base
;
374 req
->in
= (void *)req
->elem
.in_sg
[req
->elem
.in_num
- 1].iov_base
;
376 if (req
->out
->type
& VIRTIO_BLK_T_FLUSH
) {
378 qemu_vio_blk_handle_flush(mrb
->blkreq
, &mrb
->num_writes
,
380 } else if (req
->out
->type
& VIRTIO_BLK_T_SCSI_CMD
) {
382 qemu_vio_blk_handle_scsi(req
);
383 } else if (req
->out
->type
& VIRTIO_BLK_T_OUT
) {
385 qemu_iovec_init_external(&req
->qiov
, &req
->elem
.out_sg
[1],
386 req
->elem
.out_num
- 1);
387 qemu_vio_blk_handle_write(mrb
->blkreq
, &mrb
->num_writes
,
391 qemu_iovec_init_external(&req
->qiov
, &req
->elem
.in_sg
[0],
392 req
->elem
.in_num
- 1);
393 qemu_vio_blk_handle_read(req
);
397 void qemu_vio_guess_geometry(BlockDriverState
*bs
, int *pcyls
, int *pheads
, int *psecs
)
399 bdrv_guess_geometry(bs
, pcyls
, pheads
, psecs
);
402 int64_t qemu_vio_getlength(BlockDriverState
*bs
)
404 return bdrv_getlength(bs
) / 512;