qemu的外部快照实现原理
一 基础概念
1 外部快照
当一个快照被创建时,创建时当前的状态保存在当前使用的磁盘文件中,即成为一个backing file。此时一个新的overlay被创建出来保存往后的数据。
2 backing file和overlay
对基础镜像做外部快照,生成的快照文件被称为overlay,基础镜像成为backing file。backing file是只读的。示例链路如下:
base-img <-- overlay-1 <-- overlay-2 <-- overlay-3
仅支持base-img为raw file,其他节点为qcow2 file的链路,或者所有节点为qcow2 file的链路。
3 更多名词解释
- cluster: qcow2镜像存储数据的最小单位,默认64K。
- L2 entry: 描述cluster offset及其相关标志位的入口,长度为64位。
- cluster offset: normal cluster位于镜像中的起始地址,长度为64位。
- cluster type: cluster类型,根据存储内容分为normal,compressed,unallocated,zeroplain, zeroalloc。
二 COW
COW是外部快照的读写流程中最重要的部分。
1 什么是COW
COW(Copy-On-Write),也被称之为「即写即拷」快照技术或「写时复制」快照技术,这种方式通常也被称为“元数据(源数据指针表)”拷贝。顾名思义,如果有人试图改写源数据块上的原始数据,首先将原始数据拷贝到新数据块中,然后再进行改写。
2 为何需要COW
当写请求发生在backing file上,要先分配new cluster。如果只是把要写的数据写到new cluster上,那数据是不完整的,因为每次写入的数据并非刚刚是cluster的整数倍,可能是几个或几个sector,所以需要我们把剩下的部分从old cluster上复制到new cluster,最后把这个cluster标记为allocated cluster。
当我们下次读该cluster,在overlay上就可以读到,且数据是完整的,不是残缺不全的。
3 如何COW
qcow2的COW并非先复制再写入,而是先写入再复制。步骤如下:
- 分配new cluster。
- 标记写时复制的范围
cow_start和cow_end,保存在结构体QCowL2Meta。 - 写入要写的数据到new cluster。
- 把剩下的部分从old cluster复制到new cluster。
- 用新的
cluster offset更新l2 table,加上QCOW_OFLAG_COPIED标记。
三 cluster类型
1 cluster类型
typedef enum QCow2ClusterType {
QCOW2_CLUSTER_UNALLOCATED, //未分配
QCOW2_CLUSTER_ZERO_PLAIN,
QCOW2_CLUSTER_ZERO_ALLOC,
QCOW2_CLUSTER_NORMAL, //normal
QCOW2_CLUSTER_COMPRESSED, //压缩
} QCow2ClusterType;
当QCOW2_CLUSTER_NORMAL类型,且标记QCOW_OFLAG_COPIED,才无需分配cluster。其他情况均需要分配cluster。
2 如何获取cluster类型
qcow2_get_cluster_type获取cluster类型。
四 分配cluster
谁来决定分配cluster呢,是由l2 entry决定的,这里要搞清楚它的含义。
1 l2 entry各位含义,以standard clusters为例。

2 根据l2 entry决定是否分配cluster
l2 entry满足以下条件,为normal cluster,不分配新cluster。

l2 entry的每一位都为0,为unallocated cluster,需分配新cluster。

满足63bit=0,且l2 entry & L2E_OFFSET_MASK != 0。该cluster被内部快照过,需分配cluster.

