1. 程式人生 > >MIT6.828 HW11: crash

MIT6.828 HW11: crash

  在這次作業中,我們將探索xv6的log功能。主要就是建立1個crash,然後觀察recover的過程。
  xv6的log重點是將檔案系統所有的磁碟更新操作原子化,比如在建立1個檔案時涉及到在目錄中新增新入口,並標記新檔案的inode為使用中。如果沒有log的話,在兩次操作之間傳送1個crash會導致重啟後文件系統處於不正確狀態。
  第1步修改log.c如下:

#include "mmu.h"
#include "proc.h"
void
commit(void)
{
  if (log.lh.n > 0) {
    write_log()
    write_head();
    if
(proc->pid > 1) // AAA log.lh.block[0] = 0; // BBB install_trans(); if(proc->pid > 1) // AAA panic("commit mimicking crash"); // CCC log.lh.n = 0; write_head(); } }

  在建立檔案時log的第1個扇區應該存的是修改後的inode號(即type不為0,否則會標示這個塊未分配),而BBB行導致log的第1個扇區寫到磁碟上的扇區0。CCC行迫使發生1次crash。AAA行保證init程序不會做這一愚蠢的操作,因為它要為shell建立檔案。
  第2步修改recover_from_log函式如下:

static void
recover_from_log(void)
{
  read_head();      
  cprintf("recovery: n=%d but ignoring\n", log.lh.n);
  // install_trans();
  log.lh.n = 0;
  // write_head();
}

  這裡的修改會阻止log的recovery。
  然後進行測試,執行xv6,並在shell裡建立1個檔案,將傳送panic:
這裡寫圖片描述
  重新執行xc6,檢視檔案的內容,也會發生panic:
這裡寫圖片描述
  原因是檔案的修改後的inode,並被寫入磁碟log,但是在commit時並沒有被寫入原來inode對應的塊,內容被也如對應的塊,並且重啟時沒有修復。
  恢復recover_from_log函式,將會看到檔案,但是內容為空:
  這裡寫圖片描述


  由於沒有仔細研究xv6檔案系統的原始碼,不是很清楚這一步的原因。原先認為在commit時修改了記憶體中log_head的內容(使log的第1個扇區指向扇區0),導致磁碟上的log_head與記憶體中的不一致,但是內容應該被寫入對應的塊,系統在重啟時檢查到log中有完整的事務,則進行恢復,檔案修改後的inode被寫入對應的塊,會再一次將內容寫入對應的塊(該塊已經被佔用??),應該會有內容的。。。。
  要解決的問題是在在commit期間將快取中修改的塊寫入log,在之後從log中讀取到快取,再寫入對應的塊,這中間其實快取是沒變化的,所以可以取消讀log的步驟,直接將快取寫入對應的塊即可。