diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2017-02-09 13:38:09 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2017-02-27 12:59:54 -0500 |
commit | 22ad0b6ab46683975c6da032f1c2593066c7b3bd (patch) | |
tree | e4868123c476d3a4ebcdec04b50263ae49acd80a | |
parent | 5e8256ac2e378089a1bf3fae87370811b1d31625 (diff) |
f2fs: add bitmaps for empty or full NAT blocks
This patches adds bitmaps to represent empty or full NAT blocks containing
free nid entries.
If we can find valid crc|cp_ver in the last block of checkpoint pack, we'll
use these bitmaps when building free nids. In order to avoid checkpointing
burden, up-to-date bitmaps will be flushed only during umount time. So,
normally we can get this gain, but when power-cut happens, we rely on fsck.f2fs
which recovers this bitmap again.
After this patch, we build free nids from nid #0 at mount time to make more
full NAT blocks, but in runtime, we check empty NAT blocks to load free nids
without loading any NAT pages from disk.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fs/f2fs/checkpoint.c | 28 | ||||
-rw-r--r-- | fs/f2fs/debug.c | 1 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 31 | ||||
-rw-r--r-- | fs/f2fs/node.c | 188 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 2 | ||||
-rw-r--r-- | include/linux/f2fs_fs.h | 1 |
6 files changed, 231 insertions, 20 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 042f8d9afe44..cd7132121573 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -1024,6 +1024,10 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1024 | 1024 | ||
1025 | spin_lock(&sbi->cp_lock); | 1025 | spin_lock(&sbi->cp_lock); |
1026 | 1026 | ||
1027 | if (cpc->reason == CP_UMOUNT && ckpt->cp_pack_total_block_count > | ||
1028 | sbi->blocks_per_seg - NM_I(sbi)->nat_bits_blocks) | ||
1029 | disable_nat_bits(sbi, false); | ||
1030 | |||
1027 | if (cpc->reason == CP_UMOUNT) | 1031 | if (cpc->reason == CP_UMOUNT) |
1028 | __set_ckpt_flags(ckpt, CP_UMOUNT_FLAG); | 1032 | __set_ckpt_flags(ckpt, CP_UMOUNT_FLAG); |
1029 | else | 1033 | else |
@@ -1136,6 +1140,28 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1136 | 1140 | ||
1137 | start_blk = __start_cp_next_addr(sbi); | 1141 | start_blk = __start_cp_next_addr(sbi); |
1138 | 1142 | ||
1143 | /* write nat bits */ | ||
1144 | if (enabled_nat_bits(sbi, cpc)) { | ||
1145 | __u64 cp_ver = cur_cp_version(ckpt); | ||
1146 | unsigned int i; | ||
1147 | block_t blk; | ||
1148 | |||
1149 | cp_ver |= ((__u64)crc32 << 32); | ||
1150 | *(__le64 *)nm_i->nat_bits = cpu_to_le64(cp_ver); | ||
1151 | |||
1152 | blk = start_blk + sbi->blocks_per_seg - nm_i->nat_bits_blocks; | ||
1153 | for (i = 0; i < nm_i->nat_bits_blocks; i++) | ||
1154 | update_meta_page(sbi, nm_i->nat_bits + | ||
1155 | (i << F2FS_BLKSIZE_BITS), blk + i); | ||
1156 | |||
1157 | /* Flush all the NAT BITS pages */ | ||
1158 | while (get_pages(sbi, F2FS_DIRTY_META)) { | ||
1159 | sync_meta_pages(sbi, META, LONG_MAX); | ||
1160 | if (unlikely(f2fs_cp_error(sbi))) | ||
1161 | return -EIO; | ||
1162 | } | ||
1163 | } | ||
1164 | |||
1139 | /* need to wait for end_io results */ | 1165 | /* need to wait for end_io results */ |
1140 | wait_on_all_pages_writeback(sbi); | 1166 | wait_on_all_pages_writeback(sbi); |
1141 | if (unlikely(f2fs_cp_error(sbi))) | 1167 | if (unlikely(f2fs_cp_error(sbi))) |
@@ -1272,7 +1298,7 @@ int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1272 | ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver); | 1298 | ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver); |
1273 | 1299 | ||
1274 | /* write cached NAT/SIT entries to NAT/SIT area */ | 1300 | /* write cached NAT/SIT entries to NAT/SIT area */ |
1275 | flush_nat_entries(sbi); | 1301 | flush_nat_entries(sbi, cpc); |
1276 | flush_sit_entries(sbi, cpc); | 1302 | flush_sit_entries(sbi, cpc); |
1277 | 1303 | ||
1278 | /* unlock all the fs_lock[] in do_checkpoint() */ | 1304 | /* unlock all the fs_lock[] in do_checkpoint() */ |
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index de8da9fc5c99..015ad2b73a92 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c | |||
@@ -193,6 +193,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi) | |||
193 | /* build nm */ | 193 | /* build nm */ |
194 | si->base_mem += sizeof(struct f2fs_nm_info); | 194 | si->base_mem += sizeof(struct f2fs_nm_info); |
195 | si->base_mem += __bitmap_size(sbi, NAT_BITMAP); | 195 | si->base_mem += __bitmap_size(sbi, NAT_BITMAP); |
196 | si->base_mem += (NM_I(sbi)->nat_bits_blocks << F2FS_BLKSIZE_BITS); | ||
196 | 197 | ||
197 | get_cache: | 198 | get_cache: |
198 | si->cache_mem = 0; | 199 | si->cache_mem = 0; |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index e26cc6909a54..d1156cdd211e 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -554,6 +554,7 @@ struct f2fs_nm_info { | |||
554 | struct list_head nat_entries; /* cached nat entry list (clean) */ | 554 | struct list_head nat_entries; /* cached nat entry list (clean) */ |
555 | unsigned int nat_cnt; /* the # of cached nat entries */ | 555 | unsigned int nat_cnt; /* the # of cached nat entries */ |
556 | unsigned int dirty_nat_cnt; /* total num of nat entries in set */ | 556 | unsigned int dirty_nat_cnt; /* total num of nat entries in set */ |
557 | unsigned int nat_blocks; /* # of nat blocks */ | ||
557 | 558 | ||
558 | /* free node ids management */ | 559 | /* free node ids management */ |
559 | struct radix_tree_root free_nid_root;/* root of the free_nid cache */ | 560 | struct radix_tree_root free_nid_root;/* root of the free_nid cache */ |
@@ -564,6 +565,11 @@ struct f2fs_nm_info { | |||
564 | 565 | ||
565 | /* for checkpoint */ | 566 | /* for checkpoint */ |
566 | char *nat_bitmap; /* NAT bitmap pointer */ | 567 | char *nat_bitmap; /* NAT bitmap pointer */ |
568 | |||
569 | unsigned int nat_bits_blocks; /* # of nat bits blocks */ | ||
570 | unsigned char *nat_bits; /* NAT bits blocks */ | ||
571 | unsigned char *full_nat_bits; /* full NAT pages */ | ||
572 | unsigned char *empty_nat_bits; /* empty NAT pages */ | ||
567 | #ifdef CONFIG_F2FS_CHECK_FS | 573 | #ifdef CONFIG_F2FS_CHECK_FS |
568 | char *nat_bitmap_mir; /* NAT bitmap mirror */ | 574 | char *nat_bitmap_mir; /* NAT bitmap mirror */ |
569 | #endif | 575 | #endif |
@@ -1171,6 +1177,27 @@ static inline void clear_ckpt_flags(struct f2fs_sb_info *sbi, unsigned int f) | |||
1171 | spin_unlock(&sbi->cp_lock); | 1177 | spin_unlock(&sbi->cp_lock); |
1172 | } | 1178 | } |
1173 | 1179 | ||
1180 | static inline void disable_nat_bits(struct f2fs_sb_info *sbi, bool lock) | ||
1181 | { | ||
1182 | set_sbi_flag(sbi, SBI_NEED_FSCK); | ||
1183 | |||
1184 | if (lock) | ||
1185 | spin_lock(&sbi->cp_lock); | ||
1186 | __clear_ckpt_flags(F2FS_CKPT(sbi), CP_NAT_BITS_FLAG); | ||
1187 | kfree(NM_I(sbi)->nat_bits); | ||
1188 | NM_I(sbi)->nat_bits = NULL; | ||
1189 | if (lock) | ||
1190 | spin_unlock(&sbi->cp_lock); | ||
1191 | } | ||
1192 | |||
1193 | static inline bool enabled_nat_bits(struct f2fs_sb_info *sbi, | ||
1194 | struct cp_control *cpc) | ||
1195 | { | ||
1196 | bool set = is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG); | ||
1197 | |||
1198 | return (cpc) ? (cpc->reason == CP_UMOUNT) && set : set; | ||
1199 | } | ||
1200 | |||
1174 | static inline void f2fs_lock_op(struct f2fs_sb_info *sbi) | 1201 | static inline void f2fs_lock_op(struct f2fs_sb_info *sbi) |
1175 | { | 1202 | { |
1176 | down_read(&sbi->cp_rwsem); | 1203 | down_read(&sbi->cp_rwsem); |
@@ -2131,7 +2158,7 @@ void move_node_page(struct page *node_page, int gc_type); | |||
2131 | int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, | 2158 | int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, |
2132 | struct writeback_control *wbc, bool atomic); | 2159 | struct writeback_control *wbc, bool atomic); |
2133 | int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc); | 2160 | int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc); |
2134 | void build_free_nids(struct f2fs_sb_info *sbi, bool sync); | 2161 | void build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount); |
2135 | bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid); | 2162 | bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid); |
2136 | void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid); | 2163 | void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid); |
2137 | void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid); | 2164 | void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid); |
@@ -2142,7 +2169,7 @@ int recover_xattr_data(struct inode *inode, struct page *page, | |||
2142 | int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page); | 2169 | int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page); |
2143 | int restore_node_summary(struct f2fs_sb_info *sbi, | 2170 | int restore_node_summary(struct f2fs_sb_info *sbi, |
2144 | unsigned int segno, struct f2fs_summary_block *sum); | 2171 | unsigned int segno, struct f2fs_summary_block *sum); |
2145 | void flush_nat_entries(struct f2fs_sb_info *sbi); | 2172 | void flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc); |
2146 | int build_node_manager(struct f2fs_sb_info *sbi); | 2173 | int build_node_manager(struct f2fs_sb_info *sbi); |
2147 | void destroy_node_manager(struct f2fs_sb_info *sbi); | 2174 | void destroy_node_manager(struct f2fs_sb_info *sbi); |
2148 | int __init create_node_manager_caches(void); | 2175 | int __init create_node_manager_caches(void); |
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 8ebc4c78e6a4..43d35ec11851 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
@@ -338,6 +338,9 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni, | |||
338 | set_nat_flag(e, IS_CHECKPOINTED, false); | 338 | set_nat_flag(e, IS_CHECKPOINTED, false); |
339 | __set_nat_cache_dirty(nm_i, e); | 339 | __set_nat_cache_dirty(nm_i, e); |
340 | 340 | ||
341 | if (enabled_nat_bits(sbi, NULL) && new_blkaddr == NEW_ADDR) | ||
342 | clear_bit_le(NAT_BLOCK_OFFSET(ni->nid), nm_i->empty_nat_bits); | ||
343 | |||
341 | /* update fsync_mark if its inode nat entry is still alive */ | 344 | /* update fsync_mark if its inode nat entry is still alive */ |
342 | if (ni->nid != ni->ino) | 345 | if (ni->nid != ni->ino) |
343 | e = __lookup_nat_cache(nm_i, ni->ino); | 346 | e = __lookup_nat_cache(nm_i, ni->ino); |
@@ -1841,7 +1844,60 @@ static void scan_nat_page(struct f2fs_sb_info *sbi, | |||
1841 | } | 1844 | } |
1842 | } | 1845 | } |
1843 | 1846 | ||
1844 | static void __build_free_nids(struct f2fs_sb_info *sbi, bool sync) | 1847 | static int scan_nat_bits(struct f2fs_sb_info *sbi) |
1848 | { | ||
1849 | struct f2fs_nm_info *nm_i = NM_I(sbi); | ||
1850 | struct page *page; | ||
1851 | unsigned int i = 0; | ||
1852 | nid_t target = FREE_NID_PAGES * NAT_ENTRY_PER_BLOCK; | ||
1853 | nid_t nid; | ||
1854 | |||
1855 | if (!enabled_nat_bits(sbi, NULL)) | ||
1856 | return -EAGAIN; | ||
1857 | |||
1858 | down_read(&nm_i->nat_tree_lock); | ||
1859 | check_empty: | ||
1860 | i = find_next_bit_le(nm_i->empty_nat_bits, nm_i->nat_blocks, i); | ||
1861 | if (i >= nm_i->nat_blocks) { | ||
1862 | i = 0; | ||
1863 | goto check_partial; | ||
1864 | } | ||
1865 | |||
1866 | for (nid = i * NAT_ENTRY_PER_BLOCK; nid < (i + 1) * NAT_ENTRY_PER_BLOCK; | ||
1867 | nid++) { | ||
1868 | if (unlikely(nid >= nm_i->max_nid)) | ||
1869 | break; | ||
1870 | add_free_nid(sbi, nid, true); | ||
1871 | } | ||
1872 | |||
1873 | if (nm_i->nid_cnt[FREE_NID_LIST] >= target) | ||
1874 | goto out; | ||
1875 | i++; | ||
1876 | goto check_empty; | ||
1877 | |||
1878 | check_partial: | ||
1879 | i = find_next_zero_bit_le(nm_i->full_nat_bits, nm_i->nat_blocks, i); | ||
1880 | if (i >= nm_i->nat_blocks) { | ||
1881 | disable_nat_bits(sbi, true); | ||
1882 | up_read(&nm_i->nat_tree_lock); | ||
1883 | return -EINVAL; | ||
1884 | } | ||
1885 | |||
1886 | nid = i * NAT_ENTRY_PER_BLOCK; | ||
1887 | page = get_current_nat_page(sbi, nid); | ||
1888 | scan_nat_page(sbi, page, nid); | ||
1889 | f2fs_put_page(page, 1); | ||
1890 | |||
1891 | if (nm_i->nid_cnt[FREE_NID_LIST] < target) { | ||
1892 | i++; | ||
1893 | goto check_partial; | ||
1894 | } | ||
1895 | out: | ||
1896 | up_read(&nm_i->nat_tree_lock); | ||
1897 | return 0; | ||
1898 | } | ||
1899 | |||
1900 | static void __build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount) | ||
1845 | { | 1901 | { |
1846 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 1902 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
1847 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); | 1903 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
@@ -1856,6 +1912,21 @@ static void __build_free_nids(struct f2fs_sb_info *sbi, bool sync) | |||
1856 | if (!sync && !available_free_memory(sbi, FREE_NIDS)) | 1912 | if (!sync && !available_free_memory(sbi, FREE_NIDS)) |
1857 | return; | 1913 | return; |
1858 | 1914 | ||
1915 | /* try to find free nids with nat_bits */ | ||
1916 | if (!mount && !scan_nat_bits(sbi) && nm_i->nid_cnt[FREE_NID_LIST]) | ||
1917 | return; | ||
1918 | |||
1919 | /* find next valid candidate */ | ||
1920 | if (enabled_nat_bits(sbi, NULL)) { | ||
1921 | int idx = find_next_zero_bit_le(nm_i->full_nat_bits, | ||
1922 | nm_i->nat_blocks, 0); | ||
1923 | |||
1924 | if (idx >= nm_i->nat_blocks) | ||
1925 | set_sbi_flag(sbi, SBI_NEED_FSCK); | ||
1926 | else | ||
1927 | nid = idx * NAT_ENTRY_PER_BLOCK; | ||
1928 | } | ||
1929 | |||
1859 | /* readahead nat pages to be scanned */ | 1930 | /* readahead nat pages to be scanned */ |
1860 | ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES, | 1931 | ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES, |
1861 | META_NAT, true); | 1932 | META_NAT, true); |
@@ -1898,10 +1969,10 @@ static void __build_free_nids(struct f2fs_sb_info *sbi, bool sync) | |||
1898 | nm_i->ra_nid_pages, META_NAT, false); | 1969 | nm_i->ra_nid_pages, META_NAT, false); |
1899 | } | 1970 | } |
1900 | 1971 | ||
1901 | void build_free_nids(struct f2fs_sb_info *sbi, bool sync) | 1972 | void build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount) |
1902 | { | 1973 | { |
1903 | mutex_lock(&NM_I(sbi)->build_lock); | 1974 | mutex_lock(&NM_I(sbi)->build_lock); |
1904 | __build_free_nids(sbi, sync); | 1975 | __build_free_nids(sbi, sync, mount); |
1905 | mutex_unlock(&NM_I(sbi)->build_lock); | 1976 | mutex_unlock(&NM_I(sbi)->build_lock); |
1906 | } | 1977 | } |
1907 | 1978 | ||
@@ -1943,7 +2014,7 @@ retry: | |||
1943 | spin_unlock(&nm_i->nid_list_lock); | 2014 | spin_unlock(&nm_i->nid_list_lock); |
1944 | 2015 | ||
1945 | /* Let's scan nat pages and its caches to get free nids */ | 2016 | /* Let's scan nat pages and its caches to get free nids */ |
1946 | build_free_nids(sbi, true); | 2017 | build_free_nids(sbi, true, false); |
1947 | goto retry; | 2018 | goto retry; |
1948 | } | 2019 | } |
1949 | 2020 | ||
@@ -2235,8 +2306,39 @@ add_out: | |||
2235 | list_add_tail(&nes->set_list, head); | 2306 | list_add_tail(&nes->set_list, head); |
2236 | } | 2307 | } |
2237 | 2308 | ||
2309 | void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, | ||
2310 | struct page *page) | ||
2311 | { | ||
2312 | struct f2fs_nm_info *nm_i = NM_I(sbi); | ||
2313 | unsigned int nat_index = start_nid / NAT_ENTRY_PER_BLOCK; | ||
2314 | struct f2fs_nat_block *nat_blk = page_address(page); | ||
2315 | int valid = 0; | ||
2316 | int i; | ||
2317 | |||
2318 | if (!enabled_nat_bits(sbi, NULL)) | ||
2319 | return; | ||
2320 | |||
2321 | for (i = 0; i < NAT_ENTRY_PER_BLOCK; i++) { | ||
2322 | if (start_nid == 0 && i == 0) | ||
2323 | valid++; | ||
2324 | if (nat_blk->entries[i].block_addr) | ||
2325 | valid++; | ||
2326 | } | ||
2327 | if (valid == 0) { | ||
2328 | set_bit_le(nat_index, nm_i->empty_nat_bits); | ||
2329 | clear_bit_le(nat_index, nm_i->full_nat_bits); | ||
2330 | return; | ||
2331 | } | ||
2332 | |||
2333 | clear_bit_le(nat_index, nm_i->empty_nat_bits); | ||
2334 | if (valid == NAT_ENTRY_PER_BLOCK) | ||
2335 | set_bit_le(nat_index, nm_i->full_nat_bits); | ||
2336 | else | ||
2337 | clear_bit_le(nat_index, nm_i->full_nat_bits); | ||
2338 | } | ||
2339 | |||
2238 | static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, | 2340 | static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, |
2239 | struct nat_entry_set *set) | 2341 | struct nat_entry_set *set, struct cp_control *cpc) |
2240 | { | 2342 | { |
2241 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); | 2343 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
2242 | struct f2fs_journal *journal = curseg->journal; | 2344 | struct f2fs_journal *journal = curseg->journal; |
@@ -2251,7 +2353,8 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, | |||
2251 | * #1, flush nat entries to journal in current hot data summary block. | 2353 | * #1, flush nat entries to journal in current hot data summary block. |
2252 | * #2, flush nat entries to nat page. | 2354 | * #2, flush nat entries to nat page. |
2253 | */ | 2355 | */ |
2254 | if (!__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL)) | 2356 | if (enabled_nat_bits(sbi, cpc) || |
2357 | !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL)) | ||
2255 | to_journal = false; | 2358 | to_journal = false; |
2256 | 2359 | ||
2257 | if (to_journal) { | 2360 | if (to_journal) { |
@@ -2291,10 +2394,12 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, | |||
2291 | } | 2394 | } |
2292 | } | 2395 | } |
2293 | 2396 | ||
2294 | if (to_journal) | 2397 | if (to_journal) { |
2295 | up_write(&curseg->journal_rwsem); | 2398 | up_write(&curseg->journal_rwsem); |
2296 | else | 2399 | } else { |
2400 | __update_nat_bits(sbi, start_nid, page); | ||
2297 | f2fs_put_page(page, 1); | 2401 | f2fs_put_page(page, 1); |
2402 | } | ||
2298 | 2403 | ||
2299 | f2fs_bug_on(sbi, set->entry_cnt); | 2404 | f2fs_bug_on(sbi, set->entry_cnt); |
2300 | 2405 | ||
@@ -2305,7 +2410,7 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, | |||
2305 | /* | 2410 | /* |
2306 | * This function is called during the checkpointing process. | 2411 | * This function is called during the checkpointing process. |
2307 | */ | 2412 | */ |
2308 | void flush_nat_entries(struct f2fs_sb_info *sbi) | 2413 | void flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) |
2309 | { | 2414 | { |
2310 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 2415 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
2311 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); | 2416 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
@@ -2326,7 +2431,8 @@ void flush_nat_entries(struct f2fs_sb_info *sbi) | |||
2326 | * entries, remove all entries from journal and merge them | 2431 | * entries, remove all entries from journal and merge them |
2327 | * into nat entry set. | 2432 | * into nat entry set. |
2328 | */ | 2433 | */ |
2329 | if (!__has_cursum_space(journal, nm_i->dirty_nat_cnt, NAT_JOURNAL)) | 2434 | if (cpc->reason == CP_UMOUNT || |
2435 | !__has_cursum_space(journal, nm_i->dirty_nat_cnt, NAT_JOURNAL)) | ||
2330 | remove_nats_in_journal(sbi); | 2436 | remove_nats_in_journal(sbi); |
2331 | 2437 | ||
2332 | while ((found = __gang_lookup_nat_set(nm_i, | 2438 | while ((found = __gang_lookup_nat_set(nm_i, |
@@ -2340,27 +2446,72 @@ void flush_nat_entries(struct f2fs_sb_info *sbi) | |||
2340 | 2446 | ||
2341 | /* flush dirty nats in nat entry set */ | 2447 | /* flush dirty nats in nat entry set */ |
2342 | list_for_each_entry_safe(set, tmp, &sets, set_list) | 2448 | list_for_each_entry_safe(set, tmp, &sets, set_list) |
2343 | __flush_nat_entry_set(sbi, set); | 2449 | __flush_nat_entry_set(sbi, set, cpc); |
2344 | 2450 | ||
2345 | up_write(&nm_i->nat_tree_lock); | 2451 | up_write(&nm_i->nat_tree_lock); |
2346 | 2452 | ||
2347 | f2fs_bug_on(sbi, nm_i->dirty_nat_cnt); | 2453 | f2fs_bug_on(sbi, nm_i->dirty_nat_cnt); |
2348 | } | 2454 | } |
2349 | 2455 | ||
2456 | static int __get_nat_bitmaps(struct f2fs_sb_info *sbi) | ||
2457 | { | ||
2458 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); | ||
2459 | struct f2fs_nm_info *nm_i = NM_I(sbi); | ||
2460 | unsigned int nat_bits_bytes = nm_i->nat_blocks / BITS_PER_BYTE; | ||
2461 | unsigned int i; | ||
2462 | __u64 cp_ver = cur_cp_version(ckpt); | ||
2463 | size_t crc_offset = le32_to_cpu(ckpt->checksum_offset); | ||
2464 | __u64 crc = le32_to_cpu(*((__le32 *) | ||
2465 | ((unsigned char *)ckpt + crc_offset))); | ||
2466 | block_t nat_bits_addr; | ||
2467 | |||
2468 | if (!enabled_nat_bits(sbi, NULL)) | ||
2469 | return 0; | ||
2470 | |||
2471 | nm_i->nat_bits_blocks = F2FS_BYTES_TO_BLK((nat_bits_bytes << 1) + 8 + | ||
2472 | F2FS_BLKSIZE - 1); | ||
2473 | nm_i->nat_bits = kzalloc(nm_i->nat_bits_blocks << F2FS_BLKSIZE_BITS, | ||
2474 | GFP_KERNEL); | ||
2475 | if (!nm_i->nat_bits) | ||
2476 | return -ENOMEM; | ||
2477 | |||
2478 | nat_bits_addr = __start_cp_addr(sbi) + sbi->blocks_per_seg - | ||
2479 | nm_i->nat_bits_blocks; | ||
2480 | for (i = 0; i < nm_i->nat_bits_blocks; i++) { | ||
2481 | struct page *page = get_meta_page(sbi, nat_bits_addr++); | ||
2482 | |||
2483 | memcpy(nm_i->nat_bits + (i << F2FS_BLKSIZE_BITS), | ||
2484 | page_address(page), F2FS_BLKSIZE); | ||
2485 | f2fs_put_page(page, 1); | ||
2486 | } | ||
2487 | |||
2488 | cp_ver |= (crc << 32); | ||
2489 | if (cpu_to_le64(cp_ver) != *(__le64 *)nm_i->nat_bits) { | ||
2490 | disable_nat_bits(sbi, true); | ||
2491 | return 0; | ||
2492 | } | ||
2493 | |||
2494 | nm_i->full_nat_bits = nm_i->nat_bits + 8; | ||
2495 | nm_i->empty_nat_bits = nm_i->full_nat_bits + nat_bits_bytes; | ||
2496 | |||
2497 | f2fs_msg(sbi->sb, KERN_NOTICE, "Found nat_bits in checkpoint"); | ||
2498 | return 0; | ||
2499 | } | ||
2500 | |||
2350 | static int init_node_manager(struct f2fs_sb_info *sbi) | 2501 | static int init_node_manager(struct f2fs_sb_info *sbi) |
2351 | { | 2502 | { |
2352 | struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi); | 2503 | struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi); |
2353 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 2504 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
2354 | unsigned char *version_bitmap; | 2505 | unsigned char *version_bitmap; |
2355 | unsigned int nat_segs, nat_blocks; | 2506 | unsigned int nat_segs; |
2507 | int err; | ||
2356 | 2508 | ||
2357 | nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr); | 2509 | nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr); |
2358 | 2510 | ||
2359 | /* segment_count_nat includes pair segment so divide to 2. */ | 2511 | /* segment_count_nat includes pair segment so divide to 2. */ |
2360 | nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1; | 2512 | nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1; |
2361 | nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg); | 2513 | nm_i->nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg); |
2362 | 2514 | nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nm_i->nat_blocks; | |
2363 | nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks; | ||
2364 | 2515 | ||
2365 | /* not used nids: 0, node, meta, (and root counted as valid node) */ | 2516 | /* not used nids: 0, node, meta, (and root counted as valid node) */ |
2366 | nm_i->available_nids = nm_i->max_nid - sbi->total_valid_node_count - | 2517 | nm_i->available_nids = nm_i->max_nid - sbi->total_valid_node_count - |
@@ -2394,6 +2545,10 @@ static int init_node_manager(struct f2fs_sb_info *sbi) | |||
2394 | if (!nm_i->nat_bitmap) | 2545 | if (!nm_i->nat_bitmap) |
2395 | return -ENOMEM; | 2546 | return -ENOMEM; |
2396 | 2547 | ||
2548 | err = __get_nat_bitmaps(sbi); | ||
2549 | if (err) | ||
2550 | return err; | ||
2551 | |||
2397 | #ifdef CONFIG_F2FS_CHECK_FS | 2552 | #ifdef CONFIG_F2FS_CHECK_FS |
2398 | nm_i->nat_bitmap_mir = kmemdup(version_bitmap, nm_i->bitmap_size, | 2553 | nm_i->nat_bitmap_mir = kmemdup(version_bitmap, nm_i->bitmap_size, |
2399 | GFP_KERNEL); | 2554 | GFP_KERNEL); |
@@ -2416,7 +2571,7 @@ int build_node_manager(struct f2fs_sb_info *sbi) | |||
2416 | if (err) | 2571 | if (err) |
2417 | return err; | 2572 | return err; |
2418 | 2573 | ||
2419 | build_free_nids(sbi, true); | 2574 | build_free_nids(sbi, true, true); |
2420 | return 0; | 2575 | return 0; |
2421 | } | 2576 | } |
2422 | 2577 | ||
@@ -2475,6 +2630,7 @@ void destroy_node_manager(struct f2fs_sb_info *sbi) | |||
2475 | up_write(&nm_i->nat_tree_lock); | 2630 | up_write(&nm_i->nat_tree_lock); |
2476 | 2631 | ||
2477 | kfree(nm_i->nat_bitmap); | 2632 | kfree(nm_i->nat_bitmap); |
2633 | kfree(nm_i->nat_bits); | ||
2478 | #ifdef CONFIG_F2FS_CHECK_FS | 2634 | #ifdef CONFIG_F2FS_CHECK_FS |
2479 | kfree(nm_i->nat_bitmap_mir); | 2635 | kfree(nm_i->nat_bitmap_mir); |
2480 | #endif | 2636 | #endif |
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 3e95db5375ed..9eb6d89bf9e2 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -386,7 +386,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi) | |||
386 | if (!available_free_memory(sbi, FREE_NIDS)) | 386 | if (!available_free_memory(sbi, FREE_NIDS)) |
387 | try_to_free_nids(sbi, MAX_FREE_NIDS); | 387 | try_to_free_nids(sbi, MAX_FREE_NIDS); |
388 | else | 388 | else |
389 | build_free_nids(sbi, false); | 389 | build_free_nids(sbi, false, false); |
390 | 390 | ||
391 | if (!is_idle(sbi)) | 391 | if (!is_idle(sbi)) |
392 | return; | 392 | return; |
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index f0748524ca8c..1c92ace2e8f8 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h | |||
@@ -114,6 +114,7 @@ struct f2fs_super_block { | |||
114 | /* | 114 | /* |
115 | * For checkpoint | 115 | * For checkpoint |
116 | */ | 116 | */ |
117 | #define CP_NAT_BITS_FLAG 0x00000080 | ||
117 | #define CP_CRC_RECOVERY_FLAG 0x00000040 | 118 | #define CP_CRC_RECOVERY_FLAG 0x00000040 |
118 | #define CP_FASTBOOT_FLAG 0x00000020 | 119 | #define CP_FASTBOOT_FLAG 0x00000020 |
119 | #define CP_FSCK_FLAG 0x00000010 | 120 | #define CP_FSCK_FLAG 0x00000010 |