18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fs/f2fs/node.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd. 68c2ecf20Sopenharmony_ci * http://www.samsung.com/ 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#include <linux/fs.h> 98c2ecf20Sopenharmony_ci#include <linux/f2fs_fs.h> 108c2ecf20Sopenharmony_ci#include <linux/mpage.h> 118c2ecf20Sopenharmony_ci#include <linux/backing-dev.h> 128c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 138c2ecf20Sopenharmony_ci#include <linux/pagevec.h> 148c2ecf20Sopenharmony_ci#include <linux/swap.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "f2fs.h" 178c2ecf20Sopenharmony_ci#include "node.h" 188c2ecf20Sopenharmony_ci#include "segment.h" 198c2ecf20Sopenharmony_ci#include "xattr.h" 208c2ecf20Sopenharmony_ci#include "trace.h" 218c2ecf20Sopenharmony_ci#include <trace/events/f2fs.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define on_f2fs_build_free_nids(nmi) mutex_is_locked(&(nm_i)->build_lock) 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic struct kmem_cache *nat_entry_slab; 268c2ecf20Sopenharmony_cistatic struct kmem_cache *free_nid_slab; 278c2ecf20Sopenharmony_cistatic struct kmem_cache *nat_entry_set_slab; 288c2ecf20Sopenharmony_cistatic struct kmem_cache *fsync_node_entry_slab; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* 318c2ecf20Sopenharmony_ci * Check whether the given nid is within node id range. 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ciint f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci if (unlikely(nid < F2FS_ROOT_INO(sbi) || nid >= NM_I(sbi)->max_nid)) { 368c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 378c2ecf20Sopenharmony_ci f2fs_warn(sbi, "%s: out-of-range nid=%x, run fsck to fix.", 388c2ecf20Sopenharmony_ci __func__, nid); 398c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 408c2ecf20Sopenharmony_ci } 418c2ecf20Sopenharmony_ci return 0; 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cibool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 478c2ecf20Sopenharmony_ci struct sysinfo val; 488c2ecf20Sopenharmony_ci unsigned long avail_ram; 498c2ecf20Sopenharmony_ci unsigned long mem_size = 0; 508c2ecf20Sopenharmony_ci bool res = false; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci si_meminfo(&val); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* only uses low memory */ 558c2ecf20Sopenharmony_ci avail_ram = val.totalram - val.totalhigh; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci /* 588c2ecf20Sopenharmony_ci * give 25%, 25%, 50%, 50%, 50% memory for each components respectively 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_ci if (type == FREE_NIDS) { 618c2ecf20Sopenharmony_ci mem_size = (nm_i->nid_cnt[FREE_NID] * 628c2ecf20Sopenharmony_ci sizeof(struct free_nid)) >> PAGE_SHIFT; 638c2ecf20Sopenharmony_ci res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2); 648c2ecf20Sopenharmony_ci } else if (type == NAT_ENTRIES) { 658c2ecf20Sopenharmony_ci mem_size = (nm_i->nat_cnt[TOTAL_NAT] * 668c2ecf20Sopenharmony_ci sizeof(struct nat_entry)) >> PAGE_SHIFT; 678c2ecf20Sopenharmony_ci res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2); 688c2ecf20Sopenharmony_ci if (excess_cached_nats(sbi)) 698c2ecf20Sopenharmony_ci res = false; 708c2ecf20Sopenharmony_ci } else if (type == DIRTY_DENTS) { 718c2ecf20Sopenharmony_ci if (sbi->sb->s_bdi->wb.dirty_exceeded) 728c2ecf20Sopenharmony_ci return false; 738c2ecf20Sopenharmony_ci mem_size = get_pages(sbi, F2FS_DIRTY_DENTS); 748c2ecf20Sopenharmony_ci res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1); 758c2ecf20Sopenharmony_ci } else if (type == INO_ENTRIES) { 768c2ecf20Sopenharmony_ci int i; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci for (i = 0; i < MAX_INO_ENTRY; i++) 798c2ecf20Sopenharmony_ci mem_size += sbi->im[i].ino_num * 808c2ecf20Sopenharmony_ci sizeof(struct ino_entry); 818c2ecf20Sopenharmony_ci mem_size >>= PAGE_SHIFT; 828c2ecf20Sopenharmony_ci res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1); 838c2ecf20Sopenharmony_ci } else if (type == EXTENT_CACHE) { 848c2ecf20Sopenharmony_ci mem_size = (atomic_read(&sbi->total_ext_tree) * 858c2ecf20Sopenharmony_ci sizeof(struct extent_tree) + 868c2ecf20Sopenharmony_ci atomic_read(&sbi->total_ext_node) * 878c2ecf20Sopenharmony_ci sizeof(struct extent_node)) >> PAGE_SHIFT; 888c2ecf20Sopenharmony_ci res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1); 898c2ecf20Sopenharmony_ci } else if (type == INMEM_PAGES) { 908c2ecf20Sopenharmony_ci /* it allows 20% / total_ram for inmemory pages */ 918c2ecf20Sopenharmony_ci mem_size = get_pages(sbi, F2FS_INMEM_PAGES); 928c2ecf20Sopenharmony_ci res = mem_size < (val.totalram / 5); 938c2ecf20Sopenharmony_ci } else { 948c2ecf20Sopenharmony_ci if (!sbi->sb->s_bdi->wb.dirty_exceeded) 958c2ecf20Sopenharmony_ci return true; 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci return res; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic void clear_node_page_dirty(struct page *page) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci if (PageDirty(page)) { 1038c2ecf20Sopenharmony_ci f2fs_clear_page_cache_dirty_tag(page); 1048c2ecf20Sopenharmony_ci clear_page_dirty_for_io(page); 1058c2ecf20Sopenharmony_ci dec_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES); 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci ClearPageUptodate(page); 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci return f2fs_get_meta_page_retry(sbi, current_nat_addr(sbi, nid)); 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci struct page *src_page; 1188c2ecf20Sopenharmony_ci struct page *dst_page; 1198c2ecf20Sopenharmony_ci pgoff_t dst_off; 1208c2ecf20Sopenharmony_ci void *src_addr; 1218c2ecf20Sopenharmony_ci void *dst_addr; 1228c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci dst_off = next_nat_addr(sbi, current_nat_addr(sbi, nid)); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* get current nat block page with lock */ 1278c2ecf20Sopenharmony_ci src_page = get_current_nat_page(sbi, nid); 1288c2ecf20Sopenharmony_ci if (IS_ERR(src_page)) 1298c2ecf20Sopenharmony_ci return src_page; 1308c2ecf20Sopenharmony_ci dst_page = f2fs_grab_meta_page(sbi, dst_off); 1318c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, PageDirty(src_page)); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci src_addr = page_address(src_page); 1348c2ecf20Sopenharmony_ci dst_addr = page_address(dst_page); 1358c2ecf20Sopenharmony_ci memcpy(dst_addr, src_addr, PAGE_SIZE); 1368c2ecf20Sopenharmony_ci set_page_dirty(dst_page); 1378c2ecf20Sopenharmony_ci f2fs_put_page(src_page, 1); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci set_to_next_nat(nm_i, nid); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci return dst_page; 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic struct nat_entry *__alloc_nat_entry(nid_t nid, bool no_fail) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci struct nat_entry *new; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (no_fail) 1498c2ecf20Sopenharmony_ci new = f2fs_kmem_cache_alloc(nat_entry_slab, GFP_F2FS_ZERO); 1508c2ecf20Sopenharmony_ci else 1518c2ecf20Sopenharmony_ci new = kmem_cache_alloc(nat_entry_slab, GFP_F2FS_ZERO); 1528c2ecf20Sopenharmony_ci if (new) { 1538c2ecf20Sopenharmony_ci nat_set_nid(new, nid); 1548c2ecf20Sopenharmony_ci nat_reset_flag(new); 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci return new; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic void __free_nat_entry(struct nat_entry *e) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci kmem_cache_free(nat_entry_slab, e); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci/* must be locked by nat_tree_lock */ 1658c2ecf20Sopenharmony_cistatic struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i, 1668c2ecf20Sopenharmony_ci struct nat_entry *ne, struct f2fs_nat_entry *raw_ne, bool no_fail) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci if (no_fail) 1698c2ecf20Sopenharmony_ci f2fs_radix_tree_insert(&nm_i->nat_root, nat_get_nid(ne), ne); 1708c2ecf20Sopenharmony_ci else if (radix_tree_insert(&nm_i->nat_root, nat_get_nid(ne), ne)) 1718c2ecf20Sopenharmony_ci return NULL; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci if (raw_ne) 1748c2ecf20Sopenharmony_ci node_info_from_raw_nat(&ne->ni, raw_ne); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 1778c2ecf20Sopenharmony_ci list_add_tail(&ne->list, &nm_i->nat_entries); 1788c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci nm_i->nat_cnt[TOTAL_NAT]++; 1818c2ecf20Sopenharmony_ci nm_i->nat_cnt[RECLAIMABLE_NAT]++; 1828c2ecf20Sopenharmony_ci return ne; 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cistatic struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci struct nat_entry *ne; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci ne = radix_tree_lookup(&nm_i->nat_root, n); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* for recent accessed nat entry, move it to tail of lru list */ 1928c2ecf20Sopenharmony_ci if (ne && !get_nat_flag(ne, IS_DIRTY)) { 1938c2ecf20Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 1948c2ecf20Sopenharmony_ci if (!list_empty(&ne->list)) 1958c2ecf20Sopenharmony_ci list_move_tail(&ne->list, &nm_i->nat_entries); 1968c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci return ne; 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i, 2038c2ecf20Sopenharmony_ci nid_t start, unsigned int nr, struct nat_entry **ep) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci return radix_tree_gang_lookup(&nm_i->nat_root, (void **)ep, start, nr); 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci radix_tree_delete(&nm_i->nat_root, nat_get_nid(e)); 2118c2ecf20Sopenharmony_ci nm_i->nat_cnt[TOTAL_NAT]--; 2128c2ecf20Sopenharmony_ci nm_i->nat_cnt[RECLAIMABLE_NAT]--; 2138c2ecf20Sopenharmony_ci __free_nat_entry(e); 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cistatic struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i, 2178c2ecf20Sopenharmony_ci struct nat_entry *ne) 2188c2ecf20Sopenharmony_ci{ 2198c2ecf20Sopenharmony_ci nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid); 2208c2ecf20Sopenharmony_ci struct nat_entry_set *head; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci head = radix_tree_lookup(&nm_i->nat_set_root, set); 2238c2ecf20Sopenharmony_ci if (!head) { 2248c2ecf20Sopenharmony_ci head = f2fs_kmem_cache_alloc(nat_entry_set_slab, GFP_NOFS); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&head->entry_list); 2278c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&head->set_list); 2288c2ecf20Sopenharmony_ci head->set = set; 2298c2ecf20Sopenharmony_ci head->entry_cnt = 0; 2308c2ecf20Sopenharmony_ci f2fs_radix_tree_insert(&nm_i->nat_set_root, set, head); 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci return head; 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, 2368c2ecf20Sopenharmony_ci struct nat_entry *ne) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci struct nat_entry_set *head; 2398c2ecf20Sopenharmony_ci bool new_ne = nat_get_blkaddr(ne) == NEW_ADDR; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (!new_ne) 2428c2ecf20Sopenharmony_ci head = __grab_nat_entry_set(nm_i, ne); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci /* 2458c2ecf20Sopenharmony_ci * update entry_cnt in below condition: 2468c2ecf20Sopenharmony_ci * 1. update NEW_ADDR to valid block address; 2478c2ecf20Sopenharmony_ci * 2. update old block address to new one; 2488c2ecf20Sopenharmony_ci */ 2498c2ecf20Sopenharmony_ci if (!new_ne && (get_nat_flag(ne, IS_PREALLOC) || 2508c2ecf20Sopenharmony_ci !get_nat_flag(ne, IS_DIRTY))) 2518c2ecf20Sopenharmony_ci head->entry_cnt++; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci set_nat_flag(ne, IS_PREALLOC, new_ne); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci if (get_nat_flag(ne, IS_DIRTY)) 2568c2ecf20Sopenharmony_ci goto refresh_list; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci nm_i->nat_cnt[DIRTY_NAT]++; 2598c2ecf20Sopenharmony_ci nm_i->nat_cnt[RECLAIMABLE_NAT]--; 2608c2ecf20Sopenharmony_ci set_nat_flag(ne, IS_DIRTY, true); 2618c2ecf20Sopenharmony_cirefresh_list: 2628c2ecf20Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 2638c2ecf20Sopenharmony_ci if (new_ne) 2648c2ecf20Sopenharmony_ci list_del_init(&ne->list); 2658c2ecf20Sopenharmony_ci else 2668c2ecf20Sopenharmony_ci list_move_tail(&ne->list, &head->entry_list); 2678c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i, 2718c2ecf20Sopenharmony_ci struct nat_entry_set *set, struct nat_entry *ne) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 2748c2ecf20Sopenharmony_ci list_move_tail(&ne->list, &nm_i->nat_entries); 2758c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci set_nat_flag(ne, IS_DIRTY, false); 2788c2ecf20Sopenharmony_ci set->entry_cnt--; 2798c2ecf20Sopenharmony_ci nm_i->nat_cnt[DIRTY_NAT]--; 2808c2ecf20Sopenharmony_ci nm_i->nat_cnt[RECLAIMABLE_NAT]++; 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic unsigned int __gang_lookup_nat_set(struct f2fs_nm_info *nm_i, 2848c2ecf20Sopenharmony_ci nid_t start, unsigned int nr, struct nat_entry_set **ep) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci return radix_tree_gang_lookup(&nm_i->nat_set_root, (void **)ep, 2878c2ecf20Sopenharmony_ci start, nr); 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cibool f2fs_in_warm_node_list(struct f2fs_sb_info *sbi, struct page *page) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci return NODE_MAPPING(sbi) == page->mapping && 2938c2ecf20Sopenharmony_ci IS_DNODE(page) && is_cold_node(page); 2948c2ecf20Sopenharmony_ci} 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_civoid f2fs_init_fsync_node_info(struct f2fs_sb_info *sbi) 2978c2ecf20Sopenharmony_ci{ 2988c2ecf20Sopenharmony_ci spin_lock_init(&sbi->fsync_node_lock); 2998c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->fsync_node_list); 3008c2ecf20Sopenharmony_ci sbi->fsync_seg_id = 0; 3018c2ecf20Sopenharmony_ci sbi->fsync_node_num = 0; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic unsigned int f2fs_add_fsync_node_entry(struct f2fs_sb_info *sbi, 3058c2ecf20Sopenharmony_ci struct page *page) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci struct fsync_node_entry *fn; 3088c2ecf20Sopenharmony_ci unsigned long flags; 3098c2ecf20Sopenharmony_ci unsigned int seq_id; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci fn = f2fs_kmem_cache_alloc(fsync_node_entry_slab, GFP_NOFS); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci get_page(page); 3148c2ecf20Sopenharmony_ci fn->page = page; 3158c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&fn->list); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci spin_lock_irqsave(&sbi->fsync_node_lock, flags); 3188c2ecf20Sopenharmony_ci list_add_tail(&fn->list, &sbi->fsync_node_list); 3198c2ecf20Sopenharmony_ci fn->seq_id = sbi->fsync_seg_id++; 3208c2ecf20Sopenharmony_ci seq_id = fn->seq_id; 3218c2ecf20Sopenharmony_ci sbi->fsync_node_num++; 3228c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci return seq_id; 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_civoid f2fs_del_fsync_node_entry(struct f2fs_sb_info *sbi, struct page *page) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci struct fsync_node_entry *fn; 3308c2ecf20Sopenharmony_ci unsigned long flags; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci spin_lock_irqsave(&sbi->fsync_node_lock, flags); 3338c2ecf20Sopenharmony_ci list_for_each_entry(fn, &sbi->fsync_node_list, list) { 3348c2ecf20Sopenharmony_ci if (fn->page == page) { 3358c2ecf20Sopenharmony_ci list_del(&fn->list); 3368c2ecf20Sopenharmony_ci sbi->fsync_node_num--; 3378c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 3388c2ecf20Sopenharmony_ci kmem_cache_free(fsync_node_entry_slab, fn); 3398c2ecf20Sopenharmony_ci put_page(page); 3408c2ecf20Sopenharmony_ci return; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 3448c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, 1); 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_civoid f2fs_reset_fsync_node_info(struct f2fs_sb_info *sbi) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci unsigned long flags; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci spin_lock_irqsave(&sbi->fsync_node_lock, flags); 3528c2ecf20Sopenharmony_ci sbi->fsync_seg_id = 0; 3538c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ciint f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 3598c2ecf20Sopenharmony_ci struct nat_entry *e; 3608c2ecf20Sopenharmony_ci bool need = false; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci down_read(&nm_i->nat_tree_lock); 3638c2ecf20Sopenharmony_ci e = __lookup_nat_cache(nm_i, nid); 3648c2ecf20Sopenharmony_ci if (e) { 3658c2ecf20Sopenharmony_ci if (!get_nat_flag(e, IS_CHECKPOINTED) && 3668c2ecf20Sopenharmony_ci !get_nat_flag(e, HAS_FSYNCED_INODE)) 3678c2ecf20Sopenharmony_ci need = true; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci up_read(&nm_i->nat_tree_lock); 3708c2ecf20Sopenharmony_ci return need; 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cibool f2fs_is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 3768c2ecf20Sopenharmony_ci struct nat_entry *e; 3778c2ecf20Sopenharmony_ci bool is_cp = true; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci down_read(&nm_i->nat_tree_lock); 3808c2ecf20Sopenharmony_ci e = __lookup_nat_cache(nm_i, nid); 3818c2ecf20Sopenharmony_ci if (e && !get_nat_flag(e, IS_CHECKPOINTED)) 3828c2ecf20Sopenharmony_ci is_cp = false; 3838c2ecf20Sopenharmony_ci up_read(&nm_i->nat_tree_lock); 3848c2ecf20Sopenharmony_ci return is_cp; 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cibool f2fs_need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 3908c2ecf20Sopenharmony_ci struct nat_entry *e; 3918c2ecf20Sopenharmony_ci bool need_update = true; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci down_read(&nm_i->nat_tree_lock); 3948c2ecf20Sopenharmony_ci e = __lookup_nat_cache(nm_i, ino); 3958c2ecf20Sopenharmony_ci if (e && get_nat_flag(e, HAS_LAST_FSYNC) && 3968c2ecf20Sopenharmony_ci (get_nat_flag(e, IS_CHECKPOINTED) || 3978c2ecf20Sopenharmony_ci get_nat_flag(e, HAS_FSYNCED_INODE))) 3988c2ecf20Sopenharmony_ci need_update = false; 3998c2ecf20Sopenharmony_ci up_read(&nm_i->nat_tree_lock); 4008c2ecf20Sopenharmony_ci return need_update; 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci/* must be locked by nat_tree_lock */ 4048c2ecf20Sopenharmony_cistatic void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid, 4058c2ecf20Sopenharmony_ci struct f2fs_nat_entry *ne) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 4088c2ecf20Sopenharmony_ci struct nat_entry *new, *e; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci new = __alloc_nat_entry(nid, false); 4118c2ecf20Sopenharmony_ci if (!new) 4128c2ecf20Sopenharmony_ci return; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci down_write(&nm_i->nat_tree_lock); 4158c2ecf20Sopenharmony_ci e = __lookup_nat_cache(nm_i, nid); 4168c2ecf20Sopenharmony_ci if (!e) 4178c2ecf20Sopenharmony_ci e = __init_nat_entry(nm_i, new, ne, false); 4188c2ecf20Sopenharmony_ci else 4198c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, nat_get_ino(e) != le32_to_cpu(ne->ino) || 4208c2ecf20Sopenharmony_ci nat_get_blkaddr(e) != 4218c2ecf20Sopenharmony_ci le32_to_cpu(ne->block_addr) || 4228c2ecf20Sopenharmony_ci nat_get_version(e) != ne->version); 4238c2ecf20Sopenharmony_ci up_write(&nm_i->nat_tree_lock); 4248c2ecf20Sopenharmony_ci if (e != new) 4258c2ecf20Sopenharmony_ci __free_nat_entry(new); 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_cistatic void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni, 4298c2ecf20Sopenharmony_ci block_t new_blkaddr, bool fsync_done) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 4328c2ecf20Sopenharmony_ci struct nat_entry *e; 4338c2ecf20Sopenharmony_ci struct nat_entry *new = __alloc_nat_entry(ni->nid, true); 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci down_write(&nm_i->nat_tree_lock); 4368c2ecf20Sopenharmony_ci e = __lookup_nat_cache(nm_i, ni->nid); 4378c2ecf20Sopenharmony_ci if (!e) { 4388c2ecf20Sopenharmony_ci e = __init_nat_entry(nm_i, new, NULL, true); 4398c2ecf20Sopenharmony_ci copy_node_info(&e->ni, ni); 4408c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, ni->blk_addr == NEW_ADDR); 4418c2ecf20Sopenharmony_ci } else if (new_blkaddr == NEW_ADDR) { 4428c2ecf20Sopenharmony_ci /* 4438c2ecf20Sopenharmony_ci * when nid is reallocated, 4448c2ecf20Sopenharmony_ci * previous nat entry can be remained in nat cache. 4458c2ecf20Sopenharmony_ci * So, reinitialize it with new information. 4468c2ecf20Sopenharmony_ci */ 4478c2ecf20Sopenharmony_ci copy_node_info(&e->ni, ni); 4488c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, ni->blk_addr != NULL_ADDR); 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci /* let's free early to reduce memory consumption */ 4518c2ecf20Sopenharmony_ci if (e != new) 4528c2ecf20Sopenharmony_ci __free_nat_entry(new); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci /* sanity check */ 4558c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, nat_get_blkaddr(e) != ni->blk_addr); 4568c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, nat_get_blkaddr(e) == NULL_ADDR && 4578c2ecf20Sopenharmony_ci new_blkaddr == NULL_ADDR); 4588c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, nat_get_blkaddr(e) == NEW_ADDR && 4598c2ecf20Sopenharmony_ci new_blkaddr == NEW_ADDR); 4608c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, __is_valid_data_blkaddr(nat_get_blkaddr(e)) && 4618c2ecf20Sopenharmony_ci new_blkaddr == NEW_ADDR); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci /* increment version no as node is removed */ 4648c2ecf20Sopenharmony_ci if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) { 4658c2ecf20Sopenharmony_ci unsigned char version = nat_get_version(e); 4668c2ecf20Sopenharmony_ci nat_set_version(e, inc_node_version(version)); 4678c2ecf20Sopenharmony_ci } 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci /* change address */ 4708c2ecf20Sopenharmony_ci nat_set_blkaddr(e, new_blkaddr); 4718c2ecf20Sopenharmony_ci if (!__is_valid_data_blkaddr(new_blkaddr)) 4728c2ecf20Sopenharmony_ci set_nat_flag(e, IS_CHECKPOINTED, false); 4738c2ecf20Sopenharmony_ci __set_nat_cache_dirty(nm_i, e); 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci /* update fsync_mark if its inode nat entry is still alive */ 4768c2ecf20Sopenharmony_ci if (ni->nid != ni->ino) 4778c2ecf20Sopenharmony_ci e = __lookup_nat_cache(nm_i, ni->ino); 4788c2ecf20Sopenharmony_ci if (e) { 4798c2ecf20Sopenharmony_ci if (fsync_done && ni->nid == ni->ino) 4808c2ecf20Sopenharmony_ci set_nat_flag(e, HAS_FSYNCED_INODE, true); 4818c2ecf20Sopenharmony_ci set_nat_flag(e, HAS_LAST_FSYNC, fsync_done); 4828c2ecf20Sopenharmony_ci } 4838c2ecf20Sopenharmony_ci up_write(&nm_i->nat_tree_lock); 4848c2ecf20Sopenharmony_ci} 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ciint f2fs_try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 4898c2ecf20Sopenharmony_ci int nr = nr_shrink; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci if (!down_write_trylock(&nm_i->nat_tree_lock)) 4928c2ecf20Sopenharmony_ci return 0; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 4958c2ecf20Sopenharmony_ci while (nr_shrink) { 4968c2ecf20Sopenharmony_ci struct nat_entry *ne; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci if (list_empty(&nm_i->nat_entries)) 4998c2ecf20Sopenharmony_ci break; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci ne = list_first_entry(&nm_i->nat_entries, 5028c2ecf20Sopenharmony_ci struct nat_entry, list); 5038c2ecf20Sopenharmony_ci list_del(&ne->list); 5048c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci __del_from_nat_cache(nm_i, ne); 5078c2ecf20Sopenharmony_ci nr_shrink--; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 5108c2ecf20Sopenharmony_ci } 5118c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci up_write(&nm_i->nat_tree_lock); 5148c2ecf20Sopenharmony_ci return nr - nr_shrink; 5158c2ecf20Sopenharmony_ci} 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ciint f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid, 5188c2ecf20Sopenharmony_ci struct node_info *ni) 5198c2ecf20Sopenharmony_ci{ 5208c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 5218c2ecf20Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 5228c2ecf20Sopenharmony_ci struct f2fs_journal *journal = curseg->journal; 5238c2ecf20Sopenharmony_ci nid_t start_nid = START_NID(nid); 5248c2ecf20Sopenharmony_ci struct f2fs_nat_block *nat_blk; 5258c2ecf20Sopenharmony_ci struct page *page = NULL; 5268c2ecf20Sopenharmony_ci struct f2fs_nat_entry ne; 5278c2ecf20Sopenharmony_ci struct nat_entry *e; 5288c2ecf20Sopenharmony_ci pgoff_t index; 5298c2ecf20Sopenharmony_ci block_t blkaddr; 5308c2ecf20Sopenharmony_ci int i; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci ni->nid = nid; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci /* Check nat cache */ 5358c2ecf20Sopenharmony_ci down_read(&nm_i->nat_tree_lock); 5368c2ecf20Sopenharmony_ci e = __lookup_nat_cache(nm_i, nid); 5378c2ecf20Sopenharmony_ci if (e) { 5388c2ecf20Sopenharmony_ci ni->ino = nat_get_ino(e); 5398c2ecf20Sopenharmony_ci ni->blk_addr = nat_get_blkaddr(e); 5408c2ecf20Sopenharmony_ci ni->version = nat_get_version(e); 5418c2ecf20Sopenharmony_ci up_read(&nm_i->nat_tree_lock); 5428c2ecf20Sopenharmony_ci return 0; 5438c2ecf20Sopenharmony_ci } 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci memset(&ne, 0, sizeof(struct f2fs_nat_entry)); 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci /* Check current segment summary */ 5488c2ecf20Sopenharmony_ci down_read(&curseg->journal_rwsem); 5498c2ecf20Sopenharmony_ci i = f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0); 5508c2ecf20Sopenharmony_ci if (i >= 0) { 5518c2ecf20Sopenharmony_ci ne = nat_in_journal(journal, i); 5528c2ecf20Sopenharmony_ci node_info_from_raw_nat(ni, &ne); 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci up_read(&curseg->journal_rwsem); 5558c2ecf20Sopenharmony_ci if (i >= 0) { 5568c2ecf20Sopenharmony_ci up_read(&nm_i->nat_tree_lock); 5578c2ecf20Sopenharmony_ci goto cache; 5588c2ecf20Sopenharmony_ci } 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci /* Fill node_info from nat page */ 5618c2ecf20Sopenharmony_ci index = current_nat_addr(sbi, nid); 5628c2ecf20Sopenharmony_ci up_read(&nm_i->nat_tree_lock); 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci page = f2fs_get_meta_page(sbi, index); 5658c2ecf20Sopenharmony_ci if (IS_ERR(page)) 5668c2ecf20Sopenharmony_ci return PTR_ERR(page); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci nat_blk = (struct f2fs_nat_block *)page_address(page); 5698c2ecf20Sopenharmony_ci ne = nat_blk->entries[nid - start_nid]; 5708c2ecf20Sopenharmony_ci node_info_from_raw_nat(ni, &ne); 5718c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 5728c2ecf20Sopenharmony_cicache: 5738c2ecf20Sopenharmony_ci blkaddr = le32_to_cpu(ne.block_addr); 5748c2ecf20Sopenharmony_ci if (__is_valid_data_blkaddr(blkaddr) && 5758c2ecf20Sopenharmony_ci !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) 5768c2ecf20Sopenharmony_ci return -EFAULT; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci /* cache nat entry */ 5798c2ecf20Sopenharmony_ci cache_nat_entry(sbi, nid, &ne); 5808c2ecf20Sopenharmony_ci return 0; 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci/* 5848c2ecf20Sopenharmony_ci * readahead MAX_RA_NODE number of node pages. 5858c2ecf20Sopenharmony_ci */ 5868c2ecf20Sopenharmony_cistatic void f2fs_ra_node_pages(struct page *parent, int start, int n) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(parent); 5898c2ecf20Sopenharmony_ci struct blk_plug plug; 5908c2ecf20Sopenharmony_ci int i, end; 5918c2ecf20Sopenharmony_ci nid_t nid; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci blk_start_plug(&plug); 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci /* Then, try readahead for siblings of the desired node */ 5968c2ecf20Sopenharmony_ci end = start + n; 5978c2ecf20Sopenharmony_ci end = min(end, NIDS_PER_BLOCK); 5988c2ecf20Sopenharmony_ci for (i = start; i < end; i++) { 5998c2ecf20Sopenharmony_ci nid = get_nid(parent, i, false); 6008c2ecf20Sopenharmony_ci f2fs_ra_node_page(sbi, nid); 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci blk_finish_plug(&plug); 6048c2ecf20Sopenharmony_ci} 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_cipgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs) 6078c2ecf20Sopenharmony_ci{ 6088c2ecf20Sopenharmony_ci const long direct_index = ADDRS_PER_INODE(dn->inode); 6098c2ecf20Sopenharmony_ci const long direct_blks = ADDRS_PER_BLOCK(dn->inode); 6108c2ecf20Sopenharmony_ci const long indirect_blks = ADDRS_PER_BLOCK(dn->inode) * NIDS_PER_BLOCK; 6118c2ecf20Sopenharmony_ci unsigned int skipped_unit = ADDRS_PER_BLOCK(dn->inode); 6128c2ecf20Sopenharmony_ci int cur_level = dn->cur_level; 6138c2ecf20Sopenharmony_ci int max_level = dn->max_level; 6148c2ecf20Sopenharmony_ci pgoff_t base = 0; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if (!dn->max_level) 6178c2ecf20Sopenharmony_ci return pgofs + 1; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci while (max_level-- > cur_level) 6208c2ecf20Sopenharmony_ci skipped_unit *= NIDS_PER_BLOCK; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci switch (dn->max_level) { 6238c2ecf20Sopenharmony_ci case 3: 6248c2ecf20Sopenharmony_ci base += 2 * indirect_blks; 6258c2ecf20Sopenharmony_ci fallthrough; 6268c2ecf20Sopenharmony_ci case 2: 6278c2ecf20Sopenharmony_ci base += 2 * direct_blks; 6288c2ecf20Sopenharmony_ci fallthrough; 6298c2ecf20Sopenharmony_ci case 1: 6308c2ecf20Sopenharmony_ci base += direct_index; 6318c2ecf20Sopenharmony_ci break; 6328c2ecf20Sopenharmony_ci default: 6338c2ecf20Sopenharmony_ci f2fs_bug_on(F2FS_I_SB(dn->inode), 1); 6348c2ecf20Sopenharmony_ci } 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci return ((pgofs - base) / skipped_unit + 1) * skipped_unit + base; 6378c2ecf20Sopenharmony_ci} 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci/* 6408c2ecf20Sopenharmony_ci * The maximum depth is four. 6418c2ecf20Sopenharmony_ci * Offset[0] will have raw inode offset. 6428c2ecf20Sopenharmony_ci */ 6438c2ecf20Sopenharmony_cistatic int get_node_path(struct inode *inode, long block, 6448c2ecf20Sopenharmony_ci int offset[4], unsigned int noffset[4]) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci const long direct_index = ADDRS_PER_INODE(inode); 6478c2ecf20Sopenharmony_ci const long direct_blks = ADDRS_PER_BLOCK(inode); 6488c2ecf20Sopenharmony_ci const long dptrs_per_blk = NIDS_PER_BLOCK; 6498c2ecf20Sopenharmony_ci const long indirect_blks = ADDRS_PER_BLOCK(inode) * NIDS_PER_BLOCK; 6508c2ecf20Sopenharmony_ci const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK; 6518c2ecf20Sopenharmony_ci int n = 0; 6528c2ecf20Sopenharmony_ci int level = 0; 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci noffset[0] = 0; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci if (block < direct_index) { 6578c2ecf20Sopenharmony_ci offset[n] = block; 6588c2ecf20Sopenharmony_ci goto got; 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci block -= direct_index; 6618c2ecf20Sopenharmony_ci if (block < direct_blks) { 6628c2ecf20Sopenharmony_ci offset[n++] = NODE_DIR1_BLOCK; 6638c2ecf20Sopenharmony_ci noffset[n] = 1; 6648c2ecf20Sopenharmony_ci offset[n] = block; 6658c2ecf20Sopenharmony_ci level = 1; 6668c2ecf20Sopenharmony_ci goto got; 6678c2ecf20Sopenharmony_ci } 6688c2ecf20Sopenharmony_ci block -= direct_blks; 6698c2ecf20Sopenharmony_ci if (block < direct_blks) { 6708c2ecf20Sopenharmony_ci offset[n++] = NODE_DIR2_BLOCK; 6718c2ecf20Sopenharmony_ci noffset[n] = 2; 6728c2ecf20Sopenharmony_ci offset[n] = block; 6738c2ecf20Sopenharmony_ci level = 1; 6748c2ecf20Sopenharmony_ci goto got; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci block -= direct_blks; 6778c2ecf20Sopenharmony_ci if (block < indirect_blks) { 6788c2ecf20Sopenharmony_ci offset[n++] = NODE_IND1_BLOCK; 6798c2ecf20Sopenharmony_ci noffset[n] = 3; 6808c2ecf20Sopenharmony_ci offset[n++] = block / direct_blks; 6818c2ecf20Sopenharmony_ci noffset[n] = 4 + offset[n - 1]; 6828c2ecf20Sopenharmony_ci offset[n] = block % direct_blks; 6838c2ecf20Sopenharmony_ci level = 2; 6848c2ecf20Sopenharmony_ci goto got; 6858c2ecf20Sopenharmony_ci } 6868c2ecf20Sopenharmony_ci block -= indirect_blks; 6878c2ecf20Sopenharmony_ci if (block < indirect_blks) { 6888c2ecf20Sopenharmony_ci offset[n++] = NODE_IND2_BLOCK; 6898c2ecf20Sopenharmony_ci noffset[n] = 4 + dptrs_per_blk; 6908c2ecf20Sopenharmony_ci offset[n++] = block / direct_blks; 6918c2ecf20Sopenharmony_ci noffset[n] = 5 + dptrs_per_blk + offset[n - 1]; 6928c2ecf20Sopenharmony_ci offset[n] = block % direct_blks; 6938c2ecf20Sopenharmony_ci level = 2; 6948c2ecf20Sopenharmony_ci goto got; 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci block -= indirect_blks; 6978c2ecf20Sopenharmony_ci if (block < dindirect_blks) { 6988c2ecf20Sopenharmony_ci offset[n++] = NODE_DIND_BLOCK; 6998c2ecf20Sopenharmony_ci noffset[n] = 5 + (dptrs_per_blk * 2); 7008c2ecf20Sopenharmony_ci offset[n++] = block / indirect_blks; 7018c2ecf20Sopenharmony_ci noffset[n] = 6 + (dptrs_per_blk * 2) + 7028c2ecf20Sopenharmony_ci offset[n - 1] * (dptrs_per_blk + 1); 7038c2ecf20Sopenharmony_ci offset[n++] = (block / direct_blks) % dptrs_per_blk; 7048c2ecf20Sopenharmony_ci noffset[n] = 7 + (dptrs_per_blk * 2) + 7058c2ecf20Sopenharmony_ci offset[n - 2] * (dptrs_per_blk + 1) + 7068c2ecf20Sopenharmony_ci offset[n - 1]; 7078c2ecf20Sopenharmony_ci offset[n] = block % direct_blks; 7088c2ecf20Sopenharmony_ci level = 3; 7098c2ecf20Sopenharmony_ci goto got; 7108c2ecf20Sopenharmony_ci } else { 7118c2ecf20Sopenharmony_ci return -E2BIG; 7128c2ecf20Sopenharmony_ci } 7138c2ecf20Sopenharmony_cigot: 7148c2ecf20Sopenharmony_ci return level; 7158c2ecf20Sopenharmony_ci} 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci/* 7188c2ecf20Sopenharmony_ci * Caller should call f2fs_put_dnode(dn). 7198c2ecf20Sopenharmony_ci * Also, it should grab and release a rwsem by calling f2fs_lock_op() and 7208c2ecf20Sopenharmony_ci * f2fs_unlock_op() only if mode is set with ALLOC_NODE. 7218c2ecf20Sopenharmony_ci */ 7228c2ecf20Sopenharmony_ciint f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) 7238c2ecf20Sopenharmony_ci{ 7248c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); 7258c2ecf20Sopenharmony_ci struct page *npage[4]; 7268c2ecf20Sopenharmony_ci struct page *parent = NULL; 7278c2ecf20Sopenharmony_ci int offset[4]; 7288c2ecf20Sopenharmony_ci unsigned int noffset[4]; 7298c2ecf20Sopenharmony_ci nid_t nids[4]; 7308c2ecf20Sopenharmony_ci int level, i = 0; 7318c2ecf20Sopenharmony_ci int err = 0; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci level = get_node_path(dn->inode, index, offset, noffset); 7348c2ecf20Sopenharmony_ci if (level < 0) 7358c2ecf20Sopenharmony_ci return level; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci nids[0] = dn->inode->i_ino; 7388c2ecf20Sopenharmony_ci npage[0] = dn->inode_page; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci if (!npage[0]) { 7418c2ecf20Sopenharmony_ci npage[0] = f2fs_get_node_page(sbi, nids[0]); 7428c2ecf20Sopenharmony_ci if (IS_ERR(npage[0])) 7438c2ecf20Sopenharmony_ci return PTR_ERR(npage[0]); 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci /* if inline_data is set, should not report any block indices */ 7478c2ecf20Sopenharmony_ci if (f2fs_has_inline_data(dn->inode) && index) { 7488c2ecf20Sopenharmony_ci err = -ENOENT; 7498c2ecf20Sopenharmony_ci f2fs_put_page(npage[0], 1); 7508c2ecf20Sopenharmony_ci goto release_out; 7518c2ecf20Sopenharmony_ci } 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci parent = npage[0]; 7548c2ecf20Sopenharmony_ci if (level != 0) 7558c2ecf20Sopenharmony_ci nids[1] = get_nid(parent, offset[0], true); 7568c2ecf20Sopenharmony_ci dn->inode_page = npage[0]; 7578c2ecf20Sopenharmony_ci dn->inode_page_locked = true; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci /* get indirect or direct nodes */ 7608c2ecf20Sopenharmony_ci for (i = 1; i <= level; i++) { 7618c2ecf20Sopenharmony_ci bool done = false; 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci if (!nids[i] && mode == ALLOC_NODE) { 7648c2ecf20Sopenharmony_ci /* alloc new node */ 7658c2ecf20Sopenharmony_ci if (!f2fs_alloc_nid(sbi, &(nids[i]))) { 7668c2ecf20Sopenharmony_ci err = -ENOSPC; 7678c2ecf20Sopenharmony_ci goto release_pages; 7688c2ecf20Sopenharmony_ci } 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci dn->nid = nids[i]; 7718c2ecf20Sopenharmony_ci npage[i] = f2fs_new_node_page(dn, noffset[i]); 7728c2ecf20Sopenharmony_ci if (IS_ERR(npage[i])) { 7738c2ecf20Sopenharmony_ci f2fs_alloc_nid_failed(sbi, nids[i]); 7748c2ecf20Sopenharmony_ci err = PTR_ERR(npage[i]); 7758c2ecf20Sopenharmony_ci goto release_pages; 7768c2ecf20Sopenharmony_ci } 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci set_nid(parent, offset[i - 1], nids[i], i == 1); 7798c2ecf20Sopenharmony_ci f2fs_alloc_nid_done(sbi, nids[i]); 7808c2ecf20Sopenharmony_ci done = true; 7818c2ecf20Sopenharmony_ci } else if (mode == LOOKUP_NODE_RA && i == level && level > 1) { 7828c2ecf20Sopenharmony_ci npage[i] = f2fs_get_node_page_ra(parent, offset[i - 1]); 7838c2ecf20Sopenharmony_ci if (IS_ERR(npage[i])) { 7848c2ecf20Sopenharmony_ci err = PTR_ERR(npage[i]); 7858c2ecf20Sopenharmony_ci goto release_pages; 7868c2ecf20Sopenharmony_ci } 7878c2ecf20Sopenharmony_ci done = true; 7888c2ecf20Sopenharmony_ci } 7898c2ecf20Sopenharmony_ci if (i == 1) { 7908c2ecf20Sopenharmony_ci dn->inode_page_locked = false; 7918c2ecf20Sopenharmony_ci unlock_page(parent); 7928c2ecf20Sopenharmony_ci } else { 7938c2ecf20Sopenharmony_ci f2fs_put_page(parent, 1); 7948c2ecf20Sopenharmony_ci } 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci if (!done) { 7978c2ecf20Sopenharmony_ci npage[i] = f2fs_get_node_page(sbi, nids[i]); 7988c2ecf20Sopenharmony_ci if (IS_ERR(npage[i])) { 7998c2ecf20Sopenharmony_ci err = PTR_ERR(npage[i]); 8008c2ecf20Sopenharmony_ci f2fs_put_page(npage[0], 0); 8018c2ecf20Sopenharmony_ci goto release_out; 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci } 8048c2ecf20Sopenharmony_ci if (i < level) { 8058c2ecf20Sopenharmony_ci parent = npage[i]; 8068c2ecf20Sopenharmony_ci nids[i + 1] = get_nid(parent, offset[i], false); 8078c2ecf20Sopenharmony_ci } 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci dn->nid = nids[level]; 8108c2ecf20Sopenharmony_ci dn->ofs_in_node = offset[level]; 8118c2ecf20Sopenharmony_ci dn->node_page = npage[level]; 8128c2ecf20Sopenharmony_ci dn->data_blkaddr = f2fs_data_blkaddr(dn); 8138c2ecf20Sopenharmony_ci return 0; 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_cirelease_pages: 8168c2ecf20Sopenharmony_ci f2fs_put_page(parent, 1); 8178c2ecf20Sopenharmony_ci if (i > 1) 8188c2ecf20Sopenharmony_ci f2fs_put_page(npage[0], 0); 8198c2ecf20Sopenharmony_cirelease_out: 8208c2ecf20Sopenharmony_ci dn->inode_page = NULL; 8218c2ecf20Sopenharmony_ci dn->node_page = NULL; 8228c2ecf20Sopenharmony_ci if (err == -ENOENT) { 8238c2ecf20Sopenharmony_ci dn->cur_level = i; 8248c2ecf20Sopenharmony_ci dn->max_level = level; 8258c2ecf20Sopenharmony_ci dn->ofs_in_node = offset[level]; 8268c2ecf20Sopenharmony_ci } 8278c2ecf20Sopenharmony_ci return err; 8288c2ecf20Sopenharmony_ci} 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_cistatic int truncate_node(struct dnode_of_data *dn) 8318c2ecf20Sopenharmony_ci{ 8328c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); 8338c2ecf20Sopenharmony_ci struct node_info ni; 8348c2ecf20Sopenharmony_ci int err; 8358c2ecf20Sopenharmony_ci pgoff_t index; 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci err = f2fs_get_node_info(sbi, dn->nid, &ni); 8388c2ecf20Sopenharmony_ci if (err) 8398c2ecf20Sopenharmony_ci return err; 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci /* Deallocate node address */ 8428c2ecf20Sopenharmony_ci f2fs_invalidate_blocks(sbi, ni.blk_addr); 8438c2ecf20Sopenharmony_ci dec_valid_node_count(sbi, dn->inode, dn->nid == dn->inode->i_ino); 8448c2ecf20Sopenharmony_ci set_node_addr(sbi, &ni, NULL_ADDR, false); 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci if (dn->nid == dn->inode->i_ino) { 8478c2ecf20Sopenharmony_ci f2fs_remove_orphan_inode(sbi, dn->nid); 8488c2ecf20Sopenharmony_ci dec_valid_inode_count(sbi); 8498c2ecf20Sopenharmony_ci f2fs_inode_synced(dn->inode); 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci clear_node_page_dirty(dn->node_page); 8538c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_IS_DIRTY); 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci index = dn->node_page->index; 8568c2ecf20Sopenharmony_ci f2fs_put_page(dn->node_page, 1); 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci invalidate_mapping_pages(NODE_MAPPING(sbi), 8598c2ecf20Sopenharmony_ci index, index); 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci dn->node_page = NULL; 8628c2ecf20Sopenharmony_ci trace_f2fs_truncate_node(dn->inode, dn->nid, ni.blk_addr); 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci return 0; 8658c2ecf20Sopenharmony_ci} 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_cistatic int truncate_dnode(struct dnode_of_data *dn) 8688c2ecf20Sopenharmony_ci{ 8698c2ecf20Sopenharmony_ci struct page *page; 8708c2ecf20Sopenharmony_ci int err; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci if (dn->nid == 0) 8738c2ecf20Sopenharmony_ci return 1; 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci /* get direct node */ 8768c2ecf20Sopenharmony_ci page = f2fs_get_node_page(F2FS_I_SB(dn->inode), dn->nid); 8778c2ecf20Sopenharmony_ci if (PTR_ERR(page) == -ENOENT) 8788c2ecf20Sopenharmony_ci return 1; 8798c2ecf20Sopenharmony_ci else if (IS_ERR(page)) 8808c2ecf20Sopenharmony_ci return PTR_ERR(page); 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci /* Make dnode_of_data for parameter */ 8838c2ecf20Sopenharmony_ci dn->node_page = page; 8848c2ecf20Sopenharmony_ci dn->ofs_in_node = 0; 8858c2ecf20Sopenharmony_ci f2fs_truncate_data_blocks(dn); 8868c2ecf20Sopenharmony_ci err = truncate_node(dn); 8878c2ecf20Sopenharmony_ci if (err) { 8888c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 8898c2ecf20Sopenharmony_ci return err; 8908c2ecf20Sopenharmony_ci } 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci return 1; 8938c2ecf20Sopenharmony_ci} 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_cistatic int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, 8968c2ecf20Sopenharmony_ci int ofs, int depth) 8978c2ecf20Sopenharmony_ci{ 8988c2ecf20Sopenharmony_ci struct dnode_of_data rdn = *dn; 8998c2ecf20Sopenharmony_ci struct page *page; 9008c2ecf20Sopenharmony_ci struct f2fs_node *rn; 9018c2ecf20Sopenharmony_ci nid_t child_nid; 9028c2ecf20Sopenharmony_ci unsigned int child_nofs; 9038c2ecf20Sopenharmony_ci int freed = 0; 9048c2ecf20Sopenharmony_ci int i, ret; 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci if (dn->nid == 0) 9078c2ecf20Sopenharmony_ci return NIDS_PER_BLOCK + 1; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci page = f2fs_get_node_page(F2FS_I_SB(dn->inode), dn->nid); 9128c2ecf20Sopenharmony_ci if (IS_ERR(page)) { 9138c2ecf20Sopenharmony_ci trace_f2fs_truncate_nodes_exit(dn->inode, PTR_ERR(page)); 9148c2ecf20Sopenharmony_ci return PTR_ERR(page); 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci f2fs_ra_node_pages(page, ofs, NIDS_PER_BLOCK); 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci rn = F2FS_NODE(page); 9208c2ecf20Sopenharmony_ci if (depth < 3) { 9218c2ecf20Sopenharmony_ci for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) { 9228c2ecf20Sopenharmony_ci child_nid = le32_to_cpu(rn->in.nid[i]); 9238c2ecf20Sopenharmony_ci if (child_nid == 0) 9248c2ecf20Sopenharmony_ci continue; 9258c2ecf20Sopenharmony_ci rdn.nid = child_nid; 9268c2ecf20Sopenharmony_ci ret = truncate_dnode(&rdn); 9278c2ecf20Sopenharmony_ci if (ret < 0) 9288c2ecf20Sopenharmony_ci goto out_err; 9298c2ecf20Sopenharmony_ci if (set_nid(page, i, 0, false)) 9308c2ecf20Sopenharmony_ci dn->node_changed = true; 9318c2ecf20Sopenharmony_ci } 9328c2ecf20Sopenharmony_ci } else { 9338c2ecf20Sopenharmony_ci child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1; 9348c2ecf20Sopenharmony_ci for (i = ofs; i < NIDS_PER_BLOCK; i++) { 9358c2ecf20Sopenharmony_ci child_nid = le32_to_cpu(rn->in.nid[i]); 9368c2ecf20Sopenharmony_ci if (child_nid == 0) { 9378c2ecf20Sopenharmony_ci child_nofs += NIDS_PER_BLOCK + 1; 9388c2ecf20Sopenharmony_ci continue; 9398c2ecf20Sopenharmony_ci } 9408c2ecf20Sopenharmony_ci rdn.nid = child_nid; 9418c2ecf20Sopenharmony_ci ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1); 9428c2ecf20Sopenharmony_ci if (ret == (NIDS_PER_BLOCK + 1)) { 9438c2ecf20Sopenharmony_ci if (set_nid(page, i, 0, false)) 9448c2ecf20Sopenharmony_ci dn->node_changed = true; 9458c2ecf20Sopenharmony_ci child_nofs += ret; 9468c2ecf20Sopenharmony_ci } else if (ret < 0 && ret != -ENOENT) { 9478c2ecf20Sopenharmony_ci goto out_err; 9488c2ecf20Sopenharmony_ci } 9498c2ecf20Sopenharmony_ci } 9508c2ecf20Sopenharmony_ci freed = child_nofs; 9518c2ecf20Sopenharmony_ci } 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci if (!ofs) { 9548c2ecf20Sopenharmony_ci /* remove current indirect node */ 9558c2ecf20Sopenharmony_ci dn->node_page = page; 9568c2ecf20Sopenharmony_ci ret = truncate_node(dn); 9578c2ecf20Sopenharmony_ci if (ret) 9588c2ecf20Sopenharmony_ci goto out_err; 9598c2ecf20Sopenharmony_ci freed++; 9608c2ecf20Sopenharmony_ci } else { 9618c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 9628c2ecf20Sopenharmony_ci } 9638c2ecf20Sopenharmony_ci trace_f2fs_truncate_nodes_exit(dn->inode, freed); 9648c2ecf20Sopenharmony_ci return freed; 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ciout_err: 9678c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 9688c2ecf20Sopenharmony_ci trace_f2fs_truncate_nodes_exit(dn->inode, ret); 9698c2ecf20Sopenharmony_ci return ret; 9708c2ecf20Sopenharmony_ci} 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_cistatic int truncate_partial_nodes(struct dnode_of_data *dn, 9738c2ecf20Sopenharmony_ci struct f2fs_inode *ri, int *offset, int depth) 9748c2ecf20Sopenharmony_ci{ 9758c2ecf20Sopenharmony_ci struct page *pages[2]; 9768c2ecf20Sopenharmony_ci nid_t nid[3]; 9778c2ecf20Sopenharmony_ci nid_t child_nid; 9788c2ecf20Sopenharmony_ci int err = 0; 9798c2ecf20Sopenharmony_ci int i; 9808c2ecf20Sopenharmony_ci int idx = depth - 2; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci nid[0] = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]); 9838c2ecf20Sopenharmony_ci if (!nid[0]) 9848c2ecf20Sopenharmony_ci return 0; 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci /* get indirect nodes in the path */ 9878c2ecf20Sopenharmony_ci for (i = 0; i < idx + 1; i++) { 9888c2ecf20Sopenharmony_ci /* reference count'll be increased */ 9898c2ecf20Sopenharmony_ci pages[i] = f2fs_get_node_page(F2FS_I_SB(dn->inode), nid[i]); 9908c2ecf20Sopenharmony_ci if (IS_ERR(pages[i])) { 9918c2ecf20Sopenharmony_ci err = PTR_ERR(pages[i]); 9928c2ecf20Sopenharmony_ci idx = i - 1; 9938c2ecf20Sopenharmony_ci goto fail; 9948c2ecf20Sopenharmony_ci } 9958c2ecf20Sopenharmony_ci nid[i + 1] = get_nid(pages[i], offset[i + 1], false); 9968c2ecf20Sopenharmony_ci } 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci f2fs_ra_node_pages(pages[idx], offset[idx + 1], NIDS_PER_BLOCK); 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci /* free direct nodes linked to a partial indirect node */ 10018c2ecf20Sopenharmony_ci for (i = offset[idx + 1]; i < NIDS_PER_BLOCK; i++) { 10028c2ecf20Sopenharmony_ci child_nid = get_nid(pages[idx], i, false); 10038c2ecf20Sopenharmony_ci if (!child_nid) 10048c2ecf20Sopenharmony_ci continue; 10058c2ecf20Sopenharmony_ci dn->nid = child_nid; 10068c2ecf20Sopenharmony_ci err = truncate_dnode(dn); 10078c2ecf20Sopenharmony_ci if (err < 0) 10088c2ecf20Sopenharmony_ci goto fail; 10098c2ecf20Sopenharmony_ci if (set_nid(pages[idx], i, 0, false)) 10108c2ecf20Sopenharmony_ci dn->node_changed = true; 10118c2ecf20Sopenharmony_ci } 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci if (offset[idx + 1] == 0) { 10148c2ecf20Sopenharmony_ci dn->node_page = pages[idx]; 10158c2ecf20Sopenharmony_ci dn->nid = nid[idx]; 10168c2ecf20Sopenharmony_ci err = truncate_node(dn); 10178c2ecf20Sopenharmony_ci if (err) 10188c2ecf20Sopenharmony_ci goto fail; 10198c2ecf20Sopenharmony_ci } else { 10208c2ecf20Sopenharmony_ci f2fs_put_page(pages[idx], 1); 10218c2ecf20Sopenharmony_ci } 10228c2ecf20Sopenharmony_ci offset[idx]++; 10238c2ecf20Sopenharmony_ci offset[idx + 1] = 0; 10248c2ecf20Sopenharmony_ci idx--; 10258c2ecf20Sopenharmony_cifail: 10268c2ecf20Sopenharmony_ci for (i = idx; i >= 0; i--) 10278c2ecf20Sopenharmony_ci f2fs_put_page(pages[i], 1); 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci trace_f2fs_truncate_partial_nodes(dn->inode, nid, depth, err); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci return err; 10328c2ecf20Sopenharmony_ci} 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci/* 10358c2ecf20Sopenharmony_ci * All the block addresses of data and nodes should be nullified. 10368c2ecf20Sopenharmony_ci */ 10378c2ecf20Sopenharmony_ciint f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from) 10388c2ecf20Sopenharmony_ci{ 10398c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 10408c2ecf20Sopenharmony_ci int err = 0, cont = 1; 10418c2ecf20Sopenharmony_ci int level, offset[4], noffset[4]; 10428c2ecf20Sopenharmony_ci unsigned int nofs = 0; 10438c2ecf20Sopenharmony_ci struct f2fs_inode *ri; 10448c2ecf20Sopenharmony_ci struct dnode_of_data dn; 10458c2ecf20Sopenharmony_ci struct page *page; 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci trace_f2fs_truncate_inode_blocks_enter(inode, from); 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci level = get_node_path(inode, from, offset, noffset); 10508c2ecf20Sopenharmony_ci if (level < 0) { 10518c2ecf20Sopenharmony_ci trace_f2fs_truncate_inode_blocks_exit(inode, level); 10528c2ecf20Sopenharmony_ci return level; 10538c2ecf20Sopenharmony_ci } 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci page = f2fs_get_node_page(sbi, inode->i_ino); 10568c2ecf20Sopenharmony_ci if (IS_ERR(page)) { 10578c2ecf20Sopenharmony_ci trace_f2fs_truncate_inode_blocks_exit(inode, PTR_ERR(page)); 10588c2ecf20Sopenharmony_ci return PTR_ERR(page); 10598c2ecf20Sopenharmony_ci } 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci set_new_dnode(&dn, inode, page, NULL, 0); 10628c2ecf20Sopenharmony_ci unlock_page(page); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci ri = F2FS_INODE(page); 10658c2ecf20Sopenharmony_ci switch (level) { 10668c2ecf20Sopenharmony_ci case 0: 10678c2ecf20Sopenharmony_ci case 1: 10688c2ecf20Sopenharmony_ci nofs = noffset[1]; 10698c2ecf20Sopenharmony_ci break; 10708c2ecf20Sopenharmony_ci case 2: 10718c2ecf20Sopenharmony_ci nofs = noffset[1]; 10728c2ecf20Sopenharmony_ci if (!offset[level - 1]) 10738c2ecf20Sopenharmony_ci goto skip_partial; 10748c2ecf20Sopenharmony_ci err = truncate_partial_nodes(&dn, ri, offset, level); 10758c2ecf20Sopenharmony_ci if (err < 0 && err != -ENOENT) 10768c2ecf20Sopenharmony_ci goto fail; 10778c2ecf20Sopenharmony_ci nofs += 1 + NIDS_PER_BLOCK; 10788c2ecf20Sopenharmony_ci break; 10798c2ecf20Sopenharmony_ci case 3: 10808c2ecf20Sopenharmony_ci nofs = 5 + 2 * NIDS_PER_BLOCK; 10818c2ecf20Sopenharmony_ci if (!offset[level - 1]) 10828c2ecf20Sopenharmony_ci goto skip_partial; 10838c2ecf20Sopenharmony_ci err = truncate_partial_nodes(&dn, ri, offset, level); 10848c2ecf20Sopenharmony_ci if (err < 0 && err != -ENOENT) 10858c2ecf20Sopenharmony_ci goto fail; 10868c2ecf20Sopenharmony_ci break; 10878c2ecf20Sopenharmony_ci default: 10888c2ecf20Sopenharmony_ci BUG(); 10898c2ecf20Sopenharmony_ci } 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ciskip_partial: 10928c2ecf20Sopenharmony_ci while (cont) { 10938c2ecf20Sopenharmony_ci dn.nid = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]); 10948c2ecf20Sopenharmony_ci switch (offset[0]) { 10958c2ecf20Sopenharmony_ci case NODE_DIR1_BLOCK: 10968c2ecf20Sopenharmony_ci case NODE_DIR2_BLOCK: 10978c2ecf20Sopenharmony_ci err = truncate_dnode(&dn); 10988c2ecf20Sopenharmony_ci break; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci case NODE_IND1_BLOCK: 11018c2ecf20Sopenharmony_ci case NODE_IND2_BLOCK: 11028c2ecf20Sopenharmony_ci err = truncate_nodes(&dn, nofs, offset[1], 2); 11038c2ecf20Sopenharmony_ci break; 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci case NODE_DIND_BLOCK: 11068c2ecf20Sopenharmony_ci err = truncate_nodes(&dn, nofs, offset[1], 3); 11078c2ecf20Sopenharmony_ci cont = 0; 11088c2ecf20Sopenharmony_ci break; 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci default: 11118c2ecf20Sopenharmony_ci BUG(); 11128c2ecf20Sopenharmony_ci } 11138c2ecf20Sopenharmony_ci if (err < 0 && err != -ENOENT) 11148c2ecf20Sopenharmony_ci goto fail; 11158c2ecf20Sopenharmony_ci if (offset[1] == 0 && 11168c2ecf20Sopenharmony_ci ri->i_nid[offset[0] - NODE_DIR1_BLOCK]) { 11178c2ecf20Sopenharmony_ci lock_page(page); 11188c2ecf20Sopenharmony_ci BUG_ON(page->mapping != NODE_MAPPING(sbi)); 11198c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(page, NODE, true, true); 11208c2ecf20Sopenharmony_ci ri->i_nid[offset[0] - NODE_DIR1_BLOCK] = 0; 11218c2ecf20Sopenharmony_ci set_page_dirty(page); 11228c2ecf20Sopenharmony_ci unlock_page(page); 11238c2ecf20Sopenharmony_ci } 11248c2ecf20Sopenharmony_ci offset[1] = 0; 11258c2ecf20Sopenharmony_ci offset[0]++; 11268c2ecf20Sopenharmony_ci nofs += err; 11278c2ecf20Sopenharmony_ci } 11288c2ecf20Sopenharmony_cifail: 11298c2ecf20Sopenharmony_ci f2fs_put_page(page, 0); 11308c2ecf20Sopenharmony_ci trace_f2fs_truncate_inode_blocks_exit(inode, err); 11318c2ecf20Sopenharmony_ci return err > 0 ? 0 : err; 11328c2ecf20Sopenharmony_ci} 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci/* caller must lock inode page */ 11358c2ecf20Sopenharmony_ciint f2fs_truncate_xattr_node(struct inode *inode) 11368c2ecf20Sopenharmony_ci{ 11378c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 11388c2ecf20Sopenharmony_ci nid_t nid = F2FS_I(inode)->i_xattr_nid; 11398c2ecf20Sopenharmony_ci struct dnode_of_data dn; 11408c2ecf20Sopenharmony_ci struct page *npage; 11418c2ecf20Sopenharmony_ci int err; 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci if (!nid) 11448c2ecf20Sopenharmony_ci return 0; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci npage = f2fs_get_node_page(sbi, nid); 11478c2ecf20Sopenharmony_ci if (IS_ERR(npage)) 11488c2ecf20Sopenharmony_ci return PTR_ERR(npage); 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci set_new_dnode(&dn, inode, NULL, npage, nid); 11518c2ecf20Sopenharmony_ci err = truncate_node(&dn); 11528c2ecf20Sopenharmony_ci if (err) { 11538c2ecf20Sopenharmony_ci f2fs_put_page(npage, 1); 11548c2ecf20Sopenharmony_ci return err; 11558c2ecf20Sopenharmony_ci } 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci f2fs_i_xnid_write(inode, 0); 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci return 0; 11608c2ecf20Sopenharmony_ci} 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci/* 11638c2ecf20Sopenharmony_ci * Caller should grab and release a rwsem by calling f2fs_lock_op() and 11648c2ecf20Sopenharmony_ci * f2fs_unlock_op(). 11658c2ecf20Sopenharmony_ci */ 11668c2ecf20Sopenharmony_ciint f2fs_remove_inode_page(struct inode *inode) 11678c2ecf20Sopenharmony_ci{ 11688c2ecf20Sopenharmony_ci struct dnode_of_data dn; 11698c2ecf20Sopenharmony_ci int err; 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); 11728c2ecf20Sopenharmony_ci err = f2fs_get_dnode_of_data(&dn, 0, LOOKUP_NODE); 11738c2ecf20Sopenharmony_ci if (err) 11748c2ecf20Sopenharmony_ci return err; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci err = f2fs_truncate_xattr_node(inode); 11778c2ecf20Sopenharmony_ci if (err) { 11788c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 11798c2ecf20Sopenharmony_ci return err; 11808c2ecf20Sopenharmony_ci } 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci /* remove potential inline_data blocks */ 11838c2ecf20Sopenharmony_ci if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || 11848c2ecf20Sopenharmony_ci S_ISLNK(inode->i_mode)) 11858c2ecf20Sopenharmony_ci f2fs_truncate_data_blocks_range(&dn, 1); 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci /* 0 is possible, after f2fs_new_inode() has failed */ 11888c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) { 11898c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 11908c2ecf20Sopenharmony_ci return -EIO; 11918c2ecf20Sopenharmony_ci } 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci if (unlikely(inode->i_blocks != 0 && inode->i_blocks != 8)) { 11948c2ecf20Sopenharmony_ci f2fs_warn(F2FS_I_SB(inode), 11958c2ecf20Sopenharmony_ci "f2fs_remove_inode_page: inconsistent i_blocks, ino:%lu, iblocks:%llu", 11968c2ecf20Sopenharmony_ci inode->i_ino, (unsigned long long)inode->i_blocks); 11978c2ecf20Sopenharmony_ci set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK); 11988c2ecf20Sopenharmony_ci } 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci /* will put inode & node pages */ 12018c2ecf20Sopenharmony_ci err = truncate_node(&dn); 12028c2ecf20Sopenharmony_ci if (err) { 12038c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 12048c2ecf20Sopenharmony_ci return err; 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci return 0; 12078c2ecf20Sopenharmony_ci} 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_cistruct page *f2fs_new_inode_page(struct inode *inode) 12108c2ecf20Sopenharmony_ci{ 12118c2ecf20Sopenharmony_ci struct dnode_of_data dn; 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci /* allocate inode page for new inode */ 12148c2ecf20Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci /* caller should f2fs_put_page(page, 1); */ 12178c2ecf20Sopenharmony_ci return f2fs_new_node_page(&dn, 0); 12188c2ecf20Sopenharmony_ci} 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_cistruct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs) 12218c2ecf20Sopenharmony_ci{ 12228c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); 12238c2ecf20Sopenharmony_ci struct node_info new_ni; 12248c2ecf20Sopenharmony_ci struct page *page; 12258c2ecf20Sopenharmony_ci int err; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC))) 12288c2ecf20Sopenharmony_ci return ERR_PTR(-EPERM); 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci page = f2fs_grab_cache_page(NODE_MAPPING(sbi), dn->nid, false); 12318c2ecf20Sopenharmony_ci if (!page) 12328c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci if (unlikely((err = inc_valid_node_count(sbi, dn->inode, !ofs)))) 12358c2ecf20Sopenharmony_ci goto fail; 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS 12388c2ecf20Sopenharmony_ci err = f2fs_get_node_info(sbi, dn->nid, &new_ni); 12398c2ecf20Sopenharmony_ci if (err) { 12408c2ecf20Sopenharmony_ci dec_valid_node_count(sbi, dn->inode, !ofs); 12418c2ecf20Sopenharmony_ci goto fail; 12428c2ecf20Sopenharmony_ci } 12438c2ecf20Sopenharmony_ci if (unlikely(new_ni.blk_addr != NULL_ADDR)) { 12448c2ecf20Sopenharmony_ci err = -EFSCORRUPTED; 12458c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 12468c2ecf20Sopenharmony_ci goto fail; 12478c2ecf20Sopenharmony_ci } 12488c2ecf20Sopenharmony_ci#endif 12498c2ecf20Sopenharmony_ci new_ni.nid = dn->nid; 12508c2ecf20Sopenharmony_ci new_ni.ino = dn->inode->i_ino; 12518c2ecf20Sopenharmony_ci new_ni.blk_addr = NULL_ADDR; 12528c2ecf20Sopenharmony_ci new_ni.flag = 0; 12538c2ecf20Sopenharmony_ci new_ni.version = 0; 12548c2ecf20Sopenharmony_ci set_node_addr(sbi, &new_ni, NEW_ADDR, false); 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(page, NODE, true, true); 12578c2ecf20Sopenharmony_ci fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); 12588c2ecf20Sopenharmony_ci set_cold_node(page, S_ISDIR(dn->inode->i_mode)); 12598c2ecf20Sopenharmony_ci if (!PageUptodate(page)) 12608c2ecf20Sopenharmony_ci SetPageUptodate(page); 12618c2ecf20Sopenharmony_ci if (set_page_dirty(page)) 12628c2ecf20Sopenharmony_ci dn->node_changed = true; 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci if (f2fs_has_xattr_block(ofs)) 12658c2ecf20Sopenharmony_ci f2fs_i_xnid_write(dn->inode, dn->nid); 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci if (ofs == 0) 12688c2ecf20Sopenharmony_ci inc_valid_inode_count(sbi); 12698c2ecf20Sopenharmony_ci return page; 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_cifail: 12728c2ecf20Sopenharmony_ci clear_node_page_dirty(page); 12738c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 12748c2ecf20Sopenharmony_ci return ERR_PTR(err); 12758c2ecf20Sopenharmony_ci} 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci/* 12788c2ecf20Sopenharmony_ci * Caller should do after getting the following values. 12798c2ecf20Sopenharmony_ci * 0: f2fs_put_page(page, 0) 12808c2ecf20Sopenharmony_ci * LOCKED_PAGE or error: f2fs_put_page(page, 1) 12818c2ecf20Sopenharmony_ci */ 12828c2ecf20Sopenharmony_cistatic int read_node_page(struct page *page, int op_flags) 12838c2ecf20Sopenharmony_ci{ 12848c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(page); 12858c2ecf20Sopenharmony_ci struct node_info ni; 12868c2ecf20Sopenharmony_ci struct f2fs_io_info fio = { 12878c2ecf20Sopenharmony_ci .sbi = sbi, 12888c2ecf20Sopenharmony_ci .type = NODE, 12898c2ecf20Sopenharmony_ci .op = REQ_OP_READ, 12908c2ecf20Sopenharmony_ci .op_flags = op_flags, 12918c2ecf20Sopenharmony_ci .page = page, 12928c2ecf20Sopenharmony_ci .encrypted_page = NULL, 12938c2ecf20Sopenharmony_ci }; 12948c2ecf20Sopenharmony_ci int err; 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci if (PageUptodate(page)) { 12978c2ecf20Sopenharmony_ci if (!f2fs_inode_chksum_verify(sbi, page)) { 12988c2ecf20Sopenharmony_ci ClearPageUptodate(page); 12998c2ecf20Sopenharmony_ci return -EFSBADCRC; 13008c2ecf20Sopenharmony_ci } 13018c2ecf20Sopenharmony_ci return LOCKED_PAGE; 13028c2ecf20Sopenharmony_ci } 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci err = f2fs_get_node_info(sbi, page->index, &ni); 13058c2ecf20Sopenharmony_ci if (err) 13068c2ecf20Sopenharmony_ci return err; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci if (unlikely(ni.blk_addr == NULL_ADDR) || 13098c2ecf20Sopenharmony_ci is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)) { 13108c2ecf20Sopenharmony_ci ClearPageUptodate(page); 13118c2ecf20Sopenharmony_ci return -ENOENT; 13128c2ecf20Sopenharmony_ci } 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci fio.new_blkaddr = fio.old_blkaddr = ni.blk_addr; 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci err = f2fs_submit_page_bio(&fio); 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci if (!err) 13198c2ecf20Sopenharmony_ci f2fs_update_iostat(sbi, FS_NODE_READ_IO, F2FS_BLKSIZE); 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci return err; 13228c2ecf20Sopenharmony_ci} 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci/* 13258c2ecf20Sopenharmony_ci * Readahead a node page 13268c2ecf20Sopenharmony_ci */ 13278c2ecf20Sopenharmony_civoid f2fs_ra_node_page(struct f2fs_sb_info *sbi, nid_t nid) 13288c2ecf20Sopenharmony_ci{ 13298c2ecf20Sopenharmony_ci struct page *apage; 13308c2ecf20Sopenharmony_ci int err; 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci if (!nid) 13338c2ecf20Sopenharmony_ci return; 13348c2ecf20Sopenharmony_ci if (f2fs_check_nid_range(sbi, nid)) 13358c2ecf20Sopenharmony_ci return; 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci apage = xa_load(&NODE_MAPPING(sbi)->i_pages, nid); 13388c2ecf20Sopenharmony_ci if (apage) 13398c2ecf20Sopenharmony_ci return; 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci apage = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false); 13428c2ecf20Sopenharmony_ci if (!apage) 13438c2ecf20Sopenharmony_ci return; 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci err = read_node_page(apage, REQ_RAHEAD); 13468c2ecf20Sopenharmony_ci f2fs_put_page(apage, err ? 1 : 0); 13478c2ecf20Sopenharmony_ci} 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_cistatic struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid, 13508c2ecf20Sopenharmony_ci struct page *parent, int start) 13518c2ecf20Sopenharmony_ci{ 13528c2ecf20Sopenharmony_ci struct page *page; 13538c2ecf20Sopenharmony_ci int err; 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_ci if (!nid) 13568c2ecf20Sopenharmony_ci return ERR_PTR(-ENOENT); 13578c2ecf20Sopenharmony_ci if (f2fs_check_nid_range(sbi, nid)) 13588c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 13598c2ecf20Sopenharmony_cirepeat: 13608c2ecf20Sopenharmony_ci page = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false); 13618c2ecf20Sopenharmony_ci if (!page) 13628c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci err = read_node_page(page, 0); 13658c2ecf20Sopenharmony_ci if (err < 0) { 13668c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 13678c2ecf20Sopenharmony_ci return ERR_PTR(err); 13688c2ecf20Sopenharmony_ci } else if (err == LOCKED_PAGE) { 13698c2ecf20Sopenharmony_ci err = 0; 13708c2ecf20Sopenharmony_ci goto page_hit; 13718c2ecf20Sopenharmony_ci } 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci if (parent) 13748c2ecf20Sopenharmony_ci f2fs_ra_node_pages(parent, start + 1, MAX_RA_NODE); 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci lock_page(page); 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci if (unlikely(page->mapping != NODE_MAPPING(sbi))) { 13798c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 13808c2ecf20Sopenharmony_ci goto repeat; 13818c2ecf20Sopenharmony_ci } 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci if (unlikely(!PageUptodate(page))) { 13848c2ecf20Sopenharmony_ci err = -EIO; 13858c2ecf20Sopenharmony_ci goto out_err; 13868c2ecf20Sopenharmony_ci } 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci if (!f2fs_inode_chksum_verify(sbi, page)) { 13898c2ecf20Sopenharmony_ci err = -EFSBADCRC; 13908c2ecf20Sopenharmony_ci goto out_err; 13918c2ecf20Sopenharmony_ci } 13928c2ecf20Sopenharmony_cipage_hit: 13938c2ecf20Sopenharmony_ci if(unlikely(nid != nid_of_node(page))) { 13948c2ecf20Sopenharmony_ci f2fs_warn(sbi, "inconsistent node block, nid:%lu, node_footer[nid:%u,ino:%u,ofs:%u,cpver:%llu,blkaddr:%u]", 13958c2ecf20Sopenharmony_ci nid, nid_of_node(page), ino_of_node(page), 13968c2ecf20Sopenharmony_ci ofs_of_node(page), cpver_of_node(page), 13978c2ecf20Sopenharmony_ci next_blkaddr_of_node(page)); 13988c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 13998c2ecf20Sopenharmony_ci err = -EINVAL; 14008c2ecf20Sopenharmony_ciout_err: 14018c2ecf20Sopenharmony_ci ClearPageUptodate(page); 14028c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 14038c2ecf20Sopenharmony_ci return ERR_PTR(err); 14048c2ecf20Sopenharmony_ci } 14058c2ecf20Sopenharmony_ci return page; 14068c2ecf20Sopenharmony_ci} 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_cistruct page *f2fs_get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) 14098c2ecf20Sopenharmony_ci{ 14108c2ecf20Sopenharmony_ci return __get_node_page(sbi, nid, NULL, 0); 14118c2ecf20Sopenharmony_ci} 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_cistruct page *f2fs_get_node_page_ra(struct page *parent, int start) 14148c2ecf20Sopenharmony_ci{ 14158c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(parent); 14168c2ecf20Sopenharmony_ci nid_t nid = get_nid(parent, start, false); 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci return __get_node_page(sbi, nid, parent, start); 14198c2ecf20Sopenharmony_ci} 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_cistatic void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino) 14228c2ecf20Sopenharmony_ci{ 14238c2ecf20Sopenharmony_ci struct inode *inode; 14248c2ecf20Sopenharmony_ci struct page *page; 14258c2ecf20Sopenharmony_ci int ret; 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci /* should flush inline_data before evict_inode */ 14288c2ecf20Sopenharmony_ci inode = ilookup(sbi->sb, ino); 14298c2ecf20Sopenharmony_ci if (!inode) 14308c2ecf20Sopenharmony_ci return; 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci page = f2fs_pagecache_get_page(inode->i_mapping, 0, 14338c2ecf20Sopenharmony_ci FGP_LOCK|FGP_NOWAIT, 0); 14348c2ecf20Sopenharmony_ci if (!page) 14358c2ecf20Sopenharmony_ci goto iput_out; 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci if (!PageUptodate(page)) 14388c2ecf20Sopenharmony_ci goto page_out; 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci if (!PageDirty(page)) 14418c2ecf20Sopenharmony_ci goto page_out; 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci if (!clear_page_dirty_for_io(page)) 14448c2ecf20Sopenharmony_ci goto page_out; 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ci ret = f2fs_write_inline_data(inode, page); 14478c2ecf20Sopenharmony_ci inode_dec_dirty_pages(inode); 14488c2ecf20Sopenharmony_ci f2fs_remove_dirty_inode(inode); 14498c2ecf20Sopenharmony_ci if (ret) 14508c2ecf20Sopenharmony_ci set_page_dirty(page); 14518c2ecf20Sopenharmony_cipage_out: 14528c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 14538c2ecf20Sopenharmony_ciiput_out: 14548c2ecf20Sopenharmony_ci iput(inode); 14558c2ecf20Sopenharmony_ci} 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_cistatic struct page *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino) 14588c2ecf20Sopenharmony_ci{ 14598c2ecf20Sopenharmony_ci pgoff_t index; 14608c2ecf20Sopenharmony_ci struct pagevec pvec; 14618c2ecf20Sopenharmony_ci struct page *last_page = NULL; 14628c2ecf20Sopenharmony_ci int nr_pages; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci pagevec_init(&pvec); 14658c2ecf20Sopenharmony_ci index = 0; 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci while ((nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index, 14688c2ecf20Sopenharmony_ci PAGECACHE_TAG_DIRTY))) { 14698c2ecf20Sopenharmony_ci int i; 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci for (i = 0; i < nr_pages; i++) { 14728c2ecf20Sopenharmony_ci struct page *page = pvec.pages[i]; 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 14758c2ecf20Sopenharmony_ci f2fs_put_page(last_page, 0); 14768c2ecf20Sopenharmony_ci pagevec_release(&pvec); 14778c2ecf20Sopenharmony_ci return ERR_PTR(-EIO); 14788c2ecf20Sopenharmony_ci } 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci if (!IS_DNODE(page) || !is_cold_node(page)) 14818c2ecf20Sopenharmony_ci continue; 14828c2ecf20Sopenharmony_ci if (ino_of_node(page) != ino) 14838c2ecf20Sopenharmony_ci continue; 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_ci lock_page(page); 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci if (unlikely(page->mapping != NODE_MAPPING(sbi))) { 14888c2ecf20Sopenharmony_cicontinue_unlock: 14898c2ecf20Sopenharmony_ci unlock_page(page); 14908c2ecf20Sopenharmony_ci continue; 14918c2ecf20Sopenharmony_ci } 14928c2ecf20Sopenharmony_ci if (ino_of_node(page) != ino) 14938c2ecf20Sopenharmony_ci goto continue_unlock; 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_ci if (!PageDirty(page)) { 14968c2ecf20Sopenharmony_ci /* someone wrote it for us */ 14978c2ecf20Sopenharmony_ci goto continue_unlock; 14988c2ecf20Sopenharmony_ci } 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci if (last_page) 15018c2ecf20Sopenharmony_ci f2fs_put_page(last_page, 0); 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci get_page(page); 15048c2ecf20Sopenharmony_ci last_page = page; 15058c2ecf20Sopenharmony_ci unlock_page(page); 15068c2ecf20Sopenharmony_ci } 15078c2ecf20Sopenharmony_ci pagevec_release(&pvec); 15088c2ecf20Sopenharmony_ci cond_resched(); 15098c2ecf20Sopenharmony_ci } 15108c2ecf20Sopenharmony_ci return last_page; 15118c2ecf20Sopenharmony_ci} 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_cistatic int __write_node_page(struct page *page, bool atomic, bool *submitted, 15148c2ecf20Sopenharmony_ci struct writeback_control *wbc, bool do_balance, 15158c2ecf20Sopenharmony_ci enum iostat_type io_type, unsigned int *seq_id) 15168c2ecf20Sopenharmony_ci{ 15178c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(page); 15188c2ecf20Sopenharmony_ci nid_t nid; 15198c2ecf20Sopenharmony_ci struct node_info ni; 15208c2ecf20Sopenharmony_ci struct f2fs_io_info fio = { 15218c2ecf20Sopenharmony_ci .sbi = sbi, 15228c2ecf20Sopenharmony_ci .ino = ino_of_node(page), 15238c2ecf20Sopenharmony_ci .type = NODE, 15248c2ecf20Sopenharmony_ci .op = REQ_OP_WRITE, 15258c2ecf20Sopenharmony_ci .op_flags = wbc_to_write_flags(wbc), 15268c2ecf20Sopenharmony_ci .page = page, 15278c2ecf20Sopenharmony_ci .encrypted_page = NULL, 15288c2ecf20Sopenharmony_ci .submitted = false, 15298c2ecf20Sopenharmony_ci .io_type = io_type, 15308c2ecf20Sopenharmony_ci .io_wbc = wbc, 15318c2ecf20Sopenharmony_ci }; 15328c2ecf20Sopenharmony_ci unsigned int seq; 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci trace_f2fs_writepage(page, NODE); 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 15378c2ecf20Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_IS_CLOSE)) { 15388c2ecf20Sopenharmony_ci ClearPageUptodate(page); 15398c2ecf20Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_NODES); 15408c2ecf20Sopenharmony_ci unlock_page(page); 15418c2ecf20Sopenharmony_ci return 0; 15428c2ecf20Sopenharmony_ci } 15438c2ecf20Sopenharmony_ci goto redirty_out; 15448c2ecf20Sopenharmony_ci } 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 15478c2ecf20Sopenharmony_ci goto redirty_out; 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci if (!is_sbi_flag_set(sbi, SBI_CP_DISABLED) && 15508c2ecf20Sopenharmony_ci wbc->sync_mode == WB_SYNC_NONE && 15518c2ecf20Sopenharmony_ci IS_DNODE(page) && is_cold_node(page)) 15528c2ecf20Sopenharmony_ci goto redirty_out; 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci /* get old block addr of this node page */ 15558c2ecf20Sopenharmony_ci nid = nid_of_node(page); 15568c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, page->index != nid); 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_ci if (f2fs_get_node_info(sbi, nid, &ni)) 15598c2ecf20Sopenharmony_ci goto redirty_out; 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_ci if (wbc->for_reclaim) { 15628c2ecf20Sopenharmony_ci if (!down_read_trylock(&sbi->node_write)) 15638c2ecf20Sopenharmony_ci goto redirty_out; 15648c2ecf20Sopenharmony_ci } else { 15658c2ecf20Sopenharmony_ci down_read(&sbi->node_write); 15668c2ecf20Sopenharmony_ci } 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci /* This page is already truncated */ 15698c2ecf20Sopenharmony_ci if (unlikely(ni.blk_addr == NULL_ADDR)) { 15708c2ecf20Sopenharmony_ci ClearPageUptodate(page); 15718c2ecf20Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_NODES); 15728c2ecf20Sopenharmony_ci up_read(&sbi->node_write); 15738c2ecf20Sopenharmony_ci unlock_page(page); 15748c2ecf20Sopenharmony_ci return 0; 15758c2ecf20Sopenharmony_ci } 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci if (__is_valid_data_blkaddr(ni.blk_addr) && 15788c2ecf20Sopenharmony_ci !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, 15798c2ecf20Sopenharmony_ci DATA_GENERIC_ENHANCE)) { 15808c2ecf20Sopenharmony_ci up_read(&sbi->node_write); 15818c2ecf20Sopenharmony_ci goto redirty_out; 15828c2ecf20Sopenharmony_ci } 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci if (atomic && !test_opt(sbi, NOBARRIER)) 15858c2ecf20Sopenharmony_ci fio.op_flags |= REQ_PREFLUSH | REQ_FUA; 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci /* should add to global list before clearing PAGECACHE status */ 15888c2ecf20Sopenharmony_ci if (f2fs_in_warm_node_list(sbi, page)) { 15898c2ecf20Sopenharmony_ci seq = f2fs_add_fsync_node_entry(sbi, page); 15908c2ecf20Sopenharmony_ci if (seq_id) 15918c2ecf20Sopenharmony_ci *seq_id = seq; 15928c2ecf20Sopenharmony_ci } 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci set_page_writeback(page); 15958c2ecf20Sopenharmony_ci ClearPageError(page); 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_ci fio.old_blkaddr = ni.blk_addr; 15988c2ecf20Sopenharmony_ci f2fs_do_write_node_page(nid, &fio); 15998c2ecf20Sopenharmony_ci set_node_addr(sbi, &ni, fio.new_blkaddr, is_fsync_dnode(page)); 16008c2ecf20Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_NODES); 16018c2ecf20Sopenharmony_ci up_read(&sbi->node_write); 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci if (wbc->for_reclaim) { 16048c2ecf20Sopenharmony_ci f2fs_submit_merged_write_cond(sbi, NULL, page, 0, NODE); 16058c2ecf20Sopenharmony_ci submitted = NULL; 16068c2ecf20Sopenharmony_ci } 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_ci unlock_page(page); 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 16118c2ecf20Sopenharmony_ci f2fs_submit_merged_write(sbi, NODE); 16128c2ecf20Sopenharmony_ci submitted = NULL; 16138c2ecf20Sopenharmony_ci } 16148c2ecf20Sopenharmony_ci if (submitted) 16158c2ecf20Sopenharmony_ci *submitted = fio.submitted; 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci if (do_balance) 16188c2ecf20Sopenharmony_ci f2fs_balance_fs(sbi, false); 16198c2ecf20Sopenharmony_ci return 0; 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ciredirty_out: 16228c2ecf20Sopenharmony_ci redirty_page_for_writepage(wbc, page); 16238c2ecf20Sopenharmony_ci return AOP_WRITEPAGE_ACTIVATE; 16248c2ecf20Sopenharmony_ci} 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ciint f2fs_move_node_page(struct page *node_page, int gc_type) 16278c2ecf20Sopenharmony_ci{ 16288c2ecf20Sopenharmony_ci int err = 0; 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ci if (gc_type == FG_GC) { 16318c2ecf20Sopenharmony_ci struct writeback_control wbc = { 16328c2ecf20Sopenharmony_ci .sync_mode = WB_SYNC_ALL, 16338c2ecf20Sopenharmony_ci .nr_to_write = 1, 16348c2ecf20Sopenharmony_ci .for_reclaim = 0, 16358c2ecf20Sopenharmony_ci }; 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(node_page, NODE, true, true); 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci set_page_dirty(node_page); 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci if (!clear_page_dirty_for_io(node_page)) { 16428c2ecf20Sopenharmony_ci err = -EAGAIN; 16438c2ecf20Sopenharmony_ci goto out_page; 16448c2ecf20Sopenharmony_ci } 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci if (__write_node_page(node_page, false, NULL, 16478c2ecf20Sopenharmony_ci &wbc, false, FS_GC_NODE_IO, NULL)) { 16488c2ecf20Sopenharmony_ci err = -EAGAIN; 16498c2ecf20Sopenharmony_ci unlock_page(node_page); 16508c2ecf20Sopenharmony_ci } 16518c2ecf20Sopenharmony_ci goto release_page; 16528c2ecf20Sopenharmony_ci } else { 16538c2ecf20Sopenharmony_ci /* set page dirty and write it */ 16548c2ecf20Sopenharmony_ci if (!PageWriteback(node_page)) 16558c2ecf20Sopenharmony_ci set_page_dirty(node_page); 16568c2ecf20Sopenharmony_ci } 16578c2ecf20Sopenharmony_ciout_page: 16588c2ecf20Sopenharmony_ci unlock_page(node_page); 16598c2ecf20Sopenharmony_cirelease_page: 16608c2ecf20Sopenharmony_ci f2fs_put_page(node_page, 0); 16618c2ecf20Sopenharmony_ci return err; 16628c2ecf20Sopenharmony_ci} 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_cistatic int f2fs_write_node_page(struct page *page, 16658c2ecf20Sopenharmony_ci struct writeback_control *wbc) 16668c2ecf20Sopenharmony_ci{ 16678c2ecf20Sopenharmony_ci return __write_node_page(page, false, NULL, wbc, false, 16688c2ecf20Sopenharmony_ci FS_NODE_IO, NULL); 16698c2ecf20Sopenharmony_ci} 16708c2ecf20Sopenharmony_ci 16718c2ecf20Sopenharmony_ciint f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, 16728c2ecf20Sopenharmony_ci struct writeback_control *wbc, bool atomic, 16738c2ecf20Sopenharmony_ci unsigned int *seq_id) 16748c2ecf20Sopenharmony_ci{ 16758c2ecf20Sopenharmony_ci pgoff_t index; 16768c2ecf20Sopenharmony_ci struct pagevec pvec; 16778c2ecf20Sopenharmony_ci int ret = 0; 16788c2ecf20Sopenharmony_ci struct page *last_page = NULL; 16798c2ecf20Sopenharmony_ci bool marked = false; 16808c2ecf20Sopenharmony_ci nid_t ino = inode->i_ino; 16818c2ecf20Sopenharmony_ci int nr_pages; 16828c2ecf20Sopenharmony_ci int nwritten = 0; 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_ci if (atomic) { 16858c2ecf20Sopenharmony_ci last_page = last_fsync_dnode(sbi, ino); 16868c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(last_page)) 16878c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(last_page); 16888c2ecf20Sopenharmony_ci } 16898c2ecf20Sopenharmony_ciretry: 16908c2ecf20Sopenharmony_ci pagevec_init(&pvec); 16918c2ecf20Sopenharmony_ci index = 0; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci while ((nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index, 16948c2ecf20Sopenharmony_ci PAGECACHE_TAG_DIRTY))) { 16958c2ecf20Sopenharmony_ci int i; 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci for (i = 0; i < nr_pages; i++) { 16988c2ecf20Sopenharmony_ci struct page *page = pvec.pages[i]; 16998c2ecf20Sopenharmony_ci bool submitted = false; 17008c2ecf20Sopenharmony_ci 17018c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 17028c2ecf20Sopenharmony_ci f2fs_put_page(last_page, 0); 17038c2ecf20Sopenharmony_ci pagevec_release(&pvec); 17048c2ecf20Sopenharmony_ci ret = -EIO; 17058c2ecf20Sopenharmony_ci goto out; 17068c2ecf20Sopenharmony_ci } 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci if (!IS_DNODE(page) || !is_cold_node(page)) 17098c2ecf20Sopenharmony_ci continue; 17108c2ecf20Sopenharmony_ci if (ino_of_node(page) != ino) 17118c2ecf20Sopenharmony_ci continue; 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_ci lock_page(page); 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci if (unlikely(page->mapping != NODE_MAPPING(sbi))) { 17168c2ecf20Sopenharmony_cicontinue_unlock: 17178c2ecf20Sopenharmony_ci unlock_page(page); 17188c2ecf20Sopenharmony_ci continue; 17198c2ecf20Sopenharmony_ci } 17208c2ecf20Sopenharmony_ci if (ino_of_node(page) != ino) 17218c2ecf20Sopenharmony_ci goto continue_unlock; 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci if (!PageDirty(page) && page != last_page) { 17248c2ecf20Sopenharmony_ci /* someone wrote it for us */ 17258c2ecf20Sopenharmony_ci goto continue_unlock; 17268c2ecf20Sopenharmony_ci } 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(page, NODE, true, true); 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci set_fsync_mark(page, 0); 17318c2ecf20Sopenharmony_ci set_dentry_mark(page, 0); 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci if (!atomic || page == last_page) { 17348c2ecf20Sopenharmony_ci set_fsync_mark(page, 1); 17358c2ecf20Sopenharmony_ci if (IS_INODE(page)) { 17368c2ecf20Sopenharmony_ci if (is_inode_flag_set(inode, 17378c2ecf20Sopenharmony_ci FI_DIRTY_INODE)) 17388c2ecf20Sopenharmony_ci f2fs_update_inode(inode, page); 17398c2ecf20Sopenharmony_ci set_dentry_mark(page, 17408c2ecf20Sopenharmony_ci f2fs_need_dentry_mark(sbi, ino)); 17418c2ecf20Sopenharmony_ci } 17428c2ecf20Sopenharmony_ci /* may be written by other thread */ 17438c2ecf20Sopenharmony_ci if (!PageDirty(page)) 17448c2ecf20Sopenharmony_ci set_page_dirty(page); 17458c2ecf20Sopenharmony_ci } 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci if (!clear_page_dirty_for_io(page)) 17488c2ecf20Sopenharmony_ci goto continue_unlock; 17498c2ecf20Sopenharmony_ci 17508c2ecf20Sopenharmony_ci ret = __write_node_page(page, atomic && 17518c2ecf20Sopenharmony_ci page == last_page, 17528c2ecf20Sopenharmony_ci &submitted, wbc, true, 17538c2ecf20Sopenharmony_ci FS_NODE_IO, seq_id); 17548c2ecf20Sopenharmony_ci if (ret) { 17558c2ecf20Sopenharmony_ci unlock_page(page); 17568c2ecf20Sopenharmony_ci f2fs_put_page(last_page, 0); 17578c2ecf20Sopenharmony_ci break; 17588c2ecf20Sopenharmony_ci } else if (submitted) { 17598c2ecf20Sopenharmony_ci nwritten++; 17608c2ecf20Sopenharmony_ci } 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci if (page == last_page) { 17638c2ecf20Sopenharmony_ci f2fs_put_page(page, 0); 17648c2ecf20Sopenharmony_ci marked = true; 17658c2ecf20Sopenharmony_ci break; 17668c2ecf20Sopenharmony_ci } 17678c2ecf20Sopenharmony_ci } 17688c2ecf20Sopenharmony_ci pagevec_release(&pvec); 17698c2ecf20Sopenharmony_ci cond_resched(); 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci if (ret || marked) 17728c2ecf20Sopenharmony_ci break; 17738c2ecf20Sopenharmony_ci } 17748c2ecf20Sopenharmony_ci if (!ret && atomic && !marked) { 17758c2ecf20Sopenharmony_ci f2fs_debug(sbi, "Retry to write fsync mark: ino=%u, idx=%lx", 17768c2ecf20Sopenharmony_ci ino, last_page->index); 17778c2ecf20Sopenharmony_ci lock_page(last_page); 17788c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(last_page, NODE, true, true); 17798c2ecf20Sopenharmony_ci set_page_dirty(last_page); 17808c2ecf20Sopenharmony_ci unlock_page(last_page); 17818c2ecf20Sopenharmony_ci goto retry; 17828c2ecf20Sopenharmony_ci } 17838c2ecf20Sopenharmony_ciout: 17848c2ecf20Sopenharmony_ci if (nwritten) 17858c2ecf20Sopenharmony_ci f2fs_submit_merged_write_cond(sbi, NULL, NULL, ino, NODE); 17868c2ecf20Sopenharmony_ci return ret ? -EIO: 0; 17878c2ecf20Sopenharmony_ci} 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_cistatic int f2fs_match_ino(struct inode *inode, unsigned long ino, void *data) 17908c2ecf20Sopenharmony_ci{ 17918c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 17928c2ecf20Sopenharmony_ci bool clean; 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_ci if (inode->i_ino != ino) 17958c2ecf20Sopenharmony_ci return 0; 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci if (!is_inode_flag_set(inode, FI_DIRTY_INODE)) 17988c2ecf20Sopenharmony_ci return 0; 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci spin_lock(&sbi->inode_lock[DIRTY_META]); 18018c2ecf20Sopenharmony_ci clean = list_empty(&F2FS_I(inode)->gdirty_list); 18028c2ecf20Sopenharmony_ci spin_unlock(&sbi->inode_lock[DIRTY_META]); 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci if (clean) 18058c2ecf20Sopenharmony_ci return 0; 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci inode = igrab(inode); 18088c2ecf20Sopenharmony_ci if (!inode) 18098c2ecf20Sopenharmony_ci return 0; 18108c2ecf20Sopenharmony_ci return 1; 18118c2ecf20Sopenharmony_ci} 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_cistatic bool flush_dirty_inode(struct page *page) 18148c2ecf20Sopenharmony_ci{ 18158c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(page); 18168c2ecf20Sopenharmony_ci struct inode *inode; 18178c2ecf20Sopenharmony_ci nid_t ino = ino_of_node(page); 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci inode = find_inode_nowait(sbi->sb, ino, f2fs_match_ino, NULL); 18208c2ecf20Sopenharmony_ci if (!inode) 18218c2ecf20Sopenharmony_ci return false; 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci f2fs_update_inode(inode, page); 18248c2ecf20Sopenharmony_ci unlock_page(page); 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_ci iput(inode); 18278c2ecf20Sopenharmony_ci return true; 18288c2ecf20Sopenharmony_ci} 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_civoid f2fs_flush_inline_data(struct f2fs_sb_info *sbi) 18318c2ecf20Sopenharmony_ci{ 18328c2ecf20Sopenharmony_ci pgoff_t index = 0; 18338c2ecf20Sopenharmony_ci struct pagevec pvec; 18348c2ecf20Sopenharmony_ci int nr_pages; 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ci pagevec_init(&pvec); 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ci while ((nr_pages = pagevec_lookup_tag(&pvec, 18398c2ecf20Sopenharmony_ci NODE_MAPPING(sbi), &index, PAGECACHE_TAG_DIRTY))) { 18408c2ecf20Sopenharmony_ci int i; 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ci for (i = 0; i < nr_pages; i++) { 18438c2ecf20Sopenharmony_ci struct page *page = pvec.pages[i]; 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci if (!IS_DNODE(page)) 18468c2ecf20Sopenharmony_ci continue; 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci lock_page(page); 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ci if (unlikely(page->mapping != NODE_MAPPING(sbi))) { 18518c2ecf20Sopenharmony_cicontinue_unlock: 18528c2ecf20Sopenharmony_ci unlock_page(page); 18538c2ecf20Sopenharmony_ci continue; 18548c2ecf20Sopenharmony_ci } 18558c2ecf20Sopenharmony_ci 18568c2ecf20Sopenharmony_ci if (!PageDirty(page)) { 18578c2ecf20Sopenharmony_ci /* someone wrote it for us */ 18588c2ecf20Sopenharmony_ci goto continue_unlock; 18598c2ecf20Sopenharmony_ci } 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci /* flush inline_data, if it's async context. */ 18628c2ecf20Sopenharmony_ci if (is_inline_node(page)) { 18638c2ecf20Sopenharmony_ci clear_inline_node(page); 18648c2ecf20Sopenharmony_ci unlock_page(page); 18658c2ecf20Sopenharmony_ci flush_inline_data(sbi, ino_of_node(page)); 18668c2ecf20Sopenharmony_ci continue; 18678c2ecf20Sopenharmony_ci } 18688c2ecf20Sopenharmony_ci unlock_page(page); 18698c2ecf20Sopenharmony_ci } 18708c2ecf20Sopenharmony_ci pagevec_release(&pvec); 18718c2ecf20Sopenharmony_ci cond_resched(); 18728c2ecf20Sopenharmony_ci } 18738c2ecf20Sopenharmony_ci} 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ciint f2fs_sync_node_pages(struct f2fs_sb_info *sbi, 18768c2ecf20Sopenharmony_ci struct writeback_control *wbc, 18778c2ecf20Sopenharmony_ci bool do_balance, enum iostat_type io_type) 18788c2ecf20Sopenharmony_ci{ 18798c2ecf20Sopenharmony_ci pgoff_t index; 18808c2ecf20Sopenharmony_ci struct pagevec pvec; 18818c2ecf20Sopenharmony_ci int step = 0; 18828c2ecf20Sopenharmony_ci int nwritten = 0; 18838c2ecf20Sopenharmony_ci int ret = 0; 18848c2ecf20Sopenharmony_ci int nr_pages, done = 0; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci pagevec_init(&pvec); 18878c2ecf20Sopenharmony_ci 18888c2ecf20Sopenharmony_cinext_step: 18898c2ecf20Sopenharmony_ci index = 0; 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci while (!done && (nr_pages = pagevec_lookup_tag(&pvec, 18928c2ecf20Sopenharmony_ci NODE_MAPPING(sbi), &index, PAGECACHE_TAG_DIRTY))) { 18938c2ecf20Sopenharmony_ci int i; 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci for (i = 0; i < nr_pages; i++) { 18968c2ecf20Sopenharmony_ci struct page *page = pvec.pages[i]; 18978c2ecf20Sopenharmony_ci bool submitted = false; 18988c2ecf20Sopenharmony_ci bool may_dirty = true; 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci /* give a priority to WB_SYNC threads */ 19018c2ecf20Sopenharmony_ci if (atomic_read(&sbi->wb_sync_req[NODE]) && 19028c2ecf20Sopenharmony_ci wbc->sync_mode == WB_SYNC_NONE) { 19038c2ecf20Sopenharmony_ci done = 1; 19048c2ecf20Sopenharmony_ci break; 19058c2ecf20Sopenharmony_ci } 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci /* 19088c2ecf20Sopenharmony_ci * flushing sequence with step: 19098c2ecf20Sopenharmony_ci * 0. indirect nodes 19108c2ecf20Sopenharmony_ci * 1. dentry dnodes 19118c2ecf20Sopenharmony_ci * 2. file dnodes 19128c2ecf20Sopenharmony_ci */ 19138c2ecf20Sopenharmony_ci if (step == 0 && IS_DNODE(page)) 19148c2ecf20Sopenharmony_ci continue; 19158c2ecf20Sopenharmony_ci if (step == 1 && (!IS_DNODE(page) || 19168c2ecf20Sopenharmony_ci is_cold_node(page))) 19178c2ecf20Sopenharmony_ci continue; 19188c2ecf20Sopenharmony_ci if (step == 2 && (!IS_DNODE(page) || 19198c2ecf20Sopenharmony_ci !is_cold_node(page))) 19208c2ecf20Sopenharmony_ci continue; 19218c2ecf20Sopenharmony_cilock_node: 19228c2ecf20Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL) 19238c2ecf20Sopenharmony_ci lock_page(page); 19248c2ecf20Sopenharmony_ci else if (!trylock_page(page)) 19258c2ecf20Sopenharmony_ci continue; 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci if (unlikely(page->mapping != NODE_MAPPING(sbi))) { 19288c2ecf20Sopenharmony_cicontinue_unlock: 19298c2ecf20Sopenharmony_ci unlock_page(page); 19308c2ecf20Sopenharmony_ci continue; 19318c2ecf20Sopenharmony_ci } 19328c2ecf20Sopenharmony_ci 19338c2ecf20Sopenharmony_ci if (!PageDirty(page)) { 19348c2ecf20Sopenharmony_ci /* someone wrote it for us */ 19358c2ecf20Sopenharmony_ci goto continue_unlock; 19368c2ecf20Sopenharmony_ci } 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci /* flush inline_data/inode, if it's async context. */ 19398c2ecf20Sopenharmony_ci if (!do_balance) 19408c2ecf20Sopenharmony_ci goto write_node; 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_ci /* flush inline_data */ 19438c2ecf20Sopenharmony_ci if (is_inline_node(page)) { 19448c2ecf20Sopenharmony_ci clear_inline_node(page); 19458c2ecf20Sopenharmony_ci unlock_page(page); 19468c2ecf20Sopenharmony_ci flush_inline_data(sbi, ino_of_node(page)); 19478c2ecf20Sopenharmony_ci goto lock_node; 19488c2ecf20Sopenharmony_ci } 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_ci /* flush dirty inode */ 19518c2ecf20Sopenharmony_ci if (IS_INODE(page) && may_dirty) { 19528c2ecf20Sopenharmony_ci may_dirty = false; 19538c2ecf20Sopenharmony_ci if (flush_dirty_inode(page)) 19548c2ecf20Sopenharmony_ci goto lock_node; 19558c2ecf20Sopenharmony_ci } 19568c2ecf20Sopenharmony_ciwrite_node: 19578c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(page, NODE, true, true); 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_ci if (!clear_page_dirty_for_io(page)) 19608c2ecf20Sopenharmony_ci goto continue_unlock; 19618c2ecf20Sopenharmony_ci 19628c2ecf20Sopenharmony_ci set_fsync_mark(page, 0); 19638c2ecf20Sopenharmony_ci set_dentry_mark(page, 0); 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci ret = __write_node_page(page, false, &submitted, 19668c2ecf20Sopenharmony_ci wbc, do_balance, io_type, NULL); 19678c2ecf20Sopenharmony_ci if (ret) 19688c2ecf20Sopenharmony_ci unlock_page(page); 19698c2ecf20Sopenharmony_ci else if (submitted) 19708c2ecf20Sopenharmony_ci nwritten++; 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_ci if (--wbc->nr_to_write == 0) 19738c2ecf20Sopenharmony_ci break; 19748c2ecf20Sopenharmony_ci } 19758c2ecf20Sopenharmony_ci pagevec_release(&pvec); 19768c2ecf20Sopenharmony_ci cond_resched(); 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_ci if (wbc->nr_to_write == 0) { 19798c2ecf20Sopenharmony_ci step = 2; 19808c2ecf20Sopenharmony_ci break; 19818c2ecf20Sopenharmony_ci } 19828c2ecf20Sopenharmony_ci } 19838c2ecf20Sopenharmony_ci 19848c2ecf20Sopenharmony_ci if (step < 2) { 19858c2ecf20Sopenharmony_ci if (!is_sbi_flag_set(sbi, SBI_CP_DISABLED) && 19868c2ecf20Sopenharmony_ci wbc->sync_mode == WB_SYNC_NONE && step == 1) 19878c2ecf20Sopenharmony_ci goto out; 19888c2ecf20Sopenharmony_ci step++; 19898c2ecf20Sopenharmony_ci goto next_step; 19908c2ecf20Sopenharmony_ci } 19918c2ecf20Sopenharmony_ciout: 19928c2ecf20Sopenharmony_ci if (nwritten) 19938c2ecf20Sopenharmony_ci f2fs_submit_merged_write(sbi, NODE); 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) 19968c2ecf20Sopenharmony_ci return -EIO; 19978c2ecf20Sopenharmony_ci return ret; 19988c2ecf20Sopenharmony_ci} 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_ciint f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, 20018c2ecf20Sopenharmony_ci unsigned int seq_id) 20028c2ecf20Sopenharmony_ci{ 20038c2ecf20Sopenharmony_ci struct fsync_node_entry *fn; 20048c2ecf20Sopenharmony_ci struct page *page; 20058c2ecf20Sopenharmony_ci struct list_head *head = &sbi->fsync_node_list; 20068c2ecf20Sopenharmony_ci unsigned long flags; 20078c2ecf20Sopenharmony_ci unsigned int cur_seq_id = 0; 20088c2ecf20Sopenharmony_ci int ret2, ret = 0; 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci while (seq_id && cur_seq_id < seq_id) { 20118c2ecf20Sopenharmony_ci spin_lock_irqsave(&sbi->fsync_node_lock, flags); 20128c2ecf20Sopenharmony_ci if (list_empty(head)) { 20138c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 20148c2ecf20Sopenharmony_ci break; 20158c2ecf20Sopenharmony_ci } 20168c2ecf20Sopenharmony_ci fn = list_first_entry(head, struct fsync_node_entry, list); 20178c2ecf20Sopenharmony_ci if (fn->seq_id > seq_id) { 20188c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 20198c2ecf20Sopenharmony_ci break; 20208c2ecf20Sopenharmony_ci } 20218c2ecf20Sopenharmony_ci cur_seq_id = fn->seq_id; 20228c2ecf20Sopenharmony_ci page = fn->page; 20238c2ecf20Sopenharmony_ci get_page(page); 20248c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 20258c2ecf20Sopenharmony_ci 20268c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(page, NODE, true, false); 20278c2ecf20Sopenharmony_ci if (TestClearPageError(page)) 20288c2ecf20Sopenharmony_ci ret = -EIO; 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_ci put_page(page); 20318c2ecf20Sopenharmony_ci 20328c2ecf20Sopenharmony_ci if (ret) 20338c2ecf20Sopenharmony_ci break; 20348c2ecf20Sopenharmony_ci } 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci ret2 = filemap_check_errors(NODE_MAPPING(sbi)); 20378c2ecf20Sopenharmony_ci if (!ret) 20388c2ecf20Sopenharmony_ci ret = ret2; 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_ci return ret; 20418c2ecf20Sopenharmony_ci} 20428c2ecf20Sopenharmony_ci 20438c2ecf20Sopenharmony_cistatic int f2fs_write_node_pages(struct address_space *mapping, 20448c2ecf20Sopenharmony_ci struct writeback_control *wbc) 20458c2ecf20Sopenharmony_ci{ 20468c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_M_SB(mapping); 20478c2ecf20Sopenharmony_ci struct blk_plug plug; 20488c2ecf20Sopenharmony_ci long diff; 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 20518c2ecf20Sopenharmony_ci goto skip_write; 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_ci /* balancing f2fs's metadata in background */ 20548c2ecf20Sopenharmony_ci f2fs_balance_fs_bg(sbi, true); 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ci /* collect a number of dirty node pages and write together */ 20578c2ecf20Sopenharmony_ci if (wbc->sync_mode != WB_SYNC_ALL && 20588c2ecf20Sopenharmony_ci get_pages(sbi, F2FS_DIRTY_NODES) < 20598c2ecf20Sopenharmony_ci nr_pages_to_skip(sbi, NODE)) 20608c2ecf20Sopenharmony_ci goto skip_write; 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL) 20638c2ecf20Sopenharmony_ci atomic_inc(&sbi->wb_sync_req[NODE]); 20648c2ecf20Sopenharmony_ci else if (atomic_read(&sbi->wb_sync_req[NODE])) { 20658c2ecf20Sopenharmony_ci /* to avoid potential deadlock */ 20668c2ecf20Sopenharmony_ci if (current->plug) 20678c2ecf20Sopenharmony_ci blk_finish_plug(current->plug); 20688c2ecf20Sopenharmony_ci goto skip_write; 20698c2ecf20Sopenharmony_ci } 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci trace_f2fs_writepages(mapping->host, wbc, NODE); 20728c2ecf20Sopenharmony_ci 20738c2ecf20Sopenharmony_ci diff = nr_pages_to_write(sbi, NODE, wbc); 20748c2ecf20Sopenharmony_ci blk_start_plug(&plug); 20758c2ecf20Sopenharmony_ci f2fs_sync_node_pages(sbi, wbc, true, FS_NODE_IO); 20768c2ecf20Sopenharmony_ci blk_finish_plug(&plug); 20778c2ecf20Sopenharmony_ci wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff); 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL) 20808c2ecf20Sopenharmony_ci atomic_dec(&sbi->wb_sync_req[NODE]); 20818c2ecf20Sopenharmony_ci return 0; 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ciskip_write: 20848c2ecf20Sopenharmony_ci wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_NODES); 20858c2ecf20Sopenharmony_ci trace_f2fs_writepages(mapping->host, wbc, NODE); 20868c2ecf20Sopenharmony_ci return 0; 20878c2ecf20Sopenharmony_ci} 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_cistatic int f2fs_set_node_page_dirty(struct page *page) 20908c2ecf20Sopenharmony_ci{ 20918c2ecf20Sopenharmony_ci trace_f2fs_set_page_dirty(page, NODE); 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci if (!PageUptodate(page)) 20948c2ecf20Sopenharmony_ci SetPageUptodate(page); 20958c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS 20968c2ecf20Sopenharmony_ci if (IS_INODE(page)) 20978c2ecf20Sopenharmony_ci f2fs_inode_chksum_set(F2FS_P_SB(page), page); 20988c2ecf20Sopenharmony_ci#endif 20998c2ecf20Sopenharmony_ci if (!PageDirty(page)) { 21008c2ecf20Sopenharmony_ci __set_page_dirty_nobuffers(page); 21018c2ecf20Sopenharmony_ci inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES); 21028c2ecf20Sopenharmony_ci f2fs_set_page_private(page, 0); 21038c2ecf20Sopenharmony_ci f2fs_trace_pid(page); 21048c2ecf20Sopenharmony_ci return 1; 21058c2ecf20Sopenharmony_ci } 21068c2ecf20Sopenharmony_ci return 0; 21078c2ecf20Sopenharmony_ci} 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ci/* 21108c2ecf20Sopenharmony_ci * Structure of the f2fs node operations 21118c2ecf20Sopenharmony_ci */ 21128c2ecf20Sopenharmony_ciconst struct address_space_operations f2fs_node_aops = { 21138c2ecf20Sopenharmony_ci .writepage = f2fs_write_node_page, 21148c2ecf20Sopenharmony_ci .writepages = f2fs_write_node_pages, 21158c2ecf20Sopenharmony_ci .set_page_dirty = f2fs_set_node_page_dirty, 21168c2ecf20Sopenharmony_ci .invalidatepage = f2fs_invalidate_page, 21178c2ecf20Sopenharmony_ci .releasepage = f2fs_release_page, 21188c2ecf20Sopenharmony_ci#ifdef CONFIG_MIGRATION 21198c2ecf20Sopenharmony_ci .migratepage = f2fs_migrate_page, 21208c2ecf20Sopenharmony_ci#endif 21218c2ecf20Sopenharmony_ci}; 21228c2ecf20Sopenharmony_ci 21238c2ecf20Sopenharmony_cistatic struct free_nid *__lookup_free_nid_list(struct f2fs_nm_info *nm_i, 21248c2ecf20Sopenharmony_ci nid_t n) 21258c2ecf20Sopenharmony_ci{ 21268c2ecf20Sopenharmony_ci return radix_tree_lookup(&nm_i->free_nid_root, n); 21278c2ecf20Sopenharmony_ci} 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_cistatic int __insert_free_nid(struct f2fs_sb_info *sbi, 21308c2ecf20Sopenharmony_ci struct free_nid *i) 21318c2ecf20Sopenharmony_ci{ 21328c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 21338c2ecf20Sopenharmony_ci 21348c2ecf20Sopenharmony_ci int err = radix_tree_insert(&nm_i->free_nid_root, i->nid, i); 21358c2ecf20Sopenharmony_ci if (err) 21368c2ecf20Sopenharmony_ci return err; 21378c2ecf20Sopenharmony_ci 21388c2ecf20Sopenharmony_ci nm_i->nid_cnt[FREE_NID]++; 21398c2ecf20Sopenharmony_ci list_add_tail(&i->list, &nm_i->free_nid_list); 21408c2ecf20Sopenharmony_ci return 0; 21418c2ecf20Sopenharmony_ci} 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_cistatic void __remove_free_nid(struct f2fs_sb_info *sbi, 21448c2ecf20Sopenharmony_ci struct free_nid *i, enum nid_state state) 21458c2ecf20Sopenharmony_ci{ 21468c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 21478c2ecf20Sopenharmony_ci 21488c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, state != i->state); 21498c2ecf20Sopenharmony_ci nm_i->nid_cnt[state]--; 21508c2ecf20Sopenharmony_ci if (state == FREE_NID) 21518c2ecf20Sopenharmony_ci list_del(&i->list); 21528c2ecf20Sopenharmony_ci radix_tree_delete(&nm_i->free_nid_root, i->nid); 21538c2ecf20Sopenharmony_ci} 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_cistatic void __move_free_nid(struct f2fs_sb_info *sbi, struct free_nid *i, 21568c2ecf20Sopenharmony_ci enum nid_state org_state, enum nid_state dst_state) 21578c2ecf20Sopenharmony_ci{ 21588c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, org_state != i->state); 21618c2ecf20Sopenharmony_ci i->state = dst_state; 21628c2ecf20Sopenharmony_ci nm_i->nid_cnt[org_state]--; 21638c2ecf20Sopenharmony_ci nm_i->nid_cnt[dst_state]++; 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci switch (dst_state) { 21668c2ecf20Sopenharmony_ci case PREALLOC_NID: 21678c2ecf20Sopenharmony_ci list_del(&i->list); 21688c2ecf20Sopenharmony_ci break; 21698c2ecf20Sopenharmony_ci case FREE_NID: 21708c2ecf20Sopenharmony_ci list_add_tail(&i->list, &nm_i->free_nid_list); 21718c2ecf20Sopenharmony_ci break; 21728c2ecf20Sopenharmony_ci default: 21738c2ecf20Sopenharmony_ci BUG_ON(1); 21748c2ecf20Sopenharmony_ci } 21758c2ecf20Sopenharmony_ci} 21768c2ecf20Sopenharmony_ci 21778c2ecf20Sopenharmony_cistatic void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid, 21788c2ecf20Sopenharmony_ci bool set, bool build) 21798c2ecf20Sopenharmony_ci{ 21808c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 21818c2ecf20Sopenharmony_ci unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid); 21828c2ecf20Sopenharmony_ci unsigned int nid_ofs = nid - START_NID(nid); 21838c2ecf20Sopenharmony_ci 21848c2ecf20Sopenharmony_ci if (!test_bit_le(nat_ofs, nm_i->nat_block_bitmap)) 21858c2ecf20Sopenharmony_ci return; 21868c2ecf20Sopenharmony_ci 21878c2ecf20Sopenharmony_ci if (set) { 21888c2ecf20Sopenharmony_ci if (test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs])) 21898c2ecf20Sopenharmony_ci return; 21908c2ecf20Sopenharmony_ci __set_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); 21918c2ecf20Sopenharmony_ci nm_i->free_nid_count[nat_ofs]++; 21928c2ecf20Sopenharmony_ci } else { 21938c2ecf20Sopenharmony_ci if (!test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs])) 21948c2ecf20Sopenharmony_ci return; 21958c2ecf20Sopenharmony_ci __clear_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); 21968c2ecf20Sopenharmony_ci if (!build) 21978c2ecf20Sopenharmony_ci nm_i->free_nid_count[nat_ofs]--; 21988c2ecf20Sopenharmony_ci } 21998c2ecf20Sopenharmony_ci} 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci/* return if the nid is recognized as free */ 22028c2ecf20Sopenharmony_cistatic bool add_free_nid(struct f2fs_sb_info *sbi, 22038c2ecf20Sopenharmony_ci nid_t nid, bool build, bool update) 22048c2ecf20Sopenharmony_ci{ 22058c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 22068c2ecf20Sopenharmony_ci struct free_nid *i, *e; 22078c2ecf20Sopenharmony_ci struct nat_entry *ne; 22088c2ecf20Sopenharmony_ci int err = -EINVAL; 22098c2ecf20Sopenharmony_ci bool ret = false; 22108c2ecf20Sopenharmony_ci 22118c2ecf20Sopenharmony_ci /* 0 nid should not be used */ 22128c2ecf20Sopenharmony_ci if (unlikely(nid == 0)) 22138c2ecf20Sopenharmony_ci return false; 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_ci if (unlikely(f2fs_check_nid_range(sbi, nid))) 22168c2ecf20Sopenharmony_ci return false; 22178c2ecf20Sopenharmony_ci 22188c2ecf20Sopenharmony_ci i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS); 22198c2ecf20Sopenharmony_ci i->nid = nid; 22208c2ecf20Sopenharmony_ci i->state = FREE_NID; 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_ci radix_tree_preload(GFP_NOFS | __GFP_NOFAIL); 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 22258c2ecf20Sopenharmony_ci 22268c2ecf20Sopenharmony_ci if (build) { 22278c2ecf20Sopenharmony_ci /* 22288c2ecf20Sopenharmony_ci * Thread A Thread B 22298c2ecf20Sopenharmony_ci * - f2fs_create 22308c2ecf20Sopenharmony_ci * - f2fs_new_inode 22318c2ecf20Sopenharmony_ci * - f2fs_alloc_nid 22328c2ecf20Sopenharmony_ci * - __insert_nid_to_list(PREALLOC_NID) 22338c2ecf20Sopenharmony_ci * - f2fs_balance_fs_bg 22348c2ecf20Sopenharmony_ci * - f2fs_build_free_nids 22358c2ecf20Sopenharmony_ci * - __f2fs_build_free_nids 22368c2ecf20Sopenharmony_ci * - scan_nat_page 22378c2ecf20Sopenharmony_ci * - add_free_nid 22388c2ecf20Sopenharmony_ci * - __lookup_nat_cache 22398c2ecf20Sopenharmony_ci * - f2fs_add_link 22408c2ecf20Sopenharmony_ci * - f2fs_init_inode_metadata 22418c2ecf20Sopenharmony_ci * - f2fs_new_inode_page 22428c2ecf20Sopenharmony_ci * - f2fs_new_node_page 22438c2ecf20Sopenharmony_ci * - set_node_addr 22448c2ecf20Sopenharmony_ci * - f2fs_alloc_nid_done 22458c2ecf20Sopenharmony_ci * - __remove_nid_from_list(PREALLOC_NID) 22468c2ecf20Sopenharmony_ci * - __insert_nid_to_list(FREE_NID) 22478c2ecf20Sopenharmony_ci */ 22488c2ecf20Sopenharmony_ci ne = __lookup_nat_cache(nm_i, nid); 22498c2ecf20Sopenharmony_ci if (ne && (!get_nat_flag(ne, IS_CHECKPOINTED) || 22508c2ecf20Sopenharmony_ci nat_get_blkaddr(ne) != NULL_ADDR)) 22518c2ecf20Sopenharmony_ci goto err_out; 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_ci e = __lookup_free_nid_list(nm_i, nid); 22548c2ecf20Sopenharmony_ci if (e) { 22558c2ecf20Sopenharmony_ci if (e->state == FREE_NID) 22568c2ecf20Sopenharmony_ci ret = true; 22578c2ecf20Sopenharmony_ci goto err_out; 22588c2ecf20Sopenharmony_ci } 22598c2ecf20Sopenharmony_ci } 22608c2ecf20Sopenharmony_ci ret = true; 22618c2ecf20Sopenharmony_ci err = __insert_free_nid(sbi, i); 22628c2ecf20Sopenharmony_cierr_out: 22638c2ecf20Sopenharmony_ci if (update) { 22648c2ecf20Sopenharmony_ci update_free_nid_bitmap(sbi, nid, ret, build); 22658c2ecf20Sopenharmony_ci if (!build) 22668c2ecf20Sopenharmony_ci nm_i->available_nids++; 22678c2ecf20Sopenharmony_ci } 22688c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 22698c2ecf20Sopenharmony_ci radix_tree_preload_end(); 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_ci if (err) 22728c2ecf20Sopenharmony_ci kmem_cache_free(free_nid_slab, i); 22738c2ecf20Sopenharmony_ci return ret; 22748c2ecf20Sopenharmony_ci} 22758c2ecf20Sopenharmony_ci 22768c2ecf20Sopenharmony_cistatic void remove_free_nid(struct f2fs_sb_info *sbi, nid_t nid) 22778c2ecf20Sopenharmony_ci{ 22788c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 22798c2ecf20Sopenharmony_ci struct free_nid *i; 22808c2ecf20Sopenharmony_ci bool need_free = false; 22818c2ecf20Sopenharmony_ci 22828c2ecf20Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 22838c2ecf20Sopenharmony_ci i = __lookup_free_nid_list(nm_i, nid); 22848c2ecf20Sopenharmony_ci if (i && i->state == FREE_NID) { 22858c2ecf20Sopenharmony_ci __remove_free_nid(sbi, i, FREE_NID); 22868c2ecf20Sopenharmony_ci need_free = true; 22878c2ecf20Sopenharmony_ci } 22888c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 22898c2ecf20Sopenharmony_ci 22908c2ecf20Sopenharmony_ci if (need_free) 22918c2ecf20Sopenharmony_ci kmem_cache_free(free_nid_slab, i); 22928c2ecf20Sopenharmony_ci} 22938c2ecf20Sopenharmony_ci 22948c2ecf20Sopenharmony_cistatic int scan_nat_page(struct f2fs_sb_info *sbi, 22958c2ecf20Sopenharmony_ci struct page *nat_page, nid_t start_nid) 22968c2ecf20Sopenharmony_ci{ 22978c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 22988c2ecf20Sopenharmony_ci struct f2fs_nat_block *nat_blk = page_address(nat_page); 22998c2ecf20Sopenharmony_ci block_t blk_addr; 23008c2ecf20Sopenharmony_ci unsigned int nat_ofs = NAT_BLOCK_OFFSET(start_nid); 23018c2ecf20Sopenharmony_ci int i; 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_ci __set_bit_le(nat_ofs, nm_i->nat_block_bitmap); 23048c2ecf20Sopenharmony_ci 23058c2ecf20Sopenharmony_ci i = start_nid % NAT_ENTRY_PER_BLOCK; 23068c2ecf20Sopenharmony_ci 23078c2ecf20Sopenharmony_ci for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) { 23088c2ecf20Sopenharmony_ci if (unlikely(start_nid >= nm_i->max_nid)) 23098c2ecf20Sopenharmony_ci break; 23108c2ecf20Sopenharmony_ci 23118c2ecf20Sopenharmony_ci blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr); 23128c2ecf20Sopenharmony_ci 23138c2ecf20Sopenharmony_ci if (blk_addr == NEW_ADDR) 23148c2ecf20Sopenharmony_ci return -EINVAL; 23158c2ecf20Sopenharmony_ci 23168c2ecf20Sopenharmony_ci if (blk_addr == NULL_ADDR) { 23178c2ecf20Sopenharmony_ci add_free_nid(sbi, start_nid, true, true); 23188c2ecf20Sopenharmony_ci } else { 23198c2ecf20Sopenharmony_ci spin_lock(&NM_I(sbi)->nid_list_lock); 23208c2ecf20Sopenharmony_ci update_free_nid_bitmap(sbi, start_nid, false, true); 23218c2ecf20Sopenharmony_ci spin_unlock(&NM_I(sbi)->nid_list_lock); 23228c2ecf20Sopenharmony_ci } 23238c2ecf20Sopenharmony_ci } 23248c2ecf20Sopenharmony_ci 23258c2ecf20Sopenharmony_ci return 0; 23268c2ecf20Sopenharmony_ci} 23278c2ecf20Sopenharmony_ci 23288c2ecf20Sopenharmony_cistatic void scan_curseg_cache(struct f2fs_sb_info *sbi) 23298c2ecf20Sopenharmony_ci{ 23308c2ecf20Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 23318c2ecf20Sopenharmony_ci struct f2fs_journal *journal = curseg->journal; 23328c2ecf20Sopenharmony_ci int i; 23338c2ecf20Sopenharmony_ci 23348c2ecf20Sopenharmony_ci down_read(&curseg->journal_rwsem); 23358c2ecf20Sopenharmony_ci for (i = 0; i < nats_in_cursum(journal); i++) { 23368c2ecf20Sopenharmony_ci block_t addr; 23378c2ecf20Sopenharmony_ci nid_t nid; 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_ci addr = le32_to_cpu(nat_in_journal(journal, i).block_addr); 23408c2ecf20Sopenharmony_ci nid = le32_to_cpu(nid_in_journal(journal, i)); 23418c2ecf20Sopenharmony_ci if (addr == NULL_ADDR) 23428c2ecf20Sopenharmony_ci add_free_nid(sbi, nid, true, false); 23438c2ecf20Sopenharmony_ci else 23448c2ecf20Sopenharmony_ci remove_free_nid(sbi, nid); 23458c2ecf20Sopenharmony_ci } 23468c2ecf20Sopenharmony_ci up_read(&curseg->journal_rwsem); 23478c2ecf20Sopenharmony_ci} 23488c2ecf20Sopenharmony_ci 23498c2ecf20Sopenharmony_cistatic void scan_free_nid_bits(struct f2fs_sb_info *sbi) 23508c2ecf20Sopenharmony_ci{ 23518c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 23528c2ecf20Sopenharmony_ci unsigned int i, idx; 23538c2ecf20Sopenharmony_ci nid_t nid; 23548c2ecf20Sopenharmony_ci 23558c2ecf20Sopenharmony_ci down_read(&nm_i->nat_tree_lock); 23568c2ecf20Sopenharmony_ci 23578c2ecf20Sopenharmony_ci for (i = 0; i < nm_i->nat_blocks; i++) { 23588c2ecf20Sopenharmony_ci if (!test_bit_le(i, nm_i->nat_block_bitmap)) 23598c2ecf20Sopenharmony_ci continue; 23608c2ecf20Sopenharmony_ci if (!nm_i->free_nid_count[i]) 23618c2ecf20Sopenharmony_ci continue; 23628c2ecf20Sopenharmony_ci for (idx = 0; idx < NAT_ENTRY_PER_BLOCK; idx++) { 23638c2ecf20Sopenharmony_ci idx = find_next_bit_le(nm_i->free_nid_bitmap[i], 23648c2ecf20Sopenharmony_ci NAT_ENTRY_PER_BLOCK, idx); 23658c2ecf20Sopenharmony_ci if (idx >= NAT_ENTRY_PER_BLOCK) 23668c2ecf20Sopenharmony_ci break; 23678c2ecf20Sopenharmony_ci 23688c2ecf20Sopenharmony_ci nid = i * NAT_ENTRY_PER_BLOCK + idx; 23698c2ecf20Sopenharmony_ci add_free_nid(sbi, nid, true, false); 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci if (nm_i->nid_cnt[FREE_NID] >= MAX_FREE_NIDS) 23728c2ecf20Sopenharmony_ci goto out; 23738c2ecf20Sopenharmony_ci } 23748c2ecf20Sopenharmony_ci } 23758c2ecf20Sopenharmony_ciout: 23768c2ecf20Sopenharmony_ci scan_curseg_cache(sbi); 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_ci up_read(&nm_i->nat_tree_lock); 23798c2ecf20Sopenharmony_ci} 23808c2ecf20Sopenharmony_ci 23818c2ecf20Sopenharmony_cistatic int __f2fs_build_free_nids(struct f2fs_sb_info *sbi, 23828c2ecf20Sopenharmony_ci bool sync, bool mount) 23838c2ecf20Sopenharmony_ci{ 23848c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 23858c2ecf20Sopenharmony_ci int i = 0, ret; 23868c2ecf20Sopenharmony_ci nid_t nid = nm_i->next_scan_nid; 23878c2ecf20Sopenharmony_ci 23888c2ecf20Sopenharmony_ci if (unlikely(nid >= nm_i->max_nid)) 23898c2ecf20Sopenharmony_ci nid = 0; 23908c2ecf20Sopenharmony_ci 23918c2ecf20Sopenharmony_ci if (unlikely(nid % NAT_ENTRY_PER_BLOCK)) 23928c2ecf20Sopenharmony_ci nid = NAT_BLOCK_OFFSET(nid) * NAT_ENTRY_PER_BLOCK; 23938c2ecf20Sopenharmony_ci 23948c2ecf20Sopenharmony_ci /* Enough entries */ 23958c2ecf20Sopenharmony_ci if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK) 23968c2ecf20Sopenharmony_ci return 0; 23978c2ecf20Sopenharmony_ci 23988c2ecf20Sopenharmony_ci if (!sync && !f2fs_available_free_memory(sbi, FREE_NIDS)) 23998c2ecf20Sopenharmony_ci return 0; 24008c2ecf20Sopenharmony_ci 24018c2ecf20Sopenharmony_ci if (!mount) { 24028c2ecf20Sopenharmony_ci /* try to find free nids in free_nid_bitmap */ 24038c2ecf20Sopenharmony_ci scan_free_nid_bits(sbi); 24048c2ecf20Sopenharmony_ci 24058c2ecf20Sopenharmony_ci if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK) 24068c2ecf20Sopenharmony_ci return 0; 24078c2ecf20Sopenharmony_ci } 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_ci /* readahead nat pages to be scanned */ 24108c2ecf20Sopenharmony_ci f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES, 24118c2ecf20Sopenharmony_ci META_NAT, true); 24128c2ecf20Sopenharmony_ci 24138c2ecf20Sopenharmony_ci down_read(&nm_i->nat_tree_lock); 24148c2ecf20Sopenharmony_ci 24158c2ecf20Sopenharmony_ci while (1) { 24168c2ecf20Sopenharmony_ci if (!test_bit_le(NAT_BLOCK_OFFSET(nid), 24178c2ecf20Sopenharmony_ci nm_i->nat_block_bitmap)) { 24188c2ecf20Sopenharmony_ci struct page *page = get_current_nat_page(sbi, nid); 24198c2ecf20Sopenharmony_ci 24208c2ecf20Sopenharmony_ci if (IS_ERR(page)) { 24218c2ecf20Sopenharmony_ci ret = PTR_ERR(page); 24228c2ecf20Sopenharmony_ci } else { 24238c2ecf20Sopenharmony_ci ret = scan_nat_page(sbi, page, nid); 24248c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 24258c2ecf20Sopenharmony_ci } 24268c2ecf20Sopenharmony_ci 24278c2ecf20Sopenharmony_ci if (ret) { 24288c2ecf20Sopenharmony_ci up_read(&nm_i->nat_tree_lock); 24298c2ecf20Sopenharmony_ci f2fs_err(sbi, "NAT is corrupt, run fsck to fix it"); 24308c2ecf20Sopenharmony_ci return ret; 24318c2ecf20Sopenharmony_ci } 24328c2ecf20Sopenharmony_ci } 24338c2ecf20Sopenharmony_ci 24348c2ecf20Sopenharmony_ci nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK)); 24358c2ecf20Sopenharmony_ci if (unlikely(nid >= nm_i->max_nid)) 24368c2ecf20Sopenharmony_ci nid = 0; 24378c2ecf20Sopenharmony_ci 24388c2ecf20Sopenharmony_ci if (++i >= FREE_NID_PAGES) 24398c2ecf20Sopenharmony_ci break; 24408c2ecf20Sopenharmony_ci } 24418c2ecf20Sopenharmony_ci 24428c2ecf20Sopenharmony_ci /* go to the next free nat pages to find free nids abundantly */ 24438c2ecf20Sopenharmony_ci nm_i->next_scan_nid = nid; 24448c2ecf20Sopenharmony_ci 24458c2ecf20Sopenharmony_ci /* find free nids from current sum_pages */ 24468c2ecf20Sopenharmony_ci scan_curseg_cache(sbi); 24478c2ecf20Sopenharmony_ci 24488c2ecf20Sopenharmony_ci up_read(&nm_i->nat_tree_lock); 24498c2ecf20Sopenharmony_ci 24508c2ecf20Sopenharmony_ci f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid), 24518c2ecf20Sopenharmony_ci nm_i->ra_nid_pages, META_NAT, false); 24528c2ecf20Sopenharmony_ci 24538c2ecf20Sopenharmony_ci return 0; 24548c2ecf20Sopenharmony_ci} 24558c2ecf20Sopenharmony_ci 24568c2ecf20Sopenharmony_ciint f2fs_build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount) 24578c2ecf20Sopenharmony_ci{ 24588c2ecf20Sopenharmony_ci int ret; 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci mutex_lock(&NM_I(sbi)->build_lock); 24618c2ecf20Sopenharmony_ci ret = __f2fs_build_free_nids(sbi, sync, mount); 24628c2ecf20Sopenharmony_ci mutex_unlock(&NM_I(sbi)->build_lock); 24638c2ecf20Sopenharmony_ci 24648c2ecf20Sopenharmony_ci return ret; 24658c2ecf20Sopenharmony_ci} 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_ci/* 24688c2ecf20Sopenharmony_ci * If this function returns success, caller can obtain a new nid 24698c2ecf20Sopenharmony_ci * from second parameter of this function. 24708c2ecf20Sopenharmony_ci * The returned nid could be used ino as well as nid when inode is created. 24718c2ecf20Sopenharmony_ci */ 24728c2ecf20Sopenharmony_cibool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) 24738c2ecf20Sopenharmony_ci{ 24748c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 24758c2ecf20Sopenharmony_ci struct free_nid *i = NULL; 24768c2ecf20Sopenharmony_ciretry: 24778c2ecf20Sopenharmony_ci if (time_to_inject(sbi, FAULT_ALLOC_NID)) { 24788c2ecf20Sopenharmony_ci f2fs_show_injection_info(sbi, FAULT_ALLOC_NID); 24798c2ecf20Sopenharmony_ci return false; 24808c2ecf20Sopenharmony_ci } 24818c2ecf20Sopenharmony_ci 24828c2ecf20Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 24838c2ecf20Sopenharmony_ci 24848c2ecf20Sopenharmony_ci if (unlikely(nm_i->available_nids == 0)) { 24858c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 24868c2ecf20Sopenharmony_ci return false; 24878c2ecf20Sopenharmony_ci } 24888c2ecf20Sopenharmony_ci 24898c2ecf20Sopenharmony_ci /* We should not use stale free nids created by f2fs_build_free_nids */ 24908c2ecf20Sopenharmony_ci if (nm_i->nid_cnt[FREE_NID] && !on_f2fs_build_free_nids(nm_i)) { 24918c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, list_empty(&nm_i->free_nid_list)); 24928c2ecf20Sopenharmony_ci i = list_first_entry(&nm_i->free_nid_list, 24938c2ecf20Sopenharmony_ci struct free_nid, list); 24948c2ecf20Sopenharmony_ci *nid = i->nid; 24958c2ecf20Sopenharmony_ci 24968c2ecf20Sopenharmony_ci __move_free_nid(sbi, i, FREE_NID, PREALLOC_NID); 24978c2ecf20Sopenharmony_ci nm_i->available_nids--; 24988c2ecf20Sopenharmony_ci 24998c2ecf20Sopenharmony_ci update_free_nid_bitmap(sbi, *nid, false, false); 25008c2ecf20Sopenharmony_ci 25018c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 25028c2ecf20Sopenharmony_ci return true; 25038c2ecf20Sopenharmony_ci } 25048c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 25058c2ecf20Sopenharmony_ci 25068c2ecf20Sopenharmony_ci /* Let's scan nat pages and its caches to get free nids */ 25078c2ecf20Sopenharmony_ci if (!f2fs_build_free_nids(sbi, true, false)) 25088c2ecf20Sopenharmony_ci goto retry; 25098c2ecf20Sopenharmony_ci return false; 25108c2ecf20Sopenharmony_ci} 25118c2ecf20Sopenharmony_ci 25128c2ecf20Sopenharmony_ci/* 25138c2ecf20Sopenharmony_ci * f2fs_alloc_nid() should be called prior to this function. 25148c2ecf20Sopenharmony_ci */ 25158c2ecf20Sopenharmony_civoid f2fs_alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid) 25168c2ecf20Sopenharmony_ci{ 25178c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 25188c2ecf20Sopenharmony_ci struct free_nid *i; 25198c2ecf20Sopenharmony_ci 25208c2ecf20Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 25218c2ecf20Sopenharmony_ci i = __lookup_free_nid_list(nm_i, nid); 25228c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, !i); 25238c2ecf20Sopenharmony_ci __remove_free_nid(sbi, i, PREALLOC_NID); 25248c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_ci kmem_cache_free(free_nid_slab, i); 25278c2ecf20Sopenharmony_ci} 25288c2ecf20Sopenharmony_ci 25298c2ecf20Sopenharmony_ci/* 25308c2ecf20Sopenharmony_ci * f2fs_alloc_nid() should be called prior to this function. 25318c2ecf20Sopenharmony_ci */ 25328c2ecf20Sopenharmony_civoid f2fs_alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid) 25338c2ecf20Sopenharmony_ci{ 25348c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 25358c2ecf20Sopenharmony_ci struct free_nid *i; 25368c2ecf20Sopenharmony_ci bool need_free = false; 25378c2ecf20Sopenharmony_ci 25388c2ecf20Sopenharmony_ci if (!nid) 25398c2ecf20Sopenharmony_ci return; 25408c2ecf20Sopenharmony_ci 25418c2ecf20Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 25428c2ecf20Sopenharmony_ci i = __lookup_free_nid_list(nm_i, nid); 25438c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, !i); 25448c2ecf20Sopenharmony_ci 25458c2ecf20Sopenharmony_ci if (!f2fs_available_free_memory(sbi, FREE_NIDS)) { 25468c2ecf20Sopenharmony_ci __remove_free_nid(sbi, i, PREALLOC_NID); 25478c2ecf20Sopenharmony_ci need_free = true; 25488c2ecf20Sopenharmony_ci } else { 25498c2ecf20Sopenharmony_ci __move_free_nid(sbi, i, PREALLOC_NID, FREE_NID); 25508c2ecf20Sopenharmony_ci } 25518c2ecf20Sopenharmony_ci 25528c2ecf20Sopenharmony_ci nm_i->available_nids++; 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ci update_free_nid_bitmap(sbi, nid, true, false); 25558c2ecf20Sopenharmony_ci 25568c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_ci if (need_free) 25598c2ecf20Sopenharmony_ci kmem_cache_free(free_nid_slab, i); 25608c2ecf20Sopenharmony_ci} 25618c2ecf20Sopenharmony_ci 25628c2ecf20Sopenharmony_ciint f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink) 25638c2ecf20Sopenharmony_ci{ 25648c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 25658c2ecf20Sopenharmony_ci int nr = nr_shrink; 25668c2ecf20Sopenharmony_ci 25678c2ecf20Sopenharmony_ci if (nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS) 25688c2ecf20Sopenharmony_ci return 0; 25698c2ecf20Sopenharmony_ci 25708c2ecf20Sopenharmony_ci if (!mutex_trylock(&nm_i->build_lock)) 25718c2ecf20Sopenharmony_ci return 0; 25728c2ecf20Sopenharmony_ci 25738c2ecf20Sopenharmony_ci while (nr_shrink && nm_i->nid_cnt[FREE_NID] > MAX_FREE_NIDS) { 25748c2ecf20Sopenharmony_ci struct free_nid *i, *next; 25758c2ecf20Sopenharmony_ci unsigned int batch = SHRINK_NID_BATCH_SIZE; 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 25788c2ecf20Sopenharmony_ci list_for_each_entry_safe(i, next, &nm_i->free_nid_list, list) { 25798c2ecf20Sopenharmony_ci if (!nr_shrink || !batch || 25808c2ecf20Sopenharmony_ci nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS) 25818c2ecf20Sopenharmony_ci break; 25828c2ecf20Sopenharmony_ci __remove_free_nid(sbi, i, FREE_NID); 25838c2ecf20Sopenharmony_ci kmem_cache_free(free_nid_slab, i); 25848c2ecf20Sopenharmony_ci nr_shrink--; 25858c2ecf20Sopenharmony_ci batch--; 25868c2ecf20Sopenharmony_ci } 25878c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 25888c2ecf20Sopenharmony_ci } 25898c2ecf20Sopenharmony_ci 25908c2ecf20Sopenharmony_ci mutex_unlock(&nm_i->build_lock); 25918c2ecf20Sopenharmony_ci 25928c2ecf20Sopenharmony_ci return nr - nr_shrink; 25938c2ecf20Sopenharmony_ci} 25948c2ecf20Sopenharmony_ci 25958c2ecf20Sopenharmony_ciint f2fs_recover_inline_xattr(struct inode *inode, struct page *page) 25968c2ecf20Sopenharmony_ci{ 25978c2ecf20Sopenharmony_ci void *src_addr, *dst_addr; 25988c2ecf20Sopenharmony_ci size_t inline_size; 25998c2ecf20Sopenharmony_ci struct page *ipage; 26008c2ecf20Sopenharmony_ci struct f2fs_inode *ri; 26018c2ecf20Sopenharmony_ci 26028c2ecf20Sopenharmony_ci ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino); 26038c2ecf20Sopenharmony_ci if (IS_ERR(ipage)) 26048c2ecf20Sopenharmony_ci return PTR_ERR(ipage); 26058c2ecf20Sopenharmony_ci 26068c2ecf20Sopenharmony_ci ri = F2FS_INODE(page); 26078c2ecf20Sopenharmony_ci if (ri->i_inline & F2FS_INLINE_XATTR) { 26088c2ecf20Sopenharmony_ci set_inode_flag(inode, FI_INLINE_XATTR); 26098c2ecf20Sopenharmony_ci } else { 26108c2ecf20Sopenharmony_ci clear_inode_flag(inode, FI_INLINE_XATTR); 26118c2ecf20Sopenharmony_ci goto update_inode; 26128c2ecf20Sopenharmony_ci } 26138c2ecf20Sopenharmony_ci 26148c2ecf20Sopenharmony_ci dst_addr = inline_xattr_addr(inode, ipage); 26158c2ecf20Sopenharmony_ci src_addr = inline_xattr_addr(inode, page); 26168c2ecf20Sopenharmony_ci inline_size = inline_xattr_size(inode); 26178c2ecf20Sopenharmony_ci 26188c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(ipage, NODE, true, true); 26198c2ecf20Sopenharmony_ci memcpy(dst_addr, src_addr, inline_size); 26208c2ecf20Sopenharmony_ciupdate_inode: 26218c2ecf20Sopenharmony_ci f2fs_update_inode(inode, ipage); 26228c2ecf20Sopenharmony_ci f2fs_put_page(ipage, 1); 26238c2ecf20Sopenharmony_ci return 0; 26248c2ecf20Sopenharmony_ci} 26258c2ecf20Sopenharmony_ci 26268c2ecf20Sopenharmony_ciint f2fs_recover_xattr_data(struct inode *inode, struct page *page) 26278c2ecf20Sopenharmony_ci{ 26288c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 26298c2ecf20Sopenharmony_ci nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid; 26308c2ecf20Sopenharmony_ci nid_t new_xnid; 26318c2ecf20Sopenharmony_ci struct dnode_of_data dn; 26328c2ecf20Sopenharmony_ci struct node_info ni; 26338c2ecf20Sopenharmony_ci struct page *xpage; 26348c2ecf20Sopenharmony_ci int err; 26358c2ecf20Sopenharmony_ci 26368c2ecf20Sopenharmony_ci if (!prev_xnid) 26378c2ecf20Sopenharmony_ci goto recover_xnid; 26388c2ecf20Sopenharmony_ci 26398c2ecf20Sopenharmony_ci /* 1: invalidate the previous xattr nid */ 26408c2ecf20Sopenharmony_ci err = f2fs_get_node_info(sbi, prev_xnid, &ni); 26418c2ecf20Sopenharmony_ci if (err) 26428c2ecf20Sopenharmony_ci return err; 26438c2ecf20Sopenharmony_ci 26448c2ecf20Sopenharmony_ci f2fs_invalidate_blocks(sbi, ni.blk_addr); 26458c2ecf20Sopenharmony_ci dec_valid_node_count(sbi, inode, false); 26468c2ecf20Sopenharmony_ci set_node_addr(sbi, &ni, NULL_ADDR, false); 26478c2ecf20Sopenharmony_ci 26488c2ecf20Sopenharmony_cirecover_xnid: 26498c2ecf20Sopenharmony_ci /* 2: update xattr nid in inode */ 26508c2ecf20Sopenharmony_ci if (!f2fs_alloc_nid(sbi, &new_xnid)) 26518c2ecf20Sopenharmony_ci return -ENOSPC; 26528c2ecf20Sopenharmony_ci 26538c2ecf20Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, new_xnid); 26548c2ecf20Sopenharmony_ci xpage = f2fs_new_node_page(&dn, XATTR_NODE_OFFSET); 26558c2ecf20Sopenharmony_ci if (IS_ERR(xpage)) { 26568c2ecf20Sopenharmony_ci f2fs_alloc_nid_failed(sbi, new_xnid); 26578c2ecf20Sopenharmony_ci return PTR_ERR(xpage); 26588c2ecf20Sopenharmony_ci } 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ci f2fs_alloc_nid_done(sbi, new_xnid); 26618c2ecf20Sopenharmony_ci f2fs_update_inode_page(inode); 26628c2ecf20Sopenharmony_ci 26638c2ecf20Sopenharmony_ci /* 3: update and set xattr node page dirty */ 26648c2ecf20Sopenharmony_ci memcpy(F2FS_NODE(xpage), F2FS_NODE(page), VALID_XATTR_BLOCK_SIZE); 26658c2ecf20Sopenharmony_ci 26668c2ecf20Sopenharmony_ci set_page_dirty(xpage); 26678c2ecf20Sopenharmony_ci f2fs_put_page(xpage, 1); 26688c2ecf20Sopenharmony_ci 26698c2ecf20Sopenharmony_ci return 0; 26708c2ecf20Sopenharmony_ci} 26718c2ecf20Sopenharmony_ci 26728c2ecf20Sopenharmony_ciint f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) 26738c2ecf20Sopenharmony_ci{ 26748c2ecf20Sopenharmony_ci struct f2fs_inode *src, *dst; 26758c2ecf20Sopenharmony_ci nid_t ino = ino_of_node(page); 26768c2ecf20Sopenharmony_ci struct node_info old_ni, new_ni; 26778c2ecf20Sopenharmony_ci struct page *ipage; 26788c2ecf20Sopenharmony_ci int err; 26798c2ecf20Sopenharmony_ci 26808c2ecf20Sopenharmony_ci err = f2fs_get_node_info(sbi, ino, &old_ni); 26818c2ecf20Sopenharmony_ci if (err) 26828c2ecf20Sopenharmony_ci return err; 26838c2ecf20Sopenharmony_ci 26848c2ecf20Sopenharmony_ci if (unlikely(old_ni.blk_addr != NULL_ADDR)) 26858c2ecf20Sopenharmony_ci return -EINVAL; 26868c2ecf20Sopenharmony_ciretry: 26878c2ecf20Sopenharmony_ci ipage = f2fs_grab_cache_page(NODE_MAPPING(sbi), ino, false); 26888c2ecf20Sopenharmony_ci if (!ipage) { 26898c2ecf20Sopenharmony_ci congestion_wait(BLK_RW_ASYNC, DEFAULT_IO_TIMEOUT); 26908c2ecf20Sopenharmony_ci goto retry; 26918c2ecf20Sopenharmony_ci } 26928c2ecf20Sopenharmony_ci 26938c2ecf20Sopenharmony_ci /* Should not use this inode from free nid list */ 26948c2ecf20Sopenharmony_ci remove_free_nid(sbi, ino); 26958c2ecf20Sopenharmony_ci 26968c2ecf20Sopenharmony_ci if (!PageUptodate(ipage)) 26978c2ecf20Sopenharmony_ci SetPageUptodate(ipage); 26988c2ecf20Sopenharmony_ci fill_node_footer(ipage, ino, ino, 0, true); 26998c2ecf20Sopenharmony_ci set_cold_node(ipage, false); 27008c2ecf20Sopenharmony_ci 27018c2ecf20Sopenharmony_ci src = F2FS_INODE(page); 27028c2ecf20Sopenharmony_ci dst = F2FS_INODE(ipage); 27038c2ecf20Sopenharmony_ci 27048c2ecf20Sopenharmony_ci memcpy(dst, src, (unsigned long)&src->i_ext - (unsigned long)src); 27058c2ecf20Sopenharmony_ci dst->i_size = 0; 27068c2ecf20Sopenharmony_ci dst->i_blocks = cpu_to_le64(1); 27078c2ecf20Sopenharmony_ci dst->i_links = cpu_to_le32(1); 27088c2ecf20Sopenharmony_ci dst->i_xattr_nid = 0; 27098c2ecf20Sopenharmony_ci dst->i_inline = src->i_inline & (F2FS_INLINE_XATTR | F2FS_EXTRA_ATTR); 27108c2ecf20Sopenharmony_ci if (dst->i_inline & F2FS_EXTRA_ATTR) { 27118c2ecf20Sopenharmony_ci dst->i_extra_isize = src->i_extra_isize; 27128c2ecf20Sopenharmony_ci 27138c2ecf20Sopenharmony_ci if (f2fs_sb_has_flexible_inline_xattr(sbi) && 27148c2ecf20Sopenharmony_ci F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize), 27158c2ecf20Sopenharmony_ci i_inline_xattr_size)) 27168c2ecf20Sopenharmony_ci dst->i_inline_xattr_size = src->i_inline_xattr_size; 27178c2ecf20Sopenharmony_ci 27188c2ecf20Sopenharmony_ci if (f2fs_sb_has_project_quota(sbi) && 27198c2ecf20Sopenharmony_ci F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize), 27208c2ecf20Sopenharmony_ci i_projid)) 27218c2ecf20Sopenharmony_ci dst->i_projid = src->i_projid; 27228c2ecf20Sopenharmony_ci 27238c2ecf20Sopenharmony_ci if (f2fs_sb_has_inode_crtime(sbi) && 27248c2ecf20Sopenharmony_ci F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize), 27258c2ecf20Sopenharmony_ci i_crtime_nsec)) { 27268c2ecf20Sopenharmony_ci dst->i_crtime = src->i_crtime; 27278c2ecf20Sopenharmony_ci dst->i_crtime_nsec = src->i_crtime_nsec; 27288c2ecf20Sopenharmony_ci } 27298c2ecf20Sopenharmony_ci } 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_ci new_ni = old_ni; 27328c2ecf20Sopenharmony_ci new_ni.ino = ino; 27338c2ecf20Sopenharmony_ci 27348c2ecf20Sopenharmony_ci if (unlikely(inc_valid_node_count(sbi, NULL, true))) 27358c2ecf20Sopenharmony_ci WARN_ON(1); 27368c2ecf20Sopenharmony_ci set_node_addr(sbi, &new_ni, NEW_ADDR, false); 27378c2ecf20Sopenharmony_ci inc_valid_inode_count(sbi); 27388c2ecf20Sopenharmony_ci set_page_dirty(ipage); 27398c2ecf20Sopenharmony_ci f2fs_put_page(ipage, 1); 27408c2ecf20Sopenharmony_ci return 0; 27418c2ecf20Sopenharmony_ci} 27428c2ecf20Sopenharmony_ci 27438c2ecf20Sopenharmony_ciint f2fs_restore_node_summary(struct f2fs_sb_info *sbi, 27448c2ecf20Sopenharmony_ci unsigned int segno, struct f2fs_summary_block *sum) 27458c2ecf20Sopenharmony_ci{ 27468c2ecf20Sopenharmony_ci struct f2fs_node *rn; 27478c2ecf20Sopenharmony_ci struct f2fs_summary *sum_entry; 27488c2ecf20Sopenharmony_ci block_t addr; 27498c2ecf20Sopenharmony_ci int i, idx, last_offset, nrpages; 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_ci /* scan the node segment */ 27528c2ecf20Sopenharmony_ci last_offset = sbi->blocks_per_seg; 27538c2ecf20Sopenharmony_ci addr = START_BLOCK(sbi, segno); 27548c2ecf20Sopenharmony_ci sum_entry = &sum->entries[0]; 27558c2ecf20Sopenharmony_ci 27568c2ecf20Sopenharmony_ci for (i = 0; i < last_offset; i += nrpages, addr += nrpages) { 27578c2ecf20Sopenharmony_ci nrpages = min(last_offset - i, BIO_MAX_PAGES); 27588c2ecf20Sopenharmony_ci 27598c2ecf20Sopenharmony_ci /* readahead node pages */ 27608c2ecf20Sopenharmony_ci f2fs_ra_meta_pages(sbi, addr, nrpages, META_POR, true); 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci for (idx = addr; idx < addr + nrpages; idx++) { 27638c2ecf20Sopenharmony_ci struct page *page = f2fs_get_tmp_page(sbi, idx); 27648c2ecf20Sopenharmony_ci 27658c2ecf20Sopenharmony_ci if (IS_ERR(page)) 27668c2ecf20Sopenharmony_ci return PTR_ERR(page); 27678c2ecf20Sopenharmony_ci 27688c2ecf20Sopenharmony_ci rn = F2FS_NODE(page); 27698c2ecf20Sopenharmony_ci sum_entry->nid = rn->footer.nid; 27708c2ecf20Sopenharmony_ci sum_entry->version = 0; 27718c2ecf20Sopenharmony_ci sum_entry->ofs_in_node = 0; 27728c2ecf20Sopenharmony_ci sum_entry++; 27738c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 27748c2ecf20Sopenharmony_ci } 27758c2ecf20Sopenharmony_ci 27768c2ecf20Sopenharmony_ci invalidate_mapping_pages(META_MAPPING(sbi), addr, 27778c2ecf20Sopenharmony_ci addr + nrpages); 27788c2ecf20Sopenharmony_ci } 27798c2ecf20Sopenharmony_ci return 0; 27808c2ecf20Sopenharmony_ci} 27818c2ecf20Sopenharmony_ci 27828c2ecf20Sopenharmony_cistatic void remove_nats_in_journal(struct f2fs_sb_info *sbi) 27838c2ecf20Sopenharmony_ci{ 27848c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 27858c2ecf20Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 27868c2ecf20Sopenharmony_ci struct f2fs_journal *journal = curseg->journal; 27878c2ecf20Sopenharmony_ci int i; 27888c2ecf20Sopenharmony_ci 27898c2ecf20Sopenharmony_ci down_write(&curseg->journal_rwsem); 27908c2ecf20Sopenharmony_ci for (i = 0; i < nats_in_cursum(journal); i++) { 27918c2ecf20Sopenharmony_ci struct nat_entry *ne; 27928c2ecf20Sopenharmony_ci struct f2fs_nat_entry raw_ne; 27938c2ecf20Sopenharmony_ci nid_t nid = le32_to_cpu(nid_in_journal(journal, i)); 27948c2ecf20Sopenharmony_ci 27958c2ecf20Sopenharmony_ci if (f2fs_check_nid_range(sbi, nid)) 27968c2ecf20Sopenharmony_ci continue; 27978c2ecf20Sopenharmony_ci 27988c2ecf20Sopenharmony_ci raw_ne = nat_in_journal(journal, i); 27998c2ecf20Sopenharmony_ci 28008c2ecf20Sopenharmony_ci ne = __lookup_nat_cache(nm_i, nid); 28018c2ecf20Sopenharmony_ci if (!ne) { 28028c2ecf20Sopenharmony_ci ne = __alloc_nat_entry(nid, true); 28038c2ecf20Sopenharmony_ci __init_nat_entry(nm_i, ne, &raw_ne, true); 28048c2ecf20Sopenharmony_ci } 28058c2ecf20Sopenharmony_ci 28068c2ecf20Sopenharmony_ci /* 28078c2ecf20Sopenharmony_ci * if a free nat in journal has not been used after last 28088c2ecf20Sopenharmony_ci * checkpoint, we should remove it from available nids, 28098c2ecf20Sopenharmony_ci * since later we will add it again. 28108c2ecf20Sopenharmony_ci */ 28118c2ecf20Sopenharmony_ci if (!get_nat_flag(ne, IS_DIRTY) && 28128c2ecf20Sopenharmony_ci le32_to_cpu(raw_ne.block_addr) == NULL_ADDR) { 28138c2ecf20Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 28148c2ecf20Sopenharmony_ci nm_i->available_nids--; 28158c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 28168c2ecf20Sopenharmony_ci } 28178c2ecf20Sopenharmony_ci 28188c2ecf20Sopenharmony_ci __set_nat_cache_dirty(nm_i, ne); 28198c2ecf20Sopenharmony_ci } 28208c2ecf20Sopenharmony_ci update_nats_in_cursum(journal, -i); 28218c2ecf20Sopenharmony_ci up_write(&curseg->journal_rwsem); 28228c2ecf20Sopenharmony_ci} 28238c2ecf20Sopenharmony_ci 28248c2ecf20Sopenharmony_cistatic void __adjust_nat_entry_set(struct nat_entry_set *nes, 28258c2ecf20Sopenharmony_ci struct list_head *head, int max) 28268c2ecf20Sopenharmony_ci{ 28278c2ecf20Sopenharmony_ci struct nat_entry_set *cur; 28288c2ecf20Sopenharmony_ci 28298c2ecf20Sopenharmony_ci if (nes->entry_cnt >= max) 28308c2ecf20Sopenharmony_ci goto add_out; 28318c2ecf20Sopenharmony_ci 28328c2ecf20Sopenharmony_ci list_for_each_entry(cur, head, set_list) { 28338c2ecf20Sopenharmony_ci if (cur->entry_cnt >= nes->entry_cnt) { 28348c2ecf20Sopenharmony_ci list_add(&nes->set_list, cur->set_list.prev); 28358c2ecf20Sopenharmony_ci return; 28368c2ecf20Sopenharmony_ci } 28378c2ecf20Sopenharmony_ci } 28388c2ecf20Sopenharmony_ciadd_out: 28398c2ecf20Sopenharmony_ci list_add_tail(&nes->set_list, head); 28408c2ecf20Sopenharmony_ci} 28418c2ecf20Sopenharmony_ci 28428c2ecf20Sopenharmony_cistatic void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, 28438c2ecf20Sopenharmony_ci struct page *page) 28448c2ecf20Sopenharmony_ci{ 28458c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 28468c2ecf20Sopenharmony_ci unsigned int nat_index = start_nid / NAT_ENTRY_PER_BLOCK; 28478c2ecf20Sopenharmony_ci struct f2fs_nat_block *nat_blk = page_address(page); 28488c2ecf20Sopenharmony_ci int valid = 0; 28498c2ecf20Sopenharmony_ci int i = 0; 28508c2ecf20Sopenharmony_ci 28518c2ecf20Sopenharmony_ci if (!enabled_nat_bits(sbi, NULL)) 28528c2ecf20Sopenharmony_ci return; 28538c2ecf20Sopenharmony_ci 28548c2ecf20Sopenharmony_ci if (nat_index == 0) { 28558c2ecf20Sopenharmony_ci valid = 1; 28568c2ecf20Sopenharmony_ci i = 1; 28578c2ecf20Sopenharmony_ci } 28588c2ecf20Sopenharmony_ci for (; i < NAT_ENTRY_PER_BLOCK; i++) { 28598c2ecf20Sopenharmony_ci if (le32_to_cpu(nat_blk->entries[i].block_addr) != NULL_ADDR) 28608c2ecf20Sopenharmony_ci valid++; 28618c2ecf20Sopenharmony_ci } 28628c2ecf20Sopenharmony_ci if (valid == 0) { 28638c2ecf20Sopenharmony_ci __set_bit_le(nat_index, nm_i->empty_nat_bits); 28648c2ecf20Sopenharmony_ci __clear_bit_le(nat_index, nm_i->full_nat_bits); 28658c2ecf20Sopenharmony_ci return; 28668c2ecf20Sopenharmony_ci } 28678c2ecf20Sopenharmony_ci 28688c2ecf20Sopenharmony_ci __clear_bit_le(nat_index, nm_i->empty_nat_bits); 28698c2ecf20Sopenharmony_ci if (valid == NAT_ENTRY_PER_BLOCK) 28708c2ecf20Sopenharmony_ci __set_bit_le(nat_index, nm_i->full_nat_bits); 28718c2ecf20Sopenharmony_ci else 28728c2ecf20Sopenharmony_ci __clear_bit_le(nat_index, nm_i->full_nat_bits); 28738c2ecf20Sopenharmony_ci} 28748c2ecf20Sopenharmony_ci 28758c2ecf20Sopenharmony_cistatic int __flush_nat_entry_set(struct f2fs_sb_info *sbi, 28768c2ecf20Sopenharmony_ci struct nat_entry_set *set, struct cp_control *cpc) 28778c2ecf20Sopenharmony_ci{ 28788c2ecf20Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 28798c2ecf20Sopenharmony_ci struct f2fs_journal *journal = curseg->journal; 28808c2ecf20Sopenharmony_ci nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK; 28818c2ecf20Sopenharmony_ci bool to_journal = true; 28828c2ecf20Sopenharmony_ci struct f2fs_nat_block *nat_blk; 28838c2ecf20Sopenharmony_ci struct nat_entry *ne, *cur; 28848c2ecf20Sopenharmony_ci struct page *page = NULL; 28858c2ecf20Sopenharmony_ci 28868c2ecf20Sopenharmony_ci /* 28878c2ecf20Sopenharmony_ci * there are two steps to flush nat entries: 28888c2ecf20Sopenharmony_ci * #1, flush nat entries to journal in current hot data summary block. 28898c2ecf20Sopenharmony_ci * #2, flush nat entries to nat page. 28908c2ecf20Sopenharmony_ci */ 28918c2ecf20Sopenharmony_ci if (enabled_nat_bits(sbi, cpc) || 28928c2ecf20Sopenharmony_ci !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL)) 28938c2ecf20Sopenharmony_ci to_journal = false; 28948c2ecf20Sopenharmony_ci 28958c2ecf20Sopenharmony_ci if (to_journal) { 28968c2ecf20Sopenharmony_ci down_write(&curseg->journal_rwsem); 28978c2ecf20Sopenharmony_ci } else { 28988c2ecf20Sopenharmony_ci page = get_next_nat_page(sbi, start_nid); 28998c2ecf20Sopenharmony_ci if (IS_ERR(page)) 29008c2ecf20Sopenharmony_ci return PTR_ERR(page); 29018c2ecf20Sopenharmony_ci 29028c2ecf20Sopenharmony_ci nat_blk = page_address(page); 29038c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, !nat_blk); 29048c2ecf20Sopenharmony_ci } 29058c2ecf20Sopenharmony_ci 29068c2ecf20Sopenharmony_ci /* flush dirty nats in nat entry set */ 29078c2ecf20Sopenharmony_ci list_for_each_entry_safe(ne, cur, &set->entry_list, list) { 29088c2ecf20Sopenharmony_ci struct f2fs_nat_entry *raw_ne; 29098c2ecf20Sopenharmony_ci nid_t nid = nat_get_nid(ne); 29108c2ecf20Sopenharmony_ci int offset; 29118c2ecf20Sopenharmony_ci 29128c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, nat_get_blkaddr(ne) == NEW_ADDR); 29138c2ecf20Sopenharmony_ci 29148c2ecf20Sopenharmony_ci if (to_journal) { 29158c2ecf20Sopenharmony_ci offset = f2fs_lookup_journal_in_cursum(journal, 29168c2ecf20Sopenharmony_ci NAT_JOURNAL, nid, 1); 29178c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, offset < 0); 29188c2ecf20Sopenharmony_ci raw_ne = &nat_in_journal(journal, offset); 29198c2ecf20Sopenharmony_ci nid_in_journal(journal, offset) = cpu_to_le32(nid); 29208c2ecf20Sopenharmony_ci } else { 29218c2ecf20Sopenharmony_ci raw_ne = &nat_blk->entries[nid - start_nid]; 29228c2ecf20Sopenharmony_ci } 29238c2ecf20Sopenharmony_ci raw_nat_from_node_info(raw_ne, &ne->ni); 29248c2ecf20Sopenharmony_ci nat_reset_flag(ne); 29258c2ecf20Sopenharmony_ci __clear_nat_cache_dirty(NM_I(sbi), set, ne); 29268c2ecf20Sopenharmony_ci if (nat_get_blkaddr(ne) == NULL_ADDR) { 29278c2ecf20Sopenharmony_ci add_free_nid(sbi, nid, false, true); 29288c2ecf20Sopenharmony_ci } else { 29298c2ecf20Sopenharmony_ci spin_lock(&NM_I(sbi)->nid_list_lock); 29308c2ecf20Sopenharmony_ci update_free_nid_bitmap(sbi, nid, false, false); 29318c2ecf20Sopenharmony_ci spin_unlock(&NM_I(sbi)->nid_list_lock); 29328c2ecf20Sopenharmony_ci } 29338c2ecf20Sopenharmony_ci } 29348c2ecf20Sopenharmony_ci 29358c2ecf20Sopenharmony_ci if (to_journal) { 29368c2ecf20Sopenharmony_ci up_write(&curseg->journal_rwsem); 29378c2ecf20Sopenharmony_ci } else { 29388c2ecf20Sopenharmony_ci __update_nat_bits(sbi, start_nid, page); 29398c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 29408c2ecf20Sopenharmony_ci } 29418c2ecf20Sopenharmony_ci 29428c2ecf20Sopenharmony_ci /* Allow dirty nats by node block allocation in write_begin */ 29438c2ecf20Sopenharmony_ci if (!set->entry_cnt) { 29448c2ecf20Sopenharmony_ci radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set); 29458c2ecf20Sopenharmony_ci kmem_cache_free(nat_entry_set_slab, set); 29468c2ecf20Sopenharmony_ci } 29478c2ecf20Sopenharmony_ci return 0; 29488c2ecf20Sopenharmony_ci} 29498c2ecf20Sopenharmony_ci 29508c2ecf20Sopenharmony_ci/* 29518c2ecf20Sopenharmony_ci * This function is called during the checkpointing process. 29528c2ecf20Sopenharmony_ci */ 29538c2ecf20Sopenharmony_ciint f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) 29548c2ecf20Sopenharmony_ci{ 29558c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 29568c2ecf20Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 29578c2ecf20Sopenharmony_ci struct f2fs_journal *journal = curseg->journal; 29588c2ecf20Sopenharmony_ci struct nat_entry_set *setvec[SETVEC_SIZE]; 29598c2ecf20Sopenharmony_ci struct nat_entry_set *set, *tmp; 29608c2ecf20Sopenharmony_ci unsigned int found; 29618c2ecf20Sopenharmony_ci nid_t set_idx = 0; 29628c2ecf20Sopenharmony_ci LIST_HEAD(sets); 29638c2ecf20Sopenharmony_ci int err = 0; 29648c2ecf20Sopenharmony_ci 29658c2ecf20Sopenharmony_ci /* 29668c2ecf20Sopenharmony_ci * during unmount, let's flush nat_bits before checking 29678c2ecf20Sopenharmony_ci * nat_cnt[DIRTY_NAT]. 29688c2ecf20Sopenharmony_ci */ 29698c2ecf20Sopenharmony_ci if (enabled_nat_bits(sbi, cpc)) { 29708c2ecf20Sopenharmony_ci down_write(&nm_i->nat_tree_lock); 29718c2ecf20Sopenharmony_ci remove_nats_in_journal(sbi); 29728c2ecf20Sopenharmony_ci up_write(&nm_i->nat_tree_lock); 29738c2ecf20Sopenharmony_ci } 29748c2ecf20Sopenharmony_ci 29758c2ecf20Sopenharmony_ci if (!nm_i->nat_cnt[DIRTY_NAT]) 29768c2ecf20Sopenharmony_ci return 0; 29778c2ecf20Sopenharmony_ci 29788c2ecf20Sopenharmony_ci down_write(&nm_i->nat_tree_lock); 29798c2ecf20Sopenharmony_ci 29808c2ecf20Sopenharmony_ci /* 29818c2ecf20Sopenharmony_ci * if there are no enough space in journal to store dirty nat 29828c2ecf20Sopenharmony_ci * entries, remove all entries from journal and merge them 29838c2ecf20Sopenharmony_ci * into nat entry set. 29848c2ecf20Sopenharmony_ci */ 29858c2ecf20Sopenharmony_ci if (enabled_nat_bits(sbi, cpc) || 29868c2ecf20Sopenharmony_ci !__has_cursum_space(journal, 29878c2ecf20Sopenharmony_ci nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL)) 29888c2ecf20Sopenharmony_ci remove_nats_in_journal(sbi); 29898c2ecf20Sopenharmony_ci 29908c2ecf20Sopenharmony_ci while ((found = __gang_lookup_nat_set(nm_i, 29918c2ecf20Sopenharmony_ci set_idx, SETVEC_SIZE, setvec))) { 29928c2ecf20Sopenharmony_ci unsigned idx; 29938c2ecf20Sopenharmony_ci set_idx = setvec[found - 1]->set + 1; 29948c2ecf20Sopenharmony_ci for (idx = 0; idx < found; idx++) 29958c2ecf20Sopenharmony_ci __adjust_nat_entry_set(setvec[idx], &sets, 29968c2ecf20Sopenharmony_ci MAX_NAT_JENTRIES(journal)); 29978c2ecf20Sopenharmony_ci } 29988c2ecf20Sopenharmony_ci 29998c2ecf20Sopenharmony_ci /* flush dirty nats in nat entry set */ 30008c2ecf20Sopenharmony_ci list_for_each_entry_safe(set, tmp, &sets, set_list) { 30018c2ecf20Sopenharmony_ci err = __flush_nat_entry_set(sbi, set, cpc); 30028c2ecf20Sopenharmony_ci if (err) 30038c2ecf20Sopenharmony_ci break; 30048c2ecf20Sopenharmony_ci } 30058c2ecf20Sopenharmony_ci 30068c2ecf20Sopenharmony_ci up_write(&nm_i->nat_tree_lock); 30078c2ecf20Sopenharmony_ci /* Allow dirty nats by node block allocation in write_begin */ 30088c2ecf20Sopenharmony_ci 30098c2ecf20Sopenharmony_ci return err; 30108c2ecf20Sopenharmony_ci} 30118c2ecf20Sopenharmony_ci 30128c2ecf20Sopenharmony_cistatic int __get_nat_bitmaps(struct f2fs_sb_info *sbi) 30138c2ecf20Sopenharmony_ci{ 30148c2ecf20Sopenharmony_ci struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); 30158c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 30168c2ecf20Sopenharmony_ci unsigned int nat_bits_bytes = nm_i->nat_blocks / BITS_PER_BYTE; 30178c2ecf20Sopenharmony_ci unsigned int i; 30188c2ecf20Sopenharmony_ci __u64 cp_ver = cur_cp_version(ckpt); 30198c2ecf20Sopenharmony_ci block_t nat_bits_addr; 30208c2ecf20Sopenharmony_ci 30218c2ecf20Sopenharmony_ci if (!enabled_nat_bits(sbi, NULL)) 30228c2ecf20Sopenharmony_ci return 0; 30238c2ecf20Sopenharmony_ci 30248c2ecf20Sopenharmony_ci nm_i->nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8); 30258c2ecf20Sopenharmony_ci nm_i->nat_bits = f2fs_kvzalloc(sbi, 30268c2ecf20Sopenharmony_ci nm_i->nat_bits_blocks << F2FS_BLKSIZE_BITS, GFP_KERNEL); 30278c2ecf20Sopenharmony_ci if (!nm_i->nat_bits) 30288c2ecf20Sopenharmony_ci return -ENOMEM; 30298c2ecf20Sopenharmony_ci 30308c2ecf20Sopenharmony_ci nat_bits_addr = __start_cp_addr(sbi) + sbi->blocks_per_seg - 30318c2ecf20Sopenharmony_ci nm_i->nat_bits_blocks; 30328c2ecf20Sopenharmony_ci for (i = 0; i < nm_i->nat_bits_blocks; i++) { 30338c2ecf20Sopenharmony_ci struct page *page; 30348c2ecf20Sopenharmony_ci 30358c2ecf20Sopenharmony_ci page = f2fs_get_meta_page(sbi, nat_bits_addr++); 30368c2ecf20Sopenharmony_ci if (IS_ERR(page)) 30378c2ecf20Sopenharmony_ci return PTR_ERR(page); 30388c2ecf20Sopenharmony_ci 30398c2ecf20Sopenharmony_ci memcpy(nm_i->nat_bits + (i << F2FS_BLKSIZE_BITS), 30408c2ecf20Sopenharmony_ci page_address(page), F2FS_BLKSIZE); 30418c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 30428c2ecf20Sopenharmony_ci } 30438c2ecf20Sopenharmony_ci 30448c2ecf20Sopenharmony_ci cp_ver |= (cur_cp_crc(ckpt) << 32); 30458c2ecf20Sopenharmony_ci if (cpu_to_le64(cp_ver) != *(__le64 *)nm_i->nat_bits) { 30468c2ecf20Sopenharmony_ci disable_nat_bits(sbi, true); 30478c2ecf20Sopenharmony_ci return 0; 30488c2ecf20Sopenharmony_ci } 30498c2ecf20Sopenharmony_ci 30508c2ecf20Sopenharmony_ci nm_i->full_nat_bits = nm_i->nat_bits + 8; 30518c2ecf20Sopenharmony_ci nm_i->empty_nat_bits = nm_i->full_nat_bits + nat_bits_bytes; 30528c2ecf20Sopenharmony_ci 30538c2ecf20Sopenharmony_ci f2fs_notice(sbi, "Found nat_bits in checkpoint"); 30548c2ecf20Sopenharmony_ci return 0; 30558c2ecf20Sopenharmony_ci} 30568c2ecf20Sopenharmony_ci 30578c2ecf20Sopenharmony_cistatic inline void load_free_nid_bitmap(struct f2fs_sb_info *sbi) 30588c2ecf20Sopenharmony_ci{ 30598c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 30608c2ecf20Sopenharmony_ci unsigned int i = 0; 30618c2ecf20Sopenharmony_ci nid_t nid, last_nid; 30628c2ecf20Sopenharmony_ci 30638c2ecf20Sopenharmony_ci if (!enabled_nat_bits(sbi, NULL)) 30648c2ecf20Sopenharmony_ci return; 30658c2ecf20Sopenharmony_ci 30668c2ecf20Sopenharmony_ci for (i = 0; i < nm_i->nat_blocks; i++) { 30678c2ecf20Sopenharmony_ci i = find_next_bit_le(nm_i->empty_nat_bits, nm_i->nat_blocks, i); 30688c2ecf20Sopenharmony_ci if (i >= nm_i->nat_blocks) 30698c2ecf20Sopenharmony_ci break; 30708c2ecf20Sopenharmony_ci 30718c2ecf20Sopenharmony_ci __set_bit_le(i, nm_i->nat_block_bitmap); 30728c2ecf20Sopenharmony_ci 30738c2ecf20Sopenharmony_ci nid = i * NAT_ENTRY_PER_BLOCK; 30748c2ecf20Sopenharmony_ci last_nid = nid + NAT_ENTRY_PER_BLOCK; 30758c2ecf20Sopenharmony_ci 30768c2ecf20Sopenharmony_ci spin_lock(&NM_I(sbi)->nid_list_lock); 30778c2ecf20Sopenharmony_ci for (; nid < last_nid; nid++) 30788c2ecf20Sopenharmony_ci update_free_nid_bitmap(sbi, nid, true, true); 30798c2ecf20Sopenharmony_ci spin_unlock(&NM_I(sbi)->nid_list_lock); 30808c2ecf20Sopenharmony_ci } 30818c2ecf20Sopenharmony_ci 30828c2ecf20Sopenharmony_ci for (i = 0; i < nm_i->nat_blocks; i++) { 30838c2ecf20Sopenharmony_ci i = find_next_bit_le(nm_i->full_nat_bits, nm_i->nat_blocks, i); 30848c2ecf20Sopenharmony_ci if (i >= nm_i->nat_blocks) 30858c2ecf20Sopenharmony_ci break; 30868c2ecf20Sopenharmony_ci 30878c2ecf20Sopenharmony_ci __set_bit_le(i, nm_i->nat_block_bitmap); 30888c2ecf20Sopenharmony_ci } 30898c2ecf20Sopenharmony_ci} 30908c2ecf20Sopenharmony_ci 30918c2ecf20Sopenharmony_cistatic int init_node_manager(struct f2fs_sb_info *sbi) 30928c2ecf20Sopenharmony_ci{ 30938c2ecf20Sopenharmony_ci struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi); 30948c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 30958c2ecf20Sopenharmony_ci unsigned char *version_bitmap; 30968c2ecf20Sopenharmony_ci unsigned int nat_segs; 30978c2ecf20Sopenharmony_ci int err; 30988c2ecf20Sopenharmony_ci 30998c2ecf20Sopenharmony_ci nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr); 31008c2ecf20Sopenharmony_ci 31018c2ecf20Sopenharmony_ci /* segment_count_nat includes pair segment so divide to 2. */ 31028c2ecf20Sopenharmony_ci nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1; 31038c2ecf20Sopenharmony_ci nm_i->nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg); 31048c2ecf20Sopenharmony_ci nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nm_i->nat_blocks; 31058c2ecf20Sopenharmony_ci 31068c2ecf20Sopenharmony_ci /* not used nids: 0, node, meta, (and root counted as valid node) */ 31078c2ecf20Sopenharmony_ci nm_i->available_nids = nm_i->max_nid - sbi->total_valid_node_count - 31088c2ecf20Sopenharmony_ci F2FS_RESERVED_NODE_NUM; 31098c2ecf20Sopenharmony_ci nm_i->nid_cnt[FREE_NID] = 0; 31108c2ecf20Sopenharmony_ci nm_i->nid_cnt[PREALLOC_NID] = 0; 31118c2ecf20Sopenharmony_ci nm_i->ram_thresh = DEF_RAM_THRESHOLD; 31128c2ecf20Sopenharmony_ci nm_i->ra_nid_pages = DEF_RA_NID_PAGES; 31138c2ecf20Sopenharmony_ci nm_i->dirty_nats_ratio = DEF_DIRTY_NAT_RATIO_THRESHOLD; 31148c2ecf20Sopenharmony_ci 31158c2ecf20Sopenharmony_ci INIT_RADIX_TREE(&nm_i->free_nid_root, GFP_ATOMIC); 31168c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&nm_i->free_nid_list); 31178c2ecf20Sopenharmony_ci INIT_RADIX_TREE(&nm_i->nat_root, GFP_NOIO); 31188c2ecf20Sopenharmony_ci INIT_RADIX_TREE(&nm_i->nat_set_root, GFP_NOIO); 31198c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&nm_i->nat_entries); 31208c2ecf20Sopenharmony_ci spin_lock_init(&nm_i->nat_list_lock); 31218c2ecf20Sopenharmony_ci 31228c2ecf20Sopenharmony_ci mutex_init(&nm_i->build_lock); 31238c2ecf20Sopenharmony_ci spin_lock_init(&nm_i->nid_list_lock); 31248c2ecf20Sopenharmony_ci init_rwsem(&nm_i->nat_tree_lock); 31258c2ecf20Sopenharmony_ci 31268c2ecf20Sopenharmony_ci nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid); 31278c2ecf20Sopenharmony_ci nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP); 31288c2ecf20Sopenharmony_ci version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP); 31298c2ecf20Sopenharmony_ci nm_i->nat_bitmap = kmemdup(version_bitmap, nm_i->bitmap_size, 31308c2ecf20Sopenharmony_ci GFP_KERNEL); 31318c2ecf20Sopenharmony_ci if (!nm_i->nat_bitmap) 31328c2ecf20Sopenharmony_ci return -ENOMEM; 31338c2ecf20Sopenharmony_ci 31348c2ecf20Sopenharmony_ci err = __get_nat_bitmaps(sbi); 31358c2ecf20Sopenharmony_ci if (err) 31368c2ecf20Sopenharmony_ci return err; 31378c2ecf20Sopenharmony_ci 31388c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS 31398c2ecf20Sopenharmony_ci nm_i->nat_bitmap_mir = kmemdup(version_bitmap, nm_i->bitmap_size, 31408c2ecf20Sopenharmony_ci GFP_KERNEL); 31418c2ecf20Sopenharmony_ci if (!nm_i->nat_bitmap_mir) 31428c2ecf20Sopenharmony_ci return -ENOMEM; 31438c2ecf20Sopenharmony_ci#endif 31448c2ecf20Sopenharmony_ci 31458c2ecf20Sopenharmony_ci return 0; 31468c2ecf20Sopenharmony_ci} 31478c2ecf20Sopenharmony_ci 31488c2ecf20Sopenharmony_cistatic int init_free_nid_cache(struct f2fs_sb_info *sbi) 31498c2ecf20Sopenharmony_ci{ 31508c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 31518c2ecf20Sopenharmony_ci int i; 31528c2ecf20Sopenharmony_ci 31538c2ecf20Sopenharmony_ci nm_i->free_nid_bitmap = 31548c2ecf20Sopenharmony_ci f2fs_kvzalloc(sbi, array_size(sizeof(unsigned char *), 31558c2ecf20Sopenharmony_ci nm_i->nat_blocks), 31568c2ecf20Sopenharmony_ci GFP_KERNEL); 31578c2ecf20Sopenharmony_ci if (!nm_i->free_nid_bitmap) 31588c2ecf20Sopenharmony_ci return -ENOMEM; 31598c2ecf20Sopenharmony_ci 31608c2ecf20Sopenharmony_ci for (i = 0; i < nm_i->nat_blocks; i++) { 31618c2ecf20Sopenharmony_ci nm_i->free_nid_bitmap[i] = f2fs_kvzalloc(sbi, 31628c2ecf20Sopenharmony_ci f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK), GFP_KERNEL); 31638c2ecf20Sopenharmony_ci if (!nm_i->free_nid_bitmap[i]) 31648c2ecf20Sopenharmony_ci return -ENOMEM; 31658c2ecf20Sopenharmony_ci } 31668c2ecf20Sopenharmony_ci 31678c2ecf20Sopenharmony_ci nm_i->nat_block_bitmap = f2fs_kvzalloc(sbi, nm_i->nat_blocks / 8, 31688c2ecf20Sopenharmony_ci GFP_KERNEL); 31698c2ecf20Sopenharmony_ci if (!nm_i->nat_block_bitmap) 31708c2ecf20Sopenharmony_ci return -ENOMEM; 31718c2ecf20Sopenharmony_ci 31728c2ecf20Sopenharmony_ci nm_i->free_nid_count = 31738c2ecf20Sopenharmony_ci f2fs_kvzalloc(sbi, array_size(sizeof(unsigned short), 31748c2ecf20Sopenharmony_ci nm_i->nat_blocks), 31758c2ecf20Sopenharmony_ci GFP_KERNEL); 31768c2ecf20Sopenharmony_ci if (!nm_i->free_nid_count) 31778c2ecf20Sopenharmony_ci return -ENOMEM; 31788c2ecf20Sopenharmony_ci return 0; 31798c2ecf20Sopenharmony_ci} 31808c2ecf20Sopenharmony_ci 31818c2ecf20Sopenharmony_ciint f2fs_build_node_manager(struct f2fs_sb_info *sbi) 31828c2ecf20Sopenharmony_ci{ 31838c2ecf20Sopenharmony_ci int err; 31848c2ecf20Sopenharmony_ci 31858c2ecf20Sopenharmony_ci sbi->nm_info = f2fs_kzalloc(sbi, sizeof(struct f2fs_nm_info), 31868c2ecf20Sopenharmony_ci GFP_KERNEL); 31878c2ecf20Sopenharmony_ci if (!sbi->nm_info) 31888c2ecf20Sopenharmony_ci return -ENOMEM; 31898c2ecf20Sopenharmony_ci 31908c2ecf20Sopenharmony_ci err = init_node_manager(sbi); 31918c2ecf20Sopenharmony_ci if (err) 31928c2ecf20Sopenharmony_ci return err; 31938c2ecf20Sopenharmony_ci 31948c2ecf20Sopenharmony_ci err = init_free_nid_cache(sbi); 31958c2ecf20Sopenharmony_ci if (err) 31968c2ecf20Sopenharmony_ci return err; 31978c2ecf20Sopenharmony_ci 31988c2ecf20Sopenharmony_ci /* load free nid status from nat_bits table */ 31998c2ecf20Sopenharmony_ci load_free_nid_bitmap(sbi); 32008c2ecf20Sopenharmony_ci 32018c2ecf20Sopenharmony_ci return f2fs_build_free_nids(sbi, true, true); 32028c2ecf20Sopenharmony_ci} 32038c2ecf20Sopenharmony_ci 32048c2ecf20Sopenharmony_civoid f2fs_destroy_node_manager(struct f2fs_sb_info *sbi) 32058c2ecf20Sopenharmony_ci{ 32068c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 32078c2ecf20Sopenharmony_ci struct free_nid *i, *next_i; 32088c2ecf20Sopenharmony_ci struct nat_entry *natvec[NATVEC_SIZE]; 32098c2ecf20Sopenharmony_ci struct nat_entry_set *setvec[SETVEC_SIZE]; 32108c2ecf20Sopenharmony_ci nid_t nid = 0; 32118c2ecf20Sopenharmony_ci unsigned int found; 32128c2ecf20Sopenharmony_ci 32138c2ecf20Sopenharmony_ci if (!nm_i) 32148c2ecf20Sopenharmony_ci return; 32158c2ecf20Sopenharmony_ci 32168c2ecf20Sopenharmony_ci /* destroy free nid list */ 32178c2ecf20Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 32188c2ecf20Sopenharmony_ci list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) { 32198c2ecf20Sopenharmony_ci __remove_free_nid(sbi, i, FREE_NID); 32208c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 32218c2ecf20Sopenharmony_ci kmem_cache_free(free_nid_slab, i); 32228c2ecf20Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 32238c2ecf20Sopenharmony_ci } 32248c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, nm_i->nid_cnt[FREE_NID]); 32258c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, nm_i->nid_cnt[PREALLOC_NID]); 32268c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, !list_empty(&nm_i->free_nid_list)); 32278c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 32288c2ecf20Sopenharmony_ci 32298c2ecf20Sopenharmony_ci /* destroy nat cache */ 32308c2ecf20Sopenharmony_ci down_write(&nm_i->nat_tree_lock); 32318c2ecf20Sopenharmony_ci while ((found = __gang_lookup_nat_cache(nm_i, 32328c2ecf20Sopenharmony_ci nid, NATVEC_SIZE, natvec))) { 32338c2ecf20Sopenharmony_ci unsigned idx; 32348c2ecf20Sopenharmony_ci 32358c2ecf20Sopenharmony_ci nid = nat_get_nid(natvec[found - 1]) + 1; 32368c2ecf20Sopenharmony_ci for (idx = 0; idx < found; idx++) { 32378c2ecf20Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 32388c2ecf20Sopenharmony_ci list_del(&natvec[idx]->list); 32398c2ecf20Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 32408c2ecf20Sopenharmony_ci 32418c2ecf20Sopenharmony_ci __del_from_nat_cache(nm_i, natvec[idx]); 32428c2ecf20Sopenharmony_ci } 32438c2ecf20Sopenharmony_ci } 32448c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, nm_i->nat_cnt[TOTAL_NAT]); 32458c2ecf20Sopenharmony_ci 32468c2ecf20Sopenharmony_ci /* destroy nat set cache */ 32478c2ecf20Sopenharmony_ci nid = 0; 32488c2ecf20Sopenharmony_ci while ((found = __gang_lookup_nat_set(nm_i, 32498c2ecf20Sopenharmony_ci nid, SETVEC_SIZE, setvec))) { 32508c2ecf20Sopenharmony_ci unsigned idx; 32518c2ecf20Sopenharmony_ci 32528c2ecf20Sopenharmony_ci nid = setvec[found - 1]->set + 1; 32538c2ecf20Sopenharmony_ci for (idx = 0; idx < found; idx++) { 32548c2ecf20Sopenharmony_ci /* entry_cnt is not zero, when cp_error was occurred */ 32558c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, !list_empty(&setvec[idx]->entry_list)); 32568c2ecf20Sopenharmony_ci radix_tree_delete(&nm_i->nat_set_root, setvec[idx]->set); 32578c2ecf20Sopenharmony_ci kmem_cache_free(nat_entry_set_slab, setvec[idx]); 32588c2ecf20Sopenharmony_ci } 32598c2ecf20Sopenharmony_ci } 32608c2ecf20Sopenharmony_ci up_write(&nm_i->nat_tree_lock); 32618c2ecf20Sopenharmony_ci 32628c2ecf20Sopenharmony_ci kvfree(nm_i->nat_block_bitmap); 32638c2ecf20Sopenharmony_ci if (nm_i->free_nid_bitmap) { 32648c2ecf20Sopenharmony_ci int i; 32658c2ecf20Sopenharmony_ci 32668c2ecf20Sopenharmony_ci for (i = 0; i < nm_i->nat_blocks; i++) 32678c2ecf20Sopenharmony_ci kvfree(nm_i->free_nid_bitmap[i]); 32688c2ecf20Sopenharmony_ci kvfree(nm_i->free_nid_bitmap); 32698c2ecf20Sopenharmony_ci } 32708c2ecf20Sopenharmony_ci kvfree(nm_i->free_nid_count); 32718c2ecf20Sopenharmony_ci 32728c2ecf20Sopenharmony_ci kvfree(nm_i->nat_bitmap); 32738c2ecf20Sopenharmony_ci kvfree(nm_i->nat_bits); 32748c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS 32758c2ecf20Sopenharmony_ci kvfree(nm_i->nat_bitmap_mir); 32768c2ecf20Sopenharmony_ci#endif 32778c2ecf20Sopenharmony_ci sbi->nm_info = NULL; 32788c2ecf20Sopenharmony_ci kfree(nm_i); 32798c2ecf20Sopenharmony_ci} 32808c2ecf20Sopenharmony_ci 32818c2ecf20Sopenharmony_ciint __init f2fs_create_node_manager_caches(void) 32828c2ecf20Sopenharmony_ci{ 32838c2ecf20Sopenharmony_ci nat_entry_slab = f2fs_kmem_cache_create("f2fs_nat_entry", 32848c2ecf20Sopenharmony_ci sizeof(struct nat_entry)); 32858c2ecf20Sopenharmony_ci if (!nat_entry_slab) 32868c2ecf20Sopenharmony_ci goto fail; 32878c2ecf20Sopenharmony_ci 32888c2ecf20Sopenharmony_ci free_nid_slab = f2fs_kmem_cache_create("f2fs_free_nid", 32898c2ecf20Sopenharmony_ci sizeof(struct free_nid)); 32908c2ecf20Sopenharmony_ci if (!free_nid_slab) 32918c2ecf20Sopenharmony_ci goto destroy_nat_entry; 32928c2ecf20Sopenharmony_ci 32938c2ecf20Sopenharmony_ci nat_entry_set_slab = f2fs_kmem_cache_create("f2fs_nat_entry_set", 32948c2ecf20Sopenharmony_ci sizeof(struct nat_entry_set)); 32958c2ecf20Sopenharmony_ci if (!nat_entry_set_slab) 32968c2ecf20Sopenharmony_ci goto destroy_free_nid; 32978c2ecf20Sopenharmony_ci 32988c2ecf20Sopenharmony_ci fsync_node_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_node_entry", 32998c2ecf20Sopenharmony_ci sizeof(struct fsync_node_entry)); 33008c2ecf20Sopenharmony_ci if (!fsync_node_entry_slab) 33018c2ecf20Sopenharmony_ci goto destroy_nat_entry_set; 33028c2ecf20Sopenharmony_ci return 0; 33038c2ecf20Sopenharmony_ci 33048c2ecf20Sopenharmony_cidestroy_nat_entry_set: 33058c2ecf20Sopenharmony_ci kmem_cache_destroy(nat_entry_set_slab); 33068c2ecf20Sopenharmony_cidestroy_free_nid: 33078c2ecf20Sopenharmony_ci kmem_cache_destroy(free_nid_slab); 33088c2ecf20Sopenharmony_cidestroy_nat_entry: 33098c2ecf20Sopenharmony_ci kmem_cache_destroy(nat_entry_slab); 33108c2ecf20Sopenharmony_cifail: 33118c2ecf20Sopenharmony_ci return -ENOMEM; 33128c2ecf20Sopenharmony_ci} 33138c2ecf20Sopenharmony_ci 33148c2ecf20Sopenharmony_civoid f2fs_destroy_node_manager_caches(void) 33158c2ecf20Sopenharmony_ci{ 33168c2ecf20Sopenharmony_ci kmem_cache_destroy(fsync_node_entry_slab); 33178c2ecf20Sopenharmony_ci kmem_cache_destroy(nat_entry_set_slab); 33188c2ecf20Sopenharmony_ci kmem_cache_destroy(free_nid_slab); 33198c2ecf20Sopenharmony_ci kmem_cache_destroy(nat_entry_slab); 33208c2ecf20Sopenharmony_ci} 3321