NILFS2

NILFS2 是一個支援連續快照的日誌結構檔案系統 (LFS)。除了整個檔案系統的版本控制功能外,使用者甚至可以恢復幾秒鐘前錯誤覆蓋或破壞的檔案。由於 NILFS2 可以像傳統的 LFS 一樣保持一致性,因此它可以在系統崩潰後快速恢復。

NILFS2 每隔幾秒或基於同步寫入建立大量檢查點(除非沒有更改)。使用者可以選擇連續建立的檢查點中的重要版本,並可以將它們更改為快照,這些快照將被保留直到它們被改回檢查點。

在卷變滿之前,快照的數量沒有限制。每個快照都可以與其可寫掛載同時掛載為只讀檔案系統,此功能方便線上備份。

使用者空間工具包含在 nilfs-utils 包中,可從以下下載頁面獲得。至少需要 “mkfs.nilfs2”、“mount.nilfs2”、“umount.nilfs2” 和 “nilfs_cleanerd”(所謂的 cleaner 或垃圾收集器)。工具的詳細資訊在軟體包中包含的 man 頁面中描述。

專案網頁:

https://nilfs.sourceforge.io/

下載頁面:

https://nilfs.sourceforge.io/en/download.html

列表資訊:

http://vger.kernel.org/vger-lists.html#linux-nilfs

注意事項

NILFS2 尚未支援的功能

  • atime

  • 擴充套件屬性

  • POSIX ACL

  • 配額

  • fsck

  • 碎片整理

掛載選項

NILFS2 支援以下掛載選項: (*) == 預設

barrier(*)

啟用/停用寫屏障的使用。這

nobarrier

需要一個可以支援屏障的 IO 堆疊,如果 nilfs 在屏障寫入時發生錯誤,它將再次停用併發出警告。

errors=continue

在檔案系統錯誤時繼續執行。

errors=remount-ro(*)

在發生錯誤時以只讀方式重新掛載檔案系統。

errors=panic

如果發生錯誤,則停止並停止機器。

cp=n

指定要掛載的快照的檢查點編號。檢查點和快照由 lscp 使用者命令列出。只有標記為快照的檢查點才可以使用此選項掛載。快照是隻讀的,因此必須一起指定只讀掛載選項。

order=relaxed(*)

應用寬鬆的順序語義,允許將修改後的資料塊寫入磁碟而無需建立檢查點,前提是沒有元資料更新。此模式等效於 ext3 檔案系統的有序資料模式,除了資料塊的更新仍然保留原子性。這將提高覆蓋的同步寫入效能。

order=strict

應用嚴格的按順序語義,保留所有檔案操作的序列,包括覆蓋資料塊。這意味著,保證在崩潰後恢復的檔案系統中不會發生事件超車。

norecovery

在掛載時停用檔案系統的恢復。這會停用只讀掛載或快照上裝置的每次寫入訪問。此選項對於不乾淨捲上的 r/w 掛載將失敗。

discard

啟用/停用 discard/TRIM 命令的使用。

nodiscard(*)

當塊被釋放時,discard/TRIM 命令被髮送到下層塊裝置。這對於 SSD 裝置和稀疏/精簡配置的 LUN 很有用。

Ioctls

有一些 NILFS2 特定的功能可以透過系統呼叫介面由應用程式訪問。下表顯示了所有 NILFS2 特定的 ioctl 的列表。

NILFS2 特定的 ioctl 表

Ioctl

描述

NILFS_IOCTL_CHANGE_CPMODE

在檢查點和快照狀態之間更改給定檢查點的模式。此 ioctl 用於 chcp 和 mkcp 實用程式中。

NILFS_IOCTL_DELETE_CHECKPOINT

從 NILFS2 檔案系統中刪除檢查點。此 ioctl 用於 rmcp 實用程式中。

NILFS_IOCTL_GET_CPINFO

返回有關請求的檢查點的資訊。此 ioctl 由 lscp 實用程式和 nilfs_cleanerd 守護程式使用。

NILFS_IOCTL_GET_CPSTAT

返回檢查點統計資訊。此 ioctl 由 lscp、rmcp 實用程式和 nilfs_cleanerd 守護程式使用。

NILFS_IOCTL_GET_SUINFO

返回有關請求的段的段使用資訊。此 ioctl 用於 lssu、nilfs_resize 實用程式和 nilfs_cleanerd 守護程式。

NILFS_IOCTL_SET_SUINFO

修改請求的段的段使用資訊。此 ioctl 由 nilfs_cleanerd 守護程式用於跳過段的不必要的清理操作,並減少由於冗餘移動使用中的塊而導致的效能損失或快閃記憶體裝置的磨損。

NILFS_IOCTL_GET_SUSTAT

返回段使用統計資訊。此 ioctl 用於 lssu、nilfs_resize 實用程式和 nilfs_cleanerd 守護程式。

NILFS_IOCTL_GET_VINFO

返回有關虛擬塊地址的資訊。此 ioctl 由 nilfs_cleanerd 守護程式使用。

NILFS_IOCTL_GET_BDESCS

返回有關磁碟塊號的描述符的資訊。此 ioctl 由 nilfs_cleanerd 守護程式使用。

NILFS_IOCTL_CLEAN_SEGMENTS

