qemu侧 块设备调试记录(二)

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

前言

// 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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值