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

前言

// 根据前面的分析blk_aio_write_entry 有对应的 blk_aio_read_entry
// block/block-backend.c l:1537
static void blk_aio_read_entry(void *opaque)
{
    BlkAioEmAIOCB *acb = opaque;
    BlkRwCo *rwco = &acb->rwco;
    QEMUIOVector *qiov = rwco->iobuf;

    assert(qiov->size == acb->bytes);
    rwco->ret = blk_co_do_preadv(rwco->blk, rwco->offset, acb->bytes,
                                 qiov, rwco->flags);
    blk_aio_complete(acb);
}
// 搜索函数调用 block/block-backend.c l:1625
BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
                           QEMUIOVector *qiov, BdrvRequestFlags flags,
                           BlockCompletionFunc *cb, void *opaque)
{
    IO_CODE();
    assert((uint64_t)qiov->size <= INT64_MAX);
    return blk_aio_prwv(blk, offset, qiov->size, qiov,
                        blk_aio_read_entry, flags, cb, opaque);
}

#0  blk_aio_preadv
    (blk=0x555556cd5910, offset=0, qiov=0x7fff60113660, 
    flags=0, cb=<ide_buffered_readv_cb>, opaque=0x7fff60113650) at ../block/block-backend.c:1628
#1  0x00005555559d1094 in ide_buffered_readv
    (s=0x555557749fe8, sector_num=0, iov=0x55555774a2d0, nb_sectors=1, cb=0x5555559d11d9 <ide_sector_read_cb>, opaque=0x555557749fe8) at ../hw/ide/core.c:700
#2  0x00005555559d14a4 in ide_sector_read (s=0x555557749fe8) at ../hw/ide/core.c:811
#3  0x00005555559d3108 in cmd_read_pio (s=0x555557749fe8, cmd=32 ' ')
    at ../hw/ide/core.c:1530
#4  0x00005555559d4636 in ide_exec_cmd (bus=0x555557749f60, val=32)
    at ../hw/ide/core.c:2120
#5  0x00005555559d2ab7 in ide_ioport_write (opaque=0x555557749f60, addr=503, val=32)
    at ../hw/ide/core.c:1329
#6  0x0000555555be1aa7 in portio_write (opaque=0x5555577e62a0, addr=7, data=32, size=1)
    at ../softmmu/ioport.c:201
#7  0x0000555555be41d7 in memory_region_write_accessor
    (mr=0x5555577e62a0, addr=7, value=0x7fff67dfe688, size=1, shift=0, mask=255, attrs=...) at ../softmmu/memory.c:492
 
(gdb) p blk->name 
$1 = 0x555556ce3c10 "ide0-hd0"

#0  blk_aio_preadv
    (blk=0x2f86cbce761d3700, offset=512, qiov=0x555555d85542 <blk_blockalign+64>, flags=32767, cb=0x555556cd5c60, opaque=0x200) at ../block/block-backend.c:1628
#1  0x00005555559d1094 in ide_buffered_readv
    (s=0x555557749fe8, sector_num=2050, iov=0x55555774a2d0, nb_sectors=1, cb=0x5555559d11d9 <ide_sector_read_cb>, opaque=0x555557749fe8) at ../hw/ide/core.c:700
#2  0x00005555559d14a4 in ide_sector_read (s=0x555557749fe8) at ../hw/ide/core.c:811
#3  0x00005555559d4f5f in ide_data_readw (opaque=0x555557749f60, addr=496)
    at ../hw/ide/core.c:2380
#4  0x0000555555be1967 in portio_read (opaque=0x5555577e62a0, addr=0, size=2)
    at ../softmmu/ioport.c:179

添加条件断点测试

Thread 5 "qemu-system-x86" hit Breakpoint 3, blk_aio_preadv (blk=0x555556cd5910, 
    offset=1050112, qiov=0x7fff60113660, flags=0, 
    cb=0x5555559d0e4a <ide_buffered_readv_cb>, opaque=0x7fff60113650)
    at ../block/block-backend.c:1630
1630        assert((uint64_t)qiov->size <= INT64_MAX);
(gdb) b 1630  if blk->name[7] == '1'
// 或者使用
(gdb) b ../block/block-backend.c:1630 if blk->name[7] == '1'

(gdb) info b
Num     Type           Disp Enb Address            What
4       breakpoint     keep y   0x0000555555d844a7 in blk_aio_preadv 
                                                   at ../block/block-backend.c:1630
        stop only if blk->name[7] == '1'
        breakpoint already hit 1 time
        