在來自使用者空間的要求引數的環境中執行垃圾收集操作。此 ioctl 由 nilfs_cleanerd 守護程式使用。

NILFS_IOCTL_SYNC

建立一個檢查點。此 ioctl 用於 mkcp 實用程式中。

NILFS_IOCTL_RESIZE

調整 NILFS2 卷的大小。此 ioctl 由 nilfs_resize 實用程式使用。

NILFS_IOCTL_SET_ALLOC_RANGE

定義段的下限(以位元組為單位)和段的上限(以位元組為單位)。此 ioctl 由 nilfs_resize 實用程式使用。

NILFS2 用法

要將 nilfs2 用作本地檔案系統,只需

# mkfs -t nilfs2 /dev/block_device
# mount -t nilfs2 /dev/block_device /dir

這也會透過掛載助手程式 (mount.nilfs2) 呼叫 cleaner。

檢查點和快照由以下命令管理。它們的 man 頁面包含在上面的 nilfs-utils 包中。

lscp

列出檢查點或快照。

mkcp

建立檢查點或快照。

chcp

將現有檢查點更改為快照,反之亦然。

rmcp

使指定的檢查點無效。

要掛載快照

# mount -t nilfs2 -r -o cp=<cno> /dev/block_device /snap_dir

其中 <cno> 是快照的檢查點編號。

要解除安裝 NILFS2 掛載點或快照,只需

# umount /dir

然後,cleaner 守護程式將由 umount 助手程式 (umount.nilfs2) 自動關閉。

磁碟格式

nilfs2 卷被平均分成多個段,除了超級塊 (SB) 和段 #0。段是日誌的容器。每個日誌由摘要資訊塊、有效負載塊和一個可選的超級根塊 (SR) 組成。

 ______________________________________________________
| |SB| | Segment | Segment | Segment | ... | Segment | |
|_|__|_|____0____|____1____|____2____|_____|____N____|_|
0 +1K +4K       +8M       +16M      +24M  +(8MB x N)
     .             .            (Typical offsets for 4KB-block)
  .                  .
.______________________.
| log | log |... | log |
|__1__|__2__|____|__m__|
      .       .
    .               .
  .                       .
.______________________________.
| Summary | Payload blocks  |SR|
|_blocks__|_________________|__|

有效負載塊按檔案組織,每個檔案由資料塊和 B 樹節點塊組成

 |<---       File-A        --->|<---       File-B        --->|
_______________________________________________________________
 | Data blocks | B-tree blocks | Data blocks | B-tree blocks | ...
_|_____________|_______________|_____________|_______________|_

由於只有修改後的塊被寫入日誌,因此它可能具有沒有資料塊或 B 樹節點塊的檔案。

塊的組織記錄在摘要資訊塊中,其中包含一個標頭結構 (nilfs_segment_summary)、每個檔案的結構 (nilfs_finfo) 和每個塊的結構 (nilfs_binfo)

 _________________________________________________________________________
| Summary | finfo | binfo | ... | binfo | finfo | binfo | ... | binfo |...
|_blocks__|___A___|_(A,1)_|_____|(A,Na)_|___B___|_(B,1)_|_____|(B,Nb)_|___

日誌包括常規檔案、目錄檔案、符號連結檔案和幾個元資料檔案。元資料檔案是用於維護檔案系統元資料的檔案。當前版本的 NILFS2 使用以下元資料檔案

1) Inode file (ifile)             -- Stores on-disk inodes
2) Checkpoint file (cpfile)       -- Stores checkpoints
3) Segment usage file (sufile)    -- Stores allocation state of segments
4) Data address translation file  -- Maps virtual block numbers to usual
   (DAT)                             block numbers.  This file serves to
                                     make on-disk blocks relocatable.

下圖顯示了日誌的典型組織結構

 _________________________________________________________________________
| Summary | regular file | file  | ... | ifile | cpfile | sufile | DAT |SR|
|_blocks__|_or_directory_|_______|_____|_______|________|________|_____|__|

要跨越段邊界,此檔案序列可能會拆分為多個日誌。應被視為邏輯上一個日誌的日誌序列,使用段摘要中標記的標誌進行分隔。nilfs2 的恢復程式碼會查詢此邊界資訊,以確保更新的原子性。

超級根塊為每個檢查點插入。它包括三個特殊的 inode,即 DAT、cpfile 和 sufile 的 inode。常規檔案、目錄、符號連結和其他特殊檔案的 inode 包含在 ifile 中。ifile 本身的 inode 包含在 cpfile 中相應的檢查點條目中。因此,NILFS2 檔案之間的層次結構可以描述如下

Super block (SB)
     |
     v
Super root block (the latest cno=xx)
     |-- DAT
     |-- sufile
     `-- cpfile
            |-- ifile (cno=c1)
            |-- ifile (cno=c2) ---- file (ino=i1)
            :        :          |-- file (ino=i2)
            `-- ifile (cno=xx)  |-- file (ino=i3)
                                :        :
                                `-- file (ino=yy)
                                  ( regular file, directory, or symlink )

有關每個檔案的格式的詳細資訊,請參閱位於 include/uapi/linux 目錄中的 nilfs2_ondisk.h。

我們不保護有關 NILFS2 設計的任何專利或其他智慧財產權。允許複製該設計,希望其他作業系統可以共享(掛載、讀取、寫入等)以這種格式儲存的資料。