1. 程式人生 > >jffs2檔案系統刪除檔案不釋放空間

jffs2檔案系統刪除檔案不釋放空間

本文記錄了jffs2檔案系統釋放空間失敗問題的解決,以及追蹤過程。

最近在除錯時發現對jffs2檔案系統下的檔案執行刪除動作時,不釋放空間。

翻閱了jffs2的講解http://www.ibm.com/developerworks/cn/linux/l-jffs2/index.html#,還是沒有找到答案,只是隱約覺得這跟其垃圾回收有關係。

理論上行不通,只能通過實際的對比來找尋答案,比對可以正常釋放空間的另一jffs2檔案系統發現,這跟rm時,其所呼叫的jffs2_do_unlink路徑分支有關

if (!jffs2_can_mark_obsolete(c)) {//可以正常釋放
/* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */
......
} else {//不能正常釋放
......
}

通過修改判斷條件jffs2_can_mark_obsolete解決。

jffs2_can_mark_obsolete定義由CONFIG_JFFS2_FS_WRITEBUFFER和CONFIG_JFFS2_SUMMARY兩個巨集來決定。

後又在http://lists.infradead.org/pipermail/linux-mtd/2007-August/019223.html上面找到了解釋,這算是jffs2的bug,其說明如下:

I post the same mail as Re: jffs2 kernel dump with 2.6.22-rc7 because 
the problem may be the same...

In jffs2_do_unlink() in fs/jffs2/write.c
the jffs2_complete_reservation(c) is called even if 
jffs2_reserve_space() is not called. This cause an unmatched 
up(&c->alloc_sem) so the locking mechanism does not work.
People using MTD_CAP_NORFLASH flash _and_ CONFIG_JFFS2_SUMMARY do not 
see the problem (see  os-linux.h for the definition of 
jffs2_can_mark_obsolete(c)).

Regards.

     Giulio Fedel


--- fs/jffs2/write.c.orig       2007-08-17 19:01:04.000000000 +0200
+++ fs/jffs2/write.c    2007-08-17 19:00:41.000000000 +0200
@@ -549,6 +549,7 @@ int jffs2_do_unlink(struct jffs2_sb_info
                 /* File it. This will mark the old one obsolete. */
                 jffs2_add_fd_to_list(c, fd, &dir_f->dents);
                 up(&dir_f->sem);
+               jffs2_complete_reservation(c);
         } else {
                 struct jffs2_full_dirent **prev = &dir_f->dents;
                 uint32_t nhash = full_name_hash(name, namelen);
@@ -605,7 +606,6 @@ int jffs2_do_unlink(struct jffs2_sb_info
                 up(&dead_f->sem);
         }

-       jffs2_complete_reservation(c);

         return 0;
  }
大意是jffs2_complete_reservation在jffs2_reserve_space沒有被呼叫的情況下執行,會導致c->alloc_sem的不匹配,進而lock機制不生效。而使用MTD_CAP_NORFLASH型別的flash和開啟CONFIG_JFFS2_SUMMARY巨集的情況不會遇到這個問題,跟前面所述以巨集控制jffs2_do_unlink是一個意思。