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, offset=138412032, bytes=1024,
qiov=0x7fff601e51a0, flags=0) at ../block/io.c:2264
2264 {
(gdb) s
2266 return bdrv_co_pwritev_part(child, offset, bytes, qiov, 0, flags);
(gdb) p child
$24 = (BdrvChild *) 0x555556ce2d60
(gdb) p *child
$25 = {bs = 0x555556cfd550, name = 0x555556d03e90 "file", klass = 0x555556880a20 <child_of_bds>, role = 20,
opaque = 0x555556cf6200, perm = 3, shared_perm = 13, frozen = false, parent_quiesce_counter = 0, next = {
le_next = 0x0, le_prev = 0x555556cfa3a8}, next_parent = {le_next = 0x0, le_prev = 0x555556d01700}}
(gdb)
raw_co_prw
Thread 5 "qemu-system-x86" hit Breakpoint 11, raw_co_prw ( bs=0x555556cfd550,
offset=138412032, bytes=1024, qiov=0x7fff601c5cd0, type=2) at ../block/file-posix.c:2052
2052 {
(gdb) s
2053 BDRVRawState *s = bs->opaque;
(gdb) p (char *)(qiov->iov->iov_base)
$26 = 0x7fff6e9cc200 "Hello World!"
(gdb) bt
#0 raw_co_prw (bs=0x555556cfd550, offset=138412032, bytes=1024, qiov=0x7fff601c5cd0, type=2)
at ../block/file-posix.c:2053
#1 0x0000555555e05dc5 in raw_co_pwritev
(bs=0x555556cfd550, offset=138412032, bytes=1024, qiov=0x7fff601c5cd0, flags=0)
at ../block/file-posix.c:2110
#2 0x0000555555d945de in bdrv_driver_pwritev
(bs=0x555556cfd550, offset=138412032, bytes=1024, qiov=0x7fff601c5cd0, qiov_offset=0, flags=0)
at ../block/io.c:1293
#3 0x0000555555d96c6d in bdrv_aligned_pwritev
(child=0x555556ce2d60, req=0x7fff527d4ae0, offset=138412032, bytes=1024, align=1, qiov=0x7fff601c5cd0, qiov_offset=0, flags=0) at ../block/io.c:2157
#4 0x0000555555d9757c in bdrv_co_pwritev_part
(child=0x555556ce2d60, offset=138412032, bytes=1024, qiov=0x7fff601c5cd0, qiov_offset=0, flags=0)
at ../block/io.c:2349
#5 0x0000555555d97202 in bdrv_co_pwritev
(child=0x555556ce2d60, offset=138412032, bytes=1024, qiov=0x7fff601c5cd0, flags=0) at ../block/io.c:2266
#6 0x0000555555dd2641 in raw_co_pwritev()
(gdb) p *s
$27 = {fd = 15, use_lock = true, type = 0, open_flags = 2, buf_align = 1, perm = 3, shared_perm = 13,
locked_perm = 3, locked_shared_perm = 2, aio_max_batch = 0, perm_change_fd = 0, perm_change_flags = 2,
reopen_state = 0x0, has_discard = true, has_write_zeroes = true, discard_zeroes = true,
use_linux_aio = false, use_linux_io_uring = false, page_cache_inconsistent = 0, has_fallocate = true,
needs_alignment = false, force_alignment = false, drop_cache = true, check_cache_dropped = false, stats = {
discard_nb_ok = 0, discard_nb_failed = 0, discard_bytes_ok = 0}, pr_mgr = 0x0}
handle_aiocb_rw
// block/file-posix.c l:1526
static int handle_aiocb_rw(void *opaque)
{
RawPosixAIOData *aiocb = opaque;
ssize_t nbytes;
char *buf;
if (!(aiocb->aio_type & QEMU_AIO_MISALIGNED)) {
if (aiocb->io.niov == 1) {
nbytes = handle_aiocb_rw_linear(aiocb, aiocb->io.iov->iov_base);
goto out;
}
if (preadv_present) {
nbytes = handle_aiocb_rw_vector(aiocb);
if (nbytes == aiocb->aio_nbytes ||
(nbytes < 0 && nbytes != -ENOSYS)) {
goto out;
}
preadv_present = false;
}
}
buf = qemu_try_blockalign(aiocb->bs, aiocb->aio_nbytes);
if (buf == NULL) {
nbytes = -ENOMEM;
goto out;
}
if (aiocb->aio_type & QEMU_AIO_WRITE) {
char *p = buf;
int i;
for (i = 0; i < aiocb->io.niov; ++i) {
memcpy(p, aiocb->io.iov[i].iov_base, aiocb->io.iov[i].iov_len);
p += aiocb->io.iov[i].iov_len;
}
assert(p - buf == aiocb->aio_nbytes);
}
nbytes = handle_aiocb_rw_linear(aiocb, buf);
if (!(aiocb->aio_type & QEMU_AIO_WRITE)) {
char *p = buf;
size_t count = aiocb->aio_nbytes, copy;
int i;
for (i = 0; i < aiocb->io.niov && count; ++i) {
copy = count;
if (copy > aiocb->io.iov[i].iov_len) {
copy = aiocb->io.iov[i].iov_len;
}
memcpy(aiocb->io.iov[i].iov_base, p, copy);
assert(count >= copy);
p += copy;
count -= copy;
}
assert(count == 0);
}
qemu_vfree(buf);
out:
if (nbytes == aiocb->aio_nbytes) {
return 0;
} else if (nbytes >= 0 && nbytes < aiocb->aio_nbytes) {
if (aiocb->aio_type & QEMU_AIO_WRITE) {
return -EINVAL;
} else {
iov_memset(aiocb->io.iov, aiocb->io.niov, nbytes,
0, aiocb->aio_nbytes - nbytes);
return 0;
}
} else {
assert(nbytes < 0);
return nbytes;
}
}
(gdb) p *aiocb
$29 = {bs = 0x555556cfd550, aio_type = 2, aio_fildes = 15, aio_offset = 138412032, aio_nbytes = 1024, {io = {
iov = 0x7fff601f0be0, niov = 1}, ioctl = {cmd = 140734806035424, buf = 0x1}, copy_range = {
aio_fd2 = 1612647392, aio_offset2 = 1}, truncate = {prealloc = 1612647392, errp = 0x1}}}
(gdb) s
1532 if (!(aiocb->aio_type & QEMU_AIO_MISALIGNED)) {
(gdb) n
1537 if (aiocb->io.niov == 1) {
(gdb) n
1538 nbytes = handle_aiocb_rw_linear(aiocb, aiocb->io.iov->iov_base);
handle_aiocb_rw_linear
// block/file-posix.c l:1486
static ssize_t handle_aiocb_rw_linear(RawPosixAIOData *aiocb, char *buf)
{
ssize_t offset = 0;
ssize_t len;
while (offset < aiocb->aio_nbytes) {
if (aiocb->aio_type & QEMU_AIO_WRITE) {
len = pwrite(aiocb->aio_fildes,
(const char *)buf + offset,
aiocb->aio_nbytes - offset,
aiocb->aio_offset + offset);
} else {
len = pread(aiocb->aio_fildes,
buf + offset,
aiocb->aio_nbytes - offset,
aiocb->aio_offset + offset);
}
if (len == -1 && errno == EINTR) {
continue;
} else if (len == -1 && errno == EINVAL &&
(aiocb->bs->open_flags & BDRV_O_NOCACHE) &&
!(aiocb->aio_type & QEMU_AIO_WRITE) &&
offset > 0) {
break;
} else if (len == -1) {
offset = -errno;
break;
} else if (len == 0) {
break;
}
offset += len;
}
return offset;
}
handle_aiocb_rw_vector
// block/file-posix.c l:1457
static ssize_t handle_aiocb_rw_vector(RawPosixAIOData *aiocb)
{
ssize_t len;
do {
if (aiocb->aio_type & QEMU_AIO_WRITE)
len = qemu_pwritev(aiocb->aio_fildes,
aiocb->io.iov,
aiocb->io.niov,
aiocb->aio_offset);
else
len = qemu_preadv(aiocb->aio_fildes,
aiocb->io.iov,
aiocb->io.niov,
aiocb->aio_offset);
} while (len == -1 && errno == EINTR);
if (len == -1) {
return -errno;
}
return len;
}
初始化-文件打开
从raw_co_prw
函数 可以看出是从 BDRVRawState
获取fd的,查看源码是 block/file-posix
的结构体,查看该文件是raw_open_common
进行文件打开操作
#0 raw_open_common
(bs=0x555556cdd320, options=0x555556ce2910, bdrv_flags=155650, open_flags=0, device=false, errp=0x7fffffffd7d0) at ../block/file-posix.c:586
#1 0x0000555555e0344b in raw_open
(bs=0x555556cdd320, options=0x555556ce2910, flags=155650, errp=0x7fffffffd7d0)
at ../block/file-posix.c:826
#2 0x0000555555d5adfb in bdrv_open_driver
(bs=0x555556cdd320, drv=0x555556998d60 <bdrv_file>, node_name=0x0, options=0x555556ce2910, open_flags=155650, errp=0x7fffffffd8e0) at ../block.c:1623
#3 0x0000555555d5b816 in bdrv_open_common
(bs=0x555556cdd320, file=0x0, options=0x555556ce2910, errp=0x7fffffffd8e0) at ../block.c:1921
#4 0x0000555555d5f8e5 in bdrv_open_inherit
(filename=0x555556cd3060 "/home/ostest/new/ubuntu3.img", reference=0x0, options=0x555556ce2910, flags=40962, parent=0x555556cd5c60, child_class=0x555556880a20 <child_of_bds>, child_role=19, errp=0x7fffffffdae0)
at ../block.c:3990
#5 0x0000555555d5eb21 in bdrv_open_child_bs
(filename=0x555556cd3060 "/home/ostest/new/ubuntu3.img", options=0x555556cdb130, bdref_key=0x5555561f9128 "file", parent=0x555556cd5c60, child_class=0x555556880a20 <child_of_bds>, child_role=19, allow_none=true, errp=0x7fffffffdae0) at ../block.c:3623
#6 0x0000555555d5f694 in bdrv_open_inherit
(filename=0x555556cd3060 "/home/ostest/new/ubuntu3.img", reference=0x0, options=0x555556cdb130, flags=8194, parent=0x0, child_class=0x0, child_role=0, errp=0x5555569ec5a0 <error_fatal>) at ../block.c:3937
#7 0x0000555555d5fe29 in bdrv_open
(filename=0x555556cd3060 "/home/ostest/new/ubuntu3.img", reference=0x0, options=0x555556cd3730, flags=0, errp=0x5555569ec5a0 <error_fatal>) at ../block.c:4085
#8 0x0000555555d8215c in blk_new_open
(filename=0x555556cd3060 "/home/ostest/new/ubuntu3.img", reference=0x0, options=0x555556cd3730, flags=0, errp=0x5555569ec5a0 <error_fatal>) at ../block/block-backend.c:457
#9 0x0000555555d4c31d in blockdev_init
(file=0x555556cd3060 "/home/ostest/new/ubuntu3.img", bs_opts=0x555556cd3730, errp=0x5555569ec5a0 <error_fatal>) at ../blockdev.c:592
#10 0x0000555555d4d1f8 in drive_new
(all_opts=0x555556aa6560, block_default_type=IF_IDE, errp=0x5555569ec5a0 <error_fatal>)
--Type <RET> for more, q to quit, c to continue without paging--
at ../blockdev.c:981
#11 0x00005555558be5a1 in drive_init_func
(opaque=0x555556c4eee8, opts=0x555556aa6560, errp=0x5555569ec5a0 <error_fatal>) at ../softmmu/vl.c:643
#12 0x000055555606b8f2 in qemu_opts_foreach
(list=0x55555698f680 <qemu_drive_opts>, func=0x5555558be569 <drive_init_func>, opaque=0x555556c4eee8, errp=0x5555569ec5a0 <error_fatal>) at ../util/qemu-option.c:1135
#13 0x00005555558be7ed in configure_blockdev
(bdo_queue=0x5555568ace30 <bdo_queue>, machine_class=0x555556c4ee40, snapshot=0) at ../softmmu/vl.c:702
#14 0x00005555558c2b79 in qemu_create_early_backends () at ../softmmu/vl.c:1980
#15 0x00005555558c6c9d in qemu_init (argc=18, argv=0x7fffffffe2f8, envp=0x7fffffffe390)
at ../softmmu/vl.c:3714
#16 0x0000555555865a55 in main (argc=18, argv=0x7fffffffe2f8, envp=0x7fffffffe390) at ../softmmu/main.c:49
(gdb) n
588 Error *local_err = NULL;
(gdb) b 682
Breakpoint 15 at 0x555555e02f5d: file ../block/file-posix.c, line 682.
(gdb) c
Continuing.
Thread 1 "qemu-system-x86" hit Breakpoint 15, raw_open_common (bs=0x555556cdd320, options=0x555556ce2910,
bdrv_flags=155650, open_flags=0, device=false, errp=0x7fffffffd7d0) at ../block/file-posix.c:682
682 ret = fd < 0 ? -errno : 0;
(gdb) n
684 if (ret < 0) {
(gdb) p fd
$30 = 9
(gdb) p filename
$31 = 0x555556ce3980 "/home/ostest/new/ubuntu3.img"
通过 ls -l /proc/{pid}/fd
查看,与输出有点问题
通过 catch syscall
跟踪系统调用查看,但使用open
没有效果,所以得使用 open64
Thread 1 "qemu-system-x86" hit Catchpoint 20 (call to syscall openat), 0x00007ffff76b1b34 in __libc_open64 (
file=0x555556cd3290 "/home/ostest/new/ubuntu3.img", oflag=526336)
at ../sysdeps/unix/sysv/linux/open64.c:48
(gdb) n
qemu_open_cloexec (name=0x555556cd3290 "/home/ostest/new/ubuntu3.img", flags=2048, mode=0)
at ../util/osdep.c:296
296 return ret;
....
(gdb) n
cdrom_probe_device (filename=0x555556cd3290 "/home/ostest/new/ubuntu3.img") at ../block/file-posix.c:3719
3719 if (fd < 0) {
(gdb) p fd
$40 = 9
Thread 1 "qemu-system-x86" hit Catchpoint 20 (call to syscall openat), 0x00007ffff76b1b34 in __libc_open64 (
file=0x555556ce3980 "/home/ostest/new/ubuntu3.img", oflag=524288)
#4 0x0000555555e02f57 in raw_open_common()
(gdb) n
690 s->fd = fd;
(gdb) p fd
$42 = 9
Thread 1 "qemu-system-x86" hit Catchpoint 20 (call to syscall openat), 0x00007ffff76b1b34 in __libc_open64 (
file=0x555556cdd351 "/home/ostest/new/ubuntu3.img", oflag=524290)
at ../sysdeps/unix/sysv/linux/open64.c:48
(gdb) n
raw_reconfigure_getfd (bs=0x555556cdd320, flags=188418, open_flags=0x7fffffffd6ac, perm=11, force_dup=false,
errp=0x7fffffffd9d0) at ../block/file-posix.c:1079
1079 if (fd == -1) {
(gdb) p fd
$43 = 10
#1 0x0000555555e077df in raw_check_perm (bs=0x555556cdd320, perm=11, shared=5, errp=0x7fffffffd9d0)
at ../block/file-posix.c:3145
#2 0x0000555555d5c4b5 in bdrv_drv_set_perm
(bs=0x555556cdd320, perm=11, shared_perm=5, tran=0x555556ce3bb0, errp=0x7fffffffd9d0) at ../block.c:2324
#3 0x0000555555d5c89a in bdrv_node_refresh_perm
(bs=0x555556cdd320, q=0x0, tran=0x555556ce3bb0, errp=0x7fffffffd9d0) at ../block.c:2496
#4 0x0000555555d5c9ec in bdrv_list_refresh_perms
(list=0x555556ba2170 = {...}, q=0x0, tran=0x555556ce3bb0, errp=0x7fffffffd9d0) at ../block.c:2535
#5 0x0000555555d5cc00 in bdrv_refresh_perms (bs=0x555556cd5c60, errp=0x7fffffffd9d0) at ../block.c:2598
#6 0x0000555555d5de09 in bdrv_attach_child
(parent_bs=0x555556cd5c60, child_bs=0x555556cdd320, child_name=0x55555620c21c "file", child_class=0x555556880a20 <child_of_bds>, child_role=19, errp=0x7fffffffd9d0) at ../block.c:3205
#7 0x0000555555d5ebe9 in bdrv_open_child
(filename=0x0, options=0x555556cdb130, bdref_key=0x55555620c21c "file", parent=0x555556cd5c60, child_class=0x555556880a20 <child_of_bds>, child_role=19, allow_none=false, errp=0x7fffffffd9d0) at ../block.c:3665
#8 0x0000555555dc53bb in qcow2_open
(bs=0x555556cd5c60, options=0x555556cdb130, flags=139266, errp=0x7fffffffd9d0) at ../block/qcow2.c:1895
#9 0x0000555555d5ae30 in bdrv_open_driver
(bs=0x555556cd5c60, drv=0x5555569947e0 <bdrv_qcow2>, node_name=0x0, options=0x555556cdb130, open_flags=139266, errp=0x7fffffffdae0) at ../block.c:1625
#10 0x0000555555d5b816 in bdrv_open_common
(bs=0x555556cd5c60, file=0x555556ce2910, options=0x555556cdb130, errp=0x7fffffffdae0) at ../block.c:1921
#11 0x0000555555d5f8e5 in bdrv_open_inherit
(filename=0x555556cd3060 "/home/ostest/new/ubuntu3.img", reference=0x0, options=0x555556cdb130, flags=8194, parent=0x0, child_class=0x0, child_role=0, errp=0x5555569ec5a0 <error_fatal>) at ../block.c:3990
#12 0x0000555555d5fe29 in bdrv_open
(filename=0x555556cd3060 "/home/ostest/new/ubuntu3.img", reference=0x0, options=0x555556cd3730, flags=0, errp=0x5555569ec5a0 <error_fatal>) at ../block.c:4085
#13 0x0000555555d8215c in blk_new_open
(filename=0x555556cd3060 "/home/ostest/new/ubuntu3.img", reference=0x0, options=0x555556cd3730, flags=0, e--Type <RET> for more, q to quit, c to continue without paging--
rrp=0x5555569ec5a0 <error_fatal>) at ../block/block-backend.c:457
#14 0x0000555555d4c31d in blockdev_init
(file=0x555556cd3060 "/home/ostest/new/ubuntu3.img", bs_opts=0x555556cd3730, errp=0x5555569ec5a0 <error_fatal>) at ../blockdev.c:592
#15 0x0000555555d4d1f8 in drive_new
(all_opts=0x555556aa6560, block_default_type=IF_IDE, errp=0x5555569ec5a0 <error_fatal>)
at ../blockdev.c:981
#16 0x00005555558be5a1 in drive_init_func
(opaque=0x555556c4eee8, opts=0x555556aa6560, errp=0x5555569ec5a0 <error_fatal>) at ../softmmu/vl.c:643
#17 0x000055555606b8f2 in qemu_opts_foreach
(list=0x55555698f680 <qemu_drive_opts>, func=0x5555558be569 <drive_init_func>, opaque=0x555556c4eee8, errp=0x5555569ec5a0 <error_fatal>) at ../util/qemu-option.c:1135
#18 0x00005555558be7ed in configure_blockdev
(bdo_queue=0x5555568ace30 <bdo_queue>, machine_class=0x555556c4ee40, snapshot=0) at ../softmmu/vl.c:702
#19 0x00005555558c2b79 in qemu_create_early_backends () at ../softmmu/vl.c:1980
#20 0x00005555558c6c9d in qemu_init (argc=18, argv=0x7fffffffe2f8, envp=0x7fffffffe390)
at ../softmmu/vl.c:3714
#21 0x0000555555865a55 in main (argc=18, argv=0x7fffffffe2f8, envp=0x7fffffffe390) at ../softmmu/main.c:49