編寫策略指南

儘量避免事務性。核心程式碼會謹慎地避免查詢任何正在遷移的事物。這雖然很麻煩,但能讓策略的編寫更容易。

對映在構建時載入到策略中。

目標對映的每個 bio 都將參考策略。策略可以返回簡單的“命中 (HIT)”或“未命中 (MISS)”,或發起遷移。

目前策略無法發起後臺工作,例如開始寫回即將被逐出的髒塊。

因為我們對映的是 bio 而不是請求,所以策略很容易被許多小的 bio 欺騙。因此,核心目標會定期向策略發出“心跳”。建議策略在每個心跳週期內,不要為一個塊多次更新狀態(例如,命中計數)。核心透過觀察 bio 完成來發出心跳,從而嘗試瞭解 I/O 排程程式何時允許 I/O 執行。

提供的快取替換策略概述

多佇列 (mq)

此策略現在是 smq 的別名(見下文)。

接受以下可調引數,但它們不起作用

'sequential_threshold <#nr_sequential_ios>'
'random_threshold <#nr_random_ios>'
'read_promote_adjustment <value>'
'write_promote_adjustment <value>'
'discard_promote_adjustment <value>'

隨機多佇列 (smq)

此策略是預設策略。

隨機多佇列 (smq) 策略解決了多佇列 (mq) 策略的一些問題。

與 mq 策略相比,smq 策略有望降低記憶體使用、提高效能並在工作負載變化時增強適應性。smq 也沒有任何繁瑣的調優旋鈕。

使用者只需適當地重新載入使用快取目標的 DM 表,即可從“mq”切換到“smq”。這樣做會導致 mq 策略的所有提示都被丟棄。此外,快取效能可能會略有下降,直到 smq 重新計算出應快取的源裝置熱點。

記憶體使用

mq 策略佔用大量記憶體;在 64 位機器上每個快取塊佔用 88 位元組。

smq 使用 28 位索引而不是指標來實現其資料結構。它避免為每個塊儲存顯式的命中計數。它有一個“熱點”佇列,而不是預快取,該佇列使用四分之一的條目(每個熱點塊覆蓋的區域比單個快取塊更大)。

所有這些意味著 smq 每個快取塊使用約 25 位元組。儘管仍然佔用大量記憶體,但這仍然是一個顯著的改進。

級別平衡

mq 根據命中計數(約 ln(命中計數))將條目放置在多佇列結構的不同級別中。這意味著底層通常包含最多的條目,而頂層則很少。這種不平衡的級別降低了多佇列的效率。

smq 不維護命中計數,而是將命中的條目與來自上一層最不常使用的條目進行交換。整體排序是這種隨機過程的副作用。透過這種方案,我們可以決定每個多佇列級別佔用多少條目,從而做出更好的提升/降級決策。

適應性:mq 策略為每個快取塊維護一個命中計數。要將不同的塊提升到快取中,其命中計數必須超過當前快取中最低的。這意味著快取適應不同的 I/O 模式可能需要很長時間。

smq 不維護命中計數,因此很多問題都迎刃而解。此外,它還會跟蹤熱點佇列的效能,熱點佇列用於決定提升哪些塊。如果熱點佇列效能不佳,它會開始更快地在級別之間移動條目。這使得它能夠非常快速地適應新的 I/O 模式。

效能

測試表明 smq 的效能顯著優於 mq。

清理器

清理器會將快取中所有髒塊寫回以將其解除服務。

示例

表的語法是

cache <metadata dev> <cache dev> <origin dev> <block size>
<#feature_args> [<feature arg>]*
<policy> <#policy_args> [<policy arg>]*

使用 dmsetup 命令傳送訊息的語法是

dmsetup message <mapped device> 0 sequential_threshold 1024
dmsetup message <mapped device> 0 random_threshold 8

使用 dmsetup

dmsetup create blah --table "0 268435456 cache /dev/sdb /dev/sdc \
    /dev/sdd 512 0 mq 4 sequential_threshold 1024 random_threshold 8"
creates a 128GB large mapped device named 'blah' with the
sequential threshold set to 1024 and the random_threshold set to 8.