最近嘗試使用 rclone mount 直接將 Google Drive 掛載到本機資料夾,試圖存放 git repo。

嘗試期間遇到各種各樣的問題和 bug,簡單記錄一下解法。

getcwd

執行 git 相關指令時偶爾會出現 “fatal: Unable to read current working directory: No such file or directory”,且當 shell 停留在資料夾超過 –attr-timeout=1m 時,Konsole 的標題會顯示成 “dir (deleted)“。

透過 strace 追蹤 git 發現 getcwd(2) 會回傳 ENOENT 錯誤。

Google 後發現 libfuse 的這個 bug:《”pwd”, inodes, and readdir》,說是要加上 readdir_inouse_ino 選項才可避免這個問題。

然而不管是加到 -o 或是 --fuse-flag 都沒有用,查了一下原始碼才發現這些選項只能用在 cmount 而不能用在 mount 指令。因為 mount 指令底層用的是以 Go 實作的 fuse,而 cmount 才是透過 cgo 利用 libfuse。

然而官方為 Linux amd64 提供的預編譯可執行檔並沒有開啟 cgo ,所以沒有 cmount 指令。在官方論壇詢問後,作者提供了一個測試版的連結:https://beta.rclone.org/test/testbuilds-latest/ ,可下載有開啟 cgo 的版本,但似乎只有 minor 版,而沒有 patch 版本 (https://beta.rclone.org/v*X.Y.0*/testbuilds/)。

然而,即使使用了 cmount -o readdir_ino,掛載遠端資料夾作為 git repo 還是不夠穩定,即便再加上 rclone 的 cache remote (beta),依然如此。(我看論壇上關於 mount 的相關討論,可以成功拿來當媒體存儲用,看來純粹讀取沒有太大問題;但作為工作目錄,需要不時寫入,卻時常出現各種 OSError。)

自己刻一層 fuse(放棄)

因為之前用過 fuse,所以想說可以刻一個 in-memory 的簡單檔案系統用來追蹤檔案的增刪查改,但刻到一半發現需要處理刪除檔案及 persistency/serialization(以支援重新掛載)等等問題,後來就想到有另一個現成的東西可以直接利用:OverlayFS。

OverlayFS

OverlayFS 在 Linux v3.18 之後就有,它將檔案系統分成 lowerdir、upperdir(還有工作區 workdir 和掛載點)。

針對刪除檔案,它直接在 upperdir 的對應路徑建立一個裝置號碼為 0 的字元裝置,以標記該檔案從 lowerdir 被刪除;針對刪除資料夾,則在 upperdir 的對應路徑設定延伸屬性 (xattr),用來標記該資料夾已被刪除。

如此,由於 upperdir 本身是在一般檔案系統上,所以不需要額外的 serialization 機制去保存當前狀態,直接卸載/掛載即可。

至於 persistency, kmxz/overlayfs-tools 可以產生對應的 shell script,用來將 upperdir 的標記或資料更新回 lowerdir。

總結