qemu侧 块设备调试记录(二)
前言
// block/block-backend.c l:1504
static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset,
int64_t bytes,
void *iobuf, CoroutineEntry co_entry,
BdrvRequestFlags flags,
BlockCompletionFunc *cb, void *opaque)
{
BlkAioEmAIOCB *acb;
Coroutine *co;
blk_inc_in_flight(blk);
acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
acb->rwco = (BlkRwCo) {
.blk = blk,
.offset = offset,
.iobuf = iobuf,
.flags = flags,
.ret = NOT_DONE,
};
acb->bytes = bytes;
acb->has_returned = false;
// blk_aio_write_entry
co = qemu_coroutine_create(co_entry, acb);
bdrv_coroutine_enter(blk_bs(blk), co);
acb->has_returned = true;
if (acb->rwco.ret != NOT_DONE) {
replay_bh_schedule_oneshot_event(blk_get_aio_context(blk),
blk_aio_complete_bh, acb);
}
return &acb->common;
}
blk_aio_write_entry
(gdb) n
1555 assert(!qiov || qiov->size == acb->bytes);
// 执行次数比较多,添加条件断点
(gdb) b 1555 if (char)(((char *)(qiov->iov->iov_base))[0])=='H' && (char)(((char *)(qiov->iov->iov_base))[1])=='e'
(gdb) p (char *)(qiov->iov->iov_base)
$18 = 0x7fff6e4ae200 "Hello World!"
(gdb) p acb->bytes
$19 = 1024
(gdb) s
1556 rwco->ret = blk_co_do_pwritev_part(rwco->blk, rwco->offset, acb->bytes,
(gdb) s
blk_co_do_pwritev_part (blk=0x555556ce33a0, offset=138412032, bytes=1024, qiov=0x7fff601e51a0,
qiov_offset=0, flags=0) at ../block/block-backend.c:1338
(gdb) n
1365 ret = bdrv_co_pwritev_part(blk->root, offset, bytes, qiov, qiov_offset,
(gdb) s
bdrv_co_pwritev_part (child=0x555556ce3180, offset=138412032, bytes=1024, qiov=0x7fff601e51a0,
qiov_offset=0, flags=0) at ../block/io.c:2272
(gdb) n
2287 if (flags & BDRV_REQ_ZERO_WRITE) {
(gdb) n
2290 ret = bdrv_check_request32(offset, bytes, qiov, qiov_offset);
(gdb) n
2321 ret = bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad,
(gdb) n
2323 if (ret < 0) {
(gdb) p {
offset,qiov_offset,bytes}
$21 = {
138412032, 0, 1024}
(gdb) n
2331 if (flags & BDRV_REQ_ZERO_WRITE) {
(gdb) n
2337 if (padded) {
(gdb) n
2349 ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align,
(gdb) s
bdrv_aligned_pwritev (child=0x555556ce3180, req=0x7fff4f5a2e00, offset=138412032, bytes=1024,
align=1, qiov=0x7fff601e51a0, qiov_offset=0, flags=0)
at ../block/io.c:2112
(gdb) n
2157 ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, qiov_offset, flags);
(gdb) s
bdrv_driver_pwritev (bs=0x555556cf6200, offset=138412032, bytes=1024,
qiov=0x7fff601e51a0, qiov_offset=0, flags=0) at ../block/io.c:1265
(gdb) n
1280 if (drv->bdrv_co_pwritev_part) {
(gdb) p drv->bdrv_co_pwritev_part
$23 = (int (*)(BlockDriverState *, int64_t, int64_t, QEMUIOVector *, size_t, BdrvRequestFlags)) 0x0
(gdb) n
1287 if (qiov_offset > 0 || bytes != qiov->size) {
(gdb) n
1292 if (drv->bdrv_co_pwritev) {
(gdb) n
1293 ret = drv->bdrv_co_pwritev(bs, offset, bytes, qiov,
(gdb) s
raw_co_pwritev (bs=0x555556cf6200, offset=138412032, bytes=1024,
qiov=0x7fff601e51a0,flags=0) at ../block/raw-format.c:223
raw_co_pwritev
不同的 镜像格式,会调用不同的函数
(gdb) n
229 if (bs->probed && offset < BLOCK_PROBE_BUF_SIZE && bytes) {
(gdb) n
263 ret = raw_adjust_offset(bs, &offset, bytes, true);
(gdb) n
269 ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
(gdb) s
bdrv_co_pwritev (child=0x555556ce2d60

本文介绍 QEMU 中 AIO (异步 I/O) 的调试过程,重点关注 blk_aio_write_entry 函数及其实现细节。从 qemu 的 coroutine 机制开始,逐步深入到具体的 raw_co_pwritev 和 handle_aiocb_rw 函数,最后分析了文件打开的初始化流程。
最低0.47元/天 解锁文章
1373

被折叠的 条评论
为什么被折叠?



