pnfs 中的引用計數

存在多個相互關聯的快取。我們有佈局(layout),它們可以引用多個裝置,每個裝置又可以引用多個數據伺服器。每個資料伺服器可以被多個裝置引用。每個裝置可以被多個佈局引用。為了理清這些關係,我們需要進行引用計數。

struct pnfs_layout_hdr

網路命令 LAYOUTGET 對應於 `struct pnfs_layout_segment`,通常透過變數名 `lseg` 來引用。每個 `nfs_inode` 可以在 `nfsi->layout` 中持有一個指向這些佈局段快取的指標,其型別為 `struct pnfs_layout_hdr`。

我們為指向它的 inode 的頭進行引用,跨每個引用它的未完成的 RPC 呼叫(LAYOUTGET, LAYOUTRETURN, LAYOUTCOMMIT),以及其中持有的每個 `lseg`。

每個頭(非空時)也會被放入與 `struct nfs_client` (即 `cl_layouts`) 關聯的列表中。被放入此列表不會增加引用計數,因為佈局是由將其保留在列表中的 `lseg` 維持的。

deviceid_cache

`lseg` 引用裝置 ID,這些 ID 根據 `nfs_client` 和佈局驅動程式型別進行解析。裝置 ID 儲存在 RCU 快取 (`struct nfs4_deviceid_cache`) 中。快取本身在每次掛載時被引用。條目 (`struct nfs4_deviceid`) 本身在引用它們的每個 `lseg` 的生命週期內被持有。

使用 RCU 是因為裝置 ID 本質上是一種寫一次、讀多次的資料結構。32 個桶的 `hlist` 大小需要更好的理由,但考慮到每個檔案系統可以有多個裝置 ID,並且每個 `nfs_client` 可以有多個檔案系統,這個大小似乎是合理的。

雜湊程式碼從 `nfsd` 程式碼庫中複製而來。關於雜湊演算法及其變體的討論可以在此處找到。

資料伺服器快取

檔案驅動裝置引用資料伺服器,這些資料伺服器儲存在模組級別的快取中。其引用在指向它的裝置 ID 的生命週期內被持有。

lseg

`lseg` 維護一個額外的引用,對應於 `NFS_LSEG_VALID` 位,該位將其保持在 `pnfs_layout_hdr` 的列表中。當最後一個 `lseg` 從 `pnfs_layout_hdr` 的列表中移除時,`NFS_LAYOUT_DESTROYED` 位被設定,阻止任何新的 `lseg` 被新增。

佈局驅動程式

PNFS 利用所謂的佈局驅動程式。STD 定義了 4 種基本佈局型別:“檔案”、“物件”、“塊”和“彈性檔案”。對於每種型別,都有一個佈局驅動程式,帶有一個公共的函式向量表,由 `nfs-client` `pnfs-core` 呼叫以實現不同的佈局型別。

Files 佈局驅動程式碼位於:fs/nfs/filelayout/.. 目錄下 Blocks 佈局驅動程式碼位於:fs/nfs/blocklayout/.. 目錄下 Flexfiles 佈局驅動程式碼位於:fs/nfs/flexfilelayout/.. 目錄下

塊佈局設定

待辦:文件化塊佈局驅動程式的設定需求