<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          LWN大作:NFS 的早期時(shí)代!

          共 9597字,需瀏覽 20分鐘

           ·

          2022-07-07 21:35

          關(guān)注了就能看到更多這么棒的文章哦~

          NFS: the early years

          June 20, 2022
          This article was contributed by Neil Brown
          DeepL assisted translation
          https://lwn.net/Articles/897917/

          我最近因?yàn)橐恍┰蛐枰獙?NFS(網(wǎng)絡(luò)文件系統(tǒng))協(xié)議多年來的改動進(jìn)行一下回溯和反思,而且發(fā)現(xiàn)這是一個(gè)很值得給大家講講的故事。這樣的故事很容易被過多的細(xì)節(jié)所淹沒,因?yàn)榇_實(shí)有非常多這樣的細(xì)節(jié),但確實(shí)有一個(gè)想法是比其他的那些更加明顯和突出的。NFS 的最早期版本被描述為一個(gè) "stateless (無狀態(tài)的) "協(xié)議,這個(gè)術(shù)語我現(xiàn)在還偶爾聽到有人會這么說。NFS 的大部分歷史都是承認(rèn)有 state 以及添加支持而逐步演進(jìn)的。本文著眼于 NFS 早期階段的演變(以及它對 state 的處理方式)。后續(xù)會有第二部分內(nèi)容來一直講述到當(dāng)前情況。

          我所說的 "state",就是指客戶端和服務(wù)器端需要共同記住的那些信息,它們?nèi)绻谝环桨l(fā)生了改變的話,就需要讓另一方也產(chǎn)生改變。正如我們將看到的,state 中包含很多內(nèi)容。其中一個(gè)很簡單的例子就是文件的內(nèi)容,當(dāng)它被緩存(cache)在客戶端一側(cè)時(shí),其目的要么是希望能不要進(jìn)行 read requests,要么就是為了能把 write request 合并起來發(fā)出去。客戶端需要知道什么時(shí)候所緩存的數(shù)據(jù)必須要被 flush 出去或者清除掉,從而讓客戶端和服務(wù)器端基本保持同步。另一種明顯的 state 就是文件鎖(file locks)了,對于這種鎖,服務(wù)器和客戶端必須始終針對客戶端在某個(gè)時(shí)刻持有什么鎖要能確保一致。每一方都必須能夠發(fā)現(xiàn)另一方出現(xiàn)了 crash 的情況,從而能讓 lock 被丟棄(discard)或恢復(fù)(recover)。

          NFSv2 — the first version

          據(jù)推測,在 Sun Microsystems 內(nèi)部曾有一個(gè) NFS 的 "version 1",但第一個(gè)公開出來的版本就是 version 2 了,它出現(xiàn)在 1984 年。該協(xié)議在 RFC 1094 中有介紹,但這個(gè)文檔并不被視為權(quán)威性文件;相反,Sun 公司的實(shí)現(xiàn)本身定義了該協(xié)議。在同一時(shí)期,還有其他網(wǎng)絡(luò)文件系統(tǒng)被開發(fā)出來,如 AFS(the Andrew File System)和 RFS(Remote File Sharing)。與這些系統(tǒng)相比,NFS 有一個(gè)明顯的區(qū)別,那就是它很簡單。有人可能會說,它太簡單了,完全無法正確地實(shí)現(xiàn)一些 POSIX 語義。然而,這種簡單性意味著它可以為許多常見的工作場景提供良好的性能。

          20 世紀(jì) 80 年代初是 "3M Computer" 的時(shí)代,當(dāng)時(shí)個(gè)人工作站的經(jīng)常是只有 1M 字節(jié)的內(nèi)存、1 MIPS 的處理能力和 1 M 像素(單色)的顯示器。以今天的標(biāo)準(zhǔn)來看,這也太弱了,完全沒法用,而且當(dāng)時(shí)人們還認(rèn)為一百萬便士(10,000 美元)的價(jià)格是可以接受的。但這些就是 NFSv2 所必須能夠運(yùn)行的硬件環(huán)境,而且必須運(yùn)行良好才能被人們接納。歷史表明,它足以完成這項(xiàng)任務(wù)。

          Consequence of being "stateless"

          NFSv2 協(xié)議沒有對狀態(tài)管理的明確支持。沒有 "打開" 一個(gè)文件的概念,不支持 locking,也沒有在 RFC 中提到任何 caching 機(jī)制。只有簡單的、一個(gè)個(gè)互相獨(dú)立的訪問請求,所有這些都是利用文件句柄(file handle)來做的。

          "file handle" 是 NFSv2 的最核心的把其他東西統(tǒng)一起來的機(jī)制:它是一個(gè)不透明的(opaque)、32 字節(jié)的文件標(biāo)識符,在某個(gè)特定 NFS 服務(wù)器中,在所有時(shí)間內(nèi)這些 file handle 都是固定且唯一的。NFSv2 允許客戶端在一個(gè)特定目錄(由其他的 file handle 來識別)中為某個(gè)指定的名字查找文件句柄,檢查和改變這個(gè)文件句柄的屬性(所有權(quán)、大小、時(shí)間戳等),并在某個(gè)文件句柄的某個(gè)偏移位置來進(jìn)行數(shù)據(jù)塊的讀寫。

          為 NFSv2 選擇的操作是盡可能要滿足冪等的(idempotent)條件,也就是說如果某個(gè)請求被重復(fù)發(fā)送了,它在第二次或第三次執(zhí)行中的結(jié)果將會是與第一次相同的。這對于在不穩(wěn)定的網(wǎng)絡(luò)上進(jìn)行真正的無狀態(tài)操作是個(gè)必要條件。NFS 最初是通過 UDP 實(shí)現(xiàn)的,UDP 不保證數(shù)據(jù)一定能到達(dá),所以客戶端必須準(zhǔn)備好在沒有得到回復(fù)時(shí)來重新發(fā)送請求。客戶端不能知道是請求丟失了,還是回復(fù)丟失了,而真正的無狀態(tài)服務(wù)器是不能記住某個(gè)特定請求是否已經(jīng)被看到的,也就無法避免觸發(fā)重復(fù)動作。因此,當(dāng)客戶端重新發(fā)送一個(gè)請求時(shí),它可能會重復(fù)一個(gè)已經(jīng)執(zhí)行過的操作,所以必須是要 idempotent 的操作才行。

          不幸的是,并不是所有 POSIX 下的文件系統(tǒng)操作都可以是 idempotent 的。一個(gè)很好的例子就是 MKDIR,如果這個(gè)名字的目錄尚不存在,那么就應(yīng)該創(chuàng)建一個(gè)目錄;如果這個(gè)名字已經(jīng)被使用了,即使本身就是一個(gè)目錄了,也會需要返回錯(cuò)誤。這意味著重復(fù)請求可能導(dǎo)致會導(dǎo)致返回錯(cuò)誤。盡量減少這個(gè)問題的標(biāo)準(zhǔn)做法就是在服務(wù)器上實(shí)現(xiàn)一個(gè)重復(fù)請求緩存(DRC, Duplicate Request Cache)。這是對最近處理過的 non-idempotent 請求的歷史記錄,也包括返回的結(jié)果。實(shí)際上,這意味著客戶端(必須要跟蹤記錄尚未收到回復(fù)的請求)和服務(wù)器都維護(hù)一個(gè)隨時(shí)間不斷變化的未完成的請求列表。這些列表符合我們對 "state" 的定義,所以最初的 NFSv2 實(shí)際上并不是無狀態(tài)的,盡管根據(jù)規(guī)范來說它是無狀態(tài)的。

          由于服務(wù)器無法知道客戶端何時(shí)能看到自己的回復(fù),也就無法知道一個(gè)請求何時(shí)才能算是處理完成的,所以它必須使用一些啟發(fā)式規(guī)則來把舊的 cache 條目丟棄掉。不可避免地會記住許多不需要記住的請求,并可能會丟棄一些很快就會需要的請求。雖然這顯然不是最理想的方案,但經(jīng)驗(yàn)表明,這對正常的工作負(fù)荷來說已經(jīng)是相當(dāng)有效了。

          維護(hù)這個(gè) cache 就需要服務(wù)器知道每個(gè)請求來自哪個(gè)客戶端,所以它需要一些可靠的方法來識別客戶。隨著協(xié)議的發(fā)展,狀態(tài)管理變得更加明確,我們會看到這種需求反復(fù)出現(xiàn)。對于 DRC 來說,所使用的客戶端標(biāo)識符是由客戶端的 IP 地址和端口號得出的。當(dāng)后續(xù)添加了 TCP 支持的時(shí)候,協(xié)議類型也就需要與主機(jī)地址和端口號一起用上了。由于 TCP 提供了可靠的傳輸,似乎不需要 DRC,但這并不完全正確。如果網(wǎng)絡(luò)問題導(dǎo)致客戶端和服務(wù)器在很長一段時(shí)間內(nèi)無法通信,TCP 連接有可能 "中斷(break)"。NFS 做好了無限期等待的準(zhǔn)備,但是 TCP 不是這樣的。如果 TCP 確實(shí)中斷了連接,客戶端就不能知道那些未決請求的狀態(tài)了,它必須在一個(gè)新的連接上重新傳輸這些請求,這樣服務(wù)器端就可能仍然看到重復(fù)的請求了。為了確保這一點(diǎn),NFS 客戶端要注意使用與先前連接相同的 source 端口來重新建立連接。

          這個(gè) DRC 機(jī)制并不完美,部分原因是由于啟發(fā)式方法可能會在客戶端實(shí)際收到回復(fù)之前就丟棄了這些條目,還有可能的原因是在服務(wù)器重啟時(shí)沒有保留這些內(nèi)容,因此一個(gè)請求可能在服務(wù)器 crash 之前和之后都會被執(zhí)行。在許多情況下,這只是個(gè)無傷大雅的小問題,如果 "mkdir" 偶爾返回 EEXIST (本來不應(yīng)該有這個(gè)返回值),那么會有人真正受到影響嗎?但是有一種情況就被證明是會有很大問題的,而且 DRC 根本沒有對它進(jìn)行處理,那就是獨(dú)占創(chuàng)建(exclusive create)。

          在 Unix 有文件鎖的概念之前(因?yàn)樗?Edition 7 Unix 中沒有,這正是 BSD 的基礎(chǔ)),會經(jīng)常使用 lock file。如果需要獨(dú)占訪問某些文件,比如/usr/spool/mail/neilb,慣例是應(yīng)用程序必須首先創(chuàng)建一個(gè)相關(guān)名稱的 lock file,比如/usr/spool/mail/neilb.lock。這必須是一個(gè)使用 O_CREAT|O_EXCL 標(biāo)志的 "exclusive" 方式創(chuàng)建出來的,如果文件已經(jīng)存在就會失敗。如果某個(gè)應(yīng)用程序發(fā)現(xiàn)它不能創(chuàng)建該文件,因?yàn)槠渌麘?yīng)用程序已經(jīng)這樣做了,它就會等待著重新嘗試。

          Exclusive create 天生就不是一個(gè) idemotent 操作,而且 NFSv2 根本就不支持它。客戶端可以進(jìn)行查詢,如果報(bào)告說沒有現(xiàn)存的文件,他們就可以創(chuàng)建該文件。這個(gè)兩步程序顯然容易受到競態(tài)沖突影響,所以并不可靠。NFS 的這一缺陷似乎并沒有讓它變得不受歡迎了,但多年來肯定有很多人在詛咒這一點(diǎn)。這也引出了一些創(chuàng)新,使用其他方法來創(chuàng)建 lock file。

          一種方法是生成一個(gè)在所有客戶端都是唯一的字符串(可能包括主機(jī)名、進(jìn)程 ID 和時(shí)間戳),然后用這個(gè)字符串作為名稱和內(nèi)容來創(chuàng)建一個(gè)臨時(shí)文件。這個(gè)文件需要(hard)link 來創(chuàng)建 lock file 的文件名。如果 hard link 成功了,就說明拿到了鎖。如果失敗了,也就是這個(gè)名字已經(jīng)存在了,那么應(yīng)用程序可以讀取該文件的內(nèi)容。假如文件內(nèi)容與我們剛生成的唯一字符串相匹配,那么這個(gè)錯(cuò)誤就是由于重傳造成的,而且 lock 也已經(jīng)獲取到了。否則的話,應(yīng)用程序就需要休眠并再次嘗試。

          不做狀態(tài)管理的另一個(gè)不幸的后果是,文件在打開之后被 unlink 了。POSIX 對這些 unlink 但仍然保持打開狀態(tài)文件沒有什么意見,并會保證該文件能繼續(xù)正常運(yùn)行,直到它最終被關(guān)閉,此時(shí)該文件就會徹底消失。在 NFS 服務(wù)器看來,因?yàn)樗恢滥男┪募窃谀膫€(gè)客戶端上打開的,就很難做到這么好,所以 NFS 客戶端的實(shí)現(xiàn)并不依賴于服務(wù)器的幫助。而是在進(jìn)行 unlink 處理(刪除文件)時(shí),客戶端會將這個(gè)已經(jīng)打開的文件重命名為一些特殊且唯一的名字,如.nfs-xyzzy,然后在文件最終關(guān)閉時(shí)再刪掉這個(gè)名字。這使得服務(wù)端無需跟蹤客戶端的狀態(tài),但對客戶端來說偶爾會有一些不便。如果一個(gè)應(yīng)用程序打開了某個(gè)目錄中唯一的文件,unlink 該文件,然后試圖刪除該目錄,那么最后一步將會失敗,因?yàn)樵撃夸洿藭r(shí)還不是空目錄,而是包含了一個(gè)帶有特殊的.nfs-XX 名稱的文件,除非客戶端先把這個(gè)特殊文件名的文件移到父目錄中,或者將 RMDIR 也改成一個(gè)重命名操作。在實(shí)踐中,這種操作順序是非常少見的,所以 NFS 客戶端都不打算滿足這個(gè)功能。

          The NFS ecosystem

          當(dāng)我在上面說 NFSv2 不支持 file locking 時(shí),其實(shí)只講了故事的一半。也就是說這個(gè)說法是準(zhǔn)確的,但并不完整。事實(shí)上,NFS 是一套協(xié)議的一部分,所有這些協(xié)議配合在一起使用的時(shí)候,可以提供更完整的服務(wù)。NFS 不支持鎖,但有其他協(xié)議是支持鎖的。可以與 NFS 一起使用的協(xié)議包括:

          • NLM(the Network Lock Manager)。其允許客戶端對一個(gè)給定文件(使用 NFS 文件句柄來標(biāo)明)請求一個(gè) byte-range 的鎖,并允許服務(wù)器授予(或不授予),可以是立即授予,也可以是今后授予。當(dāng)然,這是一個(gè)明確的有狀態(tài)協(xié)議,因?yàn)榭蛻舳撕头?wù)器必須為每個(gè)客戶端維護(hù)相同的 lock 列表。

          • STATMON(the Status Monitor)。當(dāng)一個(gè)節(jié)點(diǎn)–無論是客戶端還是服務(wù)器端–crash 或以其他方式重啟時(shí),之前的所有暫時(shí)狀態(tài),如文件鎖等都會丟失,所以它的對端就需要對此進(jìn)行響應(yīng)。服務(wù)器端將清除掉該客戶端所持有的鎖,而客戶將試圖重新獲得丟失的鎖。在 NLM 中選擇的方法是讓每一端都在可靠的存儲設(shè)備中記錄對端列表,并在重啟時(shí)通知到所有對端;然后他們就可以自己進(jìn)行清理。這項(xiàng)記錄然后通知對等體的任務(wù)就是 STATMON 完成的了。當(dāng)然,如果一個(gè)客戶端在持有一個(gè)鎖的時(shí)候崩潰了,并且沒有重啟,服務(wù)器就永遠(yuǎn)不會知道這個(gè)鎖不再被人所持有了。這有時(shí)就會引入麻煩。

          • MOUNT。當(dāng)掛載一個(gè) NFSv2 文件系統(tǒng)時(shí),你需要知道該文件系統(tǒng) root 位置的文件句柄,而 NFS 沒有辦法提供。這是由 MOUNT 協(xié)議來處理的。該協(xié)議希望服務(wù)器能夠跟蹤記錄哪些客戶已經(jīng) mount 了哪些文件系統(tǒng),因此可以把這些有用的信息報(bào)告出來。然而,由于 MOUNT 并不與 STATMON 交互,客戶端可以重新啟動也就是事實(shí)上 umount 了文件系統(tǒng),并未告訴服務(wù)器端。雖然這種軟件仍在記錄當(dāng)前 active mount 的列表,但沒有人相信它們。

            在后來的版本中,MOUNT 還會處理 security negotiation。服務(wù)器可能需要某種 cryptographic security(如 Kerberos)才能訪問某些文件系統(tǒng),這個(gè)要求會通過 MOUNT 協(xié)議傳達(dá)給客戶端。

          • RQUOTA(remote quotas)。NFS 可以報(bào)告文件和文件系統(tǒng)的各種屬性,但有一個(gè)屬性是未被支持的,那就是 quota。可能是因?yàn)檫@些是用戶的屬性,不是文件的屬性。為了填補(bǔ)這一空白,就出現(xiàn)了 RQUOTA 協(xié)議。

          • NFSACL(POSIX draft ACL)。正如我們有 RQUOTA 來實(shí)現(xiàn) quota 功能,我們也有 NFSACL 來實(shí)現(xiàn)訪問控制列表(access control lists)。這允許檢查 ACL 并進(jìn)行設(shè)置(這一點(diǎn)跟 RQUOTA 不同)。

          除了這些,還有其他一些協(xié)議只是松散地聯(lián)系在一起,比如 "Yellow Pages",也被稱為網(wǎng)絡(luò)信息服務(wù)器(NIS),它可以讓一組機(jī)器能有完全一致的用戶名到 UID 的映射;"rpc.ugid",也可以提供幫助;甚至可能 NTP 也算,它確保了 NFS 客戶端和服務(wù)器對當(dāng)前時(shí)間的判斷是一致的。無論如何,這些都不是 NFS 的真正組成部分,但卻是讓 NFS 如此繁榮的生態(tài)系統(tǒng)的一部分。

          NFSv3 - bigger is better.

          NFSv3 是在大約十年后(1995 年)出現(xiàn)的。這時(shí),工作站的速度更快了(而且色彩更豐富了),磁盤驅(qū)動器也更大。32 位不夠代表文件中的字節(jié)數(shù)、文件系統(tǒng)中的 block 數(shù)或文件系統(tǒng)中的 inode 數(shù)了,而 32 字節(jié)也不再足以代表文件句柄,因此這些 size 都被翻倍了。NFSv3 還獲得了 READDIRPLUS 操作,用來獲取一個(gè)目錄中的所有 name 和文件屬性,這樣可以更有效地實(shí)現(xiàn) ls -l。請注意,決定何時(shí)使用 READDIRPLUS 和何時(shí)使用更簡單的 READDIR,并不是一件容易的事情。在 2022 年,Linux NFS 客戶端仍然在采用啟發(fā)式方法來進(jìn)行改進(jìn)。

          有兩個(gè)改動是專門跟 state 管理有關(guān)的,其中之一是解決上面討論的 exclusive-create 的問題,另一個(gè)是幫助維護(hù)客戶端數(shù)據(jù)的 cache。其中第一個(gè)對 CREATE 操作進(jìn)行了擴(kuò)展。

          在 NFSv3 中,一個(gè) CREATE 請求可以指定該請求是 UNCHECKED、GUARDED 還是 EXCLUSIVE 的。其中第一個(gè)是無論文件是否存在都會讓操作成功。但是如果文件存在的話,第二種方式必須要失敗,但它就像 MKDIR 一樣,可能會因?yàn)橹貍鞫鴮?dǎo)致出現(xiàn)不應(yīng)該出現(xiàn)的錯(cuò)誤,所以它不是特別有用。EXCLUSIVE 則更有用一些。

          EXCLUSIVE 這個(gè)創(chuàng)建請求會帶有 8 個(gè)字節(jié)的每個(gè)客戶端各不相同的標(biāo)識(這是我們反復(fù)用到的方式),稱為 "verifier"。RFC(RFC 1813)中建議說,"也許" 這個(gè) verifier 可以包含客戶的 IP 地址或其他一些獨(dú)特的數(shù)據(jù)。Linux NFS 客戶端使用了 jiffies 這個(gè) internal timer 的四個(gè)字節(jié)以及發(fā)出請求的進(jìn)程的 PID 的四個(gè)字節(jié)。服務(wù)器端需要在創(chuàng)建文件時(shí)將這個(gè) verifier 采用原子操作方式存儲到可靠的存儲位置。如果服務(wù)器后來被要求再創(chuàng)建一個(gè)已經(jīng)存在的文件,那么必須要對比存儲中的客戶端標(biāo)識符和請求中的標(biāo)識符,在匹配的情況下,服務(wù)器必須報(bào)告說 exclusive create 成功了,也就是判定這是之前請求的一次重復(fù)發(fā)起。

          Linux NFS 服務(wù)器在其創(chuàng)建的文件的 mtime 和 atime 字段中會存儲這個(gè) verifier。NFSv3 協(xié)議承認(rèn)這種可能性,并要求一旦客戶端收到表示成功創(chuàng)建的回復(fù),就必須發(fā)出 SETATTR 請求,從而讓服務(wù)器這邊可以把存儲了 verifier 的這些文件屬性改成正確的值。這個(gè) SETATTR 步驟向服務(wù)器確認(rèn)了一些非冪等的請求已經(jīng)完成了,這樣就應(yīng)該可能對 DRC 實(shí)現(xiàn)有幫助了。

          Client-side caching and close-to-open cache consistency

          NFSv2 RFC 并沒有描述客戶端緩存,但這并不意味著實(shí)現(xiàn)方案里面也沒有做任何緩存。他們必須要非常小心。只有當(dāng)有充分的理由認(rèn)為數(shù)據(jù)在服務(wù)器上沒有變化時(shí),cache 數(shù)據(jù)才是安全的。NFS 的實(shí)現(xiàn)方案里給客戶端提供了兩種方法,用來讓其相信 cache 的數(shù)據(jù)是可以安全使用的。

          NFS 服務(wù)器可以把一個(gè)文件的各種屬性報(bào)告上來,尤其是 size 和最后更改時(shí)間。如果這些值跟以前的一樣,那么基本可以判定文件內(nèi)容沒有改變。NFSv2 允許將更改的時(shí)間戳按微秒為單位來上報(bào),但這并不意味著服務(wù)端也可以保持這種精度水平。甚至在 NFSv2 首次使用起來的二十年后,還有一些很重要的 Linux 文件系統(tǒng)只能按秒為精度單位來提供時(shí)間戳。因此,如果一個(gè) NFS 客戶端看到一個(gè)至少過去一秒鐘的時(shí)間戳,然后讀取數(shù)據(jù),它就可以判定這些緩存數(shù)據(jù)是安全的,這樣一直到它看到時(shí)間戳變化為止。如果它看到的時(shí)間戳是在 "當(dāng)前時(shí)間" 的一秒鐘之內(nèi),那么就不太好確定是否安全了。

          NFSv3 引入了 FSINFO 請求,可以供服務(wù)器上報(bào)各種限制和設(shè)置信息,并包括了一個(gè) "time_delta",這是假設(shè)文件修改時(shí)間以及其他時(shí)間戳中的時(shí)間精度應(yīng)該到什么水平。這樣客戶端的 cache 維護(hù)就可以更精確一些。

          如上所述,在看到文件的屬性發(fā)生變化之前,可以安全地使用文件的緩存數(shù)據(jù)。客戶端可能實(shí)現(xiàn)成不再查看文件的屬性,因此就永遠(yuǎn)看不到文件變動了,但這是不允許的。確認(rèn)數(shù)據(jù)安全的話,需要客戶端進(jìn)行屬性檢查的時(shí)機(jī)方面遵守兩條規(guī)則:

          第一條規(guī)則很簡單:就是偶爾檢查一下。協(xié)議中沒有規(guī)定最小或最大的 timeout 時(shí)間,但大多數(shù)實(shí)現(xiàn)中都允許配置這些 timeout 值。Linux 默認(rèn)的是三秒鐘的超時(shí),只要沒有任何變動的話,超時(shí)時(shí)間就會成倍地增長,最長會增加到一分鐘。這意味著客戶端可以從緩存中提供最多 60 秒的數(shù)據(jù),但不會更長了。第二條規(guī)則是建立在一個(gè)假設(shè)上,也就是多個(gè)應(yīng)用程序永遠(yuǎn)不會同時(shí)打開同一個(gè)文件,除非它們使用了 locking 鎖定或者都是只讀訪問。

          在客戶端打開一個(gè)文件時(shí),它必須驗(yàn)證緩存中的數(shù)據(jù)(通過檢查時(shí)間戳來判斷),并丟棄那些它不能確定的數(shù)據(jù)。只要文件保持 open 狀態(tài),客戶端就可以認(rèn)為服務(wù)器上不會再發(fā)生變動了(除了它自己要求變動之外)。當(dāng)它關(guān)閉文件時(shí),客戶端必須在關(guān)閉完成前將所有的變動傳遞到服務(wù)器上。如果每個(gè)客戶端都這樣做,那么任何一個(gè)打開文件的應(yīng)用程序都會看到其他應(yīng)用程序在這次打開之前其他客戶端對文件進(jìn)行 close 操作時(shí)完成的所有修改了,所以這種模式有時(shí)被稱為 "close-to-open consistency"。

          當(dāng)使用 byte-range locking 的時(shí)候,也可以使用類似的基本模型,但 open 操作變成了客戶端被授予鎖的時(shí)刻,而 close 則是它釋放鎖的時(shí)刻。在被授予鎖之后,客戶端必須重新驗(yàn)證或清除鎖范圍內(nèi)的任何已經(jīng)緩存的數(shù)據(jù),在釋放鎖之前,它必須將這個(gè)區(qū)域的緩存變化傳遞合并到服務(wù)器上。

          由于上面說的都是依靠修改時(shí)間點(diǎn)來驗(yàn)證 cache 的,而這個(gè)時(shí)間戳在任何客戶端寫入文件時(shí)都會更新,因此邏輯上的含義是,當(dāng)客戶端寫入文件時(shí),它必須清除自己的 cache,因?yàn)闀r(shí)間戳已經(jīng)改變了。在文件關(guān)閉(或這個(gè)區(qū)域被解鎖)之前都是可以繼續(xù)使用緩存的,但不能超過這個(gè)時(shí)間段。在使用 byte-range 鎖時(shí),這種需求尤其明顯。一個(gè)客戶可能會 lock 一個(gè)區(qū)域,進(jìn)行寫入,然后再 unlock。另一個(gè)客戶端可能會 lock、寫入和 unlock 另一個(gè)不同的區(qū)域,而寫入請求正好發(fā)生在同一時(shí)間。任何一個(gè)客戶端都不可能知道另一個(gè)客戶端是否寫了這個(gè)文件,因?yàn)闀r(shí)間戳是涵蓋整個(gè)文件而不僅僅是一個(gè)范圍的。所以他們都必須在下次打開或 lock 文件之前清除他們的相應(yīng) cache。

          至少,在 NFSv3 中引入 weak cache consistencies(wcc)屬性之前是沒有辦法判斷的。在 NFSv3 WRITE 請求的回復(fù)中,在寫請求之前和之后允許服務(wù)端上報(bào)一些屬性(如 size 和時(shí)間戳),并且要求,如果它確實(shí)報(bào)告了這些屬性,那么在這兩組屬性之間是沒有發(fā)生其他 write 操作的。客戶端可以使用這些信息來檢測時(shí)間戳的變化是純粹是由于它自己的寫入導(dǎo)致的,還是由于其他客戶端的寫入導(dǎo)致的。因此,它可以確定它是否是唯一一個(gè)向文件寫入的客戶端(這是最常見的情況),并且在這種情況下,哪怕時(shí)間戳在變化了,也可以保留其 cache。在對 SETATTR 和修改目錄的請求(如 CREATE 或 REMOVE)的回復(fù)中也是可以使用 Wcc 屬性的,所以客戶端也可以判斷它是否是一個(gè)目錄中唯一進(jìn)行操作的一方,并相應(yīng)地管理它的緩存。

          這被稱為 "weak" cache consistency,因?yàn)樗匀恍枰蛻舳伺紶杹頇z查時(shí)間戳。強(qiáng)緩存一致性則要求服務(wù)器明確地告訴客戶端這里即將發(fā)生改動,不過要等到 NFS 的后面的版本才會帶有這個(gè)支持了。盡管是 weak 方式的,但它仍然是一個(gè)明顯的進(jìn)步,可以允許客戶端保持對服務(wù)器狀態(tài)的了解,因此是對無狀態(tài)協(xié)議這個(gè)說法的又一個(gè)打擊。

          順便說一句,Linux NFS 服務(wù)端并沒有在對文件進(jìn)行 write 時(shí)提供這些 wcc 屬性。要做到這一點(diǎn)的話,它需要在收集文件屬性以及進(jìn)行寫入時(shí)必須持有文件鎖。從 Linux 2.3.7 開始,底層文件系統(tǒng)負(fù)責(zé)在寫入過程中加鎖,所以 nfsd 不能以原子操作方式來提供這些屬性。不過,Linux NFS 確實(shí)為目錄內(nèi)的修改提供了 wcc 屬性。

          NFS - the next generation

          這些早期版本的 NFS,都是在 Sun Microsystems 內(nèi)部開發(fā)的。這些代碼可供其他 Unix 廠商在他們的產(chǎn)品中使用,雖然這些廠商能夠根據(jù)需要來調(diào)整實(shí)現(xiàn),但他們不能改變協(xié)議,畢竟那是由 Sun 公司控制的。

          隨著新千年的到來,人們對 NFS 的興趣不斷增加,就出現(xiàn)了獨(dú)立的第三方的實(shí)現(xiàn)。這導(dǎo)致了更多的開發(fā)者對如何改進(jìn) NFS 提出了意見,還是非常了解細(xì)節(jié)并且深思熟慮過的意見。為了滿足這些開發(fā)者,同時(shí)又不至于引出分裂的危機(jī),就需要一個(gè)機(jī)制可以用來聽取和回答這些意見。這個(gè)機(jī)制的性質(zhì),以及在 NFS 協(xié)議的后續(xù)版本中出現(xiàn)的改動,將是我們后續(xù)需要講述的主題。

          全文完
          LWN 文章遵循 CC BY-SA 4.0 許可協(xié)議。

          歡迎分享、轉(zhuǎn)載及基于現(xiàn)有協(xié)議再創(chuàng)作~

          長按下面二維碼關(guān)注,關(guān)注 LWN 深度文章以及開源社區(qū)的各種新近言論~



          瀏覽 40
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  2020天天日天天操 | 中国婬乱a一级毛片多女 | www.五月婷婷 | 天天撸在线 | 亚洲成人人体艺术在线观看 |