Linux

塊設備記憶體與文件系統

  • May 4, 2019

塊設備提供緩衝。這意味著write()在核心將數據寫入設備之前,塊設備上可以返回成功。程序可以通過呼叫來等待所有緩衝的寫入fsync()

我已經使用dd(或cat)將文件系統映像寫入設備。這些命令預設不呼叫fsync()

接下來,假設我要將mount寫入的塊設備作為文件系統。

我認為sync在安裝它之前使用該命令是最安全的。但是如果我不同步塊設備怎麼辦?文件系統是否有可能嘗試讀取一些尚未寫入設備的塊?那麼它可以讀取設備的舊內容,而不是文件系統映像中的正確數據嗎?

我的主要興趣是 Linux 行為。(而且 StackExchange 鼓勵我提出一個具體問題。不過,我也可以對任何替代或歷史行為表示贊同 :-)。

當程序關閉塊設備文件時,Linux 會刷新相關的記憶體,迫使程序等待。然而,這只適用於最後一個close()。如果其他東西仍然打開塊設備,則不會發生這種情況。包括同一塊設備的任何分區是否仍然打開。

所以在一般情況下,最好以某種方式同步設備。

為了安全起見,您應該同步設備的方式是dd使用選項執行您的命令conv=fsync。沒有這個,核心將不會返回寫入錯誤。dmesg因此,如果您查看核心日誌 ( ) ,您只會注意到一個錯誤。

除了等待所有記憶體的寫入之外,最後一個close()還丟棄所有記憶體 ( kill_bdev())。通過查看命令的輸出,我已經為自己驗證了這一點free

linux-4.20/fs/block_dev.c:1778

static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
{
   struct gendisk *disk = bdev->bd_disk;
   struct block_device *victim = NULL;

   mutex_lock_nested(&bdev->bd_mutex, for_part);
   if (for_part)
       bdev->bd_part_count--;

   if (!--bdev->bd_openers) {
       WARN_ON_ONCE(bdev->bd_holders);
       sync_blockdev(bdev);
       kill_bdev(bdev);

如果您不熟悉 C 程式碼,上面的最後一個塊相當於:

   bdev->bd_openers = bdev->bd_openers - 1;
   if (bdev->bd_openers == 0) {
       WARN_ON_ONCE(bdev->bd_holders);
       sync_blockdev(bdev);
       kill_bdev(bdev);

引用自:https://unix.stackexchange.com/questions/473854