用位图定位增量备份范围
QEMU dirty bitmap 为磁盘区间记录是否被写入,使增量备份能够只复制发生变化的范围。
相关概念
工程问题#
完整复制大容量虚拟磁盘昂贵;系统需要在持续写入期间紧凑记录改动,并维护正确的备份边界。
实际实现#
BdrvDirtyBitmap 用分层 HBitmap 跟踪磁盘范围;叶层每个 bit 对应固定粒度的区间,区间内有写入即置脏。bdrv_set_dirty 仅更新已启用的位图,增量备份按脏范围复制并管理作业边界。
处理流程#
- 显式创建并启用跟踪位图
- 磁盘写入将相应范围置位
- 增量作业读取脏区间
- 按作业结果管理位图及后续边界
源码片段#
固定版本 · 原文摘录block/dirty-bitmap.cv9.2.0 · L656–L674
656void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes)657{658 BdrvDirtyBitmap *bitmap;659 IO_CODE();660661 if (QLIST_EMPTY(&bs->dirty_bitmaps)) {662 return;663 }664665 bdrv_dirty_bitmaps_lock(bs);666 QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {667 if (!bdrv_dirty_bitmap_enabled(bitmap)) {668 continue;669 }670 assert(!bdrv_dirty_bitmap_readonly(bitmap));671 hbitmap_set(bitmap->bitmap, offset, bytes);672 }673 bdrv_dirty_bitmaps_unlock(bs);674}bdrv_set_dirty
一次块设备写入范围会遍历该设备关联的位图,只更新 enabled 的位图,并调用 HBitmap 置位。锁保护的是脏位图更新;粒度映射由 HBitmap 完成,这里没有展示备份数据复制或成功后的位图切换。
CMIT
收益与取舍#
工程分析带来的收益
- 位图存储随磁盘容量线性且紧凑
- 避免逐字节比较整个镜像
付出的代价
- 粒度越细,位图与维护成本越高
- 粒度越粗,未改变数据也可能随整段复制
可比较的选择
写入日志可保留更细的变更历史,但日志增长、重放与压缩更复杂。
版本与适用范围#
对应块设备增量备份,位图必须显式启用;不要与迁移时跟踪客体 RAM 的脏页机制混同。
参考来源#
源码、官方文档与原始论文01
QEMU · Dirty Bitmaps and Incremental Backup
官方文档v9.2.0docs/interop/bitmaps.rst · Overview / Bitmap Persistence
相关实现与比较#
2 个相关案例libvirt 将 vCPU 允许使用的宿主 CPU 集合表示为位图,并转换为运行时亲和性配置。
附源码片段 · 调度与资源分配
Linux 普通定时器把较近超时放进细粒度槽,远期超时放进粗粒度槽,使用位图寻找待处理槽。v6.12 的这套时间轮不再逐层级联迁移。
附源码片段 · 调度与资源分配