NFS協定端對端實例解析之寫資料流程

2023.10.02

NFS協定端對端實例解析之寫資料流程

服務端向RPC註冊了各種回呼函數,當接收到客戶端的請求時會呼叫特定的回呼函數進行處理。本範例將呼叫nfsd3_proc_write函數。此函數最後呼叫VFS層的寫入資料函數,而VFS寫入資料函數則呼叫特定檔案系統(例如Ext4)的函數完成最終的寫入資料操作。號

對於NFS來說,其寫入模式包含同步寫,非同步寫和直接寫等模式。模式的差異在於開啟檔案時指定的參數。限於篇幅,本文很難一一介紹所有模式,這裡主要介紹一個核心流程。

NFS作為Linux下的檔案系統,為了實現與VFS的對接,NFS也要實作一套函數指標介面。以文件相關的操作為例,其實作的函數指標如下所示。對於寫入資料來說,VFS會呼叫NFS的nfs_file_write函數。

圖片圖片

在該函數中,如果有SYNC標記則會觸發同步寫的流程,否則寫入快取後就會傳回給呼叫者。本節我們主要關注觸發同步寫的流程,也就是資料是如何從NFS檔案系統傳送到服務端的。

直接寫入和同步寫入都會觸發將資料傳送到服務端的流程,本節以同步寫入為例介紹資料是如何傳送到服務端的。如果觸發同步刷寫,那麼會呼叫nfs_file_fsync函數,該函數是將快取資料傳輸到服務端的入口。此函數到後端存取介面nfs_do_writepage的主線流程如下圖所示。

圖片圖片

nfs_file_fsync主線流程

這裡nfs_do_writepage用來將一個快取頁傳送到服務端,具體實作如下程式碼所示。其中主要是功能由nfs_page_async_flush函數完成。這裡比較重要的參數是pgio,在該參數中有頁資料傳輸相關的函數指針,關於該參數類型的詳細定義請參考內核原始碼。

圖片圖片

然後我們再從nfs_page_async_flush函數開始計數看一下主線流程,具體下圖所示。函數nfs_generic_pg_pgios就是在pgio初始化的函數指針,其在nfs_pageio_doio中被呼叫。此主線流程最終呼叫到nfs_initiate_pgio函數,該函數完成PRC訊息和參數的封裝,然後呼叫RPC服務的API函數完成請求。

nfs_page_async_flush主線流程nfs_page_async_flush主線流程

當nfs_initiate_pgio呼叫rpc_run_task函數後,整個流程就進入RPC服務內部了。也就是進入RPC服務狀態機的流程了。關於RPC狀態機的處理流程的介紹請參考本號相關內容。

最後,我們將整個寫入流程的簡圖展示一下,這裡包含客戶端的函數呼叫流程和服務端的處理流程。其中客戶端的流程中省略了部分函數呼叫。

網路檔案系統存取示意圖網路檔案系統存取示意圖

服務端向RPC註冊了各種回呼函數,當接收到客戶端的請求時會呼叫特定的回呼函數進行處理。本範例將呼叫nfsd3_proc_write函數。此函數最後呼叫VFS層的寫入資料函數,而VFS寫入資料函數則呼叫特定檔案系統(例如Ext4)的函數完成最終的寫入資料操作。