qemu創建快照後刪除快照導致qemu crashed的BUG

問題描述:
啓動一個虛擬機,創建三個快照,刪除第一個快照時報錯:合併磁盤失敗
通過測試,創建虛擬機(ubuntu1604,win7),啓動虛擬機,創建兩個快照,刪除第一個快照,瘦終端自自動關閉
vdsm報錯如下:
2018-07-20 17:00:50,641+0800 ERROR (jsonrpc/2) [jsonrpc.JsonRpcServer] Internal server error (init:607)
Traceback (most recent call last):
File “/usr/lib/python2.7/dist-packages/yajsonrpc/init.py”, line 602, in _handle_request
res = method(**params)
File “/usr/lib/python2.7/dist-packages/vdsm/rpc/Bridge.py”, line 198, in _dynamicMethod
result = fn(*methodArgs)
File “/usr/share/vdsm/API.py”, line 1349, in getAllVmIoTunePolicies
io_tune_policies_dict = self._cif.getAllVmIoTunePolicies()
File “/usr/share/vdsm/clientIF.py”, line 459, in getAllVmIoTunePolicies
‘current_values’: v.getIoTune()}File “/usr/share/vdsm/virt/vm.py”, line 2885, in getIoTune
result = self.getIoTuneResponse()
File “/usr/share/vdsm/virt/vm.py”, line 2898, in getIoTuneResponse
res = self._dom.blockIoTune(
File “/usr/lib/python2.7/dist-packages/vdsm/virt/virdomain.py”, line 47, in getattr
% self.vmid)
NotConnectedError: VM u’9e11571a-8ffb-4b64-bdfa-d5a38638be7e’ was not started yet or was shut down
qemu報錯如下:
qemu-system-x86_64: /build/qemu-2.6+dfsg/block/io.c:1342: bdrv_co_do_pwritev: Assertion `!(bs->open_flags & 0x0800)’ failed.
2018-07-20 09:00:49.595+0000: shutting down, reason=crashed

libvirt到qemu的blockcommit調用用流程:

Created with Raphaël 2.1.2blockcommitvirDomainBlockCommitqemuDomainBlockCommitqemuMonitorBlockCommitqemuMonitorJsoNBlockCommit

qemu中的blockcommit流程

Created with Raphaël 2.1.2block-commitqmp_block_commitblock-commitqmp_block_commit

qemu更更新磁盤preTop的head流程:(base<-top<-preTop)commit_complete

Created with Raphaël 2.1.2bdrv_drop_intermediatebdrv_change_backing_fileqcow2_change_backing_fileqcow2_update_headerbdrv_pwritebdrv_pwritevbdrv_prwv_co

其中,對磁盤頭的更新默認更新整個磁盤頭,磁盤頭中包含了該磁盤的parent磁盤。
問題在於top合併到base之後,系統會通過bdrv_pwritev向preTop磁盤中寫入數據,如果該磁盤非active,則assert斷言言會導致qemu crash,解決方
案爲增加磁盤頭例外。

結論
最後實測刪除多次均不會導致qemu crash。

附qemu快照刪除流程:
初始快照鏈:
base<-snap1<-snap2<-snap3<-active
其中除active層爲rw,其餘層均爲ro
刪除snap1:
1)snap1默認爲base, snap2默認爲top, snap3默認爲preTop。
2)通過blockcommit將top層的改動覆蓋到base層
3)複寫preTop層的head,將其parent從top修改爲base
4)手動刪除top

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章