瀏覽代碼

f2fs: avoid race for summary information

In order to do GC more reliably, I'd like to lock the vicitm summary page
until its GC is completed, and also prevent any checkpoint process.

Reviewed-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Jaegeuk Kim 12 年之前
父節點
當前提交
b74737541c
共有 3 個文件被更改,包括 7 次插入10 次删除
  1. 1 7
      fs/f2fs/gc.c
  2. 1 1
      fs/f2fs/node.c
  3. 5 2
      fs/f2fs/super.c

+ 1 - 7
fs/f2fs/gc.c

@@ -642,12 +642,6 @@ static void do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
 	if (IS_ERR(sum_page))
 	if (IS_ERR(sum_page))
 		return;
 		return;
 
 
-	/*
-	 * CP needs to lock sum_page. In this time, we don't need
-	 * to lock this page, because this summary page is not gone anywhere.
-	 * Also, this page is not gonna be updated before GC is done.
-	 */
-	unlock_page(sum_page);
 	sum = page_address(sum_page);
 	sum = page_address(sum_page);
 
 
 	switch (GET_SUM_TYPE((&sum->footer))) {
 	switch (GET_SUM_TYPE((&sum->footer))) {
@@ -661,7 +655,7 @@ static void do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
 	stat_inc_seg_count(sbi, GET_SUM_TYPE((&sum->footer)));
 	stat_inc_seg_count(sbi, GET_SUM_TYPE((&sum->footer)));
 	stat_inc_call_count(sbi->stat_info);
 	stat_inc_call_count(sbi->stat_info);
 
 
-	f2fs_put_page(sum_page, 0);
+	f2fs_put_page(sum_page, 1);
 }
 }
 
 
 int f2fs_gc(struct f2fs_sb_info *sbi)
 int f2fs_gc(struct f2fs_sb_info *sbi)

+ 1 - 1
fs/f2fs/node.c

@@ -1149,7 +1149,7 @@ static int f2fs_write_node_pages(struct address_space *mapping,
 
 
 	/* First check balancing cached NAT entries */
 	/* First check balancing cached NAT entries */
 	if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) {
 	if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) {
-		write_checkpoint(sbi, false);
+		f2fs_sync_fs(sbi->sb, true);
 		return 0;
 		return 0;
 	}
 	}
 
 

+ 5 - 2
fs/f2fs/super.c

@@ -137,10 +137,13 @@ int f2fs_sync_fs(struct super_block *sb, int sync)
 	if (!sbi->s_dirty && !get_pages(sbi, F2FS_DIRTY_NODES))
 	if (!sbi->s_dirty && !get_pages(sbi, F2FS_DIRTY_NODES))
 		return 0;
 		return 0;
 
 
-	if (sync)
+	if (sync) {
+		mutex_lock(&sbi->gc_mutex);
 		write_checkpoint(sbi, false);
 		write_checkpoint(sbi, false);
-	else
+		mutex_unlock(&sbi->gc_mutex);
+	} else {
 		f2fs_balance_fs(sbi);
 		f2fs_balance_fs(sbi);
+	}
 
 
 	return 0;
 	return 0;
 }
 }