QEMU/块设备增量备份

用位图定位增量备份范围

QEMU dirty bitmap 为磁盘区间记录是否被写入,使增量备份能够只复制发生变化的范围。

v9.2.0存储与数据放置核验 2026-10-08
相关概念

工程问题#

完整复制大容量虚拟磁盘昂贵;系统需要在持续写入期间紧凑记录改动,并维护正确的备份边界。

实际实现#

BdrvDirtyBitmap 用分层 HBitmap 跟踪磁盘范围;叶层每个 bit 对应固定粒度的区间,区间内有写入即置脏。bdrv_set_dirty 仅更新已启用的位图,增量备份按脏范围复制并管理作业边界。

处理流程#

  1. 显式创建并启用跟踪位图
  2. 磁盘写入将相应范围置位
  3. 增量作业读取脏区间
  4. 按作业结果管理位图及后续边界

源码片段#

固定版本 · 原文摘录
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 完成,这里没有展示备份数据复制或成功后的位图切换。

收益与取舍#

工程分析

带来的收益

  • 位图存储随磁盘容量线性且紧凑
  • 避免逐字节比较整个镜像

付出的代价

  • 粒度越细,位图与维护成本越高
  • 粒度越粗,未改变数据也可能随整段复制

可比较的选择

写入日志可保留更细的变更历史,但日志增长、重放与压缩更复杂。

版本与适用范围#

对应块设备增量备份,位图必须显式启用;不要与迁移时跟踪客体 RAM 的脏页机制混同。

参考来源#

源码、官方文档与原始论文
01
QEMU · Dirty Bitmaps and Incremental Backup

docs/interop/bitmaps.rst · Overview / Bitmap Persistence

官方文档v9.2.0

相关实现与比较#

2 个相关案例
4 个匹配案例