aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWanpeng Li <wanpeng.li@linux.intel.com>2015-03-08 23:00:55 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2015-04-10 18:08:39 -0400
commit57ed1e95babbd2df33f70eb820c7a9984199557b (patch)
tree3d277b6e2f932be5bca5ab8735b7ae60ebf28e13
parente0150392ddfaaf5ccf338893f6db177a2c64a7ee (diff)
f2fs: fix unlocked nat set cache operation
nm_i->nat_tree_lock is used to sync both the operations of nat entry cache tree and nat set cache tree, however, it isn't held when flush nat entries during checkpoint which lead to potential race, this patch fix it by holding the lock when gang lookup nat set cache and delete item from nat set cache. Signed-off-by: Wanpeng Li <wanpeng.li@linux.intel.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--fs/f2fs/node.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 4687eae6c116..8ab0cf1930bd 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1830,6 +1830,7 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi,
1830 struct f2fs_nat_block *nat_blk; 1830 struct f2fs_nat_block *nat_blk;
1831 struct nat_entry *ne, *cur; 1831 struct nat_entry *ne, *cur;
1832 struct page *page = NULL; 1832 struct page *page = NULL;
1833 struct f2fs_nm_info *nm_i = NM_I(sbi);
1833 1834
1834 /* 1835 /*
1835 * there are two steps to flush nat entries: 1836 * there are two steps to flush nat entries:
@@ -1883,7 +1884,9 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi,
1883 1884
1884 f2fs_bug_on(sbi, set->entry_cnt); 1885 f2fs_bug_on(sbi, set->entry_cnt);
1885 1886
1887 down_write(&nm_i->nat_tree_lock);
1886 radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set); 1888 radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set);
1889 up_write(&nm_i->nat_tree_lock);
1887 kmem_cache_free(nat_entry_set_slab, set); 1890 kmem_cache_free(nat_entry_set_slab, set);
1888} 1891}
1889 1892
@@ -1911,6 +1914,7 @@ void flush_nat_entries(struct f2fs_sb_info *sbi)
1911 if (!__has_cursum_space(sum, nm_i->dirty_nat_cnt, NAT_JOURNAL)) 1914 if (!__has_cursum_space(sum, nm_i->dirty_nat_cnt, NAT_JOURNAL))
1912 remove_nats_in_journal(sbi); 1915 remove_nats_in_journal(sbi);
1913 1916
1917 down_write(&nm_i->nat_tree_lock);
1914 while ((found = __gang_lookup_nat_set(nm_i, 1918 while ((found = __gang_lookup_nat_set(nm_i,
1915 set_idx, SETVEC_SIZE, setvec))) { 1919 set_idx, SETVEC_SIZE, setvec))) {
1916 unsigned idx; 1920 unsigned idx;
@@ -1919,6 +1923,7 @@ void flush_nat_entries(struct f2fs_sb_info *sbi)
1919 __adjust_nat_entry_set(setvec[idx], &sets, 1923 __adjust_nat_entry_set(setvec[idx], &sets,
1920 MAX_NAT_JENTRIES(sum)); 1924 MAX_NAT_JENTRIES(sum));
1921 } 1925 }
1926 up_write(&nm_i->nat_tree_lock);
1922 1927
1923 /* flush dirty nats in nat entry set */ 1928 /* flush dirty nats in nat entry set */
1924 list_for_each_entry_safe(set, tmp, &sets, set_list) 1929 list_for_each_entry_safe(set, tmp, &sets, set_list)