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