本人目前就职于烽火集成,从事云计算产品架构设计相关工作,长期专注于内核、虚拟化、分布式、云计算等方向。
技术交流请联系:xiaoding@fiberhome.com
热迁移的概念已经不陌生了,在虚拟化发展中,热迁移也越来越多的应用在商用场景。今天就来分析下热迁移的代码,详细了解下这一过程如何实现的。
首先,从官网上翻译下关于热迁移的算法描述。
vmA:要迁移的主机
vmB:接受迁移的主机
1.准备阶段
启动vmB,vmA连接到vmB,开启内存脏页日志和其他
2.转移内存
vmA持续运行,第一次传送所有内存到vmB,然后递归传输脏页到vmB。(每次传输需要耗费一定时间,该时间会产生新的脏页)
3.停止虚拟机
vmA suspend,执行sync,同步vmA磁盘信息。
4.传输状态
所有vmA的设备状态和脏页被传输。
5.继续运行
vmB开始运行,虚拟机迁移成功。
下面开始从代码看看这一流程的实现
位于migration.c的函数qmp_migrate就是迁移的入口函数
无论哪个协议,最终都会调用到migrate_fd_connect函数。该函数主要创建了迁移线程。
ram设备在vm初始化时注册的各种handle,这个用处下面会详细说。
线程主要分为3个部分,准备阶段,循环执行迁移,最后处理。
第一阶段
在迁移前,先调用了ram_save_setup函数,用来进行迁移初始化,比如压缩算法,用来记录脏页的bitmap等。
memory_global_dirty_log_start函数,开始标记要开始进行脏页统计了。
宏MEMORY_LISTENER_CALL_GLOBAL主要调用memory_listenesrs中注册的各个内存模块的log_global_start函数。kvm在这里重新注册了新的memory_region来设置了dirty_log标记。
在kvm下,通过memory_listener_register函数注册了内存变化监听。
通知kvm后,要调用migration_bitmap_sync函数来设置脏页。
开始第二阶段:迁移
ram_save_pending比较简单,就是调用了migration_bitmap_sync函数。
ram_save_iterate真正开始进行迁移的函数。主要调用ram_find_and_save_block对page进行迁移。
ram_find_and_save_block真正的传输函数。
qemu_savevm_state_complete函数完成了最后的操作。
ram_save_complete做了最后的处理,传输剩下的脏页。
vmstate_save主要是调用vmstate_save_state,以及为了以前的方式做了兼容处理。
vmstate_save_state 根据vmsd中定义的handle开始一系列处理
至此,基本代码走读结束。