轉:nfs-ganesha cache lru問題

項目中在使用ganesha2.3.3版本中,遇到一個棘手的問題。
    我們是自己實現的一個分佈式文件系統,對接的ganesha-nfs的2.3.3的接口。有一個應用場景是將目錄通過nfs掛載給vmware,以建立虛擬機使用。最近在測試強壓力測試(vdbench做着壓力測試,還開着虛擬機)中,出現了虛擬機開啓時報文件不存在的錯誤,再次開啓就好了。
    首先是開啓調試日誌,預感這種問題應該是在強壓力測試下才可能出現的, 讓測試想辦法再復現。剛開始以爲我們文件系統的cache存在問題,進行了一下簡單的cache代碼排查,暫時沒有發現問題。
     終於過了兩天測試告訴我們復現了,謝天謝地,興奮的跑去查日誌,查找找不到目錄的所有條目,發現一條重要的線索,有一條lookup記錄居然通過vdbench中的目錄作爲父目錄,去查找掛載給vmware的文件夾中的目錄(名字取得騷氣,很容易看出來),我說你們兩個一點血緣關係都沒有,去找什麼,難道想處對象嗎?直覺告訴我,可能真的與cache相關,但是不會是我們的cache,而是ganesha中的cache,可惜之前懶,加之工作量大,人手不足,沒有仔細看ganesha-nfs的inode cache的代碼,不知道爲什麼會發生這樣的事情,只有拿出殺手鐗,抓包,通過抓包找到這樣發送的原因,在針對性的看代碼。
    手動復現抓包真的是一個不可取的工程,而且鬼知道下一次復現是什麼時候,包又不能一直在抓着,太大。讓測試寫了個自動化測試的腳本,給虛擬機開機時,調用抓包,開機成功,重新抓包。開機失敗,保存當次抓包的數據。
     漫長等待自動化測試跑了兩三天,果然又復現了,這一次還不逮着你。使用最原始但是最有效的方法,將開機成功的包,和開機失敗的包一行一行的對比,眼睛都快看瞎了的情況下,終於發現了問題,萬惡的lookup.., 在開機時,一次vmware文件夾中的目錄在進行lookup .., 居然返回了vdbench中一個目錄的句柄,然後客戶端傻傻的用這個句柄去查找這個目錄,當然是找不到。而在我們的調試日誌裏,沒有出現這一次的lookup..的記錄,說明是在ganesha的cache中查到就返回了,我去,果然和我猜的一樣,只能去啃2.3.3的代碼了,因爲最新的ganesha重構了inode cache,代碼結構不一樣了。
    使用了各種方法,加各種調試日誌,使用valgrind查看是否被別人踩錯內存,意外的發現裏面的cache_entry_t條目的dir.parent沒有進行過釋放,按理說沒有釋放最多內存泄漏,也不會出現類似這個問題。但是仔細看了代碼後發現,cache條目在lru滿了的情況下,會回收重複利用,而新malloc的cache條目由於是使用的calloc,默認初始話爲0,回收的時候,沒有釋放parent條目,也就沒有重新初始化爲其他的值,在調用cache_inode_new_entry就已經加入到全局的avl樹中了,之後纔對dir.parent字段進行賦值,在多線程高壓的環境下,lookup .. 的時候就可能利用這個時間差,找到了一個回收的cache對應的parent,導致出現了這個問題。
    我讓測試將配置文件中的lru的閾值改小進行測試,這個問題果然很快就復現了,哈哈,天助我也,我就在回收的時候將parent釋放,並且初始化爲NULL,這樣應該就不存在這個問題了。合入代碼之後,在lru改小的情況下已經跑了三四天了,果然沒有出現此問題。如果沒有vmware頻繁的調用lookup..這個問題估計很難被發現。
    其實在最新的ganesha中,重構之後的mdcache,這個內存泄漏的問題已經不存在了,和ganesha的開發者交流了一下,建議我們使用最新的穩定版的ganesha,因爲之前的版本可能還存在這樣那樣的問題,我們也要考慮換成2.5穩定版的ganesha了,不過這一次調試也是一個學習的過程。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章