五 读写流程
1 读流程
发生在qcow2_co_preadv中,分为两种情况:
- 要读的数据在overlay上。
- 要读的数据在backing file上。
qcow2_co_preadv
ret = qcow2_get_cluster_offset //计算cluster offset,并返回cluster type。
switch (ret)
case QCOW2_CLUSTER_UNALLOCATED:
if (bs->backing) //读取backing file上的数据。
bdrv_co_preadv
case QCOW2_CLUSTER_NORMAL:
bdrv_co_preadv //读取overlay上的数据。
2 写流程
发生在qcow2_co_pwritev中,流程如下:
- 如果不需要分配new cluster,将数据写入overlay。
- 如果需要分配new cluster,但是没有backing file,或者backing file上找不到cluster offset,将数据写入new cluster。
- 如果需要分配new cluster,且在backing file能找到cluster offset,执行COW。
qcow2_co_pwritev
qcow2_alloc_cluster_offset //获取cluster offset,如果获取失败,分配new cluster。
handle_alloc_space //new cluster填充零。
bdrv_co_pwritev //将数据写入cluster。
qcow2_handle_l2meta //当需要COW时,该函数执行COW。
qemu的外部快照实现原理的更多相关文章
- Libvirt外部快照
外部快照的创建 实验环境 CentOS 7 升级QEMU CentOS 7自带的qemu版本太低需要升级 $ sudo yum install -y gcc $ sudo yum install -y ...
- ROW/COW 快照技术原理解析
NOTE:ROW/COW 最新更新请跳转<再谈 COW.ROW 快照技术> 目录 目录 快照与备份的区别 Snapshot 快照技术 全量快照 增量快照 COW 写时拷贝快照技术 ROW ...
- KVM&Libvirt基本概念及开发杂谈
导读 大家好,本次肖力分享的主题是KVM&Libvirt基本概念及开发杂谈,内容有些凌乱松散,主要基于自己早期整理的笔记内容和实践感悟,有些内容难免有失偏颇,望见谅.前面先介绍下需要了解的基本 ...
- KVM 介绍(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 实例的快照 (Nova Instances Snapshot Libvirt)
学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...
- 使用libvirtAPI打快照原理
参考: https://blog.51cto.com/3646344/2096347 https://blog.51cto.com/3646344/2096351(磁盘外部快照) API接口: htt ...
- KVM(七)使用 libvirt 做 QEMU/KVM 快照和 Nova 实例的快照
本文将梳理 QEMU/KVM 快照相关的知识,以及在 OpenStack Nova 中使用 libvirt 来对 QEMU/KVM 虚机做快照的过程. 1. QEMU/KVM 快照 1.1 概念 QE ...
- qemu-img 快照的一些总结
qemu-img 快照的一些总结 http://www.openext.org/2014/06/qemu-img-snapshot-re http://blog.csdn.net/muge0913/a ...
- 使用virsh命令创建KVM虚拟机快照
查看虚拟机所在主机和虚拟机名称:[root@node-1 ~]# nova show a88dcf5d-c8b2-46a5-af27-a176d8235c9d|grep hyper| OS-EXT-S ...
- KVM虚拟机快照备份
KVM 快照的定义:快照就是将虚机在某一个时间点上的磁盘.内存和设备状态保存一下,以备将来之用.它包括以下几类: (1)磁盘快照:磁盘的内容(可能是虚机的全部磁盘或者部分磁盘)在某个时间点上被保存,然 ...
- [原] KVM 虚拟化原理探究 —— 目录
KVM 虚拟化原理探究 -- 目录 标签(空格分隔): KVM KVM 虚拟化原理探究(1)- overview KVM 虚拟化原理探究(2)- QEMU启动过程 KVM 虚拟化原理探究(3)- CP ...
随机推荐
- 大麦基于HarmonyOS星盾安全架构,打造全链路安全抢票方案
6月21日,在华为开发者大会2025 "安全与隐私分论坛"上,大麦作为鸿蒙生态应用开发优秀案例,受邀进行议题演讲,分享其基于鸿蒙系统星盾安全架构构建的票务安全创新实践.大麦娱乐无线 ...
- 一个工具管理你的所有 SDK 版本!
众所周知,我们在面对同一个 SDK 的不同版本时,需要使用到不同的工具来管理,例如: Java:JEnv NodeJs:nvm ... 它们的原理都是基于系统的软连接,让环境变量指向一个软连接来实现切 ...
- left join 和 where 区别
RT https://leetcode.cn/problems/replace-employee-id-with-the-unique-identifier/solution/ select b.un ...
- CGI 简单的python显示的页面
简介 python 进行服务器的页面的显示 cgi common gateway interface 公用网关接口 简单操作 python3 -m http.server --cgi 8001 新建一 ...
- lingo 练习 二
简介 练习测试 KeyPoints: 条件过滤的应用,循环乘法的应用 EX1.求sets中前几个数的和 model: data: N=6; enddata sets: number/1..N/:x; ...
- STM32 IAP(OTA)
一.背景知识 STM32启动流程(从内部flash启动)[1] 正常情况下,程序从Flash启动时的流程如下:(转载自) https://blog.csdn.net/qq_42190402/artic ...
- ETL中如何自定义规则
一.ETL中的规则 在使用规则之前我们先来了解一下什么是规则,ETL中规则在很多组件中都能看见,可以理解为按照事前约定好的逻辑去执行,规则可以使得数据更加的规范统一,同时也不需要去纵向的修改底层代码, ...
- ETL数据仓库的使用方式
一.ETL的过程 在 ETL 过程中,数据从源系统中抽取(Extract),经过各种转换(Transform)操作,最后加载(Load)到目标数据仓库中.以下是 ETL 数仓流程的基本步骤: 抽取(E ...
- Rust中的匿名函数与闭包
一.匿名函数 语法:"|参数名| 语句" 参考下面的这个示例: fn add(a: i32, b: i32) -> i32 { a + b } fn main() { let ...
- SpringBoot--如何创建自己的自动配置
在实际开发中,仅靠SpringBoot的自动配置是远远不够的,比如要访问多个数据源,自动配置就完全无能为力了. 自动配置的本质 本质就是在容器中预配置要整合的框架所需的基础Bean. 以MyBatis ...