qemu HBitmap原理

一:磁盤位圖HBitmap分析
使用unsigned long已經可以勝任bitmap的實現,可是當bitmap比較大的時候,它的操做效率很低。像BloclDriver維持bitmap,磁盤文件的每一個塊都對應一個bit爲,那麼這張bitmap表是很大的。若是在熱遷移過程當中,須要將鏡像文件熱遷移到目標宿主機上,每次查詢bitmap的效率很低。所以,QEMU針對磁盤鏡像文件設計了HBitmap數據結構。算法

HBitmap數據結構以下:
struct HBitmap {
uint64_t size;
uint64_t count;
int granularity;
HBitmap meta;
unsigned long
levels[HBITMAP_LEVELS];
uint64_t sizes[HBITMAP_LEVELS];
};數組

uint64_t size : 虛擬機磁盤大小,計算方式:size = (size + (1ULL << granularity) - 1) >> granularity。 如虛擬鏡像大小爲1G,size = (102410241024 + (1ULL<<16) -1 ) >>16 即size=16385
int granularity : 12-16,默認是16
unsigned long *levels[HBITMAP_LEVELS] : 保存每一層的位圖
uint64_t sizes[HBITMAP_LEVELS] : 記錄levels每一層對應的數組大小數據結構

磁盤50g時,HBitmap數據結構對應的信息:
{
size = 819200,
count = 4,
granularity = 16,
meta = 0x0,
levels = {0x56131ac3cce0, 0x56131ac3ccc0, 0x56131ac3cca0, 0x56131a70e090, 0x56131a70e060, 0x56131ac62eb0, 0x56131b630400},
sizes = {1, 1, 1, 1, 4, 200, 12800}
}ide

uint64_t sizes[HBITMAP_LEVELS] 每層設置的最大數組,以上層數組的值向右偏移BITS_PER_LEVEL=6位,算法以下:
for (i = HBITMAP_LEVELS; i-- > 0; ) {
size = MAX((size + BITS_PER_LONG - 1) >> BITS_PER_LEVEL, 1);
hb->sizes[i] = size;
hb->levels[i] = g_new0(unsigned long, size);
}函數

HBitmap層次結構圖,總共7層,下層記錄上層的修改bit位,當上層某bit位置爲1時,下層會相應的位記錄
qemu HBitmap原理ui

二:根據偏移地址在HBitmap中設置
例如,虛擬機在磁盤的起始位置start=2292187136寫入count=262144字節設計

  1. 計算第6層word位置(起始word和結束word)
    startpos = 2292187136 >>16>>6 即start = 546,在第6層的第546個位置開始
    lastpos = (start + count - 1) >>16 >>6。在第6層的第546個位置結束
    lastpos = (2292187136 + 262144 - 1) >> 16 >>6 = 546code

  2. 計算第6層word中對應的bit位
    firsh = start >> 16 = 2292187136 >> 16 = 34976
    last = (start + count - 1) >> 16 = (2292187136 + 262144 - 1) >> 16 = 34979
    mask = 2UL << (last & (BITS_PER_LONG - 1))
    mask -= 1UL << (firsh & (BITS_PER_LONG - 1))
    mask = 2UL << (34979 & (64 - 1)) - (34976 & (64 - 1)) = 0xf00000000
    轉換成二進制,在word中的第32, 33,34,35位分別寫入1blog

  3. 第6層有bit位寫入爲1時,繼續設置第5層
    先計算第5層的word位(起始word和結束word)
    startpos = 546 >> 6 = 8
    lastpos = 546 >> 6 = 8
    即寫入第5層的第8個word位置get

    計算第5層word中對應的bit位
    mask = 2UL << (546 & (64 - 1)) - (546 & (64 - 1)) = 0x400000000
    轉換成二進制,在word中第34位寫入1
  4. 若是該層有bit爲修改,依次設置下層,直到第0層

三: 根據地址獲取對應的bit位例如,虛擬機在磁盤的起始位置start=2292187136,計算該起始位置對應的bit位是否設置爲1bit = 1UL <<(start >>hb->granularity) & (BITS_PER_LONG - 1)bit = 1UL <<((2292187136 >> 16) & (64 -1)) = 0x100000000轉換成二進制,在word中第32位爲1,與在HBitmap中設置的一致。具體實現見函數hbitmap_get

相關文章
相關標籤/搜索