(gdb) bt
#0  blk_aio_preadv
    (blk=0x555556ce33a0, offset=0, qiov=0x7fff600f3660, flags=0, cb=0x5555558b7f0a <dma_blk_cb>, opaque=0x7fff600f3600) at ../block/block-backend.c:1630
#1  0x00005555558b8595 in dma_blk_read_io_func
    (offset=0, iov=0x7fff600f3660, cb=0x5555558b7f0a <dma_blk_cb>, cb_opaque=0x7fff600f3600, opaque=0x555556ce33a0) at ../softmmu/dma-helpers.c:253
#2  0x00005555558b82b8 in dma_blk_cb (opaque=0x7fff600f3600, ret=0)
    at ../softmmu/dma-helpers.c:178
#3  0x00005555558b8540 in dma_blk_io
    (ctx=0x555556aa7050, sg=0x55555774a6e0, offset=0, align=512, io_func=0x5555558b8546 <dma_blk_read_io_func>, io_func_opaque=0x555556ce33a0, cb=0x5555559d175b <ide_dma_cb>, opaque=0x55555774a3b8, dir=DMA_DIRECTION_FROM_DEVICE) at ../softmmu/dma-helpers.c:242
#4  0x00005555558b85f6 in dma_blk_read
    (blk=0x555556ce33a0, sg=0x55555774a6e0, offset=0, align=512, cb=
    0x5555559d175b <ide_dma_cb>, opaque=0x55555774a3b8) at ../softmmu/dma-helpers.c:260
#5  0x00005555559d1ae1 in ide_dma_cb (opaque=0x55555774a3b8, ret=0)
    at ../hw/ide/core.c:948
#6  0x00005555559da80e in bmdma_cmd_writeb (bm=0x55555774b140, val=9)
--Type <RET> for more, q to quit, c to continue without paging--
    at ../hw/ide/pci.c:306
#7  0x00005555559db0a2 in bmdma_write (opaque=0x55555774b140, addr=0, val=9, size=1)
    at ../hw/ide/piix.c:76

dma_blk_read_io_func

(gdb) b ../softmmu/dma-helpers.c:253 if blk->name[7] == '1'

Thread 5 "qemu-system-x86" hit Breakpoint 7, dma_blk_read_io_func (offset=138412032, 
    iov=0x7fff601ddfa0, cb=0x5555558b7f0a <dma_blk_cb>, cb_opaque=0x7fff601ddf40, 
    opaque=0x555556ce33a0) at ../softmmu/dma-helpers.c:253
253         return blk_aio_preadv(blk, offset, iov, 0, cb, cb_opaque);
(gdb) n
0x0000555556078d90 in qemu_coroutine_switch (from_=0x555557870a90, to_=0x7ffff672db20, 
    action=COROUTINE_TERMINATE) at ../util/coroutine-ucontext.c:302
302         ret = sigsetjmp(from->env, 0);
(gdb) n
303         if (ret == 0) {
(gdb) n
311         finish_switch_fiber(fake_stack_save);
(gdb) n
313         return ret;
(gdb) n
314     }
(gdb) n
coroutine_trampoline (i0=1468467856, i1=21845) at ../util/coroutine-ucontext.c:173
173             co->entry(co->entry_arg);
(gdb) n
0x0000555556078d90 in qemu_coroutine_switch (from_=0x7fff67dff5a0, to_=0x555557870a90, 
    action=COROUTINE_ENTER) at ../util/coroutine-ucontext.c:302
302         ret = sigsetjmp(from->env, 0);
(gdb) n
303         if (ret == 0) {
(gdb) n
311         finish_switch_fiber(fake_stack_save);
(gdb) n
[Thread 0x7ffff5437700 (LWP 167615) exited]
313         return ret;
(gdb) n
314     }
(gdb) n
qemu_aio_coroutine_enter (ctx=0x555556aa7050, co=0x555557870a90)
    at ../util/qemu-coroutine.c:154
154             QSIMPLEQ_PREPEND(&pending, &to->co_queue_wakeup);
(gdb) n
156             switch (ret) {
(gdb) n
114         while (!QSIMPLEQ_EMPTY(&pending)) {
(gdb) n
168     }
(gdb) n
aio_co_enter (ctx=0x555556aa7050, co=0x555557870a90) at ../util/async.c:655
655             aio_context_release(ctx);
(gdb) n
657     }
(gdb) n
bdrv_coroutine_enter (bs=0x555556cf6200, co=0x555557870a90) at ../block.c:7247
7247    }
(gdb) n
blk_aio_prwv (blk=0x555556ce33a0, offset=138412032, bytes=1024, iobuf=0x7fff601ddfa0, 
    co_entry=0x555555d8409e <blk_aio_read_entry>, flags=0, 
    cb=0x5555558b7f0a <dma_blk_cb>, opaque=0x7fff601ddf40)
    at ../block/block-backend.c:1528
1528        acb->has_returned = true;
(gdb) n
1529        if (acb->rwco.ret != NOT_DONE) {
(gdb) n
1534        return &acb->common;
(gdb) n
1535    }
(gdb) n
blk_aio_preadv (blk=0x555556ce33a0, offset=138412032, qiov=0x7fff601ddfa0, flags=0, 
    cb=0x5555558b7f0a <dma_blk_cb>, opaque=0x7fff601ddf40)
    at ../block/block-backend.c:1633
1633    }
(gdb) n
dma_blk_read_io_func (offset=138412032, iov=0x7fff601ddfa0, 
    cb=0x5555558b7f0a <dma_blk_cb>, cb_opaque=0x7fff601ddf40, opaque=0x555556ce33a0)
    at ../softmmu/dma-helpers.c:254
254     }

// 从这里看是已读取到数据
(gdb) p (char *)(iov->iov->iov_base)
$12 = 0x7fff79b41800 "Hello World!"
(gdb) n
dma_blk_cb (opaque=0x7fff601ddf40, ret=0) at ../softmmu/dma-helpers.c:178
178         dbs->acb = dbs->io_func(dbs->offset, &dbs->iov,
(gdb) p (char *)(dbs.iov->iov->iov_base)
$13 = 0x7fff79b41800 "Hello World!"
(gdb) n
dma_blk_io (ctx=0x555556aa7050, sg=0x55555773a190, offset=138412032, align=512, 
    io_func=0x5555558b8546 <dma_blk_read_io_func>, io_func_opaque=0x555556ce33a0, 
    cb=0x5555559d175b <ide_dma_cb>, opaque=0x555557739e68, 
    dir=DMA_DIRECTION_FROM_DEVICE) at ../softmmu/dma-helpers.c:243
243         return &dbs->common;
(gdb) p (char *)(dbs.iov->iov->iov_base)
$14 = 0x7fff79b41800 "Hello World!"

blk_aio_read_entry

// block/block-backend.c l:1537
static void blk_aio_read_entry(void *opaque)
{
    BlkAioEmAIOCB *acb = opaque;
    BlkRwCo *rwco = &acb->rwco;
    QEMUIOVector *qiov = rwco->iobuf;

    assert(qiov->size == acb->bytes);
    rwco->ret = blk_co_do_preadv(rwco->blk, rwco->offset, acb->bytes,
                                 qiov, rwco->flags);
    blk_aio_complete(acb);
}

static void blk_aio_complete(BlkAioEmAIOCB *acb)
{
    if (acb->has_returned) {
        acb->common.cb(acb->common.opaque, acb->rwco.ret);
        blk_dec_in_flight(acb->rwco.blk);
        qemu_aio_unref(acb);
    }
}

调试记录

hit Breakpoint 12, blk_aio_read_entry ()
(gdb) n
1544        rwco->ret = blk_co_do_preadv(rwco->blk, rwco->offset, acb->bytes,
(gdb) p rwco->blk->name 
$19 = 0x555556d03cb0 "ide0-hd1"
gdb) b 1546
Breakpoint 15 at 0x555555d84136: file ../block/block-backend.c, line 1546.
(gdb) n
0x0000555556078d90 in qemu_coroutine_switch (from_=0x7fff67dff5a0, to_=0x7fff601f8500, 
    action=COROUTINE_ENTER) at ../util/coroutine-ucontext.c:302
302         ret = sigsetjmp(from->env, 0);

// 此时查看函数栈
(gdb) bt
#0  0x0000555556078d90 in qemu_coroutine_switch
    (from_=0x7fff67dff5a0, to_=0x7fff601f8500, action=COROUTINE_ENTER)
    at ../util/coroutine-ucontext.c:302
#1  0x0000555556087fd2 in qemu_aio_coroutine_enter
    (ctx=0x555556aa7050, co=0x7fff601f8500) at ../util/qemu-coroutine.c:149
#2  0x0000555556077269 in aio_co_enter (ctx=0x555556aa7050, co=0x7fff601f8500)
    at ../util/async.c:654
#3  0x0000555555d663ca in bdrv_coroutine_enter (bs=0x555556cf6200, co=0x7fff601f8500)
    at ../block.c:7246
#4  0x0000555555d8405d in blk_aio_prwv
    (blk=0x555556ce33a0, offset=138412032, bytes=1024, iobuf=0x7fff601ddfa0, co_entry=0x555555d8409e <blk_aio_read_entry>, flags=0, cb=0x5555558b7f0a <dma_blk_cb>, opaque=0x7fff601ddf40) at ../block/block-backend.c:1526
#5  0x0000555555d8450b in blk_aio_preadv
    (blk=0x555556ce33a0, offset=138412032, qiov=0x7fff601ddfa0, flags=0, cb=0x5555558b7f0a <dma_blk_cb>, opaque=0x7fff601ddf40) at ../block/block-backend.c:1631
#6  0x00005555558b8595 in dma_blk_read_io_func

// blk_aio_prwv :
(gdb) p (char *) ((QEMUIOVector *)acb->rwco->iobuf)->iov->iov_base
$42 = 0x7fff74e36800 ""

// 此时返回的iov还是空
(gdb) p (char *)(dbs->iov.iov->iov_base)
$25 = 0x7fff7e914800 ""

(gdb) c
Continuing.
[New Thread 0x7ffff5437700 (LWP 168527)]
[Switching to Thread 0x7ffff672dc80 (LWP 164609)]

Thread 1 "qemu-system-x86" hit Breakpoint 15, blk_aio_read_entry (
    opaque=0x7fff601f8b70) at ../block/block-backend.c:1546
1546        blk_aio_complete(acb);

回调处理

(gdb) s
1490        if (acb->has_returned) {
// 在 blk_aio_prwv
(gdb) p acb->has_returned 
$26 = true

(gdb) s
1491            acb->common.cb(acb->common.opaque, acb->rwco.ret);
(gdb) s
dma_blk_cb (opaque=0x555556cf6200, ret=0) at ../softmmu/dma-helpers.c:114
// 此时打印已经获取到数据
(gdb) p (char *)(dbs->iov.iov->iov_base)
$27 = 0x7fff7e914800 "Hello World!"

(gdb) n
124         if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
(gdb) n
125             dma_complete(dbs, ret);
(gdb) s
dma_complete (dbs=0x7fff601c6480, ret=0) at ../softmmu/dma-helpers.c:101
(gdb) p *dbs
$46 = {common = {aiocb_info = 0x555556758720 <dma_aiocb_info>, bs = 0x0, 
    cb = 0x5555559d175b <ide_dma_cb>
(gdb) p (char *)dbs->iov.iov->iov_base
$48 = 0x7fff74e36800 "Hello World!"

(gdb) n
107             dbs->common.cb(dbs->common.opaque, ret);
(gdb) s
ide_dma_cb (opaque=0x400, ret=1) at ../hw/ide/core.c:865

(gdb) n
886         if (s->io_buffer_size > s->nsector * 512) {
(gdb) n
894             n = s->io_buffer_size >> 9;
(gdb) n
897         sector_num = ide_get_sector(s);
(gdb) n
898         if (n > 0) {
(gdb) n
899             assert(n * 512 == s->sg.size);
(gdb) n
900             dma_buf_commit(s, s->sg.size);
(gdb) n
901             sector_num += n;
(gdb) n
902             ide_set_sector(s, sector_num);
(gdb) n
903             s->nsector -= n;
(gdb) n
907         if (s->nsector == 0) {
(gdb) n
908             s->status = READY_STAT | SEEK_STAT;
(gdb) n
909             ide_set_irq(s->bus);
(gdb) n
910             goto eot;
(gdb) n
967         if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
(gdb) n
968             block_acct_done(blk_get_stats(s->blk), &s->acct);
(gdb) p s->bus->cmd
$49 = 8 '\b'

(gdb) p *(s->bus->irq)
$51 = {parent_obj = {class = 0x555556b7de10, free = 0x555555862d60 <g_free@plt>, 
    Python Exception <class 'gdb.error'> There is no member named keys.: 
properties = 0x5555577e5f00, ref = 1, parent = 0x0}, 
  handler = 0x5555559da6d4 <bmdma_irq>, opaque = 0x55555773abf0, n = 0}

断点命中顺序

// fd 通过 /proc/${pid}/fd 参考,type = 1 是读
(gdb) i b
Num     Type           Disp Enb Address            What
12      breakpoint     keep y   0x0000555555d8409e in blk_aio_read_entry 
                                                   at ../block/block-backend.c:1538
        breakpoint already hit 11 times
15      breakpoint     keep y   0x0000555555d84136 in blk_aio_read_entry 
                                                   at 
        breakpoint already hit 9 times
22      breakpoint     keep y   0x0000555555e05cf5 in raw_co_prw 
                                                   at ../block/file-posix.c:2095
        stop only if s->fd == 14 && type == 1
        breakpoint already hit 2 times
23      breakpoint     keep y   0x0000555555e05d0c in raw_co_prw 
                                                   at ../block/file-posix.c:2096
        stop only if s->fd == 14 && type == 1
        breakpoint already hit 2 times

Thread 5 "qemu-system-x86" hit Breakpoint 12, blk_aio_read_entry (
    opaque=0x7fff5f6f6ee8) at ../block/block-backend.c:1538
1538    {
(gdb) c
Continuing.

Thread 5 "qemu-system-x86" hit Breakpoint 22, raw_co_prw (bs=0x555556cfd550, 
    offset=138412032, bytes=1024, qiov=0x7fff601c64e0, type=1)
    at ../block/file-posix.c:2095
2095        return raw_thread_pool_submit(bs, handle_aiocb_rw, &acb);
(gdb) p (char *)qiov->iov->iov_base
$65 = 0x7fff73bde800 ""
(gdb) c
Continuing.
[Thread 0x7ffff5437700 (LWP 169281) exited]
[New Thread 0x7ffff5437700 (LWP 169285)]
[Switching to Thread 0x7ffff672dc80 (LWP 164609)]

Thread 1 "qemu-system-x86" hit Breakpoint 23, raw_co_prw (bs=0x555556cfd550, 
    offset=138412032, bytes=1024, qiov=0x7fff601c64e0, type=1)
    at ../block/file-posix.c:2096
2096    }
(gdb) p (char *)qiov->iov->iov_base
$66 = 0x7fff73bde800 "Hello World!"
(gdb) c
Continuing.
[Thread 0x7ffff5437700 (LWP 169285) exited]

Thread 1 "qemu-system-x86" hit Breakpoint 15, blk_aio_read_entry (
    opaque=0x7fff601f9780) at ../block/block-backend.c:1546
1546        blk_aio_complete(acb);
(gdb) 

命令记录

// 查看位置,指定打断点
(gdb) list ../hw/ide/core.c:909
// 然后指定文件位置打断点
(gdb) b ../hw/ide/core.c:909 if s->blk->name[7] == '1' 
(gdb) b ../hw/ide/core.c:932 if s->blk->name[7] == '1'
(gdb) l ../softmmu/dma-helpers.c:125

// dma_blk_cb->dma_complete
(gdb) b ../softmmu/dma-helpers.c:125 if ((BlockBackend *)(dbs->io_func_opaque))->name[7] == '1' && dbs->iov.size == 1024 && dbs->dir == 1

// dma_blk_cb->dma_memory_unmap, 没看见调试作用
(gdb) b ../softmmu/dma-helpers.c:148 if ((BlockBackend *)(dbs->io_func_opaque))->name[7] == '1' && dbs->iov.size == 1024

// blk_aio_prwv 这里需要 判断co_entry=0x555555d8409e <blk_aio_read_entry>
(gdb) b ../block/block-backend.c:1525 if blk->name[7] == '1'  && bytes==1024 && co_entry == 0x555555d8409e
(gdb) b ../block/block-backend.c:1527 if blk->name[7] == '1'  && bytes==1024 && co_entry == 0x555555d8409e

// blk_aio_read_entry
(gdb) b ../block/block-backend.c:1544 if rwco->blk->name[7] == '1' && acb->bytes==1024
(gdb) b ../block/block-backend.c:1546 if rwco->blk->name[7] == '1' && acb->bytes==1024

// dma_blk_read_io_func
(gdb) b ../softmmu/dma-helpers.c:254 if blk->name[7] == '1' && iov->size==1024

blk_aio_prwv():
(gdb) p (char *) ((QEMUIOVector *)iobuf)->iov->iov_base
(gdb) p  ((QEMUIOVector *)iobuf)->iov->iov_len
(gdb) call strlen((char *) ((QEMUIOVector *)iobuf)->iov->iov_base)

dma_complete():
(gdb) p (char *)dbs->iov.iov->iov_base

blk_aio_read_entry():
(gdb) p  (char *)qiov->iov->iov_base

dma_blk_read_io_func():
(gdb) call strlen((char *) iov->iov->iov_base)
(gdb) p (char *)iov->iov->iov_base

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值