162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/f2fs/node.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd. 662306a36Sopenharmony_ci * http://www.samsung.com/ 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#include <linux/fs.h> 962306a36Sopenharmony_ci#include <linux/f2fs_fs.h> 1062306a36Sopenharmony_ci#include <linux/mpage.h> 1162306a36Sopenharmony_ci#include <linux/sched/mm.h> 1262306a36Sopenharmony_ci#include <linux/blkdev.h> 1362306a36Sopenharmony_ci#include <linux/pagevec.h> 1462306a36Sopenharmony_ci#include <linux/swap.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "f2fs.h" 1762306a36Sopenharmony_ci#include "node.h" 1862306a36Sopenharmony_ci#include "segment.h" 1962306a36Sopenharmony_ci#include "xattr.h" 2062306a36Sopenharmony_ci#include "iostat.h" 2162306a36Sopenharmony_ci#include <trace/events/f2fs.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define on_f2fs_build_free_nids(nmi) mutex_is_locked(&(nm_i)->build_lock) 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic struct kmem_cache *nat_entry_slab; 2662306a36Sopenharmony_cistatic struct kmem_cache *free_nid_slab; 2762306a36Sopenharmony_cistatic struct kmem_cache *nat_entry_set_slab; 2862306a36Sopenharmony_cistatic struct kmem_cache *fsync_node_entry_slab; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* 3162306a36Sopenharmony_ci * Check whether the given nid is within node id range. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ciint f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci if (unlikely(nid < F2FS_ROOT_INO(sbi) || nid >= NM_I(sbi)->max_nid)) { 3662306a36Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 3762306a36Sopenharmony_ci f2fs_warn(sbi, "%s: out-of-range nid=%x, run fsck to fix.", 3862306a36Sopenharmony_ci __func__, nid); 3962306a36Sopenharmony_ci f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE); 4062306a36Sopenharmony_ci return -EFSCORRUPTED; 4162306a36Sopenharmony_ci } 4262306a36Sopenharmony_ci return 0; 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cibool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 4862306a36Sopenharmony_ci struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; 4962306a36Sopenharmony_ci struct sysinfo val; 5062306a36Sopenharmony_ci unsigned long avail_ram; 5162306a36Sopenharmony_ci unsigned long mem_size = 0; 5262306a36Sopenharmony_ci bool res = false; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci if (!nm_i) 5562306a36Sopenharmony_ci return true; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci si_meminfo(&val); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* only uses low memory */ 6062306a36Sopenharmony_ci avail_ram = val.totalram - val.totalhigh; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci /* 6362306a36Sopenharmony_ci * give 25%, 25%, 50%, 50%, 25%, 25% memory for each components respectively 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci if (type == FREE_NIDS) { 6662306a36Sopenharmony_ci mem_size = (nm_i->nid_cnt[FREE_NID] * 6762306a36Sopenharmony_ci sizeof(struct free_nid)) >> PAGE_SHIFT; 6862306a36Sopenharmony_ci res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2); 6962306a36Sopenharmony_ci } else if (type == NAT_ENTRIES) { 7062306a36Sopenharmony_ci mem_size = (nm_i->nat_cnt[TOTAL_NAT] * 7162306a36Sopenharmony_ci sizeof(struct nat_entry)) >> PAGE_SHIFT; 7262306a36Sopenharmony_ci res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2); 7362306a36Sopenharmony_ci if (excess_cached_nats(sbi)) 7462306a36Sopenharmony_ci res = false; 7562306a36Sopenharmony_ci } else if (type == DIRTY_DENTS) { 7662306a36Sopenharmony_ci if (sbi->sb->s_bdi->wb.dirty_exceeded) 7762306a36Sopenharmony_ci return false; 7862306a36Sopenharmony_ci mem_size = get_pages(sbi, F2FS_DIRTY_DENTS); 7962306a36Sopenharmony_ci res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1); 8062306a36Sopenharmony_ci } else if (type == INO_ENTRIES) { 8162306a36Sopenharmony_ci int i; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci for (i = 0; i < MAX_INO_ENTRY; i++) 8462306a36Sopenharmony_ci mem_size += sbi->im[i].ino_num * 8562306a36Sopenharmony_ci sizeof(struct ino_entry); 8662306a36Sopenharmony_ci mem_size >>= PAGE_SHIFT; 8762306a36Sopenharmony_ci res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1); 8862306a36Sopenharmony_ci } else if (type == READ_EXTENT_CACHE || type == AGE_EXTENT_CACHE) { 8962306a36Sopenharmony_ci enum extent_type etype = type == READ_EXTENT_CACHE ? 9062306a36Sopenharmony_ci EX_READ : EX_BLOCK_AGE; 9162306a36Sopenharmony_ci struct extent_tree_info *eti = &sbi->extent_tree[etype]; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci mem_size = (atomic_read(&eti->total_ext_tree) * 9462306a36Sopenharmony_ci sizeof(struct extent_tree) + 9562306a36Sopenharmony_ci atomic_read(&eti->total_ext_node) * 9662306a36Sopenharmony_ci sizeof(struct extent_node)) >> PAGE_SHIFT; 9762306a36Sopenharmony_ci res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2); 9862306a36Sopenharmony_ci } else if (type == DISCARD_CACHE) { 9962306a36Sopenharmony_ci mem_size = (atomic_read(&dcc->discard_cmd_cnt) * 10062306a36Sopenharmony_ci sizeof(struct discard_cmd)) >> PAGE_SHIFT; 10162306a36Sopenharmony_ci res = mem_size < (avail_ram * nm_i->ram_thresh / 100); 10262306a36Sopenharmony_ci } else if (type == COMPRESS_PAGE) { 10362306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 10462306a36Sopenharmony_ci unsigned long free_ram = val.freeram; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci /* 10762306a36Sopenharmony_ci * free memory is lower than watermark or cached page count 10862306a36Sopenharmony_ci * exceed threshold, deny caching compress page. 10962306a36Sopenharmony_ci */ 11062306a36Sopenharmony_ci res = (free_ram > avail_ram * sbi->compress_watermark / 100) && 11162306a36Sopenharmony_ci (COMPRESS_MAPPING(sbi)->nrpages < 11262306a36Sopenharmony_ci free_ram * sbi->compress_percent / 100); 11362306a36Sopenharmony_ci#else 11462306a36Sopenharmony_ci res = false; 11562306a36Sopenharmony_ci#endif 11662306a36Sopenharmony_ci } else { 11762306a36Sopenharmony_ci if (!sbi->sb->s_bdi->wb.dirty_exceeded) 11862306a36Sopenharmony_ci return true; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci return res; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic void clear_node_page_dirty(struct page *page) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci if (PageDirty(page)) { 12662306a36Sopenharmony_ci f2fs_clear_page_cache_dirty_tag(page); 12762306a36Sopenharmony_ci clear_page_dirty_for_io(page); 12862306a36Sopenharmony_ci dec_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES); 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci ClearPageUptodate(page); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci return f2fs_get_meta_page_retry(sbi, current_nat_addr(sbi, nid)); 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cistatic struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci struct page *src_page; 14162306a36Sopenharmony_ci struct page *dst_page; 14262306a36Sopenharmony_ci pgoff_t dst_off; 14362306a36Sopenharmony_ci void *src_addr; 14462306a36Sopenharmony_ci void *dst_addr; 14562306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci dst_off = next_nat_addr(sbi, current_nat_addr(sbi, nid)); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci /* get current nat block page with lock */ 15062306a36Sopenharmony_ci src_page = get_current_nat_page(sbi, nid); 15162306a36Sopenharmony_ci if (IS_ERR(src_page)) 15262306a36Sopenharmony_ci return src_page; 15362306a36Sopenharmony_ci dst_page = f2fs_grab_meta_page(sbi, dst_off); 15462306a36Sopenharmony_ci f2fs_bug_on(sbi, PageDirty(src_page)); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci src_addr = page_address(src_page); 15762306a36Sopenharmony_ci dst_addr = page_address(dst_page); 15862306a36Sopenharmony_ci memcpy(dst_addr, src_addr, PAGE_SIZE); 15962306a36Sopenharmony_ci set_page_dirty(dst_page); 16062306a36Sopenharmony_ci f2fs_put_page(src_page, 1); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci set_to_next_nat(nm_i, nid); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci return dst_page; 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic struct nat_entry *__alloc_nat_entry(struct f2fs_sb_info *sbi, 16862306a36Sopenharmony_ci nid_t nid, bool no_fail) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci struct nat_entry *new; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci new = f2fs_kmem_cache_alloc(nat_entry_slab, 17362306a36Sopenharmony_ci GFP_F2FS_ZERO, no_fail, sbi); 17462306a36Sopenharmony_ci if (new) { 17562306a36Sopenharmony_ci nat_set_nid(new, nid); 17662306a36Sopenharmony_ci nat_reset_flag(new); 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci return new; 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic void __free_nat_entry(struct nat_entry *e) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci kmem_cache_free(nat_entry_slab, e); 18462306a36Sopenharmony_ci} 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci/* must be locked by nat_tree_lock */ 18762306a36Sopenharmony_cistatic struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i, 18862306a36Sopenharmony_ci struct nat_entry *ne, struct f2fs_nat_entry *raw_ne, bool no_fail) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci if (no_fail) 19162306a36Sopenharmony_ci f2fs_radix_tree_insert(&nm_i->nat_root, nat_get_nid(ne), ne); 19262306a36Sopenharmony_ci else if (radix_tree_insert(&nm_i->nat_root, nat_get_nid(ne), ne)) 19362306a36Sopenharmony_ci return NULL; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if (raw_ne) 19662306a36Sopenharmony_ci node_info_from_raw_nat(&ne->ni, raw_ne); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 19962306a36Sopenharmony_ci list_add_tail(&ne->list, &nm_i->nat_entries); 20062306a36Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci nm_i->nat_cnt[TOTAL_NAT]++; 20362306a36Sopenharmony_ci nm_i->nat_cnt[RECLAIMABLE_NAT]++; 20462306a36Sopenharmony_ci return ne; 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_cistatic struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n) 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci struct nat_entry *ne; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci ne = radix_tree_lookup(&nm_i->nat_root, n); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci /* for recent accessed nat entry, move it to tail of lru list */ 21462306a36Sopenharmony_ci if (ne && !get_nat_flag(ne, IS_DIRTY)) { 21562306a36Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 21662306a36Sopenharmony_ci if (!list_empty(&ne->list)) 21762306a36Sopenharmony_ci list_move_tail(&ne->list, &nm_i->nat_entries); 21862306a36Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci return ne; 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i, 22562306a36Sopenharmony_ci nid_t start, unsigned int nr, struct nat_entry **ep) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci return radix_tree_gang_lookup(&nm_i->nat_root, (void **)ep, start, nr); 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_cistatic void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci radix_tree_delete(&nm_i->nat_root, nat_get_nid(e)); 23362306a36Sopenharmony_ci nm_i->nat_cnt[TOTAL_NAT]--; 23462306a36Sopenharmony_ci nm_i->nat_cnt[RECLAIMABLE_NAT]--; 23562306a36Sopenharmony_ci __free_nat_entry(e); 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i, 23962306a36Sopenharmony_ci struct nat_entry *ne) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid); 24262306a36Sopenharmony_ci struct nat_entry_set *head; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci head = radix_tree_lookup(&nm_i->nat_set_root, set); 24562306a36Sopenharmony_ci if (!head) { 24662306a36Sopenharmony_ci head = f2fs_kmem_cache_alloc(nat_entry_set_slab, 24762306a36Sopenharmony_ci GFP_NOFS, true, NULL); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci INIT_LIST_HEAD(&head->entry_list); 25062306a36Sopenharmony_ci INIT_LIST_HEAD(&head->set_list); 25162306a36Sopenharmony_ci head->set = set; 25262306a36Sopenharmony_ci head->entry_cnt = 0; 25362306a36Sopenharmony_ci f2fs_radix_tree_insert(&nm_i->nat_set_root, set, head); 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci return head; 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, 25962306a36Sopenharmony_ci struct nat_entry *ne) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci struct nat_entry_set *head; 26262306a36Sopenharmony_ci bool new_ne = nat_get_blkaddr(ne) == NEW_ADDR; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci if (!new_ne) 26562306a36Sopenharmony_ci head = __grab_nat_entry_set(nm_i, ne); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci /* 26862306a36Sopenharmony_ci * update entry_cnt in below condition: 26962306a36Sopenharmony_ci * 1. update NEW_ADDR to valid block address; 27062306a36Sopenharmony_ci * 2. update old block address to new one; 27162306a36Sopenharmony_ci */ 27262306a36Sopenharmony_ci if (!new_ne && (get_nat_flag(ne, IS_PREALLOC) || 27362306a36Sopenharmony_ci !get_nat_flag(ne, IS_DIRTY))) 27462306a36Sopenharmony_ci head->entry_cnt++; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci set_nat_flag(ne, IS_PREALLOC, new_ne); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (get_nat_flag(ne, IS_DIRTY)) 27962306a36Sopenharmony_ci goto refresh_list; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci nm_i->nat_cnt[DIRTY_NAT]++; 28262306a36Sopenharmony_ci nm_i->nat_cnt[RECLAIMABLE_NAT]--; 28362306a36Sopenharmony_ci set_nat_flag(ne, IS_DIRTY, true); 28462306a36Sopenharmony_cirefresh_list: 28562306a36Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 28662306a36Sopenharmony_ci if (new_ne) 28762306a36Sopenharmony_ci list_del_init(&ne->list); 28862306a36Sopenharmony_ci else 28962306a36Sopenharmony_ci list_move_tail(&ne->list, &head->entry_list); 29062306a36Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i, 29462306a36Sopenharmony_ci struct nat_entry_set *set, struct nat_entry *ne) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 29762306a36Sopenharmony_ci list_move_tail(&ne->list, &nm_i->nat_entries); 29862306a36Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci set_nat_flag(ne, IS_DIRTY, false); 30162306a36Sopenharmony_ci set->entry_cnt--; 30262306a36Sopenharmony_ci nm_i->nat_cnt[DIRTY_NAT]--; 30362306a36Sopenharmony_ci nm_i->nat_cnt[RECLAIMABLE_NAT]++; 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistatic unsigned int __gang_lookup_nat_set(struct f2fs_nm_info *nm_i, 30762306a36Sopenharmony_ci nid_t start, unsigned int nr, struct nat_entry_set **ep) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci return radix_tree_gang_lookup(&nm_i->nat_set_root, (void **)ep, 31062306a36Sopenharmony_ci start, nr); 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_cibool f2fs_in_warm_node_list(struct f2fs_sb_info *sbi, struct page *page) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci return NODE_MAPPING(sbi) == page->mapping && 31662306a36Sopenharmony_ci IS_DNODE(page) && is_cold_node(page); 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_civoid f2fs_init_fsync_node_info(struct f2fs_sb_info *sbi) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci spin_lock_init(&sbi->fsync_node_lock); 32262306a36Sopenharmony_ci INIT_LIST_HEAD(&sbi->fsync_node_list); 32362306a36Sopenharmony_ci sbi->fsync_seg_id = 0; 32462306a36Sopenharmony_ci sbi->fsync_node_num = 0; 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic unsigned int f2fs_add_fsync_node_entry(struct f2fs_sb_info *sbi, 32862306a36Sopenharmony_ci struct page *page) 32962306a36Sopenharmony_ci{ 33062306a36Sopenharmony_ci struct fsync_node_entry *fn; 33162306a36Sopenharmony_ci unsigned long flags; 33262306a36Sopenharmony_ci unsigned int seq_id; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci fn = f2fs_kmem_cache_alloc(fsync_node_entry_slab, 33562306a36Sopenharmony_ci GFP_NOFS, true, NULL); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci get_page(page); 33862306a36Sopenharmony_ci fn->page = page; 33962306a36Sopenharmony_ci INIT_LIST_HEAD(&fn->list); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci spin_lock_irqsave(&sbi->fsync_node_lock, flags); 34262306a36Sopenharmony_ci list_add_tail(&fn->list, &sbi->fsync_node_list); 34362306a36Sopenharmony_ci fn->seq_id = sbi->fsync_seg_id++; 34462306a36Sopenharmony_ci seq_id = fn->seq_id; 34562306a36Sopenharmony_ci sbi->fsync_node_num++; 34662306a36Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci return seq_id; 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_civoid f2fs_del_fsync_node_entry(struct f2fs_sb_info *sbi, struct page *page) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci struct fsync_node_entry *fn; 35462306a36Sopenharmony_ci unsigned long flags; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci spin_lock_irqsave(&sbi->fsync_node_lock, flags); 35762306a36Sopenharmony_ci list_for_each_entry(fn, &sbi->fsync_node_list, list) { 35862306a36Sopenharmony_ci if (fn->page == page) { 35962306a36Sopenharmony_ci list_del(&fn->list); 36062306a36Sopenharmony_ci sbi->fsync_node_num--; 36162306a36Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 36262306a36Sopenharmony_ci kmem_cache_free(fsync_node_entry_slab, fn); 36362306a36Sopenharmony_ci put_page(page); 36462306a36Sopenharmony_ci return; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 36862306a36Sopenharmony_ci f2fs_bug_on(sbi, 1); 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_civoid f2fs_reset_fsync_node_info(struct f2fs_sb_info *sbi) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci unsigned long flags; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci spin_lock_irqsave(&sbi->fsync_node_lock, flags); 37662306a36Sopenharmony_ci sbi->fsync_seg_id = 0; 37762306a36Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 37862306a36Sopenharmony_ci} 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ciint f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid) 38162306a36Sopenharmony_ci{ 38262306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 38362306a36Sopenharmony_ci struct nat_entry *e; 38462306a36Sopenharmony_ci bool need = false; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci f2fs_down_read(&nm_i->nat_tree_lock); 38762306a36Sopenharmony_ci e = __lookup_nat_cache(nm_i, nid); 38862306a36Sopenharmony_ci if (e) { 38962306a36Sopenharmony_ci if (!get_nat_flag(e, IS_CHECKPOINTED) && 39062306a36Sopenharmony_ci !get_nat_flag(e, HAS_FSYNCED_INODE)) 39162306a36Sopenharmony_ci need = true; 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_ci f2fs_up_read(&nm_i->nat_tree_lock); 39462306a36Sopenharmony_ci return need; 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cibool f2fs_is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 40062306a36Sopenharmony_ci struct nat_entry *e; 40162306a36Sopenharmony_ci bool is_cp = true; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci f2fs_down_read(&nm_i->nat_tree_lock); 40462306a36Sopenharmony_ci e = __lookup_nat_cache(nm_i, nid); 40562306a36Sopenharmony_ci if (e && !get_nat_flag(e, IS_CHECKPOINTED)) 40662306a36Sopenharmony_ci is_cp = false; 40762306a36Sopenharmony_ci f2fs_up_read(&nm_i->nat_tree_lock); 40862306a36Sopenharmony_ci return is_cp; 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cibool f2fs_need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 41462306a36Sopenharmony_ci struct nat_entry *e; 41562306a36Sopenharmony_ci bool need_update = true; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci f2fs_down_read(&nm_i->nat_tree_lock); 41862306a36Sopenharmony_ci e = __lookup_nat_cache(nm_i, ino); 41962306a36Sopenharmony_ci if (e && get_nat_flag(e, HAS_LAST_FSYNC) && 42062306a36Sopenharmony_ci (get_nat_flag(e, IS_CHECKPOINTED) || 42162306a36Sopenharmony_ci get_nat_flag(e, HAS_FSYNCED_INODE))) 42262306a36Sopenharmony_ci need_update = false; 42362306a36Sopenharmony_ci f2fs_up_read(&nm_i->nat_tree_lock); 42462306a36Sopenharmony_ci return need_update; 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci/* must be locked by nat_tree_lock */ 42862306a36Sopenharmony_cistatic void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid, 42962306a36Sopenharmony_ci struct f2fs_nat_entry *ne) 43062306a36Sopenharmony_ci{ 43162306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 43262306a36Sopenharmony_ci struct nat_entry *new, *e; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci /* Let's mitigate lock contention of nat_tree_lock during checkpoint */ 43562306a36Sopenharmony_ci if (f2fs_rwsem_is_locked(&sbi->cp_global_sem)) 43662306a36Sopenharmony_ci return; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci new = __alloc_nat_entry(sbi, nid, false); 43962306a36Sopenharmony_ci if (!new) 44062306a36Sopenharmony_ci return; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci f2fs_down_write(&nm_i->nat_tree_lock); 44362306a36Sopenharmony_ci e = __lookup_nat_cache(nm_i, nid); 44462306a36Sopenharmony_ci if (!e) 44562306a36Sopenharmony_ci e = __init_nat_entry(nm_i, new, ne, false); 44662306a36Sopenharmony_ci else 44762306a36Sopenharmony_ci f2fs_bug_on(sbi, nat_get_ino(e) != le32_to_cpu(ne->ino) || 44862306a36Sopenharmony_ci nat_get_blkaddr(e) != 44962306a36Sopenharmony_ci le32_to_cpu(ne->block_addr) || 45062306a36Sopenharmony_ci nat_get_version(e) != ne->version); 45162306a36Sopenharmony_ci f2fs_up_write(&nm_i->nat_tree_lock); 45262306a36Sopenharmony_ci if (e != new) 45362306a36Sopenharmony_ci __free_nat_entry(new); 45462306a36Sopenharmony_ci} 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_cistatic void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni, 45762306a36Sopenharmony_ci block_t new_blkaddr, bool fsync_done) 45862306a36Sopenharmony_ci{ 45962306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 46062306a36Sopenharmony_ci struct nat_entry *e; 46162306a36Sopenharmony_ci struct nat_entry *new = __alloc_nat_entry(sbi, ni->nid, true); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci f2fs_down_write(&nm_i->nat_tree_lock); 46462306a36Sopenharmony_ci e = __lookup_nat_cache(nm_i, ni->nid); 46562306a36Sopenharmony_ci if (!e) { 46662306a36Sopenharmony_ci e = __init_nat_entry(nm_i, new, NULL, true); 46762306a36Sopenharmony_ci copy_node_info(&e->ni, ni); 46862306a36Sopenharmony_ci f2fs_bug_on(sbi, ni->blk_addr == NEW_ADDR); 46962306a36Sopenharmony_ci } else if (new_blkaddr == NEW_ADDR) { 47062306a36Sopenharmony_ci /* 47162306a36Sopenharmony_ci * when nid is reallocated, 47262306a36Sopenharmony_ci * previous nat entry can be remained in nat cache. 47362306a36Sopenharmony_ci * So, reinitialize it with new information. 47462306a36Sopenharmony_ci */ 47562306a36Sopenharmony_ci copy_node_info(&e->ni, ni); 47662306a36Sopenharmony_ci f2fs_bug_on(sbi, ni->blk_addr != NULL_ADDR); 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci /* let's free early to reduce memory consumption */ 47962306a36Sopenharmony_ci if (e != new) 48062306a36Sopenharmony_ci __free_nat_entry(new); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci /* sanity check */ 48362306a36Sopenharmony_ci f2fs_bug_on(sbi, nat_get_blkaddr(e) != ni->blk_addr); 48462306a36Sopenharmony_ci f2fs_bug_on(sbi, nat_get_blkaddr(e) == NULL_ADDR && 48562306a36Sopenharmony_ci new_blkaddr == NULL_ADDR); 48662306a36Sopenharmony_ci f2fs_bug_on(sbi, nat_get_blkaddr(e) == NEW_ADDR && 48762306a36Sopenharmony_ci new_blkaddr == NEW_ADDR); 48862306a36Sopenharmony_ci f2fs_bug_on(sbi, __is_valid_data_blkaddr(nat_get_blkaddr(e)) && 48962306a36Sopenharmony_ci new_blkaddr == NEW_ADDR); 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci /* increment version no as node is removed */ 49262306a36Sopenharmony_ci if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) { 49362306a36Sopenharmony_ci unsigned char version = nat_get_version(e); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci nat_set_version(e, inc_node_version(version)); 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci /* change address */ 49962306a36Sopenharmony_ci nat_set_blkaddr(e, new_blkaddr); 50062306a36Sopenharmony_ci if (!__is_valid_data_blkaddr(new_blkaddr)) 50162306a36Sopenharmony_ci set_nat_flag(e, IS_CHECKPOINTED, false); 50262306a36Sopenharmony_ci __set_nat_cache_dirty(nm_i, e); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci /* update fsync_mark if its inode nat entry is still alive */ 50562306a36Sopenharmony_ci if (ni->nid != ni->ino) 50662306a36Sopenharmony_ci e = __lookup_nat_cache(nm_i, ni->ino); 50762306a36Sopenharmony_ci if (e) { 50862306a36Sopenharmony_ci if (fsync_done && ni->nid == ni->ino) 50962306a36Sopenharmony_ci set_nat_flag(e, HAS_FSYNCED_INODE, true); 51062306a36Sopenharmony_ci set_nat_flag(e, HAS_LAST_FSYNC, fsync_done); 51162306a36Sopenharmony_ci } 51262306a36Sopenharmony_ci f2fs_up_write(&nm_i->nat_tree_lock); 51362306a36Sopenharmony_ci} 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ciint f2fs_try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 51862306a36Sopenharmony_ci int nr = nr_shrink; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci if (!f2fs_down_write_trylock(&nm_i->nat_tree_lock)) 52162306a36Sopenharmony_ci return 0; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 52462306a36Sopenharmony_ci while (nr_shrink) { 52562306a36Sopenharmony_ci struct nat_entry *ne; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci if (list_empty(&nm_i->nat_entries)) 52862306a36Sopenharmony_ci break; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci ne = list_first_entry(&nm_i->nat_entries, 53162306a36Sopenharmony_ci struct nat_entry, list); 53262306a36Sopenharmony_ci list_del(&ne->list); 53362306a36Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci __del_from_nat_cache(nm_i, ne); 53662306a36Sopenharmony_ci nr_shrink--; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci f2fs_up_write(&nm_i->nat_tree_lock); 54362306a36Sopenharmony_ci return nr - nr_shrink; 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ciint f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid, 54762306a36Sopenharmony_ci struct node_info *ni, bool checkpoint_context) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 55062306a36Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 55162306a36Sopenharmony_ci struct f2fs_journal *journal = curseg->journal; 55262306a36Sopenharmony_ci nid_t start_nid = START_NID(nid); 55362306a36Sopenharmony_ci struct f2fs_nat_block *nat_blk; 55462306a36Sopenharmony_ci struct page *page = NULL; 55562306a36Sopenharmony_ci struct f2fs_nat_entry ne; 55662306a36Sopenharmony_ci struct nat_entry *e; 55762306a36Sopenharmony_ci pgoff_t index; 55862306a36Sopenharmony_ci block_t blkaddr; 55962306a36Sopenharmony_ci int i; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci ni->nid = nid; 56262306a36Sopenharmony_ciretry: 56362306a36Sopenharmony_ci /* Check nat cache */ 56462306a36Sopenharmony_ci f2fs_down_read(&nm_i->nat_tree_lock); 56562306a36Sopenharmony_ci e = __lookup_nat_cache(nm_i, nid); 56662306a36Sopenharmony_ci if (e) { 56762306a36Sopenharmony_ci ni->ino = nat_get_ino(e); 56862306a36Sopenharmony_ci ni->blk_addr = nat_get_blkaddr(e); 56962306a36Sopenharmony_ci ni->version = nat_get_version(e); 57062306a36Sopenharmony_ci f2fs_up_read(&nm_i->nat_tree_lock); 57162306a36Sopenharmony_ci return 0; 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci /* 57562306a36Sopenharmony_ci * Check current segment summary by trying to grab journal_rwsem first. 57662306a36Sopenharmony_ci * This sem is on the critical path on the checkpoint requiring the above 57762306a36Sopenharmony_ci * nat_tree_lock. Therefore, we should retry, if we failed to grab here 57862306a36Sopenharmony_ci * while not bothering checkpoint. 57962306a36Sopenharmony_ci */ 58062306a36Sopenharmony_ci if (!f2fs_rwsem_is_locked(&sbi->cp_global_sem) || checkpoint_context) { 58162306a36Sopenharmony_ci down_read(&curseg->journal_rwsem); 58262306a36Sopenharmony_ci } else if (f2fs_rwsem_is_contended(&nm_i->nat_tree_lock) || 58362306a36Sopenharmony_ci !down_read_trylock(&curseg->journal_rwsem)) { 58462306a36Sopenharmony_ci f2fs_up_read(&nm_i->nat_tree_lock); 58562306a36Sopenharmony_ci goto retry; 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci i = f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0); 58962306a36Sopenharmony_ci if (i >= 0) { 59062306a36Sopenharmony_ci ne = nat_in_journal(journal, i); 59162306a36Sopenharmony_ci node_info_from_raw_nat(ni, &ne); 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci up_read(&curseg->journal_rwsem); 59462306a36Sopenharmony_ci if (i >= 0) { 59562306a36Sopenharmony_ci f2fs_up_read(&nm_i->nat_tree_lock); 59662306a36Sopenharmony_ci goto cache; 59762306a36Sopenharmony_ci } 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci /* Fill node_info from nat page */ 60062306a36Sopenharmony_ci index = current_nat_addr(sbi, nid); 60162306a36Sopenharmony_ci f2fs_up_read(&nm_i->nat_tree_lock); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci page = f2fs_get_meta_page(sbi, index); 60462306a36Sopenharmony_ci if (IS_ERR(page)) 60562306a36Sopenharmony_ci return PTR_ERR(page); 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci nat_blk = (struct f2fs_nat_block *)page_address(page); 60862306a36Sopenharmony_ci ne = nat_blk->entries[nid - start_nid]; 60962306a36Sopenharmony_ci node_info_from_raw_nat(ni, &ne); 61062306a36Sopenharmony_ci f2fs_put_page(page, 1); 61162306a36Sopenharmony_cicache: 61262306a36Sopenharmony_ci blkaddr = le32_to_cpu(ne.block_addr); 61362306a36Sopenharmony_ci if (__is_valid_data_blkaddr(blkaddr) && 61462306a36Sopenharmony_ci !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) 61562306a36Sopenharmony_ci return -EFAULT; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci /* cache nat entry */ 61862306a36Sopenharmony_ci cache_nat_entry(sbi, nid, &ne); 61962306a36Sopenharmony_ci return 0; 62062306a36Sopenharmony_ci} 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci/* 62362306a36Sopenharmony_ci * readahead MAX_RA_NODE number of node pages. 62462306a36Sopenharmony_ci */ 62562306a36Sopenharmony_cistatic void f2fs_ra_node_pages(struct page *parent, int start, int n) 62662306a36Sopenharmony_ci{ 62762306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(parent); 62862306a36Sopenharmony_ci struct blk_plug plug; 62962306a36Sopenharmony_ci int i, end; 63062306a36Sopenharmony_ci nid_t nid; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci blk_start_plug(&plug); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci /* Then, try readahead for siblings of the desired node */ 63562306a36Sopenharmony_ci end = start + n; 63662306a36Sopenharmony_ci end = min(end, NIDS_PER_BLOCK); 63762306a36Sopenharmony_ci for (i = start; i < end; i++) { 63862306a36Sopenharmony_ci nid = get_nid(parent, i, false); 63962306a36Sopenharmony_ci f2fs_ra_node_page(sbi, nid); 64062306a36Sopenharmony_ci } 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci blk_finish_plug(&plug); 64362306a36Sopenharmony_ci} 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cipgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs) 64662306a36Sopenharmony_ci{ 64762306a36Sopenharmony_ci const long direct_index = ADDRS_PER_INODE(dn->inode); 64862306a36Sopenharmony_ci const long direct_blks = ADDRS_PER_BLOCK(dn->inode); 64962306a36Sopenharmony_ci const long indirect_blks = ADDRS_PER_BLOCK(dn->inode) * NIDS_PER_BLOCK; 65062306a36Sopenharmony_ci unsigned int skipped_unit = ADDRS_PER_BLOCK(dn->inode); 65162306a36Sopenharmony_ci int cur_level = dn->cur_level; 65262306a36Sopenharmony_ci int max_level = dn->max_level; 65362306a36Sopenharmony_ci pgoff_t base = 0; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci if (!dn->max_level) 65662306a36Sopenharmony_ci return pgofs + 1; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci while (max_level-- > cur_level) 65962306a36Sopenharmony_ci skipped_unit *= NIDS_PER_BLOCK; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci switch (dn->max_level) { 66262306a36Sopenharmony_ci case 3: 66362306a36Sopenharmony_ci base += 2 * indirect_blks; 66462306a36Sopenharmony_ci fallthrough; 66562306a36Sopenharmony_ci case 2: 66662306a36Sopenharmony_ci base += 2 * direct_blks; 66762306a36Sopenharmony_ci fallthrough; 66862306a36Sopenharmony_ci case 1: 66962306a36Sopenharmony_ci base += direct_index; 67062306a36Sopenharmony_ci break; 67162306a36Sopenharmony_ci default: 67262306a36Sopenharmony_ci f2fs_bug_on(F2FS_I_SB(dn->inode), 1); 67362306a36Sopenharmony_ci } 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci return ((pgofs - base) / skipped_unit + 1) * skipped_unit + base; 67662306a36Sopenharmony_ci} 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci/* 67962306a36Sopenharmony_ci * The maximum depth is four. 68062306a36Sopenharmony_ci * Offset[0] will have raw inode offset. 68162306a36Sopenharmony_ci */ 68262306a36Sopenharmony_cistatic int get_node_path(struct inode *inode, long block, 68362306a36Sopenharmony_ci int offset[4], unsigned int noffset[4]) 68462306a36Sopenharmony_ci{ 68562306a36Sopenharmony_ci const long direct_index = ADDRS_PER_INODE(inode); 68662306a36Sopenharmony_ci const long direct_blks = ADDRS_PER_BLOCK(inode); 68762306a36Sopenharmony_ci const long dptrs_per_blk = NIDS_PER_BLOCK; 68862306a36Sopenharmony_ci const long indirect_blks = ADDRS_PER_BLOCK(inode) * NIDS_PER_BLOCK; 68962306a36Sopenharmony_ci const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK; 69062306a36Sopenharmony_ci int n = 0; 69162306a36Sopenharmony_ci int level = 0; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci noffset[0] = 0; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci if (block < direct_index) { 69662306a36Sopenharmony_ci offset[n] = block; 69762306a36Sopenharmony_ci goto got; 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_ci block -= direct_index; 70062306a36Sopenharmony_ci if (block < direct_blks) { 70162306a36Sopenharmony_ci offset[n++] = NODE_DIR1_BLOCK; 70262306a36Sopenharmony_ci noffset[n] = 1; 70362306a36Sopenharmony_ci offset[n] = block; 70462306a36Sopenharmony_ci level = 1; 70562306a36Sopenharmony_ci goto got; 70662306a36Sopenharmony_ci } 70762306a36Sopenharmony_ci block -= direct_blks; 70862306a36Sopenharmony_ci if (block < direct_blks) { 70962306a36Sopenharmony_ci offset[n++] = NODE_DIR2_BLOCK; 71062306a36Sopenharmony_ci noffset[n] = 2; 71162306a36Sopenharmony_ci offset[n] = block; 71262306a36Sopenharmony_ci level = 1; 71362306a36Sopenharmony_ci goto got; 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci block -= direct_blks; 71662306a36Sopenharmony_ci if (block < indirect_blks) { 71762306a36Sopenharmony_ci offset[n++] = NODE_IND1_BLOCK; 71862306a36Sopenharmony_ci noffset[n] = 3; 71962306a36Sopenharmony_ci offset[n++] = block / direct_blks; 72062306a36Sopenharmony_ci noffset[n] = 4 + offset[n - 1]; 72162306a36Sopenharmony_ci offset[n] = block % direct_blks; 72262306a36Sopenharmony_ci level = 2; 72362306a36Sopenharmony_ci goto got; 72462306a36Sopenharmony_ci } 72562306a36Sopenharmony_ci block -= indirect_blks; 72662306a36Sopenharmony_ci if (block < indirect_blks) { 72762306a36Sopenharmony_ci offset[n++] = NODE_IND2_BLOCK; 72862306a36Sopenharmony_ci noffset[n] = 4 + dptrs_per_blk; 72962306a36Sopenharmony_ci offset[n++] = block / direct_blks; 73062306a36Sopenharmony_ci noffset[n] = 5 + dptrs_per_blk + offset[n - 1]; 73162306a36Sopenharmony_ci offset[n] = block % direct_blks; 73262306a36Sopenharmony_ci level = 2; 73362306a36Sopenharmony_ci goto got; 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci block -= indirect_blks; 73662306a36Sopenharmony_ci if (block < dindirect_blks) { 73762306a36Sopenharmony_ci offset[n++] = NODE_DIND_BLOCK; 73862306a36Sopenharmony_ci noffset[n] = 5 + (dptrs_per_blk * 2); 73962306a36Sopenharmony_ci offset[n++] = block / indirect_blks; 74062306a36Sopenharmony_ci noffset[n] = 6 + (dptrs_per_blk * 2) + 74162306a36Sopenharmony_ci offset[n - 1] * (dptrs_per_blk + 1); 74262306a36Sopenharmony_ci offset[n++] = (block / direct_blks) % dptrs_per_blk; 74362306a36Sopenharmony_ci noffset[n] = 7 + (dptrs_per_blk * 2) + 74462306a36Sopenharmony_ci offset[n - 2] * (dptrs_per_blk + 1) + 74562306a36Sopenharmony_ci offset[n - 1]; 74662306a36Sopenharmony_ci offset[n] = block % direct_blks; 74762306a36Sopenharmony_ci level = 3; 74862306a36Sopenharmony_ci goto got; 74962306a36Sopenharmony_ci } else { 75062306a36Sopenharmony_ci return -E2BIG; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_cigot: 75362306a36Sopenharmony_ci return level; 75462306a36Sopenharmony_ci} 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci/* 75762306a36Sopenharmony_ci * Caller should call f2fs_put_dnode(dn). 75862306a36Sopenharmony_ci * Also, it should grab and release a rwsem by calling f2fs_lock_op() and 75962306a36Sopenharmony_ci * f2fs_unlock_op() only if mode is set with ALLOC_NODE. 76062306a36Sopenharmony_ci */ 76162306a36Sopenharmony_ciint f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) 76262306a36Sopenharmony_ci{ 76362306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); 76462306a36Sopenharmony_ci struct page *npage[4]; 76562306a36Sopenharmony_ci struct page *parent = NULL; 76662306a36Sopenharmony_ci int offset[4]; 76762306a36Sopenharmony_ci unsigned int noffset[4]; 76862306a36Sopenharmony_ci nid_t nids[4]; 76962306a36Sopenharmony_ci int level, i = 0; 77062306a36Sopenharmony_ci int err = 0; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci level = get_node_path(dn->inode, index, offset, noffset); 77362306a36Sopenharmony_ci if (level < 0) 77462306a36Sopenharmony_ci return level; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci nids[0] = dn->inode->i_ino; 77762306a36Sopenharmony_ci npage[0] = dn->inode_page; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci if (!npage[0]) { 78062306a36Sopenharmony_ci npage[0] = f2fs_get_node_page(sbi, nids[0]); 78162306a36Sopenharmony_ci if (IS_ERR(npage[0])) 78262306a36Sopenharmony_ci return PTR_ERR(npage[0]); 78362306a36Sopenharmony_ci } 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci /* if inline_data is set, should not report any block indices */ 78662306a36Sopenharmony_ci if (f2fs_has_inline_data(dn->inode) && index) { 78762306a36Sopenharmony_ci err = -ENOENT; 78862306a36Sopenharmony_ci f2fs_put_page(npage[0], 1); 78962306a36Sopenharmony_ci goto release_out; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci parent = npage[0]; 79362306a36Sopenharmony_ci if (level != 0) 79462306a36Sopenharmony_ci nids[1] = get_nid(parent, offset[0], true); 79562306a36Sopenharmony_ci dn->inode_page = npage[0]; 79662306a36Sopenharmony_ci dn->inode_page_locked = true; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci /* get indirect or direct nodes */ 79962306a36Sopenharmony_ci for (i = 1; i <= level; i++) { 80062306a36Sopenharmony_ci bool done = false; 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci if (!nids[i] && mode == ALLOC_NODE) { 80362306a36Sopenharmony_ci /* alloc new node */ 80462306a36Sopenharmony_ci if (!f2fs_alloc_nid(sbi, &(nids[i]))) { 80562306a36Sopenharmony_ci err = -ENOSPC; 80662306a36Sopenharmony_ci goto release_pages; 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci dn->nid = nids[i]; 81062306a36Sopenharmony_ci npage[i] = f2fs_new_node_page(dn, noffset[i]); 81162306a36Sopenharmony_ci if (IS_ERR(npage[i])) { 81262306a36Sopenharmony_ci f2fs_alloc_nid_failed(sbi, nids[i]); 81362306a36Sopenharmony_ci err = PTR_ERR(npage[i]); 81462306a36Sopenharmony_ci goto release_pages; 81562306a36Sopenharmony_ci } 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci set_nid(parent, offset[i - 1], nids[i], i == 1); 81862306a36Sopenharmony_ci f2fs_alloc_nid_done(sbi, nids[i]); 81962306a36Sopenharmony_ci done = true; 82062306a36Sopenharmony_ci } else if (mode == LOOKUP_NODE_RA && i == level && level > 1) { 82162306a36Sopenharmony_ci npage[i] = f2fs_get_node_page_ra(parent, offset[i - 1]); 82262306a36Sopenharmony_ci if (IS_ERR(npage[i])) { 82362306a36Sopenharmony_ci err = PTR_ERR(npage[i]); 82462306a36Sopenharmony_ci goto release_pages; 82562306a36Sopenharmony_ci } 82662306a36Sopenharmony_ci done = true; 82762306a36Sopenharmony_ci } 82862306a36Sopenharmony_ci if (i == 1) { 82962306a36Sopenharmony_ci dn->inode_page_locked = false; 83062306a36Sopenharmony_ci unlock_page(parent); 83162306a36Sopenharmony_ci } else { 83262306a36Sopenharmony_ci f2fs_put_page(parent, 1); 83362306a36Sopenharmony_ci } 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci if (!done) { 83662306a36Sopenharmony_ci npage[i] = f2fs_get_node_page(sbi, nids[i]); 83762306a36Sopenharmony_ci if (IS_ERR(npage[i])) { 83862306a36Sopenharmony_ci err = PTR_ERR(npage[i]); 83962306a36Sopenharmony_ci f2fs_put_page(npage[0], 0); 84062306a36Sopenharmony_ci goto release_out; 84162306a36Sopenharmony_ci } 84262306a36Sopenharmony_ci } 84362306a36Sopenharmony_ci if (i < level) { 84462306a36Sopenharmony_ci parent = npage[i]; 84562306a36Sopenharmony_ci nids[i + 1] = get_nid(parent, offset[i], false); 84662306a36Sopenharmony_ci } 84762306a36Sopenharmony_ci } 84862306a36Sopenharmony_ci dn->nid = nids[level]; 84962306a36Sopenharmony_ci dn->ofs_in_node = offset[level]; 85062306a36Sopenharmony_ci dn->node_page = npage[level]; 85162306a36Sopenharmony_ci dn->data_blkaddr = f2fs_data_blkaddr(dn); 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci if (is_inode_flag_set(dn->inode, FI_COMPRESSED_FILE) && 85462306a36Sopenharmony_ci f2fs_sb_has_readonly(sbi)) { 85562306a36Sopenharmony_ci unsigned int cluster_size = F2FS_I(dn->inode)->i_cluster_size; 85662306a36Sopenharmony_ci unsigned int ofs_in_node = dn->ofs_in_node; 85762306a36Sopenharmony_ci pgoff_t fofs = index; 85862306a36Sopenharmony_ci unsigned int c_len; 85962306a36Sopenharmony_ci block_t blkaddr; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci /* should align fofs and ofs_in_node to cluster_size */ 86262306a36Sopenharmony_ci if (fofs % cluster_size) { 86362306a36Sopenharmony_ci fofs = round_down(fofs, cluster_size); 86462306a36Sopenharmony_ci ofs_in_node = round_down(ofs_in_node, cluster_size); 86562306a36Sopenharmony_ci } 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci c_len = f2fs_cluster_blocks_are_contiguous(dn, ofs_in_node); 86862306a36Sopenharmony_ci if (!c_len) 86962306a36Sopenharmony_ci goto out; 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci blkaddr = data_blkaddr(dn->inode, dn->node_page, ofs_in_node); 87262306a36Sopenharmony_ci if (blkaddr == COMPRESS_ADDR) 87362306a36Sopenharmony_ci blkaddr = data_blkaddr(dn->inode, dn->node_page, 87462306a36Sopenharmony_ci ofs_in_node + 1); 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci f2fs_update_read_extent_tree_range_compressed(dn->inode, 87762306a36Sopenharmony_ci fofs, blkaddr, cluster_size, c_len); 87862306a36Sopenharmony_ci } 87962306a36Sopenharmony_ciout: 88062306a36Sopenharmony_ci return 0; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_cirelease_pages: 88362306a36Sopenharmony_ci f2fs_put_page(parent, 1); 88462306a36Sopenharmony_ci if (i > 1) 88562306a36Sopenharmony_ci f2fs_put_page(npage[0], 0); 88662306a36Sopenharmony_cirelease_out: 88762306a36Sopenharmony_ci dn->inode_page = NULL; 88862306a36Sopenharmony_ci dn->node_page = NULL; 88962306a36Sopenharmony_ci if (err == -ENOENT) { 89062306a36Sopenharmony_ci dn->cur_level = i; 89162306a36Sopenharmony_ci dn->max_level = level; 89262306a36Sopenharmony_ci dn->ofs_in_node = offset[level]; 89362306a36Sopenharmony_ci } 89462306a36Sopenharmony_ci return err; 89562306a36Sopenharmony_ci} 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_cistatic int truncate_node(struct dnode_of_data *dn) 89862306a36Sopenharmony_ci{ 89962306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); 90062306a36Sopenharmony_ci struct node_info ni; 90162306a36Sopenharmony_ci int err; 90262306a36Sopenharmony_ci pgoff_t index; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci err = f2fs_get_node_info(sbi, dn->nid, &ni, false); 90562306a36Sopenharmony_ci if (err) 90662306a36Sopenharmony_ci return err; 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci /* Deallocate node address */ 90962306a36Sopenharmony_ci f2fs_invalidate_blocks(sbi, ni.blk_addr); 91062306a36Sopenharmony_ci dec_valid_node_count(sbi, dn->inode, dn->nid == dn->inode->i_ino); 91162306a36Sopenharmony_ci set_node_addr(sbi, &ni, NULL_ADDR, false); 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci if (dn->nid == dn->inode->i_ino) { 91462306a36Sopenharmony_ci f2fs_remove_orphan_inode(sbi, dn->nid); 91562306a36Sopenharmony_ci dec_valid_inode_count(sbi); 91662306a36Sopenharmony_ci f2fs_inode_synced(dn->inode); 91762306a36Sopenharmony_ci } 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci clear_node_page_dirty(dn->node_page); 92062306a36Sopenharmony_ci set_sbi_flag(sbi, SBI_IS_DIRTY); 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci index = dn->node_page->index; 92362306a36Sopenharmony_ci f2fs_put_page(dn->node_page, 1); 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci invalidate_mapping_pages(NODE_MAPPING(sbi), 92662306a36Sopenharmony_ci index, index); 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci dn->node_page = NULL; 92962306a36Sopenharmony_ci trace_f2fs_truncate_node(dn->inode, dn->nid, ni.blk_addr); 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci return 0; 93262306a36Sopenharmony_ci} 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_cistatic int truncate_dnode(struct dnode_of_data *dn) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); 93762306a36Sopenharmony_ci struct page *page; 93862306a36Sopenharmony_ci int err; 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci if (dn->nid == 0) 94162306a36Sopenharmony_ci return 1; 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci /* get direct node */ 94462306a36Sopenharmony_ci page = f2fs_get_node_page(sbi, dn->nid); 94562306a36Sopenharmony_ci if (PTR_ERR(page) == -ENOENT) 94662306a36Sopenharmony_ci return 1; 94762306a36Sopenharmony_ci else if (IS_ERR(page)) 94862306a36Sopenharmony_ci return PTR_ERR(page); 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci if (IS_INODE(page) || ino_of_node(page) != dn->inode->i_ino) { 95162306a36Sopenharmony_ci f2fs_err(sbi, "incorrect node reference, ino: %lu, nid: %u, ino_of_node: %u", 95262306a36Sopenharmony_ci dn->inode->i_ino, dn->nid, ino_of_node(page)); 95362306a36Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 95462306a36Sopenharmony_ci f2fs_handle_error(sbi, ERROR_INVALID_NODE_REFERENCE); 95562306a36Sopenharmony_ci f2fs_put_page(page, 1); 95662306a36Sopenharmony_ci return -EFSCORRUPTED; 95762306a36Sopenharmony_ci } 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci /* Make dnode_of_data for parameter */ 96062306a36Sopenharmony_ci dn->node_page = page; 96162306a36Sopenharmony_ci dn->ofs_in_node = 0; 96262306a36Sopenharmony_ci f2fs_truncate_data_blocks_range(dn, ADDRS_PER_BLOCK(dn->inode)); 96362306a36Sopenharmony_ci err = truncate_node(dn); 96462306a36Sopenharmony_ci if (err) { 96562306a36Sopenharmony_ci f2fs_put_page(page, 1); 96662306a36Sopenharmony_ci return err; 96762306a36Sopenharmony_ci } 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci return 1; 97062306a36Sopenharmony_ci} 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_cistatic int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, 97362306a36Sopenharmony_ci int ofs, int depth) 97462306a36Sopenharmony_ci{ 97562306a36Sopenharmony_ci struct dnode_of_data rdn = *dn; 97662306a36Sopenharmony_ci struct page *page; 97762306a36Sopenharmony_ci struct f2fs_node *rn; 97862306a36Sopenharmony_ci nid_t child_nid; 97962306a36Sopenharmony_ci unsigned int child_nofs; 98062306a36Sopenharmony_ci int freed = 0; 98162306a36Sopenharmony_ci int i, ret; 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci if (dn->nid == 0) 98462306a36Sopenharmony_ci return NIDS_PER_BLOCK + 1; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr); 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci page = f2fs_get_node_page(F2FS_I_SB(dn->inode), dn->nid); 98962306a36Sopenharmony_ci if (IS_ERR(page)) { 99062306a36Sopenharmony_ci trace_f2fs_truncate_nodes_exit(dn->inode, PTR_ERR(page)); 99162306a36Sopenharmony_ci return PTR_ERR(page); 99262306a36Sopenharmony_ci } 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci f2fs_ra_node_pages(page, ofs, NIDS_PER_BLOCK); 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci rn = F2FS_NODE(page); 99762306a36Sopenharmony_ci if (depth < 3) { 99862306a36Sopenharmony_ci for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) { 99962306a36Sopenharmony_ci child_nid = le32_to_cpu(rn->in.nid[i]); 100062306a36Sopenharmony_ci if (child_nid == 0) 100162306a36Sopenharmony_ci continue; 100262306a36Sopenharmony_ci rdn.nid = child_nid; 100362306a36Sopenharmony_ci ret = truncate_dnode(&rdn); 100462306a36Sopenharmony_ci if (ret < 0) 100562306a36Sopenharmony_ci goto out_err; 100662306a36Sopenharmony_ci if (set_nid(page, i, 0, false)) 100762306a36Sopenharmony_ci dn->node_changed = true; 100862306a36Sopenharmony_ci } 100962306a36Sopenharmony_ci } else { 101062306a36Sopenharmony_ci child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1; 101162306a36Sopenharmony_ci for (i = ofs; i < NIDS_PER_BLOCK; i++) { 101262306a36Sopenharmony_ci child_nid = le32_to_cpu(rn->in.nid[i]); 101362306a36Sopenharmony_ci if (child_nid == 0) { 101462306a36Sopenharmony_ci child_nofs += NIDS_PER_BLOCK + 1; 101562306a36Sopenharmony_ci continue; 101662306a36Sopenharmony_ci } 101762306a36Sopenharmony_ci rdn.nid = child_nid; 101862306a36Sopenharmony_ci ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1); 101962306a36Sopenharmony_ci if (ret == (NIDS_PER_BLOCK + 1)) { 102062306a36Sopenharmony_ci if (set_nid(page, i, 0, false)) 102162306a36Sopenharmony_ci dn->node_changed = true; 102262306a36Sopenharmony_ci child_nofs += ret; 102362306a36Sopenharmony_ci } else if (ret < 0 && ret != -ENOENT) { 102462306a36Sopenharmony_ci goto out_err; 102562306a36Sopenharmony_ci } 102662306a36Sopenharmony_ci } 102762306a36Sopenharmony_ci freed = child_nofs; 102862306a36Sopenharmony_ci } 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci if (!ofs) { 103162306a36Sopenharmony_ci /* remove current indirect node */ 103262306a36Sopenharmony_ci dn->node_page = page; 103362306a36Sopenharmony_ci ret = truncate_node(dn); 103462306a36Sopenharmony_ci if (ret) 103562306a36Sopenharmony_ci goto out_err; 103662306a36Sopenharmony_ci freed++; 103762306a36Sopenharmony_ci } else { 103862306a36Sopenharmony_ci f2fs_put_page(page, 1); 103962306a36Sopenharmony_ci } 104062306a36Sopenharmony_ci trace_f2fs_truncate_nodes_exit(dn->inode, freed); 104162306a36Sopenharmony_ci return freed; 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ciout_err: 104462306a36Sopenharmony_ci f2fs_put_page(page, 1); 104562306a36Sopenharmony_ci trace_f2fs_truncate_nodes_exit(dn->inode, ret); 104662306a36Sopenharmony_ci return ret; 104762306a36Sopenharmony_ci} 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_cistatic int truncate_partial_nodes(struct dnode_of_data *dn, 105062306a36Sopenharmony_ci struct f2fs_inode *ri, int *offset, int depth) 105162306a36Sopenharmony_ci{ 105262306a36Sopenharmony_ci struct page *pages[2]; 105362306a36Sopenharmony_ci nid_t nid[3]; 105462306a36Sopenharmony_ci nid_t child_nid; 105562306a36Sopenharmony_ci int err = 0; 105662306a36Sopenharmony_ci int i; 105762306a36Sopenharmony_ci int idx = depth - 2; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci nid[0] = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]); 106062306a36Sopenharmony_ci if (!nid[0]) 106162306a36Sopenharmony_ci return 0; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci /* get indirect nodes in the path */ 106462306a36Sopenharmony_ci for (i = 0; i < idx + 1; i++) { 106562306a36Sopenharmony_ci /* reference count'll be increased */ 106662306a36Sopenharmony_ci pages[i] = f2fs_get_node_page(F2FS_I_SB(dn->inode), nid[i]); 106762306a36Sopenharmony_ci if (IS_ERR(pages[i])) { 106862306a36Sopenharmony_ci err = PTR_ERR(pages[i]); 106962306a36Sopenharmony_ci idx = i - 1; 107062306a36Sopenharmony_ci goto fail; 107162306a36Sopenharmony_ci } 107262306a36Sopenharmony_ci nid[i + 1] = get_nid(pages[i], offset[i + 1], false); 107362306a36Sopenharmony_ci } 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci f2fs_ra_node_pages(pages[idx], offset[idx + 1], NIDS_PER_BLOCK); 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci /* free direct nodes linked to a partial indirect node */ 107862306a36Sopenharmony_ci for (i = offset[idx + 1]; i < NIDS_PER_BLOCK; i++) { 107962306a36Sopenharmony_ci child_nid = get_nid(pages[idx], i, false); 108062306a36Sopenharmony_ci if (!child_nid) 108162306a36Sopenharmony_ci continue; 108262306a36Sopenharmony_ci dn->nid = child_nid; 108362306a36Sopenharmony_ci err = truncate_dnode(dn); 108462306a36Sopenharmony_ci if (err < 0) 108562306a36Sopenharmony_ci goto fail; 108662306a36Sopenharmony_ci if (set_nid(pages[idx], i, 0, false)) 108762306a36Sopenharmony_ci dn->node_changed = true; 108862306a36Sopenharmony_ci } 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci if (offset[idx + 1] == 0) { 109162306a36Sopenharmony_ci dn->node_page = pages[idx]; 109262306a36Sopenharmony_ci dn->nid = nid[idx]; 109362306a36Sopenharmony_ci err = truncate_node(dn); 109462306a36Sopenharmony_ci if (err) 109562306a36Sopenharmony_ci goto fail; 109662306a36Sopenharmony_ci } else { 109762306a36Sopenharmony_ci f2fs_put_page(pages[idx], 1); 109862306a36Sopenharmony_ci } 109962306a36Sopenharmony_ci offset[idx]++; 110062306a36Sopenharmony_ci offset[idx + 1] = 0; 110162306a36Sopenharmony_ci idx--; 110262306a36Sopenharmony_cifail: 110362306a36Sopenharmony_ci for (i = idx; i >= 0; i--) 110462306a36Sopenharmony_ci f2fs_put_page(pages[i], 1); 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci trace_f2fs_truncate_partial_nodes(dn->inode, nid, depth, err); 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci return err; 110962306a36Sopenharmony_ci} 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci/* 111262306a36Sopenharmony_ci * All the block addresses of data and nodes should be nullified. 111362306a36Sopenharmony_ci */ 111462306a36Sopenharmony_ciint f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from) 111562306a36Sopenharmony_ci{ 111662306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 111762306a36Sopenharmony_ci int err = 0, cont = 1; 111862306a36Sopenharmony_ci int level, offset[4], noffset[4]; 111962306a36Sopenharmony_ci unsigned int nofs = 0; 112062306a36Sopenharmony_ci struct f2fs_inode *ri; 112162306a36Sopenharmony_ci struct dnode_of_data dn; 112262306a36Sopenharmony_ci struct page *page; 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci trace_f2fs_truncate_inode_blocks_enter(inode, from); 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci level = get_node_path(inode, from, offset, noffset); 112762306a36Sopenharmony_ci if (level < 0) { 112862306a36Sopenharmony_ci trace_f2fs_truncate_inode_blocks_exit(inode, level); 112962306a36Sopenharmony_ci return level; 113062306a36Sopenharmony_ci } 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci page = f2fs_get_node_page(sbi, inode->i_ino); 113362306a36Sopenharmony_ci if (IS_ERR(page)) { 113462306a36Sopenharmony_ci trace_f2fs_truncate_inode_blocks_exit(inode, PTR_ERR(page)); 113562306a36Sopenharmony_ci return PTR_ERR(page); 113662306a36Sopenharmony_ci } 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci set_new_dnode(&dn, inode, page, NULL, 0); 113962306a36Sopenharmony_ci unlock_page(page); 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci ri = F2FS_INODE(page); 114262306a36Sopenharmony_ci switch (level) { 114362306a36Sopenharmony_ci case 0: 114462306a36Sopenharmony_ci case 1: 114562306a36Sopenharmony_ci nofs = noffset[1]; 114662306a36Sopenharmony_ci break; 114762306a36Sopenharmony_ci case 2: 114862306a36Sopenharmony_ci nofs = noffset[1]; 114962306a36Sopenharmony_ci if (!offset[level - 1]) 115062306a36Sopenharmony_ci goto skip_partial; 115162306a36Sopenharmony_ci err = truncate_partial_nodes(&dn, ri, offset, level); 115262306a36Sopenharmony_ci if (err < 0 && err != -ENOENT) 115362306a36Sopenharmony_ci goto fail; 115462306a36Sopenharmony_ci nofs += 1 + NIDS_PER_BLOCK; 115562306a36Sopenharmony_ci break; 115662306a36Sopenharmony_ci case 3: 115762306a36Sopenharmony_ci nofs = 5 + 2 * NIDS_PER_BLOCK; 115862306a36Sopenharmony_ci if (!offset[level - 1]) 115962306a36Sopenharmony_ci goto skip_partial; 116062306a36Sopenharmony_ci err = truncate_partial_nodes(&dn, ri, offset, level); 116162306a36Sopenharmony_ci if (err < 0 && err != -ENOENT) 116262306a36Sopenharmony_ci goto fail; 116362306a36Sopenharmony_ci break; 116462306a36Sopenharmony_ci default: 116562306a36Sopenharmony_ci BUG(); 116662306a36Sopenharmony_ci } 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ciskip_partial: 116962306a36Sopenharmony_ci while (cont) { 117062306a36Sopenharmony_ci dn.nid = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]); 117162306a36Sopenharmony_ci switch (offset[0]) { 117262306a36Sopenharmony_ci case NODE_DIR1_BLOCK: 117362306a36Sopenharmony_ci case NODE_DIR2_BLOCK: 117462306a36Sopenharmony_ci err = truncate_dnode(&dn); 117562306a36Sopenharmony_ci break; 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci case NODE_IND1_BLOCK: 117862306a36Sopenharmony_ci case NODE_IND2_BLOCK: 117962306a36Sopenharmony_ci err = truncate_nodes(&dn, nofs, offset[1], 2); 118062306a36Sopenharmony_ci break; 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci case NODE_DIND_BLOCK: 118362306a36Sopenharmony_ci err = truncate_nodes(&dn, nofs, offset[1], 3); 118462306a36Sopenharmony_ci cont = 0; 118562306a36Sopenharmony_ci break; 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci default: 118862306a36Sopenharmony_ci BUG(); 118962306a36Sopenharmony_ci } 119062306a36Sopenharmony_ci if (err < 0 && err != -ENOENT) 119162306a36Sopenharmony_ci goto fail; 119262306a36Sopenharmony_ci if (offset[1] == 0 && 119362306a36Sopenharmony_ci ri->i_nid[offset[0] - NODE_DIR1_BLOCK]) { 119462306a36Sopenharmony_ci lock_page(page); 119562306a36Sopenharmony_ci BUG_ON(page->mapping != NODE_MAPPING(sbi)); 119662306a36Sopenharmony_ci f2fs_wait_on_page_writeback(page, NODE, true, true); 119762306a36Sopenharmony_ci ri->i_nid[offset[0] - NODE_DIR1_BLOCK] = 0; 119862306a36Sopenharmony_ci set_page_dirty(page); 119962306a36Sopenharmony_ci unlock_page(page); 120062306a36Sopenharmony_ci } 120162306a36Sopenharmony_ci offset[1] = 0; 120262306a36Sopenharmony_ci offset[0]++; 120362306a36Sopenharmony_ci nofs += err; 120462306a36Sopenharmony_ci } 120562306a36Sopenharmony_cifail: 120662306a36Sopenharmony_ci f2fs_put_page(page, 0); 120762306a36Sopenharmony_ci trace_f2fs_truncate_inode_blocks_exit(inode, err); 120862306a36Sopenharmony_ci return err > 0 ? 0 : err; 120962306a36Sopenharmony_ci} 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci/* caller must lock inode page */ 121262306a36Sopenharmony_ciint f2fs_truncate_xattr_node(struct inode *inode) 121362306a36Sopenharmony_ci{ 121462306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 121562306a36Sopenharmony_ci nid_t nid = F2FS_I(inode)->i_xattr_nid; 121662306a36Sopenharmony_ci struct dnode_of_data dn; 121762306a36Sopenharmony_ci struct page *npage; 121862306a36Sopenharmony_ci int err; 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci if (!nid) 122162306a36Sopenharmony_ci return 0; 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci npage = f2fs_get_node_page(sbi, nid); 122462306a36Sopenharmony_ci if (IS_ERR(npage)) 122562306a36Sopenharmony_ci return PTR_ERR(npage); 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci set_new_dnode(&dn, inode, NULL, npage, nid); 122862306a36Sopenharmony_ci err = truncate_node(&dn); 122962306a36Sopenharmony_ci if (err) { 123062306a36Sopenharmony_ci f2fs_put_page(npage, 1); 123162306a36Sopenharmony_ci return err; 123262306a36Sopenharmony_ci } 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci f2fs_i_xnid_write(inode, 0); 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci return 0; 123762306a36Sopenharmony_ci} 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci/* 124062306a36Sopenharmony_ci * Caller should grab and release a rwsem by calling f2fs_lock_op() and 124162306a36Sopenharmony_ci * f2fs_unlock_op(). 124262306a36Sopenharmony_ci */ 124362306a36Sopenharmony_ciint f2fs_remove_inode_page(struct inode *inode) 124462306a36Sopenharmony_ci{ 124562306a36Sopenharmony_ci struct dnode_of_data dn; 124662306a36Sopenharmony_ci int err; 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); 124962306a36Sopenharmony_ci err = f2fs_get_dnode_of_data(&dn, 0, LOOKUP_NODE); 125062306a36Sopenharmony_ci if (err) 125162306a36Sopenharmony_ci return err; 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci err = f2fs_truncate_xattr_node(inode); 125462306a36Sopenharmony_ci if (err) { 125562306a36Sopenharmony_ci f2fs_put_dnode(&dn); 125662306a36Sopenharmony_ci return err; 125762306a36Sopenharmony_ci } 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci /* remove potential inline_data blocks */ 126062306a36Sopenharmony_ci if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || 126162306a36Sopenharmony_ci S_ISLNK(inode->i_mode)) 126262306a36Sopenharmony_ci f2fs_truncate_data_blocks_range(&dn, 1); 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci /* 0 is possible, after f2fs_new_inode() has failed */ 126562306a36Sopenharmony_ci if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) { 126662306a36Sopenharmony_ci f2fs_put_dnode(&dn); 126762306a36Sopenharmony_ci return -EIO; 126862306a36Sopenharmony_ci } 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci if (unlikely(inode->i_blocks != 0 && inode->i_blocks != 8)) { 127162306a36Sopenharmony_ci f2fs_warn(F2FS_I_SB(inode), 127262306a36Sopenharmony_ci "f2fs_remove_inode_page: inconsistent i_blocks, ino:%lu, iblocks:%llu", 127362306a36Sopenharmony_ci inode->i_ino, (unsigned long long)inode->i_blocks); 127462306a36Sopenharmony_ci set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK); 127562306a36Sopenharmony_ci } 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci /* will put inode & node pages */ 127862306a36Sopenharmony_ci err = truncate_node(&dn); 127962306a36Sopenharmony_ci if (err) { 128062306a36Sopenharmony_ci f2fs_put_dnode(&dn); 128162306a36Sopenharmony_ci return err; 128262306a36Sopenharmony_ci } 128362306a36Sopenharmony_ci return 0; 128462306a36Sopenharmony_ci} 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_cistruct page *f2fs_new_inode_page(struct inode *inode) 128762306a36Sopenharmony_ci{ 128862306a36Sopenharmony_ci struct dnode_of_data dn; 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci /* allocate inode page for new inode */ 129162306a36Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci /* caller should f2fs_put_page(page, 1); */ 129462306a36Sopenharmony_ci return f2fs_new_node_page(&dn, 0); 129562306a36Sopenharmony_ci} 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_cistruct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs) 129862306a36Sopenharmony_ci{ 129962306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); 130062306a36Sopenharmony_ci struct node_info new_ni; 130162306a36Sopenharmony_ci struct page *page; 130262306a36Sopenharmony_ci int err; 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC))) 130562306a36Sopenharmony_ci return ERR_PTR(-EPERM); 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci page = f2fs_grab_cache_page(NODE_MAPPING(sbi), dn->nid, false); 130862306a36Sopenharmony_ci if (!page) 130962306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci if (unlikely((err = inc_valid_node_count(sbi, dn->inode, !ofs)))) 131262306a36Sopenharmony_ci goto fail; 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS 131562306a36Sopenharmony_ci err = f2fs_get_node_info(sbi, dn->nid, &new_ni, false); 131662306a36Sopenharmony_ci if (err) { 131762306a36Sopenharmony_ci dec_valid_node_count(sbi, dn->inode, !ofs); 131862306a36Sopenharmony_ci goto fail; 131962306a36Sopenharmony_ci } 132062306a36Sopenharmony_ci if (unlikely(new_ni.blk_addr != NULL_ADDR)) { 132162306a36Sopenharmony_ci err = -EFSCORRUPTED; 132262306a36Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 132362306a36Sopenharmony_ci f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR); 132462306a36Sopenharmony_ci goto fail; 132562306a36Sopenharmony_ci } 132662306a36Sopenharmony_ci#endif 132762306a36Sopenharmony_ci new_ni.nid = dn->nid; 132862306a36Sopenharmony_ci new_ni.ino = dn->inode->i_ino; 132962306a36Sopenharmony_ci new_ni.blk_addr = NULL_ADDR; 133062306a36Sopenharmony_ci new_ni.flag = 0; 133162306a36Sopenharmony_ci new_ni.version = 0; 133262306a36Sopenharmony_ci set_node_addr(sbi, &new_ni, NEW_ADDR, false); 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci f2fs_wait_on_page_writeback(page, NODE, true, true); 133562306a36Sopenharmony_ci fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); 133662306a36Sopenharmony_ci set_cold_node(page, S_ISDIR(dn->inode->i_mode)); 133762306a36Sopenharmony_ci if (!PageUptodate(page)) 133862306a36Sopenharmony_ci SetPageUptodate(page); 133962306a36Sopenharmony_ci if (set_page_dirty(page)) 134062306a36Sopenharmony_ci dn->node_changed = true; 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci if (f2fs_has_xattr_block(ofs)) 134362306a36Sopenharmony_ci f2fs_i_xnid_write(dn->inode, dn->nid); 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci if (ofs == 0) 134662306a36Sopenharmony_ci inc_valid_inode_count(sbi); 134762306a36Sopenharmony_ci return page; 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_cifail: 135062306a36Sopenharmony_ci clear_node_page_dirty(page); 135162306a36Sopenharmony_ci f2fs_put_page(page, 1); 135262306a36Sopenharmony_ci return ERR_PTR(err); 135362306a36Sopenharmony_ci} 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci/* 135662306a36Sopenharmony_ci * Caller should do after getting the following values. 135762306a36Sopenharmony_ci * 0: f2fs_put_page(page, 0) 135862306a36Sopenharmony_ci * LOCKED_PAGE or error: f2fs_put_page(page, 1) 135962306a36Sopenharmony_ci */ 136062306a36Sopenharmony_cistatic int read_node_page(struct page *page, blk_opf_t op_flags) 136162306a36Sopenharmony_ci{ 136262306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(page); 136362306a36Sopenharmony_ci struct node_info ni; 136462306a36Sopenharmony_ci struct f2fs_io_info fio = { 136562306a36Sopenharmony_ci .sbi = sbi, 136662306a36Sopenharmony_ci .type = NODE, 136762306a36Sopenharmony_ci .op = REQ_OP_READ, 136862306a36Sopenharmony_ci .op_flags = op_flags, 136962306a36Sopenharmony_ci .page = page, 137062306a36Sopenharmony_ci .encrypted_page = NULL, 137162306a36Sopenharmony_ci }; 137262306a36Sopenharmony_ci int err; 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci if (PageUptodate(page)) { 137562306a36Sopenharmony_ci if (!f2fs_inode_chksum_verify(sbi, page)) { 137662306a36Sopenharmony_ci ClearPageUptodate(page); 137762306a36Sopenharmony_ci return -EFSBADCRC; 137862306a36Sopenharmony_ci } 137962306a36Sopenharmony_ci return LOCKED_PAGE; 138062306a36Sopenharmony_ci } 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci err = f2fs_get_node_info(sbi, page->index, &ni, false); 138362306a36Sopenharmony_ci if (err) 138462306a36Sopenharmony_ci return err; 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci /* NEW_ADDR can be seen, after cp_error drops some dirty node pages */ 138762306a36Sopenharmony_ci if (unlikely(ni.blk_addr == NULL_ADDR || ni.blk_addr == NEW_ADDR)) { 138862306a36Sopenharmony_ci ClearPageUptodate(page); 138962306a36Sopenharmony_ci return -ENOENT; 139062306a36Sopenharmony_ci } 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci fio.new_blkaddr = fio.old_blkaddr = ni.blk_addr; 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci err = f2fs_submit_page_bio(&fio); 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci if (!err) 139762306a36Sopenharmony_ci f2fs_update_iostat(sbi, NULL, FS_NODE_READ_IO, F2FS_BLKSIZE); 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci return err; 140062306a36Sopenharmony_ci} 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci/* 140362306a36Sopenharmony_ci * Readahead a node page 140462306a36Sopenharmony_ci */ 140562306a36Sopenharmony_civoid f2fs_ra_node_page(struct f2fs_sb_info *sbi, nid_t nid) 140662306a36Sopenharmony_ci{ 140762306a36Sopenharmony_ci struct page *apage; 140862306a36Sopenharmony_ci int err; 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci if (!nid) 141162306a36Sopenharmony_ci return; 141262306a36Sopenharmony_ci if (f2fs_check_nid_range(sbi, nid)) 141362306a36Sopenharmony_ci return; 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ci apage = xa_load(&NODE_MAPPING(sbi)->i_pages, nid); 141662306a36Sopenharmony_ci if (apage) 141762306a36Sopenharmony_ci return; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci apage = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false); 142062306a36Sopenharmony_ci if (!apage) 142162306a36Sopenharmony_ci return; 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci err = read_node_page(apage, REQ_RAHEAD); 142462306a36Sopenharmony_ci f2fs_put_page(apage, err ? 1 : 0); 142562306a36Sopenharmony_ci} 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_cistatic struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid, 142862306a36Sopenharmony_ci struct page *parent, int start) 142962306a36Sopenharmony_ci{ 143062306a36Sopenharmony_ci struct page *page; 143162306a36Sopenharmony_ci int err; 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci if (!nid) 143462306a36Sopenharmony_ci return ERR_PTR(-ENOENT); 143562306a36Sopenharmony_ci if (f2fs_check_nid_range(sbi, nid)) 143662306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 143762306a36Sopenharmony_cirepeat: 143862306a36Sopenharmony_ci page = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false); 143962306a36Sopenharmony_ci if (!page) 144062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci err = read_node_page(page, 0); 144362306a36Sopenharmony_ci if (err < 0) { 144462306a36Sopenharmony_ci goto out_put_err; 144562306a36Sopenharmony_ci } else if (err == LOCKED_PAGE) { 144662306a36Sopenharmony_ci err = 0; 144762306a36Sopenharmony_ci goto page_hit; 144862306a36Sopenharmony_ci } 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci if (parent) 145162306a36Sopenharmony_ci f2fs_ra_node_pages(parent, start + 1, MAX_RA_NODE); 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci lock_page(page); 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci if (unlikely(page->mapping != NODE_MAPPING(sbi))) { 145662306a36Sopenharmony_ci f2fs_put_page(page, 1); 145762306a36Sopenharmony_ci goto repeat; 145862306a36Sopenharmony_ci } 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci if (unlikely(!PageUptodate(page))) { 146162306a36Sopenharmony_ci err = -EIO; 146262306a36Sopenharmony_ci goto out_err; 146362306a36Sopenharmony_ci } 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_ci if (!f2fs_inode_chksum_verify(sbi, page)) { 146662306a36Sopenharmony_ci err = -EFSBADCRC; 146762306a36Sopenharmony_ci goto out_err; 146862306a36Sopenharmony_ci } 146962306a36Sopenharmony_cipage_hit: 147062306a36Sopenharmony_ci if (likely(nid == nid_of_node(page))) 147162306a36Sopenharmony_ci return page; 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci f2fs_warn(sbi, "inconsistent node block, nid:%lu, node_footer[nid:%u,ino:%u,ofs:%u,cpver:%llu,blkaddr:%u]", 147462306a36Sopenharmony_ci nid, nid_of_node(page), ino_of_node(page), 147562306a36Sopenharmony_ci ofs_of_node(page), cpver_of_node(page), 147662306a36Sopenharmony_ci next_blkaddr_of_node(page)); 147762306a36Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 147862306a36Sopenharmony_ci f2fs_handle_error(sbi, ERROR_INCONSISTENT_FOOTER); 147962306a36Sopenharmony_ci err = -EFSCORRUPTED; 148062306a36Sopenharmony_ciout_err: 148162306a36Sopenharmony_ci ClearPageUptodate(page); 148262306a36Sopenharmony_ciout_put_err: 148362306a36Sopenharmony_ci /* ENOENT comes from read_node_page which is not an error. */ 148462306a36Sopenharmony_ci if (err != -ENOENT) 148562306a36Sopenharmony_ci f2fs_handle_page_eio(sbi, page->index, NODE); 148662306a36Sopenharmony_ci f2fs_put_page(page, 1); 148762306a36Sopenharmony_ci return ERR_PTR(err); 148862306a36Sopenharmony_ci} 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_cistruct page *f2fs_get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) 149162306a36Sopenharmony_ci{ 149262306a36Sopenharmony_ci return __get_node_page(sbi, nid, NULL, 0); 149362306a36Sopenharmony_ci} 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_cistruct page *f2fs_get_node_page_ra(struct page *parent, int start) 149662306a36Sopenharmony_ci{ 149762306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(parent); 149862306a36Sopenharmony_ci nid_t nid = get_nid(parent, start, false); 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci return __get_node_page(sbi, nid, parent, start); 150162306a36Sopenharmony_ci} 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_cistatic void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino) 150462306a36Sopenharmony_ci{ 150562306a36Sopenharmony_ci struct inode *inode; 150662306a36Sopenharmony_ci struct page *page; 150762306a36Sopenharmony_ci int ret; 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci /* should flush inline_data before evict_inode */ 151062306a36Sopenharmony_ci inode = ilookup(sbi->sb, ino); 151162306a36Sopenharmony_ci if (!inode) 151262306a36Sopenharmony_ci return; 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_ci page = f2fs_pagecache_get_page(inode->i_mapping, 0, 151562306a36Sopenharmony_ci FGP_LOCK|FGP_NOWAIT, 0); 151662306a36Sopenharmony_ci if (!page) 151762306a36Sopenharmony_ci goto iput_out; 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci if (!PageUptodate(page)) 152062306a36Sopenharmony_ci goto page_out; 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci if (!PageDirty(page)) 152362306a36Sopenharmony_ci goto page_out; 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci if (!clear_page_dirty_for_io(page)) 152662306a36Sopenharmony_ci goto page_out; 152762306a36Sopenharmony_ci 152862306a36Sopenharmony_ci ret = f2fs_write_inline_data(inode, page); 152962306a36Sopenharmony_ci inode_dec_dirty_pages(inode); 153062306a36Sopenharmony_ci f2fs_remove_dirty_inode(inode); 153162306a36Sopenharmony_ci if (ret) 153262306a36Sopenharmony_ci set_page_dirty(page); 153362306a36Sopenharmony_cipage_out: 153462306a36Sopenharmony_ci f2fs_put_page(page, 1); 153562306a36Sopenharmony_ciiput_out: 153662306a36Sopenharmony_ci iput(inode); 153762306a36Sopenharmony_ci} 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_cistatic struct page *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino) 154062306a36Sopenharmony_ci{ 154162306a36Sopenharmony_ci pgoff_t index; 154262306a36Sopenharmony_ci struct folio_batch fbatch; 154362306a36Sopenharmony_ci struct page *last_page = NULL; 154462306a36Sopenharmony_ci int nr_folios; 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci folio_batch_init(&fbatch); 154762306a36Sopenharmony_ci index = 0; 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci while ((nr_folios = filemap_get_folios_tag(NODE_MAPPING(sbi), &index, 155062306a36Sopenharmony_ci (pgoff_t)-1, PAGECACHE_TAG_DIRTY, 155162306a36Sopenharmony_ci &fbatch))) { 155262306a36Sopenharmony_ci int i; 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci for (i = 0; i < nr_folios; i++) { 155562306a36Sopenharmony_ci struct page *page = &fbatch.folios[i]->page; 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 155862306a36Sopenharmony_ci f2fs_put_page(last_page, 0); 155962306a36Sopenharmony_ci folio_batch_release(&fbatch); 156062306a36Sopenharmony_ci return ERR_PTR(-EIO); 156162306a36Sopenharmony_ci } 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci if (!IS_DNODE(page) || !is_cold_node(page)) 156462306a36Sopenharmony_ci continue; 156562306a36Sopenharmony_ci if (ino_of_node(page) != ino) 156662306a36Sopenharmony_ci continue; 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci lock_page(page); 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci if (unlikely(page->mapping != NODE_MAPPING(sbi))) { 157162306a36Sopenharmony_cicontinue_unlock: 157262306a36Sopenharmony_ci unlock_page(page); 157362306a36Sopenharmony_ci continue; 157462306a36Sopenharmony_ci } 157562306a36Sopenharmony_ci if (ino_of_node(page) != ino) 157662306a36Sopenharmony_ci goto continue_unlock; 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci if (!PageDirty(page)) { 157962306a36Sopenharmony_ci /* someone wrote it for us */ 158062306a36Sopenharmony_ci goto continue_unlock; 158162306a36Sopenharmony_ci } 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_ci if (last_page) 158462306a36Sopenharmony_ci f2fs_put_page(last_page, 0); 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_ci get_page(page); 158762306a36Sopenharmony_ci last_page = page; 158862306a36Sopenharmony_ci unlock_page(page); 158962306a36Sopenharmony_ci } 159062306a36Sopenharmony_ci folio_batch_release(&fbatch); 159162306a36Sopenharmony_ci cond_resched(); 159262306a36Sopenharmony_ci } 159362306a36Sopenharmony_ci return last_page; 159462306a36Sopenharmony_ci} 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_cistatic int __write_node_page(struct page *page, bool atomic, bool *submitted, 159762306a36Sopenharmony_ci struct writeback_control *wbc, bool do_balance, 159862306a36Sopenharmony_ci enum iostat_type io_type, unsigned int *seq_id) 159962306a36Sopenharmony_ci{ 160062306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(page); 160162306a36Sopenharmony_ci nid_t nid; 160262306a36Sopenharmony_ci struct node_info ni; 160362306a36Sopenharmony_ci struct f2fs_io_info fio = { 160462306a36Sopenharmony_ci .sbi = sbi, 160562306a36Sopenharmony_ci .ino = ino_of_node(page), 160662306a36Sopenharmony_ci .type = NODE, 160762306a36Sopenharmony_ci .op = REQ_OP_WRITE, 160862306a36Sopenharmony_ci .op_flags = wbc_to_write_flags(wbc), 160962306a36Sopenharmony_ci .page = page, 161062306a36Sopenharmony_ci .encrypted_page = NULL, 161162306a36Sopenharmony_ci .submitted = 0, 161262306a36Sopenharmony_ci .io_type = io_type, 161362306a36Sopenharmony_ci .io_wbc = wbc, 161462306a36Sopenharmony_ci }; 161562306a36Sopenharmony_ci unsigned int seq; 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_ci trace_f2fs_writepage(page, NODE); 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 162062306a36Sopenharmony_ci /* keep node pages in remount-ro mode */ 162162306a36Sopenharmony_ci if (F2FS_OPTION(sbi).errors == MOUNT_ERRORS_READONLY) 162262306a36Sopenharmony_ci goto redirty_out; 162362306a36Sopenharmony_ci ClearPageUptodate(page); 162462306a36Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_NODES); 162562306a36Sopenharmony_ci unlock_page(page); 162662306a36Sopenharmony_ci return 0; 162762306a36Sopenharmony_ci } 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 163062306a36Sopenharmony_ci goto redirty_out; 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci if (!is_sbi_flag_set(sbi, SBI_CP_DISABLED) && 163362306a36Sopenharmony_ci wbc->sync_mode == WB_SYNC_NONE && 163462306a36Sopenharmony_ci IS_DNODE(page) && is_cold_node(page)) 163562306a36Sopenharmony_ci goto redirty_out; 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci /* get old block addr of this node page */ 163862306a36Sopenharmony_ci nid = nid_of_node(page); 163962306a36Sopenharmony_ci f2fs_bug_on(sbi, page->index != nid); 164062306a36Sopenharmony_ci 164162306a36Sopenharmony_ci if (f2fs_get_node_info(sbi, nid, &ni, !do_balance)) 164262306a36Sopenharmony_ci goto redirty_out; 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci if (wbc->for_reclaim) { 164562306a36Sopenharmony_ci if (!f2fs_down_read_trylock(&sbi->node_write)) 164662306a36Sopenharmony_ci goto redirty_out; 164762306a36Sopenharmony_ci } else { 164862306a36Sopenharmony_ci f2fs_down_read(&sbi->node_write); 164962306a36Sopenharmony_ci } 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci /* This page is already truncated */ 165262306a36Sopenharmony_ci if (unlikely(ni.blk_addr == NULL_ADDR)) { 165362306a36Sopenharmony_ci ClearPageUptodate(page); 165462306a36Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_NODES); 165562306a36Sopenharmony_ci f2fs_up_read(&sbi->node_write); 165662306a36Sopenharmony_ci unlock_page(page); 165762306a36Sopenharmony_ci return 0; 165862306a36Sopenharmony_ci } 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci if (__is_valid_data_blkaddr(ni.blk_addr) && 166162306a36Sopenharmony_ci !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, 166262306a36Sopenharmony_ci DATA_GENERIC_ENHANCE)) { 166362306a36Sopenharmony_ci f2fs_up_read(&sbi->node_write); 166462306a36Sopenharmony_ci goto redirty_out; 166562306a36Sopenharmony_ci } 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_ci if (atomic && !test_opt(sbi, NOBARRIER) && !f2fs_sb_has_blkzoned(sbi)) 166862306a36Sopenharmony_ci fio.op_flags |= REQ_PREFLUSH | REQ_FUA; 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci /* should add to global list before clearing PAGECACHE status */ 167162306a36Sopenharmony_ci if (f2fs_in_warm_node_list(sbi, page)) { 167262306a36Sopenharmony_ci seq = f2fs_add_fsync_node_entry(sbi, page); 167362306a36Sopenharmony_ci if (seq_id) 167462306a36Sopenharmony_ci *seq_id = seq; 167562306a36Sopenharmony_ci } 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci set_page_writeback(page); 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci fio.old_blkaddr = ni.blk_addr; 168062306a36Sopenharmony_ci f2fs_do_write_node_page(nid, &fio); 168162306a36Sopenharmony_ci set_node_addr(sbi, &ni, fio.new_blkaddr, is_fsync_dnode(page)); 168262306a36Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_NODES); 168362306a36Sopenharmony_ci f2fs_up_read(&sbi->node_write); 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci if (wbc->for_reclaim) { 168662306a36Sopenharmony_ci f2fs_submit_merged_write_cond(sbi, NULL, page, 0, NODE); 168762306a36Sopenharmony_ci submitted = NULL; 168862306a36Sopenharmony_ci } 168962306a36Sopenharmony_ci 169062306a36Sopenharmony_ci unlock_page(page); 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 169362306a36Sopenharmony_ci f2fs_submit_merged_write(sbi, NODE); 169462306a36Sopenharmony_ci submitted = NULL; 169562306a36Sopenharmony_ci } 169662306a36Sopenharmony_ci if (submitted) 169762306a36Sopenharmony_ci *submitted = fio.submitted; 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci if (do_balance) 170062306a36Sopenharmony_ci f2fs_balance_fs(sbi, false); 170162306a36Sopenharmony_ci return 0; 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ciredirty_out: 170462306a36Sopenharmony_ci redirty_page_for_writepage(wbc, page); 170562306a36Sopenharmony_ci return AOP_WRITEPAGE_ACTIVATE; 170662306a36Sopenharmony_ci} 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ciint f2fs_move_node_page(struct page *node_page, int gc_type) 170962306a36Sopenharmony_ci{ 171062306a36Sopenharmony_ci int err = 0; 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_ci if (gc_type == FG_GC) { 171362306a36Sopenharmony_ci struct writeback_control wbc = { 171462306a36Sopenharmony_ci .sync_mode = WB_SYNC_ALL, 171562306a36Sopenharmony_ci .nr_to_write = 1, 171662306a36Sopenharmony_ci .for_reclaim = 0, 171762306a36Sopenharmony_ci }; 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci f2fs_wait_on_page_writeback(node_page, NODE, true, true); 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ci set_page_dirty(node_page); 172262306a36Sopenharmony_ci 172362306a36Sopenharmony_ci if (!clear_page_dirty_for_io(node_page)) { 172462306a36Sopenharmony_ci err = -EAGAIN; 172562306a36Sopenharmony_ci goto out_page; 172662306a36Sopenharmony_ci } 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci if (__write_node_page(node_page, false, NULL, 172962306a36Sopenharmony_ci &wbc, false, FS_GC_NODE_IO, NULL)) { 173062306a36Sopenharmony_ci err = -EAGAIN; 173162306a36Sopenharmony_ci unlock_page(node_page); 173262306a36Sopenharmony_ci } 173362306a36Sopenharmony_ci goto release_page; 173462306a36Sopenharmony_ci } else { 173562306a36Sopenharmony_ci /* set page dirty and write it */ 173662306a36Sopenharmony_ci if (!PageWriteback(node_page)) 173762306a36Sopenharmony_ci set_page_dirty(node_page); 173862306a36Sopenharmony_ci } 173962306a36Sopenharmony_ciout_page: 174062306a36Sopenharmony_ci unlock_page(node_page); 174162306a36Sopenharmony_cirelease_page: 174262306a36Sopenharmony_ci f2fs_put_page(node_page, 0); 174362306a36Sopenharmony_ci return err; 174462306a36Sopenharmony_ci} 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_cistatic int f2fs_write_node_page(struct page *page, 174762306a36Sopenharmony_ci struct writeback_control *wbc) 174862306a36Sopenharmony_ci{ 174962306a36Sopenharmony_ci return __write_node_page(page, false, NULL, wbc, false, 175062306a36Sopenharmony_ci FS_NODE_IO, NULL); 175162306a36Sopenharmony_ci} 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ciint f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, 175462306a36Sopenharmony_ci struct writeback_control *wbc, bool atomic, 175562306a36Sopenharmony_ci unsigned int *seq_id) 175662306a36Sopenharmony_ci{ 175762306a36Sopenharmony_ci pgoff_t index; 175862306a36Sopenharmony_ci struct folio_batch fbatch; 175962306a36Sopenharmony_ci int ret = 0; 176062306a36Sopenharmony_ci struct page *last_page = NULL; 176162306a36Sopenharmony_ci bool marked = false; 176262306a36Sopenharmony_ci nid_t ino = inode->i_ino; 176362306a36Sopenharmony_ci int nr_folios; 176462306a36Sopenharmony_ci int nwritten = 0; 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci if (atomic) { 176762306a36Sopenharmony_ci last_page = last_fsync_dnode(sbi, ino); 176862306a36Sopenharmony_ci if (IS_ERR_OR_NULL(last_page)) 176962306a36Sopenharmony_ci return PTR_ERR_OR_ZERO(last_page); 177062306a36Sopenharmony_ci } 177162306a36Sopenharmony_ciretry: 177262306a36Sopenharmony_ci folio_batch_init(&fbatch); 177362306a36Sopenharmony_ci index = 0; 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_ci while ((nr_folios = filemap_get_folios_tag(NODE_MAPPING(sbi), &index, 177662306a36Sopenharmony_ci (pgoff_t)-1, PAGECACHE_TAG_DIRTY, 177762306a36Sopenharmony_ci &fbatch))) { 177862306a36Sopenharmony_ci int i; 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci for (i = 0; i < nr_folios; i++) { 178162306a36Sopenharmony_ci struct page *page = &fbatch.folios[i]->page; 178262306a36Sopenharmony_ci bool submitted = false; 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 178562306a36Sopenharmony_ci f2fs_put_page(last_page, 0); 178662306a36Sopenharmony_ci folio_batch_release(&fbatch); 178762306a36Sopenharmony_ci ret = -EIO; 178862306a36Sopenharmony_ci goto out; 178962306a36Sopenharmony_ci } 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ci if (!IS_DNODE(page) || !is_cold_node(page)) 179262306a36Sopenharmony_ci continue; 179362306a36Sopenharmony_ci if (ino_of_node(page) != ino) 179462306a36Sopenharmony_ci continue; 179562306a36Sopenharmony_ci 179662306a36Sopenharmony_ci lock_page(page); 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ci if (unlikely(page->mapping != NODE_MAPPING(sbi))) { 179962306a36Sopenharmony_cicontinue_unlock: 180062306a36Sopenharmony_ci unlock_page(page); 180162306a36Sopenharmony_ci continue; 180262306a36Sopenharmony_ci } 180362306a36Sopenharmony_ci if (ino_of_node(page) != ino) 180462306a36Sopenharmony_ci goto continue_unlock; 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci if (!PageDirty(page) && page != last_page) { 180762306a36Sopenharmony_ci /* someone wrote it for us */ 180862306a36Sopenharmony_ci goto continue_unlock; 180962306a36Sopenharmony_ci } 181062306a36Sopenharmony_ci 181162306a36Sopenharmony_ci f2fs_wait_on_page_writeback(page, NODE, true, true); 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci set_fsync_mark(page, 0); 181462306a36Sopenharmony_ci set_dentry_mark(page, 0); 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci if (!atomic || page == last_page) { 181762306a36Sopenharmony_ci set_fsync_mark(page, 1); 181862306a36Sopenharmony_ci percpu_counter_inc(&sbi->rf_node_block_count); 181962306a36Sopenharmony_ci if (IS_INODE(page)) { 182062306a36Sopenharmony_ci if (is_inode_flag_set(inode, 182162306a36Sopenharmony_ci FI_DIRTY_INODE)) 182262306a36Sopenharmony_ci f2fs_update_inode(inode, page); 182362306a36Sopenharmony_ci set_dentry_mark(page, 182462306a36Sopenharmony_ci f2fs_need_dentry_mark(sbi, ino)); 182562306a36Sopenharmony_ci } 182662306a36Sopenharmony_ci /* may be written by other thread */ 182762306a36Sopenharmony_ci if (!PageDirty(page)) 182862306a36Sopenharmony_ci set_page_dirty(page); 182962306a36Sopenharmony_ci } 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci if (!clear_page_dirty_for_io(page)) 183262306a36Sopenharmony_ci goto continue_unlock; 183362306a36Sopenharmony_ci 183462306a36Sopenharmony_ci ret = __write_node_page(page, atomic && 183562306a36Sopenharmony_ci page == last_page, 183662306a36Sopenharmony_ci &submitted, wbc, true, 183762306a36Sopenharmony_ci FS_NODE_IO, seq_id); 183862306a36Sopenharmony_ci if (ret) { 183962306a36Sopenharmony_ci unlock_page(page); 184062306a36Sopenharmony_ci f2fs_put_page(last_page, 0); 184162306a36Sopenharmony_ci break; 184262306a36Sopenharmony_ci } else if (submitted) { 184362306a36Sopenharmony_ci nwritten++; 184462306a36Sopenharmony_ci } 184562306a36Sopenharmony_ci 184662306a36Sopenharmony_ci if (page == last_page) { 184762306a36Sopenharmony_ci f2fs_put_page(page, 0); 184862306a36Sopenharmony_ci marked = true; 184962306a36Sopenharmony_ci break; 185062306a36Sopenharmony_ci } 185162306a36Sopenharmony_ci } 185262306a36Sopenharmony_ci folio_batch_release(&fbatch); 185362306a36Sopenharmony_ci cond_resched(); 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ci if (ret || marked) 185662306a36Sopenharmony_ci break; 185762306a36Sopenharmony_ci } 185862306a36Sopenharmony_ci if (!ret && atomic && !marked) { 185962306a36Sopenharmony_ci f2fs_debug(sbi, "Retry to write fsync mark: ino=%u, idx=%lx", 186062306a36Sopenharmony_ci ino, last_page->index); 186162306a36Sopenharmony_ci lock_page(last_page); 186262306a36Sopenharmony_ci f2fs_wait_on_page_writeback(last_page, NODE, true, true); 186362306a36Sopenharmony_ci set_page_dirty(last_page); 186462306a36Sopenharmony_ci unlock_page(last_page); 186562306a36Sopenharmony_ci goto retry; 186662306a36Sopenharmony_ci } 186762306a36Sopenharmony_ciout: 186862306a36Sopenharmony_ci if (nwritten) 186962306a36Sopenharmony_ci f2fs_submit_merged_write_cond(sbi, NULL, NULL, ino, NODE); 187062306a36Sopenharmony_ci return ret ? -EIO : 0; 187162306a36Sopenharmony_ci} 187262306a36Sopenharmony_ci 187362306a36Sopenharmony_cistatic int f2fs_match_ino(struct inode *inode, unsigned long ino, void *data) 187462306a36Sopenharmony_ci{ 187562306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 187662306a36Sopenharmony_ci bool clean; 187762306a36Sopenharmony_ci 187862306a36Sopenharmony_ci if (inode->i_ino != ino) 187962306a36Sopenharmony_ci return 0; 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ci if (!is_inode_flag_set(inode, FI_DIRTY_INODE)) 188262306a36Sopenharmony_ci return 0; 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_ci spin_lock(&sbi->inode_lock[DIRTY_META]); 188562306a36Sopenharmony_ci clean = list_empty(&F2FS_I(inode)->gdirty_list); 188662306a36Sopenharmony_ci spin_unlock(&sbi->inode_lock[DIRTY_META]); 188762306a36Sopenharmony_ci 188862306a36Sopenharmony_ci if (clean) 188962306a36Sopenharmony_ci return 0; 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_ci inode = igrab(inode); 189262306a36Sopenharmony_ci if (!inode) 189362306a36Sopenharmony_ci return 0; 189462306a36Sopenharmony_ci return 1; 189562306a36Sopenharmony_ci} 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_cistatic bool flush_dirty_inode(struct page *page) 189862306a36Sopenharmony_ci{ 189962306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(page); 190062306a36Sopenharmony_ci struct inode *inode; 190162306a36Sopenharmony_ci nid_t ino = ino_of_node(page); 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci inode = find_inode_nowait(sbi->sb, ino, f2fs_match_ino, NULL); 190462306a36Sopenharmony_ci if (!inode) 190562306a36Sopenharmony_ci return false; 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci f2fs_update_inode(inode, page); 190862306a36Sopenharmony_ci unlock_page(page); 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci iput(inode); 191162306a36Sopenharmony_ci return true; 191262306a36Sopenharmony_ci} 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_civoid f2fs_flush_inline_data(struct f2fs_sb_info *sbi) 191562306a36Sopenharmony_ci{ 191662306a36Sopenharmony_ci pgoff_t index = 0; 191762306a36Sopenharmony_ci struct folio_batch fbatch; 191862306a36Sopenharmony_ci int nr_folios; 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_ci folio_batch_init(&fbatch); 192162306a36Sopenharmony_ci 192262306a36Sopenharmony_ci while ((nr_folios = filemap_get_folios_tag(NODE_MAPPING(sbi), &index, 192362306a36Sopenharmony_ci (pgoff_t)-1, PAGECACHE_TAG_DIRTY, 192462306a36Sopenharmony_ci &fbatch))) { 192562306a36Sopenharmony_ci int i; 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_ci for (i = 0; i < nr_folios; i++) { 192862306a36Sopenharmony_ci struct page *page = &fbatch.folios[i]->page; 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci if (!IS_DNODE(page)) 193162306a36Sopenharmony_ci continue; 193262306a36Sopenharmony_ci 193362306a36Sopenharmony_ci lock_page(page); 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_ci if (unlikely(page->mapping != NODE_MAPPING(sbi))) { 193662306a36Sopenharmony_cicontinue_unlock: 193762306a36Sopenharmony_ci unlock_page(page); 193862306a36Sopenharmony_ci continue; 193962306a36Sopenharmony_ci } 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ci if (!PageDirty(page)) { 194262306a36Sopenharmony_ci /* someone wrote it for us */ 194362306a36Sopenharmony_ci goto continue_unlock; 194462306a36Sopenharmony_ci } 194562306a36Sopenharmony_ci 194662306a36Sopenharmony_ci /* flush inline_data, if it's async context. */ 194762306a36Sopenharmony_ci if (page_private_inline(page)) { 194862306a36Sopenharmony_ci clear_page_private_inline(page); 194962306a36Sopenharmony_ci unlock_page(page); 195062306a36Sopenharmony_ci flush_inline_data(sbi, ino_of_node(page)); 195162306a36Sopenharmony_ci continue; 195262306a36Sopenharmony_ci } 195362306a36Sopenharmony_ci unlock_page(page); 195462306a36Sopenharmony_ci } 195562306a36Sopenharmony_ci folio_batch_release(&fbatch); 195662306a36Sopenharmony_ci cond_resched(); 195762306a36Sopenharmony_ci } 195862306a36Sopenharmony_ci} 195962306a36Sopenharmony_ci 196062306a36Sopenharmony_ciint f2fs_sync_node_pages(struct f2fs_sb_info *sbi, 196162306a36Sopenharmony_ci struct writeback_control *wbc, 196262306a36Sopenharmony_ci bool do_balance, enum iostat_type io_type) 196362306a36Sopenharmony_ci{ 196462306a36Sopenharmony_ci pgoff_t index; 196562306a36Sopenharmony_ci struct folio_batch fbatch; 196662306a36Sopenharmony_ci int step = 0; 196762306a36Sopenharmony_ci int nwritten = 0; 196862306a36Sopenharmony_ci int ret = 0; 196962306a36Sopenharmony_ci int nr_folios, done = 0; 197062306a36Sopenharmony_ci 197162306a36Sopenharmony_ci folio_batch_init(&fbatch); 197262306a36Sopenharmony_ci 197362306a36Sopenharmony_cinext_step: 197462306a36Sopenharmony_ci index = 0; 197562306a36Sopenharmony_ci 197662306a36Sopenharmony_ci while (!done && (nr_folios = filemap_get_folios_tag(NODE_MAPPING(sbi), 197762306a36Sopenharmony_ci &index, (pgoff_t)-1, PAGECACHE_TAG_DIRTY, 197862306a36Sopenharmony_ci &fbatch))) { 197962306a36Sopenharmony_ci int i; 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_ci for (i = 0; i < nr_folios; i++) { 198262306a36Sopenharmony_ci struct page *page = &fbatch.folios[i]->page; 198362306a36Sopenharmony_ci bool submitted = false; 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ci /* give a priority to WB_SYNC threads */ 198662306a36Sopenharmony_ci if (atomic_read(&sbi->wb_sync_req[NODE]) && 198762306a36Sopenharmony_ci wbc->sync_mode == WB_SYNC_NONE) { 198862306a36Sopenharmony_ci done = 1; 198962306a36Sopenharmony_ci break; 199062306a36Sopenharmony_ci } 199162306a36Sopenharmony_ci 199262306a36Sopenharmony_ci /* 199362306a36Sopenharmony_ci * flushing sequence with step: 199462306a36Sopenharmony_ci * 0. indirect nodes 199562306a36Sopenharmony_ci * 1. dentry dnodes 199662306a36Sopenharmony_ci * 2. file dnodes 199762306a36Sopenharmony_ci */ 199862306a36Sopenharmony_ci if (step == 0 && IS_DNODE(page)) 199962306a36Sopenharmony_ci continue; 200062306a36Sopenharmony_ci if (step == 1 && (!IS_DNODE(page) || 200162306a36Sopenharmony_ci is_cold_node(page))) 200262306a36Sopenharmony_ci continue; 200362306a36Sopenharmony_ci if (step == 2 && (!IS_DNODE(page) || 200462306a36Sopenharmony_ci !is_cold_node(page))) 200562306a36Sopenharmony_ci continue; 200662306a36Sopenharmony_cilock_node: 200762306a36Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL) 200862306a36Sopenharmony_ci lock_page(page); 200962306a36Sopenharmony_ci else if (!trylock_page(page)) 201062306a36Sopenharmony_ci continue; 201162306a36Sopenharmony_ci 201262306a36Sopenharmony_ci if (unlikely(page->mapping != NODE_MAPPING(sbi))) { 201362306a36Sopenharmony_cicontinue_unlock: 201462306a36Sopenharmony_ci unlock_page(page); 201562306a36Sopenharmony_ci continue; 201662306a36Sopenharmony_ci } 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_ci if (!PageDirty(page)) { 201962306a36Sopenharmony_ci /* someone wrote it for us */ 202062306a36Sopenharmony_ci goto continue_unlock; 202162306a36Sopenharmony_ci } 202262306a36Sopenharmony_ci 202362306a36Sopenharmony_ci /* flush inline_data/inode, if it's async context. */ 202462306a36Sopenharmony_ci if (!do_balance) 202562306a36Sopenharmony_ci goto write_node; 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ci /* flush inline_data */ 202862306a36Sopenharmony_ci if (page_private_inline(page)) { 202962306a36Sopenharmony_ci clear_page_private_inline(page); 203062306a36Sopenharmony_ci unlock_page(page); 203162306a36Sopenharmony_ci flush_inline_data(sbi, ino_of_node(page)); 203262306a36Sopenharmony_ci goto lock_node; 203362306a36Sopenharmony_ci } 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci /* flush dirty inode */ 203662306a36Sopenharmony_ci if (IS_INODE(page) && flush_dirty_inode(page)) 203762306a36Sopenharmony_ci goto lock_node; 203862306a36Sopenharmony_ciwrite_node: 203962306a36Sopenharmony_ci f2fs_wait_on_page_writeback(page, NODE, true, true); 204062306a36Sopenharmony_ci 204162306a36Sopenharmony_ci if (!clear_page_dirty_for_io(page)) 204262306a36Sopenharmony_ci goto continue_unlock; 204362306a36Sopenharmony_ci 204462306a36Sopenharmony_ci set_fsync_mark(page, 0); 204562306a36Sopenharmony_ci set_dentry_mark(page, 0); 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci ret = __write_node_page(page, false, &submitted, 204862306a36Sopenharmony_ci wbc, do_balance, io_type, NULL); 204962306a36Sopenharmony_ci if (ret) 205062306a36Sopenharmony_ci unlock_page(page); 205162306a36Sopenharmony_ci else if (submitted) 205262306a36Sopenharmony_ci nwritten++; 205362306a36Sopenharmony_ci 205462306a36Sopenharmony_ci if (--wbc->nr_to_write == 0) 205562306a36Sopenharmony_ci break; 205662306a36Sopenharmony_ci } 205762306a36Sopenharmony_ci folio_batch_release(&fbatch); 205862306a36Sopenharmony_ci cond_resched(); 205962306a36Sopenharmony_ci 206062306a36Sopenharmony_ci if (wbc->nr_to_write == 0) { 206162306a36Sopenharmony_ci step = 2; 206262306a36Sopenharmony_ci break; 206362306a36Sopenharmony_ci } 206462306a36Sopenharmony_ci } 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci if (step < 2) { 206762306a36Sopenharmony_ci if (!is_sbi_flag_set(sbi, SBI_CP_DISABLED) && 206862306a36Sopenharmony_ci wbc->sync_mode == WB_SYNC_NONE && step == 1) 206962306a36Sopenharmony_ci goto out; 207062306a36Sopenharmony_ci step++; 207162306a36Sopenharmony_ci goto next_step; 207262306a36Sopenharmony_ci } 207362306a36Sopenharmony_ciout: 207462306a36Sopenharmony_ci if (nwritten) 207562306a36Sopenharmony_ci f2fs_submit_merged_write(sbi, NODE); 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) 207862306a36Sopenharmony_ci return -EIO; 207962306a36Sopenharmony_ci return ret; 208062306a36Sopenharmony_ci} 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_ciint f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, 208362306a36Sopenharmony_ci unsigned int seq_id) 208462306a36Sopenharmony_ci{ 208562306a36Sopenharmony_ci struct fsync_node_entry *fn; 208662306a36Sopenharmony_ci struct page *page; 208762306a36Sopenharmony_ci struct list_head *head = &sbi->fsync_node_list; 208862306a36Sopenharmony_ci unsigned long flags; 208962306a36Sopenharmony_ci unsigned int cur_seq_id = 0; 209062306a36Sopenharmony_ci 209162306a36Sopenharmony_ci while (seq_id && cur_seq_id < seq_id) { 209262306a36Sopenharmony_ci spin_lock_irqsave(&sbi->fsync_node_lock, flags); 209362306a36Sopenharmony_ci if (list_empty(head)) { 209462306a36Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 209562306a36Sopenharmony_ci break; 209662306a36Sopenharmony_ci } 209762306a36Sopenharmony_ci fn = list_first_entry(head, struct fsync_node_entry, list); 209862306a36Sopenharmony_ci if (fn->seq_id > seq_id) { 209962306a36Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 210062306a36Sopenharmony_ci break; 210162306a36Sopenharmony_ci } 210262306a36Sopenharmony_ci cur_seq_id = fn->seq_id; 210362306a36Sopenharmony_ci page = fn->page; 210462306a36Sopenharmony_ci get_page(page); 210562306a36Sopenharmony_ci spin_unlock_irqrestore(&sbi->fsync_node_lock, flags); 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_ci f2fs_wait_on_page_writeback(page, NODE, true, false); 210862306a36Sopenharmony_ci 210962306a36Sopenharmony_ci put_page(page); 211062306a36Sopenharmony_ci } 211162306a36Sopenharmony_ci 211262306a36Sopenharmony_ci return filemap_check_errors(NODE_MAPPING(sbi)); 211362306a36Sopenharmony_ci} 211462306a36Sopenharmony_ci 211562306a36Sopenharmony_cistatic int f2fs_write_node_pages(struct address_space *mapping, 211662306a36Sopenharmony_ci struct writeback_control *wbc) 211762306a36Sopenharmony_ci{ 211862306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_M_SB(mapping); 211962306a36Sopenharmony_ci struct blk_plug plug; 212062306a36Sopenharmony_ci long diff; 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 212362306a36Sopenharmony_ci goto skip_write; 212462306a36Sopenharmony_ci 212562306a36Sopenharmony_ci /* balancing f2fs's metadata in background */ 212662306a36Sopenharmony_ci f2fs_balance_fs_bg(sbi, true); 212762306a36Sopenharmony_ci 212862306a36Sopenharmony_ci /* collect a number of dirty node pages and write together */ 212962306a36Sopenharmony_ci if (wbc->sync_mode != WB_SYNC_ALL && 213062306a36Sopenharmony_ci get_pages(sbi, F2FS_DIRTY_NODES) < 213162306a36Sopenharmony_ci nr_pages_to_skip(sbi, NODE)) 213262306a36Sopenharmony_ci goto skip_write; 213362306a36Sopenharmony_ci 213462306a36Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL) 213562306a36Sopenharmony_ci atomic_inc(&sbi->wb_sync_req[NODE]); 213662306a36Sopenharmony_ci else if (atomic_read(&sbi->wb_sync_req[NODE])) { 213762306a36Sopenharmony_ci /* to avoid potential deadlock */ 213862306a36Sopenharmony_ci if (current->plug) 213962306a36Sopenharmony_ci blk_finish_plug(current->plug); 214062306a36Sopenharmony_ci goto skip_write; 214162306a36Sopenharmony_ci } 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci trace_f2fs_writepages(mapping->host, wbc, NODE); 214462306a36Sopenharmony_ci 214562306a36Sopenharmony_ci diff = nr_pages_to_write(sbi, NODE, wbc); 214662306a36Sopenharmony_ci blk_start_plug(&plug); 214762306a36Sopenharmony_ci f2fs_sync_node_pages(sbi, wbc, true, FS_NODE_IO); 214862306a36Sopenharmony_ci blk_finish_plug(&plug); 214962306a36Sopenharmony_ci wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff); 215062306a36Sopenharmony_ci 215162306a36Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL) 215262306a36Sopenharmony_ci atomic_dec(&sbi->wb_sync_req[NODE]); 215362306a36Sopenharmony_ci return 0; 215462306a36Sopenharmony_ci 215562306a36Sopenharmony_ciskip_write: 215662306a36Sopenharmony_ci wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_NODES); 215762306a36Sopenharmony_ci trace_f2fs_writepages(mapping->host, wbc, NODE); 215862306a36Sopenharmony_ci return 0; 215962306a36Sopenharmony_ci} 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_cistatic bool f2fs_dirty_node_folio(struct address_space *mapping, 216262306a36Sopenharmony_ci struct folio *folio) 216362306a36Sopenharmony_ci{ 216462306a36Sopenharmony_ci trace_f2fs_set_page_dirty(&folio->page, NODE); 216562306a36Sopenharmony_ci 216662306a36Sopenharmony_ci if (!folio_test_uptodate(folio)) 216762306a36Sopenharmony_ci folio_mark_uptodate(folio); 216862306a36Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS 216962306a36Sopenharmony_ci if (IS_INODE(&folio->page)) 217062306a36Sopenharmony_ci f2fs_inode_chksum_set(F2FS_M_SB(mapping), &folio->page); 217162306a36Sopenharmony_ci#endif 217262306a36Sopenharmony_ci if (filemap_dirty_folio(mapping, folio)) { 217362306a36Sopenharmony_ci inc_page_count(F2FS_M_SB(mapping), F2FS_DIRTY_NODES); 217462306a36Sopenharmony_ci set_page_private_reference(&folio->page); 217562306a36Sopenharmony_ci return true; 217662306a36Sopenharmony_ci } 217762306a36Sopenharmony_ci return false; 217862306a36Sopenharmony_ci} 217962306a36Sopenharmony_ci 218062306a36Sopenharmony_ci/* 218162306a36Sopenharmony_ci * Structure of the f2fs node operations 218262306a36Sopenharmony_ci */ 218362306a36Sopenharmony_ciconst struct address_space_operations f2fs_node_aops = { 218462306a36Sopenharmony_ci .writepage = f2fs_write_node_page, 218562306a36Sopenharmony_ci .writepages = f2fs_write_node_pages, 218662306a36Sopenharmony_ci .dirty_folio = f2fs_dirty_node_folio, 218762306a36Sopenharmony_ci .invalidate_folio = f2fs_invalidate_folio, 218862306a36Sopenharmony_ci .release_folio = f2fs_release_folio, 218962306a36Sopenharmony_ci .migrate_folio = filemap_migrate_folio, 219062306a36Sopenharmony_ci}; 219162306a36Sopenharmony_ci 219262306a36Sopenharmony_cistatic struct free_nid *__lookup_free_nid_list(struct f2fs_nm_info *nm_i, 219362306a36Sopenharmony_ci nid_t n) 219462306a36Sopenharmony_ci{ 219562306a36Sopenharmony_ci return radix_tree_lookup(&nm_i->free_nid_root, n); 219662306a36Sopenharmony_ci} 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_cistatic int __insert_free_nid(struct f2fs_sb_info *sbi, 219962306a36Sopenharmony_ci struct free_nid *i) 220062306a36Sopenharmony_ci{ 220162306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 220262306a36Sopenharmony_ci int err = radix_tree_insert(&nm_i->free_nid_root, i->nid, i); 220362306a36Sopenharmony_ci 220462306a36Sopenharmony_ci if (err) 220562306a36Sopenharmony_ci return err; 220662306a36Sopenharmony_ci 220762306a36Sopenharmony_ci nm_i->nid_cnt[FREE_NID]++; 220862306a36Sopenharmony_ci list_add_tail(&i->list, &nm_i->free_nid_list); 220962306a36Sopenharmony_ci return 0; 221062306a36Sopenharmony_ci} 221162306a36Sopenharmony_ci 221262306a36Sopenharmony_cistatic void __remove_free_nid(struct f2fs_sb_info *sbi, 221362306a36Sopenharmony_ci struct free_nid *i, enum nid_state state) 221462306a36Sopenharmony_ci{ 221562306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 221662306a36Sopenharmony_ci 221762306a36Sopenharmony_ci f2fs_bug_on(sbi, state != i->state); 221862306a36Sopenharmony_ci nm_i->nid_cnt[state]--; 221962306a36Sopenharmony_ci if (state == FREE_NID) 222062306a36Sopenharmony_ci list_del(&i->list); 222162306a36Sopenharmony_ci radix_tree_delete(&nm_i->free_nid_root, i->nid); 222262306a36Sopenharmony_ci} 222362306a36Sopenharmony_ci 222462306a36Sopenharmony_cistatic void __move_free_nid(struct f2fs_sb_info *sbi, struct free_nid *i, 222562306a36Sopenharmony_ci enum nid_state org_state, enum nid_state dst_state) 222662306a36Sopenharmony_ci{ 222762306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 222862306a36Sopenharmony_ci 222962306a36Sopenharmony_ci f2fs_bug_on(sbi, org_state != i->state); 223062306a36Sopenharmony_ci i->state = dst_state; 223162306a36Sopenharmony_ci nm_i->nid_cnt[org_state]--; 223262306a36Sopenharmony_ci nm_i->nid_cnt[dst_state]++; 223362306a36Sopenharmony_ci 223462306a36Sopenharmony_ci switch (dst_state) { 223562306a36Sopenharmony_ci case PREALLOC_NID: 223662306a36Sopenharmony_ci list_del(&i->list); 223762306a36Sopenharmony_ci break; 223862306a36Sopenharmony_ci case FREE_NID: 223962306a36Sopenharmony_ci list_add_tail(&i->list, &nm_i->free_nid_list); 224062306a36Sopenharmony_ci break; 224162306a36Sopenharmony_ci default: 224262306a36Sopenharmony_ci BUG_ON(1); 224362306a36Sopenharmony_ci } 224462306a36Sopenharmony_ci} 224562306a36Sopenharmony_ci 224662306a36Sopenharmony_cibool f2fs_nat_bitmap_enabled(struct f2fs_sb_info *sbi) 224762306a36Sopenharmony_ci{ 224862306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 224962306a36Sopenharmony_ci unsigned int i; 225062306a36Sopenharmony_ci bool ret = true; 225162306a36Sopenharmony_ci 225262306a36Sopenharmony_ci f2fs_down_read(&nm_i->nat_tree_lock); 225362306a36Sopenharmony_ci for (i = 0; i < nm_i->nat_blocks; i++) { 225462306a36Sopenharmony_ci if (!test_bit_le(i, nm_i->nat_block_bitmap)) { 225562306a36Sopenharmony_ci ret = false; 225662306a36Sopenharmony_ci break; 225762306a36Sopenharmony_ci } 225862306a36Sopenharmony_ci } 225962306a36Sopenharmony_ci f2fs_up_read(&nm_i->nat_tree_lock); 226062306a36Sopenharmony_ci 226162306a36Sopenharmony_ci return ret; 226262306a36Sopenharmony_ci} 226362306a36Sopenharmony_ci 226462306a36Sopenharmony_cistatic void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid, 226562306a36Sopenharmony_ci bool set, bool build) 226662306a36Sopenharmony_ci{ 226762306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 226862306a36Sopenharmony_ci unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid); 226962306a36Sopenharmony_ci unsigned int nid_ofs = nid - START_NID(nid); 227062306a36Sopenharmony_ci 227162306a36Sopenharmony_ci if (!test_bit_le(nat_ofs, nm_i->nat_block_bitmap)) 227262306a36Sopenharmony_ci return; 227362306a36Sopenharmony_ci 227462306a36Sopenharmony_ci if (set) { 227562306a36Sopenharmony_ci if (test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs])) 227662306a36Sopenharmony_ci return; 227762306a36Sopenharmony_ci __set_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); 227862306a36Sopenharmony_ci nm_i->free_nid_count[nat_ofs]++; 227962306a36Sopenharmony_ci } else { 228062306a36Sopenharmony_ci if (!test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs])) 228162306a36Sopenharmony_ci return; 228262306a36Sopenharmony_ci __clear_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); 228362306a36Sopenharmony_ci if (!build) 228462306a36Sopenharmony_ci nm_i->free_nid_count[nat_ofs]--; 228562306a36Sopenharmony_ci } 228662306a36Sopenharmony_ci} 228762306a36Sopenharmony_ci 228862306a36Sopenharmony_ci/* return if the nid is recognized as free */ 228962306a36Sopenharmony_cistatic bool add_free_nid(struct f2fs_sb_info *sbi, 229062306a36Sopenharmony_ci nid_t nid, bool build, bool update) 229162306a36Sopenharmony_ci{ 229262306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 229362306a36Sopenharmony_ci struct free_nid *i, *e; 229462306a36Sopenharmony_ci struct nat_entry *ne; 229562306a36Sopenharmony_ci int err = -EINVAL; 229662306a36Sopenharmony_ci bool ret = false; 229762306a36Sopenharmony_ci 229862306a36Sopenharmony_ci /* 0 nid should not be used */ 229962306a36Sopenharmony_ci if (unlikely(nid == 0)) 230062306a36Sopenharmony_ci return false; 230162306a36Sopenharmony_ci 230262306a36Sopenharmony_ci if (unlikely(f2fs_check_nid_range(sbi, nid))) 230362306a36Sopenharmony_ci return false; 230462306a36Sopenharmony_ci 230562306a36Sopenharmony_ci i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS, true, NULL); 230662306a36Sopenharmony_ci i->nid = nid; 230762306a36Sopenharmony_ci i->state = FREE_NID; 230862306a36Sopenharmony_ci 230962306a36Sopenharmony_ci radix_tree_preload(GFP_NOFS | __GFP_NOFAIL); 231062306a36Sopenharmony_ci 231162306a36Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 231262306a36Sopenharmony_ci 231362306a36Sopenharmony_ci if (build) { 231462306a36Sopenharmony_ci /* 231562306a36Sopenharmony_ci * Thread A Thread B 231662306a36Sopenharmony_ci * - f2fs_create 231762306a36Sopenharmony_ci * - f2fs_new_inode 231862306a36Sopenharmony_ci * - f2fs_alloc_nid 231962306a36Sopenharmony_ci * - __insert_nid_to_list(PREALLOC_NID) 232062306a36Sopenharmony_ci * - f2fs_balance_fs_bg 232162306a36Sopenharmony_ci * - f2fs_build_free_nids 232262306a36Sopenharmony_ci * - __f2fs_build_free_nids 232362306a36Sopenharmony_ci * - scan_nat_page 232462306a36Sopenharmony_ci * - add_free_nid 232562306a36Sopenharmony_ci * - __lookup_nat_cache 232662306a36Sopenharmony_ci * - f2fs_add_link 232762306a36Sopenharmony_ci * - f2fs_init_inode_metadata 232862306a36Sopenharmony_ci * - f2fs_new_inode_page 232962306a36Sopenharmony_ci * - f2fs_new_node_page 233062306a36Sopenharmony_ci * - set_node_addr 233162306a36Sopenharmony_ci * - f2fs_alloc_nid_done 233262306a36Sopenharmony_ci * - __remove_nid_from_list(PREALLOC_NID) 233362306a36Sopenharmony_ci * - __insert_nid_to_list(FREE_NID) 233462306a36Sopenharmony_ci */ 233562306a36Sopenharmony_ci ne = __lookup_nat_cache(nm_i, nid); 233662306a36Sopenharmony_ci if (ne && (!get_nat_flag(ne, IS_CHECKPOINTED) || 233762306a36Sopenharmony_ci nat_get_blkaddr(ne) != NULL_ADDR)) 233862306a36Sopenharmony_ci goto err_out; 233962306a36Sopenharmony_ci 234062306a36Sopenharmony_ci e = __lookup_free_nid_list(nm_i, nid); 234162306a36Sopenharmony_ci if (e) { 234262306a36Sopenharmony_ci if (e->state == FREE_NID) 234362306a36Sopenharmony_ci ret = true; 234462306a36Sopenharmony_ci goto err_out; 234562306a36Sopenharmony_ci } 234662306a36Sopenharmony_ci } 234762306a36Sopenharmony_ci ret = true; 234862306a36Sopenharmony_ci err = __insert_free_nid(sbi, i); 234962306a36Sopenharmony_cierr_out: 235062306a36Sopenharmony_ci if (update) { 235162306a36Sopenharmony_ci update_free_nid_bitmap(sbi, nid, ret, build); 235262306a36Sopenharmony_ci if (!build) 235362306a36Sopenharmony_ci nm_i->available_nids++; 235462306a36Sopenharmony_ci } 235562306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 235662306a36Sopenharmony_ci radix_tree_preload_end(); 235762306a36Sopenharmony_ci 235862306a36Sopenharmony_ci if (err) 235962306a36Sopenharmony_ci kmem_cache_free(free_nid_slab, i); 236062306a36Sopenharmony_ci return ret; 236162306a36Sopenharmony_ci} 236262306a36Sopenharmony_ci 236362306a36Sopenharmony_cistatic void remove_free_nid(struct f2fs_sb_info *sbi, nid_t nid) 236462306a36Sopenharmony_ci{ 236562306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 236662306a36Sopenharmony_ci struct free_nid *i; 236762306a36Sopenharmony_ci bool need_free = false; 236862306a36Sopenharmony_ci 236962306a36Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 237062306a36Sopenharmony_ci i = __lookup_free_nid_list(nm_i, nid); 237162306a36Sopenharmony_ci if (i && i->state == FREE_NID) { 237262306a36Sopenharmony_ci __remove_free_nid(sbi, i, FREE_NID); 237362306a36Sopenharmony_ci need_free = true; 237462306a36Sopenharmony_ci } 237562306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_ci if (need_free) 237862306a36Sopenharmony_ci kmem_cache_free(free_nid_slab, i); 237962306a36Sopenharmony_ci} 238062306a36Sopenharmony_ci 238162306a36Sopenharmony_cistatic int scan_nat_page(struct f2fs_sb_info *sbi, 238262306a36Sopenharmony_ci struct page *nat_page, nid_t start_nid) 238362306a36Sopenharmony_ci{ 238462306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 238562306a36Sopenharmony_ci struct f2fs_nat_block *nat_blk = page_address(nat_page); 238662306a36Sopenharmony_ci block_t blk_addr; 238762306a36Sopenharmony_ci unsigned int nat_ofs = NAT_BLOCK_OFFSET(start_nid); 238862306a36Sopenharmony_ci int i; 238962306a36Sopenharmony_ci 239062306a36Sopenharmony_ci __set_bit_le(nat_ofs, nm_i->nat_block_bitmap); 239162306a36Sopenharmony_ci 239262306a36Sopenharmony_ci i = start_nid % NAT_ENTRY_PER_BLOCK; 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_ci for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) { 239562306a36Sopenharmony_ci if (unlikely(start_nid >= nm_i->max_nid)) 239662306a36Sopenharmony_ci break; 239762306a36Sopenharmony_ci 239862306a36Sopenharmony_ci blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr); 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_ci if (blk_addr == NEW_ADDR) 240162306a36Sopenharmony_ci return -EFSCORRUPTED; 240262306a36Sopenharmony_ci 240362306a36Sopenharmony_ci if (blk_addr == NULL_ADDR) { 240462306a36Sopenharmony_ci add_free_nid(sbi, start_nid, true, true); 240562306a36Sopenharmony_ci } else { 240662306a36Sopenharmony_ci spin_lock(&NM_I(sbi)->nid_list_lock); 240762306a36Sopenharmony_ci update_free_nid_bitmap(sbi, start_nid, false, true); 240862306a36Sopenharmony_ci spin_unlock(&NM_I(sbi)->nid_list_lock); 240962306a36Sopenharmony_ci } 241062306a36Sopenharmony_ci } 241162306a36Sopenharmony_ci 241262306a36Sopenharmony_ci return 0; 241362306a36Sopenharmony_ci} 241462306a36Sopenharmony_ci 241562306a36Sopenharmony_cistatic void scan_curseg_cache(struct f2fs_sb_info *sbi) 241662306a36Sopenharmony_ci{ 241762306a36Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 241862306a36Sopenharmony_ci struct f2fs_journal *journal = curseg->journal; 241962306a36Sopenharmony_ci int i; 242062306a36Sopenharmony_ci 242162306a36Sopenharmony_ci down_read(&curseg->journal_rwsem); 242262306a36Sopenharmony_ci for (i = 0; i < nats_in_cursum(journal); i++) { 242362306a36Sopenharmony_ci block_t addr; 242462306a36Sopenharmony_ci nid_t nid; 242562306a36Sopenharmony_ci 242662306a36Sopenharmony_ci addr = le32_to_cpu(nat_in_journal(journal, i).block_addr); 242762306a36Sopenharmony_ci nid = le32_to_cpu(nid_in_journal(journal, i)); 242862306a36Sopenharmony_ci if (addr == NULL_ADDR) 242962306a36Sopenharmony_ci add_free_nid(sbi, nid, true, false); 243062306a36Sopenharmony_ci else 243162306a36Sopenharmony_ci remove_free_nid(sbi, nid); 243262306a36Sopenharmony_ci } 243362306a36Sopenharmony_ci up_read(&curseg->journal_rwsem); 243462306a36Sopenharmony_ci} 243562306a36Sopenharmony_ci 243662306a36Sopenharmony_cistatic void scan_free_nid_bits(struct f2fs_sb_info *sbi) 243762306a36Sopenharmony_ci{ 243862306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 243962306a36Sopenharmony_ci unsigned int i, idx; 244062306a36Sopenharmony_ci nid_t nid; 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci f2fs_down_read(&nm_i->nat_tree_lock); 244362306a36Sopenharmony_ci 244462306a36Sopenharmony_ci for (i = 0; i < nm_i->nat_blocks; i++) { 244562306a36Sopenharmony_ci if (!test_bit_le(i, nm_i->nat_block_bitmap)) 244662306a36Sopenharmony_ci continue; 244762306a36Sopenharmony_ci if (!nm_i->free_nid_count[i]) 244862306a36Sopenharmony_ci continue; 244962306a36Sopenharmony_ci for (idx = 0; idx < NAT_ENTRY_PER_BLOCK; idx++) { 245062306a36Sopenharmony_ci idx = find_next_bit_le(nm_i->free_nid_bitmap[i], 245162306a36Sopenharmony_ci NAT_ENTRY_PER_BLOCK, idx); 245262306a36Sopenharmony_ci if (idx >= NAT_ENTRY_PER_BLOCK) 245362306a36Sopenharmony_ci break; 245462306a36Sopenharmony_ci 245562306a36Sopenharmony_ci nid = i * NAT_ENTRY_PER_BLOCK + idx; 245662306a36Sopenharmony_ci add_free_nid(sbi, nid, true, false); 245762306a36Sopenharmony_ci 245862306a36Sopenharmony_ci if (nm_i->nid_cnt[FREE_NID] >= MAX_FREE_NIDS) 245962306a36Sopenharmony_ci goto out; 246062306a36Sopenharmony_ci } 246162306a36Sopenharmony_ci } 246262306a36Sopenharmony_ciout: 246362306a36Sopenharmony_ci scan_curseg_cache(sbi); 246462306a36Sopenharmony_ci 246562306a36Sopenharmony_ci f2fs_up_read(&nm_i->nat_tree_lock); 246662306a36Sopenharmony_ci} 246762306a36Sopenharmony_ci 246862306a36Sopenharmony_cistatic int __f2fs_build_free_nids(struct f2fs_sb_info *sbi, 246962306a36Sopenharmony_ci bool sync, bool mount) 247062306a36Sopenharmony_ci{ 247162306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 247262306a36Sopenharmony_ci int i = 0, ret; 247362306a36Sopenharmony_ci nid_t nid = nm_i->next_scan_nid; 247462306a36Sopenharmony_ci 247562306a36Sopenharmony_ci if (unlikely(nid >= nm_i->max_nid)) 247662306a36Sopenharmony_ci nid = 0; 247762306a36Sopenharmony_ci 247862306a36Sopenharmony_ci if (unlikely(nid % NAT_ENTRY_PER_BLOCK)) 247962306a36Sopenharmony_ci nid = NAT_BLOCK_OFFSET(nid) * NAT_ENTRY_PER_BLOCK; 248062306a36Sopenharmony_ci 248162306a36Sopenharmony_ci /* Enough entries */ 248262306a36Sopenharmony_ci if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK) 248362306a36Sopenharmony_ci return 0; 248462306a36Sopenharmony_ci 248562306a36Sopenharmony_ci if (!sync && !f2fs_available_free_memory(sbi, FREE_NIDS)) 248662306a36Sopenharmony_ci return 0; 248762306a36Sopenharmony_ci 248862306a36Sopenharmony_ci if (!mount) { 248962306a36Sopenharmony_ci /* try to find free nids in free_nid_bitmap */ 249062306a36Sopenharmony_ci scan_free_nid_bits(sbi); 249162306a36Sopenharmony_ci 249262306a36Sopenharmony_ci if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK) 249362306a36Sopenharmony_ci return 0; 249462306a36Sopenharmony_ci } 249562306a36Sopenharmony_ci 249662306a36Sopenharmony_ci /* readahead nat pages to be scanned */ 249762306a36Sopenharmony_ci f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES, 249862306a36Sopenharmony_ci META_NAT, true); 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ci f2fs_down_read(&nm_i->nat_tree_lock); 250162306a36Sopenharmony_ci 250262306a36Sopenharmony_ci while (1) { 250362306a36Sopenharmony_ci if (!test_bit_le(NAT_BLOCK_OFFSET(nid), 250462306a36Sopenharmony_ci nm_i->nat_block_bitmap)) { 250562306a36Sopenharmony_ci struct page *page = get_current_nat_page(sbi, nid); 250662306a36Sopenharmony_ci 250762306a36Sopenharmony_ci if (IS_ERR(page)) { 250862306a36Sopenharmony_ci ret = PTR_ERR(page); 250962306a36Sopenharmony_ci } else { 251062306a36Sopenharmony_ci ret = scan_nat_page(sbi, page, nid); 251162306a36Sopenharmony_ci f2fs_put_page(page, 1); 251262306a36Sopenharmony_ci } 251362306a36Sopenharmony_ci 251462306a36Sopenharmony_ci if (ret) { 251562306a36Sopenharmony_ci f2fs_up_read(&nm_i->nat_tree_lock); 251662306a36Sopenharmony_ci 251762306a36Sopenharmony_ci if (ret == -EFSCORRUPTED) { 251862306a36Sopenharmony_ci f2fs_err(sbi, "NAT is corrupt, run fsck to fix it"); 251962306a36Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 252062306a36Sopenharmony_ci f2fs_handle_error(sbi, 252162306a36Sopenharmony_ci ERROR_INCONSISTENT_NAT); 252262306a36Sopenharmony_ci } 252362306a36Sopenharmony_ci 252462306a36Sopenharmony_ci return ret; 252562306a36Sopenharmony_ci } 252662306a36Sopenharmony_ci } 252762306a36Sopenharmony_ci 252862306a36Sopenharmony_ci nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK)); 252962306a36Sopenharmony_ci if (unlikely(nid >= nm_i->max_nid)) 253062306a36Sopenharmony_ci nid = 0; 253162306a36Sopenharmony_ci 253262306a36Sopenharmony_ci if (++i >= FREE_NID_PAGES) 253362306a36Sopenharmony_ci break; 253462306a36Sopenharmony_ci } 253562306a36Sopenharmony_ci 253662306a36Sopenharmony_ci /* go to the next free nat pages to find free nids abundantly */ 253762306a36Sopenharmony_ci nm_i->next_scan_nid = nid; 253862306a36Sopenharmony_ci 253962306a36Sopenharmony_ci /* find free nids from current sum_pages */ 254062306a36Sopenharmony_ci scan_curseg_cache(sbi); 254162306a36Sopenharmony_ci 254262306a36Sopenharmony_ci f2fs_up_read(&nm_i->nat_tree_lock); 254362306a36Sopenharmony_ci 254462306a36Sopenharmony_ci f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid), 254562306a36Sopenharmony_ci nm_i->ra_nid_pages, META_NAT, false); 254662306a36Sopenharmony_ci 254762306a36Sopenharmony_ci return 0; 254862306a36Sopenharmony_ci} 254962306a36Sopenharmony_ci 255062306a36Sopenharmony_ciint f2fs_build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount) 255162306a36Sopenharmony_ci{ 255262306a36Sopenharmony_ci int ret; 255362306a36Sopenharmony_ci 255462306a36Sopenharmony_ci mutex_lock(&NM_I(sbi)->build_lock); 255562306a36Sopenharmony_ci ret = __f2fs_build_free_nids(sbi, sync, mount); 255662306a36Sopenharmony_ci mutex_unlock(&NM_I(sbi)->build_lock); 255762306a36Sopenharmony_ci 255862306a36Sopenharmony_ci return ret; 255962306a36Sopenharmony_ci} 256062306a36Sopenharmony_ci 256162306a36Sopenharmony_ci/* 256262306a36Sopenharmony_ci * If this function returns success, caller can obtain a new nid 256362306a36Sopenharmony_ci * from second parameter of this function. 256462306a36Sopenharmony_ci * The returned nid could be used ino as well as nid when inode is created. 256562306a36Sopenharmony_ci */ 256662306a36Sopenharmony_cibool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) 256762306a36Sopenharmony_ci{ 256862306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 256962306a36Sopenharmony_ci struct free_nid *i = NULL; 257062306a36Sopenharmony_ciretry: 257162306a36Sopenharmony_ci if (time_to_inject(sbi, FAULT_ALLOC_NID)) 257262306a36Sopenharmony_ci return false; 257362306a36Sopenharmony_ci 257462306a36Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 257562306a36Sopenharmony_ci 257662306a36Sopenharmony_ci if (unlikely(nm_i->available_nids == 0)) { 257762306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 257862306a36Sopenharmony_ci return false; 257962306a36Sopenharmony_ci } 258062306a36Sopenharmony_ci 258162306a36Sopenharmony_ci /* We should not use stale free nids created by f2fs_build_free_nids */ 258262306a36Sopenharmony_ci if (nm_i->nid_cnt[FREE_NID] && !on_f2fs_build_free_nids(nm_i)) { 258362306a36Sopenharmony_ci f2fs_bug_on(sbi, list_empty(&nm_i->free_nid_list)); 258462306a36Sopenharmony_ci i = list_first_entry(&nm_i->free_nid_list, 258562306a36Sopenharmony_ci struct free_nid, list); 258662306a36Sopenharmony_ci *nid = i->nid; 258762306a36Sopenharmony_ci 258862306a36Sopenharmony_ci __move_free_nid(sbi, i, FREE_NID, PREALLOC_NID); 258962306a36Sopenharmony_ci nm_i->available_nids--; 259062306a36Sopenharmony_ci 259162306a36Sopenharmony_ci update_free_nid_bitmap(sbi, *nid, false, false); 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 259462306a36Sopenharmony_ci return true; 259562306a36Sopenharmony_ci } 259662306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 259762306a36Sopenharmony_ci 259862306a36Sopenharmony_ci /* Let's scan nat pages and its caches to get free nids */ 259962306a36Sopenharmony_ci if (!f2fs_build_free_nids(sbi, true, false)) 260062306a36Sopenharmony_ci goto retry; 260162306a36Sopenharmony_ci return false; 260262306a36Sopenharmony_ci} 260362306a36Sopenharmony_ci 260462306a36Sopenharmony_ci/* 260562306a36Sopenharmony_ci * f2fs_alloc_nid() should be called prior to this function. 260662306a36Sopenharmony_ci */ 260762306a36Sopenharmony_civoid f2fs_alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid) 260862306a36Sopenharmony_ci{ 260962306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 261062306a36Sopenharmony_ci struct free_nid *i; 261162306a36Sopenharmony_ci 261262306a36Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 261362306a36Sopenharmony_ci i = __lookup_free_nid_list(nm_i, nid); 261462306a36Sopenharmony_ci f2fs_bug_on(sbi, !i); 261562306a36Sopenharmony_ci __remove_free_nid(sbi, i, PREALLOC_NID); 261662306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 261762306a36Sopenharmony_ci 261862306a36Sopenharmony_ci kmem_cache_free(free_nid_slab, i); 261962306a36Sopenharmony_ci} 262062306a36Sopenharmony_ci 262162306a36Sopenharmony_ci/* 262262306a36Sopenharmony_ci * f2fs_alloc_nid() should be called prior to this function. 262362306a36Sopenharmony_ci */ 262462306a36Sopenharmony_civoid f2fs_alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid) 262562306a36Sopenharmony_ci{ 262662306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 262762306a36Sopenharmony_ci struct free_nid *i; 262862306a36Sopenharmony_ci bool need_free = false; 262962306a36Sopenharmony_ci 263062306a36Sopenharmony_ci if (!nid) 263162306a36Sopenharmony_ci return; 263262306a36Sopenharmony_ci 263362306a36Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 263462306a36Sopenharmony_ci i = __lookup_free_nid_list(nm_i, nid); 263562306a36Sopenharmony_ci f2fs_bug_on(sbi, !i); 263662306a36Sopenharmony_ci 263762306a36Sopenharmony_ci if (!f2fs_available_free_memory(sbi, FREE_NIDS)) { 263862306a36Sopenharmony_ci __remove_free_nid(sbi, i, PREALLOC_NID); 263962306a36Sopenharmony_ci need_free = true; 264062306a36Sopenharmony_ci } else { 264162306a36Sopenharmony_ci __move_free_nid(sbi, i, PREALLOC_NID, FREE_NID); 264262306a36Sopenharmony_ci } 264362306a36Sopenharmony_ci 264462306a36Sopenharmony_ci nm_i->available_nids++; 264562306a36Sopenharmony_ci 264662306a36Sopenharmony_ci update_free_nid_bitmap(sbi, nid, true, false); 264762306a36Sopenharmony_ci 264862306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 264962306a36Sopenharmony_ci 265062306a36Sopenharmony_ci if (need_free) 265162306a36Sopenharmony_ci kmem_cache_free(free_nid_slab, i); 265262306a36Sopenharmony_ci} 265362306a36Sopenharmony_ci 265462306a36Sopenharmony_ciint f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink) 265562306a36Sopenharmony_ci{ 265662306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 265762306a36Sopenharmony_ci int nr = nr_shrink; 265862306a36Sopenharmony_ci 265962306a36Sopenharmony_ci if (nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS) 266062306a36Sopenharmony_ci return 0; 266162306a36Sopenharmony_ci 266262306a36Sopenharmony_ci if (!mutex_trylock(&nm_i->build_lock)) 266362306a36Sopenharmony_ci return 0; 266462306a36Sopenharmony_ci 266562306a36Sopenharmony_ci while (nr_shrink && nm_i->nid_cnt[FREE_NID] > MAX_FREE_NIDS) { 266662306a36Sopenharmony_ci struct free_nid *i, *next; 266762306a36Sopenharmony_ci unsigned int batch = SHRINK_NID_BATCH_SIZE; 266862306a36Sopenharmony_ci 266962306a36Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 267062306a36Sopenharmony_ci list_for_each_entry_safe(i, next, &nm_i->free_nid_list, list) { 267162306a36Sopenharmony_ci if (!nr_shrink || !batch || 267262306a36Sopenharmony_ci nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS) 267362306a36Sopenharmony_ci break; 267462306a36Sopenharmony_ci __remove_free_nid(sbi, i, FREE_NID); 267562306a36Sopenharmony_ci kmem_cache_free(free_nid_slab, i); 267662306a36Sopenharmony_ci nr_shrink--; 267762306a36Sopenharmony_ci batch--; 267862306a36Sopenharmony_ci } 267962306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 268062306a36Sopenharmony_ci } 268162306a36Sopenharmony_ci 268262306a36Sopenharmony_ci mutex_unlock(&nm_i->build_lock); 268362306a36Sopenharmony_ci 268462306a36Sopenharmony_ci return nr - nr_shrink; 268562306a36Sopenharmony_ci} 268662306a36Sopenharmony_ci 268762306a36Sopenharmony_ciint f2fs_recover_inline_xattr(struct inode *inode, struct page *page) 268862306a36Sopenharmony_ci{ 268962306a36Sopenharmony_ci void *src_addr, *dst_addr; 269062306a36Sopenharmony_ci size_t inline_size; 269162306a36Sopenharmony_ci struct page *ipage; 269262306a36Sopenharmony_ci struct f2fs_inode *ri; 269362306a36Sopenharmony_ci 269462306a36Sopenharmony_ci ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino); 269562306a36Sopenharmony_ci if (IS_ERR(ipage)) 269662306a36Sopenharmony_ci return PTR_ERR(ipage); 269762306a36Sopenharmony_ci 269862306a36Sopenharmony_ci ri = F2FS_INODE(page); 269962306a36Sopenharmony_ci if (ri->i_inline & F2FS_INLINE_XATTR) { 270062306a36Sopenharmony_ci if (!f2fs_has_inline_xattr(inode)) { 270162306a36Sopenharmony_ci set_inode_flag(inode, FI_INLINE_XATTR); 270262306a36Sopenharmony_ci stat_inc_inline_xattr(inode); 270362306a36Sopenharmony_ci } 270462306a36Sopenharmony_ci } else { 270562306a36Sopenharmony_ci if (f2fs_has_inline_xattr(inode)) { 270662306a36Sopenharmony_ci stat_dec_inline_xattr(inode); 270762306a36Sopenharmony_ci clear_inode_flag(inode, FI_INLINE_XATTR); 270862306a36Sopenharmony_ci } 270962306a36Sopenharmony_ci goto update_inode; 271062306a36Sopenharmony_ci } 271162306a36Sopenharmony_ci 271262306a36Sopenharmony_ci dst_addr = inline_xattr_addr(inode, ipage); 271362306a36Sopenharmony_ci src_addr = inline_xattr_addr(inode, page); 271462306a36Sopenharmony_ci inline_size = inline_xattr_size(inode); 271562306a36Sopenharmony_ci 271662306a36Sopenharmony_ci f2fs_wait_on_page_writeback(ipage, NODE, true, true); 271762306a36Sopenharmony_ci memcpy(dst_addr, src_addr, inline_size); 271862306a36Sopenharmony_ciupdate_inode: 271962306a36Sopenharmony_ci f2fs_update_inode(inode, ipage); 272062306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 272162306a36Sopenharmony_ci return 0; 272262306a36Sopenharmony_ci} 272362306a36Sopenharmony_ci 272462306a36Sopenharmony_ciint f2fs_recover_xattr_data(struct inode *inode, struct page *page) 272562306a36Sopenharmony_ci{ 272662306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 272762306a36Sopenharmony_ci nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid; 272862306a36Sopenharmony_ci nid_t new_xnid; 272962306a36Sopenharmony_ci struct dnode_of_data dn; 273062306a36Sopenharmony_ci struct node_info ni; 273162306a36Sopenharmony_ci struct page *xpage; 273262306a36Sopenharmony_ci int err; 273362306a36Sopenharmony_ci 273462306a36Sopenharmony_ci if (!prev_xnid) 273562306a36Sopenharmony_ci goto recover_xnid; 273662306a36Sopenharmony_ci 273762306a36Sopenharmony_ci /* 1: invalidate the previous xattr nid */ 273862306a36Sopenharmony_ci err = f2fs_get_node_info(sbi, prev_xnid, &ni, false); 273962306a36Sopenharmony_ci if (err) 274062306a36Sopenharmony_ci return err; 274162306a36Sopenharmony_ci 274262306a36Sopenharmony_ci f2fs_invalidate_blocks(sbi, ni.blk_addr); 274362306a36Sopenharmony_ci dec_valid_node_count(sbi, inode, false); 274462306a36Sopenharmony_ci set_node_addr(sbi, &ni, NULL_ADDR, false); 274562306a36Sopenharmony_ci 274662306a36Sopenharmony_cirecover_xnid: 274762306a36Sopenharmony_ci /* 2: update xattr nid in inode */ 274862306a36Sopenharmony_ci if (!f2fs_alloc_nid(sbi, &new_xnid)) 274962306a36Sopenharmony_ci return -ENOSPC; 275062306a36Sopenharmony_ci 275162306a36Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, new_xnid); 275262306a36Sopenharmony_ci xpage = f2fs_new_node_page(&dn, XATTR_NODE_OFFSET); 275362306a36Sopenharmony_ci if (IS_ERR(xpage)) { 275462306a36Sopenharmony_ci f2fs_alloc_nid_failed(sbi, new_xnid); 275562306a36Sopenharmony_ci return PTR_ERR(xpage); 275662306a36Sopenharmony_ci } 275762306a36Sopenharmony_ci 275862306a36Sopenharmony_ci f2fs_alloc_nid_done(sbi, new_xnid); 275962306a36Sopenharmony_ci f2fs_update_inode_page(inode); 276062306a36Sopenharmony_ci 276162306a36Sopenharmony_ci /* 3: update and set xattr node page dirty */ 276262306a36Sopenharmony_ci if (page) { 276362306a36Sopenharmony_ci memcpy(F2FS_NODE(xpage), F2FS_NODE(page), 276462306a36Sopenharmony_ci VALID_XATTR_BLOCK_SIZE); 276562306a36Sopenharmony_ci set_page_dirty(xpage); 276662306a36Sopenharmony_ci } 276762306a36Sopenharmony_ci f2fs_put_page(xpage, 1); 276862306a36Sopenharmony_ci 276962306a36Sopenharmony_ci return 0; 277062306a36Sopenharmony_ci} 277162306a36Sopenharmony_ci 277262306a36Sopenharmony_ciint f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) 277362306a36Sopenharmony_ci{ 277462306a36Sopenharmony_ci struct f2fs_inode *src, *dst; 277562306a36Sopenharmony_ci nid_t ino = ino_of_node(page); 277662306a36Sopenharmony_ci struct node_info old_ni, new_ni; 277762306a36Sopenharmony_ci struct page *ipage; 277862306a36Sopenharmony_ci int err; 277962306a36Sopenharmony_ci 278062306a36Sopenharmony_ci err = f2fs_get_node_info(sbi, ino, &old_ni, false); 278162306a36Sopenharmony_ci if (err) 278262306a36Sopenharmony_ci return err; 278362306a36Sopenharmony_ci 278462306a36Sopenharmony_ci if (unlikely(old_ni.blk_addr != NULL_ADDR)) 278562306a36Sopenharmony_ci return -EINVAL; 278662306a36Sopenharmony_ciretry: 278762306a36Sopenharmony_ci ipage = f2fs_grab_cache_page(NODE_MAPPING(sbi), ino, false); 278862306a36Sopenharmony_ci if (!ipage) { 278962306a36Sopenharmony_ci memalloc_retry_wait(GFP_NOFS); 279062306a36Sopenharmony_ci goto retry; 279162306a36Sopenharmony_ci } 279262306a36Sopenharmony_ci 279362306a36Sopenharmony_ci /* Should not use this inode from free nid list */ 279462306a36Sopenharmony_ci remove_free_nid(sbi, ino); 279562306a36Sopenharmony_ci 279662306a36Sopenharmony_ci if (!PageUptodate(ipage)) 279762306a36Sopenharmony_ci SetPageUptodate(ipage); 279862306a36Sopenharmony_ci fill_node_footer(ipage, ino, ino, 0, true); 279962306a36Sopenharmony_ci set_cold_node(ipage, false); 280062306a36Sopenharmony_ci 280162306a36Sopenharmony_ci src = F2FS_INODE(page); 280262306a36Sopenharmony_ci dst = F2FS_INODE(ipage); 280362306a36Sopenharmony_ci 280462306a36Sopenharmony_ci memcpy(dst, src, offsetof(struct f2fs_inode, i_ext)); 280562306a36Sopenharmony_ci dst->i_size = 0; 280662306a36Sopenharmony_ci dst->i_blocks = cpu_to_le64(1); 280762306a36Sopenharmony_ci dst->i_links = cpu_to_le32(1); 280862306a36Sopenharmony_ci dst->i_xattr_nid = 0; 280962306a36Sopenharmony_ci dst->i_inline = src->i_inline & (F2FS_INLINE_XATTR | F2FS_EXTRA_ATTR); 281062306a36Sopenharmony_ci if (dst->i_inline & F2FS_EXTRA_ATTR) { 281162306a36Sopenharmony_ci dst->i_extra_isize = src->i_extra_isize; 281262306a36Sopenharmony_ci 281362306a36Sopenharmony_ci if (f2fs_sb_has_flexible_inline_xattr(sbi) && 281462306a36Sopenharmony_ci F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize), 281562306a36Sopenharmony_ci i_inline_xattr_size)) 281662306a36Sopenharmony_ci dst->i_inline_xattr_size = src->i_inline_xattr_size; 281762306a36Sopenharmony_ci 281862306a36Sopenharmony_ci if (f2fs_sb_has_project_quota(sbi) && 281962306a36Sopenharmony_ci F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize), 282062306a36Sopenharmony_ci i_projid)) 282162306a36Sopenharmony_ci dst->i_projid = src->i_projid; 282262306a36Sopenharmony_ci 282362306a36Sopenharmony_ci if (f2fs_sb_has_inode_crtime(sbi) && 282462306a36Sopenharmony_ci F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize), 282562306a36Sopenharmony_ci i_crtime_nsec)) { 282662306a36Sopenharmony_ci dst->i_crtime = src->i_crtime; 282762306a36Sopenharmony_ci dst->i_crtime_nsec = src->i_crtime_nsec; 282862306a36Sopenharmony_ci } 282962306a36Sopenharmony_ci } 283062306a36Sopenharmony_ci 283162306a36Sopenharmony_ci new_ni = old_ni; 283262306a36Sopenharmony_ci new_ni.ino = ino; 283362306a36Sopenharmony_ci 283462306a36Sopenharmony_ci if (unlikely(inc_valid_node_count(sbi, NULL, true))) 283562306a36Sopenharmony_ci WARN_ON(1); 283662306a36Sopenharmony_ci set_node_addr(sbi, &new_ni, NEW_ADDR, false); 283762306a36Sopenharmony_ci inc_valid_inode_count(sbi); 283862306a36Sopenharmony_ci set_page_dirty(ipage); 283962306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 284062306a36Sopenharmony_ci return 0; 284162306a36Sopenharmony_ci} 284262306a36Sopenharmony_ci 284362306a36Sopenharmony_ciint f2fs_restore_node_summary(struct f2fs_sb_info *sbi, 284462306a36Sopenharmony_ci unsigned int segno, struct f2fs_summary_block *sum) 284562306a36Sopenharmony_ci{ 284662306a36Sopenharmony_ci struct f2fs_node *rn; 284762306a36Sopenharmony_ci struct f2fs_summary *sum_entry; 284862306a36Sopenharmony_ci block_t addr; 284962306a36Sopenharmony_ci int i, idx, last_offset, nrpages; 285062306a36Sopenharmony_ci 285162306a36Sopenharmony_ci /* scan the node segment */ 285262306a36Sopenharmony_ci last_offset = sbi->blocks_per_seg; 285362306a36Sopenharmony_ci addr = START_BLOCK(sbi, segno); 285462306a36Sopenharmony_ci sum_entry = &sum->entries[0]; 285562306a36Sopenharmony_ci 285662306a36Sopenharmony_ci for (i = 0; i < last_offset; i += nrpages, addr += nrpages) { 285762306a36Sopenharmony_ci nrpages = bio_max_segs(last_offset - i); 285862306a36Sopenharmony_ci 285962306a36Sopenharmony_ci /* readahead node pages */ 286062306a36Sopenharmony_ci f2fs_ra_meta_pages(sbi, addr, nrpages, META_POR, true); 286162306a36Sopenharmony_ci 286262306a36Sopenharmony_ci for (idx = addr; idx < addr + nrpages; idx++) { 286362306a36Sopenharmony_ci struct page *page = f2fs_get_tmp_page(sbi, idx); 286462306a36Sopenharmony_ci 286562306a36Sopenharmony_ci if (IS_ERR(page)) 286662306a36Sopenharmony_ci return PTR_ERR(page); 286762306a36Sopenharmony_ci 286862306a36Sopenharmony_ci rn = F2FS_NODE(page); 286962306a36Sopenharmony_ci sum_entry->nid = rn->footer.nid; 287062306a36Sopenharmony_ci sum_entry->version = 0; 287162306a36Sopenharmony_ci sum_entry->ofs_in_node = 0; 287262306a36Sopenharmony_ci sum_entry++; 287362306a36Sopenharmony_ci f2fs_put_page(page, 1); 287462306a36Sopenharmony_ci } 287562306a36Sopenharmony_ci 287662306a36Sopenharmony_ci invalidate_mapping_pages(META_MAPPING(sbi), addr, 287762306a36Sopenharmony_ci addr + nrpages); 287862306a36Sopenharmony_ci } 287962306a36Sopenharmony_ci return 0; 288062306a36Sopenharmony_ci} 288162306a36Sopenharmony_ci 288262306a36Sopenharmony_cistatic void remove_nats_in_journal(struct f2fs_sb_info *sbi) 288362306a36Sopenharmony_ci{ 288462306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 288562306a36Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 288662306a36Sopenharmony_ci struct f2fs_journal *journal = curseg->journal; 288762306a36Sopenharmony_ci int i; 288862306a36Sopenharmony_ci 288962306a36Sopenharmony_ci down_write(&curseg->journal_rwsem); 289062306a36Sopenharmony_ci for (i = 0; i < nats_in_cursum(journal); i++) { 289162306a36Sopenharmony_ci struct nat_entry *ne; 289262306a36Sopenharmony_ci struct f2fs_nat_entry raw_ne; 289362306a36Sopenharmony_ci nid_t nid = le32_to_cpu(nid_in_journal(journal, i)); 289462306a36Sopenharmony_ci 289562306a36Sopenharmony_ci if (f2fs_check_nid_range(sbi, nid)) 289662306a36Sopenharmony_ci continue; 289762306a36Sopenharmony_ci 289862306a36Sopenharmony_ci raw_ne = nat_in_journal(journal, i); 289962306a36Sopenharmony_ci 290062306a36Sopenharmony_ci ne = __lookup_nat_cache(nm_i, nid); 290162306a36Sopenharmony_ci if (!ne) { 290262306a36Sopenharmony_ci ne = __alloc_nat_entry(sbi, nid, true); 290362306a36Sopenharmony_ci __init_nat_entry(nm_i, ne, &raw_ne, true); 290462306a36Sopenharmony_ci } 290562306a36Sopenharmony_ci 290662306a36Sopenharmony_ci /* 290762306a36Sopenharmony_ci * if a free nat in journal has not been used after last 290862306a36Sopenharmony_ci * checkpoint, we should remove it from available nids, 290962306a36Sopenharmony_ci * since later we will add it again. 291062306a36Sopenharmony_ci */ 291162306a36Sopenharmony_ci if (!get_nat_flag(ne, IS_DIRTY) && 291262306a36Sopenharmony_ci le32_to_cpu(raw_ne.block_addr) == NULL_ADDR) { 291362306a36Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 291462306a36Sopenharmony_ci nm_i->available_nids--; 291562306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 291662306a36Sopenharmony_ci } 291762306a36Sopenharmony_ci 291862306a36Sopenharmony_ci __set_nat_cache_dirty(nm_i, ne); 291962306a36Sopenharmony_ci } 292062306a36Sopenharmony_ci update_nats_in_cursum(journal, -i); 292162306a36Sopenharmony_ci up_write(&curseg->journal_rwsem); 292262306a36Sopenharmony_ci} 292362306a36Sopenharmony_ci 292462306a36Sopenharmony_cistatic void __adjust_nat_entry_set(struct nat_entry_set *nes, 292562306a36Sopenharmony_ci struct list_head *head, int max) 292662306a36Sopenharmony_ci{ 292762306a36Sopenharmony_ci struct nat_entry_set *cur; 292862306a36Sopenharmony_ci 292962306a36Sopenharmony_ci if (nes->entry_cnt >= max) 293062306a36Sopenharmony_ci goto add_out; 293162306a36Sopenharmony_ci 293262306a36Sopenharmony_ci list_for_each_entry(cur, head, set_list) { 293362306a36Sopenharmony_ci if (cur->entry_cnt >= nes->entry_cnt) { 293462306a36Sopenharmony_ci list_add(&nes->set_list, cur->set_list.prev); 293562306a36Sopenharmony_ci return; 293662306a36Sopenharmony_ci } 293762306a36Sopenharmony_ci } 293862306a36Sopenharmony_ciadd_out: 293962306a36Sopenharmony_ci list_add_tail(&nes->set_list, head); 294062306a36Sopenharmony_ci} 294162306a36Sopenharmony_ci 294262306a36Sopenharmony_cistatic void __update_nat_bits(struct f2fs_nm_info *nm_i, unsigned int nat_ofs, 294362306a36Sopenharmony_ci unsigned int valid) 294462306a36Sopenharmony_ci{ 294562306a36Sopenharmony_ci if (valid == 0) { 294662306a36Sopenharmony_ci __set_bit_le(nat_ofs, nm_i->empty_nat_bits); 294762306a36Sopenharmony_ci __clear_bit_le(nat_ofs, nm_i->full_nat_bits); 294862306a36Sopenharmony_ci return; 294962306a36Sopenharmony_ci } 295062306a36Sopenharmony_ci 295162306a36Sopenharmony_ci __clear_bit_le(nat_ofs, nm_i->empty_nat_bits); 295262306a36Sopenharmony_ci if (valid == NAT_ENTRY_PER_BLOCK) 295362306a36Sopenharmony_ci __set_bit_le(nat_ofs, nm_i->full_nat_bits); 295462306a36Sopenharmony_ci else 295562306a36Sopenharmony_ci __clear_bit_le(nat_ofs, nm_i->full_nat_bits); 295662306a36Sopenharmony_ci} 295762306a36Sopenharmony_ci 295862306a36Sopenharmony_cistatic void update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, 295962306a36Sopenharmony_ci struct page *page) 296062306a36Sopenharmony_ci{ 296162306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 296262306a36Sopenharmony_ci unsigned int nat_index = start_nid / NAT_ENTRY_PER_BLOCK; 296362306a36Sopenharmony_ci struct f2fs_nat_block *nat_blk = page_address(page); 296462306a36Sopenharmony_ci int valid = 0; 296562306a36Sopenharmony_ci int i = 0; 296662306a36Sopenharmony_ci 296762306a36Sopenharmony_ci if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG)) 296862306a36Sopenharmony_ci return; 296962306a36Sopenharmony_ci 297062306a36Sopenharmony_ci if (nat_index == 0) { 297162306a36Sopenharmony_ci valid = 1; 297262306a36Sopenharmony_ci i = 1; 297362306a36Sopenharmony_ci } 297462306a36Sopenharmony_ci for (; i < NAT_ENTRY_PER_BLOCK; i++) { 297562306a36Sopenharmony_ci if (le32_to_cpu(nat_blk->entries[i].block_addr) != NULL_ADDR) 297662306a36Sopenharmony_ci valid++; 297762306a36Sopenharmony_ci } 297862306a36Sopenharmony_ci 297962306a36Sopenharmony_ci __update_nat_bits(nm_i, nat_index, valid); 298062306a36Sopenharmony_ci} 298162306a36Sopenharmony_ci 298262306a36Sopenharmony_civoid f2fs_enable_nat_bits(struct f2fs_sb_info *sbi) 298362306a36Sopenharmony_ci{ 298462306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 298562306a36Sopenharmony_ci unsigned int nat_ofs; 298662306a36Sopenharmony_ci 298762306a36Sopenharmony_ci f2fs_down_read(&nm_i->nat_tree_lock); 298862306a36Sopenharmony_ci 298962306a36Sopenharmony_ci for (nat_ofs = 0; nat_ofs < nm_i->nat_blocks; nat_ofs++) { 299062306a36Sopenharmony_ci unsigned int valid = 0, nid_ofs = 0; 299162306a36Sopenharmony_ci 299262306a36Sopenharmony_ci /* handle nid zero due to it should never be used */ 299362306a36Sopenharmony_ci if (unlikely(nat_ofs == 0)) { 299462306a36Sopenharmony_ci valid = 1; 299562306a36Sopenharmony_ci nid_ofs = 1; 299662306a36Sopenharmony_ci } 299762306a36Sopenharmony_ci 299862306a36Sopenharmony_ci for (; nid_ofs < NAT_ENTRY_PER_BLOCK; nid_ofs++) { 299962306a36Sopenharmony_ci if (!test_bit_le(nid_ofs, 300062306a36Sopenharmony_ci nm_i->free_nid_bitmap[nat_ofs])) 300162306a36Sopenharmony_ci valid++; 300262306a36Sopenharmony_ci } 300362306a36Sopenharmony_ci 300462306a36Sopenharmony_ci __update_nat_bits(nm_i, nat_ofs, valid); 300562306a36Sopenharmony_ci } 300662306a36Sopenharmony_ci 300762306a36Sopenharmony_ci f2fs_up_read(&nm_i->nat_tree_lock); 300862306a36Sopenharmony_ci} 300962306a36Sopenharmony_ci 301062306a36Sopenharmony_cistatic int __flush_nat_entry_set(struct f2fs_sb_info *sbi, 301162306a36Sopenharmony_ci struct nat_entry_set *set, struct cp_control *cpc) 301262306a36Sopenharmony_ci{ 301362306a36Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 301462306a36Sopenharmony_ci struct f2fs_journal *journal = curseg->journal; 301562306a36Sopenharmony_ci nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK; 301662306a36Sopenharmony_ci bool to_journal = true; 301762306a36Sopenharmony_ci struct f2fs_nat_block *nat_blk; 301862306a36Sopenharmony_ci struct nat_entry *ne, *cur; 301962306a36Sopenharmony_ci struct page *page = NULL; 302062306a36Sopenharmony_ci 302162306a36Sopenharmony_ci /* 302262306a36Sopenharmony_ci * there are two steps to flush nat entries: 302362306a36Sopenharmony_ci * #1, flush nat entries to journal in current hot data summary block. 302462306a36Sopenharmony_ci * #2, flush nat entries to nat page. 302562306a36Sopenharmony_ci */ 302662306a36Sopenharmony_ci if ((cpc->reason & CP_UMOUNT) || 302762306a36Sopenharmony_ci !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL)) 302862306a36Sopenharmony_ci to_journal = false; 302962306a36Sopenharmony_ci 303062306a36Sopenharmony_ci if (to_journal) { 303162306a36Sopenharmony_ci down_write(&curseg->journal_rwsem); 303262306a36Sopenharmony_ci } else { 303362306a36Sopenharmony_ci page = get_next_nat_page(sbi, start_nid); 303462306a36Sopenharmony_ci if (IS_ERR(page)) 303562306a36Sopenharmony_ci return PTR_ERR(page); 303662306a36Sopenharmony_ci 303762306a36Sopenharmony_ci nat_blk = page_address(page); 303862306a36Sopenharmony_ci f2fs_bug_on(sbi, !nat_blk); 303962306a36Sopenharmony_ci } 304062306a36Sopenharmony_ci 304162306a36Sopenharmony_ci /* flush dirty nats in nat entry set */ 304262306a36Sopenharmony_ci list_for_each_entry_safe(ne, cur, &set->entry_list, list) { 304362306a36Sopenharmony_ci struct f2fs_nat_entry *raw_ne; 304462306a36Sopenharmony_ci nid_t nid = nat_get_nid(ne); 304562306a36Sopenharmony_ci int offset; 304662306a36Sopenharmony_ci 304762306a36Sopenharmony_ci f2fs_bug_on(sbi, nat_get_blkaddr(ne) == NEW_ADDR); 304862306a36Sopenharmony_ci 304962306a36Sopenharmony_ci if (to_journal) { 305062306a36Sopenharmony_ci offset = f2fs_lookup_journal_in_cursum(journal, 305162306a36Sopenharmony_ci NAT_JOURNAL, nid, 1); 305262306a36Sopenharmony_ci f2fs_bug_on(sbi, offset < 0); 305362306a36Sopenharmony_ci raw_ne = &nat_in_journal(journal, offset); 305462306a36Sopenharmony_ci nid_in_journal(journal, offset) = cpu_to_le32(nid); 305562306a36Sopenharmony_ci } else { 305662306a36Sopenharmony_ci raw_ne = &nat_blk->entries[nid - start_nid]; 305762306a36Sopenharmony_ci } 305862306a36Sopenharmony_ci raw_nat_from_node_info(raw_ne, &ne->ni); 305962306a36Sopenharmony_ci nat_reset_flag(ne); 306062306a36Sopenharmony_ci __clear_nat_cache_dirty(NM_I(sbi), set, ne); 306162306a36Sopenharmony_ci if (nat_get_blkaddr(ne) == NULL_ADDR) { 306262306a36Sopenharmony_ci add_free_nid(sbi, nid, false, true); 306362306a36Sopenharmony_ci } else { 306462306a36Sopenharmony_ci spin_lock(&NM_I(sbi)->nid_list_lock); 306562306a36Sopenharmony_ci update_free_nid_bitmap(sbi, nid, false, false); 306662306a36Sopenharmony_ci spin_unlock(&NM_I(sbi)->nid_list_lock); 306762306a36Sopenharmony_ci } 306862306a36Sopenharmony_ci } 306962306a36Sopenharmony_ci 307062306a36Sopenharmony_ci if (to_journal) { 307162306a36Sopenharmony_ci up_write(&curseg->journal_rwsem); 307262306a36Sopenharmony_ci } else { 307362306a36Sopenharmony_ci update_nat_bits(sbi, start_nid, page); 307462306a36Sopenharmony_ci f2fs_put_page(page, 1); 307562306a36Sopenharmony_ci } 307662306a36Sopenharmony_ci 307762306a36Sopenharmony_ci /* Allow dirty nats by node block allocation in write_begin */ 307862306a36Sopenharmony_ci if (!set->entry_cnt) { 307962306a36Sopenharmony_ci radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set); 308062306a36Sopenharmony_ci kmem_cache_free(nat_entry_set_slab, set); 308162306a36Sopenharmony_ci } 308262306a36Sopenharmony_ci return 0; 308362306a36Sopenharmony_ci} 308462306a36Sopenharmony_ci 308562306a36Sopenharmony_ci/* 308662306a36Sopenharmony_ci * This function is called during the checkpointing process. 308762306a36Sopenharmony_ci */ 308862306a36Sopenharmony_ciint f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) 308962306a36Sopenharmony_ci{ 309062306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 309162306a36Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 309262306a36Sopenharmony_ci struct f2fs_journal *journal = curseg->journal; 309362306a36Sopenharmony_ci struct nat_entry_set *setvec[NAT_VEC_SIZE]; 309462306a36Sopenharmony_ci struct nat_entry_set *set, *tmp; 309562306a36Sopenharmony_ci unsigned int found; 309662306a36Sopenharmony_ci nid_t set_idx = 0; 309762306a36Sopenharmony_ci LIST_HEAD(sets); 309862306a36Sopenharmony_ci int err = 0; 309962306a36Sopenharmony_ci 310062306a36Sopenharmony_ci /* 310162306a36Sopenharmony_ci * during unmount, let's flush nat_bits before checking 310262306a36Sopenharmony_ci * nat_cnt[DIRTY_NAT]. 310362306a36Sopenharmony_ci */ 310462306a36Sopenharmony_ci if (cpc->reason & CP_UMOUNT) { 310562306a36Sopenharmony_ci f2fs_down_write(&nm_i->nat_tree_lock); 310662306a36Sopenharmony_ci remove_nats_in_journal(sbi); 310762306a36Sopenharmony_ci f2fs_up_write(&nm_i->nat_tree_lock); 310862306a36Sopenharmony_ci } 310962306a36Sopenharmony_ci 311062306a36Sopenharmony_ci if (!nm_i->nat_cnt[DIRTY_NAT]) 311162306a36Sopenharmony_ci return 0; 311262306a36Sopenharmony_ci 311362306a36Sopenharmony_ci f2fs_down_write(&nm_i->nat_tree_lock); 311462306a36Sopenharmony_ci 311562306a36Sopenharmony_ci /* 311662306a36Sopenharmony_ci * if there are no enough space in journal to store dirty nat 311762306a36Sopenharmony_ci * entries, remove all entries from journal and merge them 311862306a36Sopenharmony_ci * into nat entry set. 311962306a36Sopenharmony_ci */ 312062306a36Sopenharmony_ci if (cpc->reason & CP_UMOUNT || 312162306a36Sopenharmony_ci !__has_cursum_space(journal, 312262306a36Sopenharmony_ci nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL)) 312362306a36Sopenharmony_ci remove_nats_in_journal(sbi); 312462306a36Sopenharmony_ci 312562306a36Sopenharmony_ci while ((found = __gang_lookup_nat_set(nm_i, 312662306a36Sopenharmony_ci set_idx, NAT_VEC_SIZE, setvec))) { 312762306a36Sopenharmony_ci unsigned idx; 312862306a36Sopenharmony_ci 312962306a36Sopenharmony_ci set_idx = setvec[found - 1]->set + 1; 313062306a36Sopenharmony_ci for (idx = 0; idx < found; idx++) 313162306a36Sopenharmony_ci __adjust_nat_entry_set(setvec[idx], &sets, 313262306a36Sopenharmony_ci MAX_NAT_JENTRIES(journal)); 313362306a36Sopenharmony_ci } 313462306a36Sopenharmony_ci 313562306a36Sopenharmony_ci /* flush dirty nats in nat entry set */ 313662306a36Sopenharmony_ci list_for_each_entry_safe(set, tmp, &sets, set_list) { 313762306a36Sopenharmony_ci err = __flush_nat_entry_set(sbi, set, cpc); 313862306a36Sopenharmony_ci if (err) 313962306a36Sopenharmony_ci break; 314062306a36Sopenharmony_ci } 314162306a36Sopenharmony_ci 314262306a36Sopenharmony_ci f2fs_up_write(&nm_i->nat_tree_lock); 314362306a36Sopenharmony_ci /* Allow dirty nats by node block allocation in write_begin */ 314462306a36Sopenharmony_ci 314562306a36Sopenharmony_ci return err; 314662306a36Sopenharmony_ci} 314762306a36Sopenharmony_ci 314862306a36Sopenharmony_cistatic int __get_nat_bitmaps(struct f2fs_sb_info *sbi) 314962306a36Sopenharmony_ci{ 315062306a36Sopenharmony_ci struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); 315162306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 315262306a36Sopenharmony_ci unsigned int nat_bits_bytes = nm_i->nat_blocks / BITS_PER_BYTE; 315362306a36Sopenharmony_ci unsigned int i; 315462306a36Sopenharmony_ci __u64 cp_ver = cur_cp_version(ckpt); 315562306a36Sopenharmony_ci block_t nat_bits_addr; 315662306a36Sopenharmony_ci 315762306a36Sopenharmony_ci nm_i->nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8); 315862306a36Sopenharmony_ci nm_i->nat_bits = f2fs_kvzalloc(sbi, 315962306a36Sopenharmony_ci nm_i->nat_bits_blocks << F2FS_BLKSIZE_BITS, GFP_KERNEL); 316062306a36Sopenharmony_ci if (!nm_i->nat_bits) 316162306a36Sopenharmony_ci return -ENOMEM; 316262306a36Sopenharmony_ci 316362306a36Sopenharmony_ci nm_i->full_nat_bits = nm_i->nat_bits + 8; 316462306a36Sopenharmony_ci nm_i->empty_nat_bits = nm_i->full_nat_bits + nat_bits_bytes; 316562306a36Sopenharmony_ci 316662306a36Sopenharmony_ci if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG)) 316762306a36Sopenharmony_ci return 0; 316862306a36Sopenharmony_ci 316962306a36Sopenharmony_ci nat_bits_addr = __start_cp_addr(sbi) + sbi->blocks_per_seg - 317062306a36Sopenharmony_ci nm_i->nat_bits_blocks; 317162306a36Sopenharmony_ci for (i = 0; i < nm_i->nat_bits_blocks; i++) { 317262306a36Sopenharmony_ci struct page *page; 317362306a36Sopenharmony_ci 317462306a36Sopenharmony_ci page = f2fs_get_meta_page(sbi, nat_bits_addr++); 317562306a36Sopenharmony_ci if (IS_ERR(page)) 317662306a36Sopenharmony_ci return PTR_ERR(page); 317762306a36Sopenharmony_ci 317862306a36Sopenharmony_ci memcpy(nm_i->nat_bits + (i << F2FS_BLKSIZE_BITS), 317962306a36Sopenharmony_ci page_address(page), F2FS_BLKSIZE); 318062306a36Sopenharmony_ci f2fs_put_page(page, 1); 318162306a36Sopenharmony_ci } 318262306a36Sopenharmony_ci 318362306a36Sopenharmony_ci cp_ver |= (cur_cp_crc(ckpt) << 32); 318462306a36Sopenharmony_ci if (cpu_to_le64(cp_ver) != *(__le64 *)nm_i->nat_bits) { 318562306a36Sopenharmony_ci clear_ckpt_flags(sbi, CP_NAT_BITS_FLAG); 318662306a36Sopenharmony_ci f2fs_notice(sbi, "Disable nat_bits due to incorrect cp_ver (%llu, %llu)", 318762306a36Sopenharmony_ci cp_ver, le64_to_cpu(*(__le64 *)nm_i->nat_bits)); 318862306a36Sopenharmony_ci return 0; 318962306a36Sopenharmony_ci } 319062306a36Sopenharmony_ci 319162306a36Sopenharmony_ci f2fs_notice(sbi, "Found nat_bits in checkpoint"); 319262306a36Sopenharmony_ci return 0; 319362306a36Sopenharmony_ci} 319462306a36Sopenharmony_ci 319562306a36Sopenharmony_cistatic inline void load_free_nid_bitmap(struct f2fs_sb_info *sbi) 319662306a36Sopenharmony_ci{ 319762306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 319862306a36Sopenharmony_ci unsigned int i = 0; 319962306a36Sopenharmony_ci nid_t nid, last_nid; 320062306a36Sopenharmony_ci 320162306a36Sopenharmony_ci if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG)) 320262306a36Sopenharmony_ci return; 320362306a36Sopenharmony_ci 320462306a36Sopenharmony_ci for (i = 0; i < nm_i->nat_blocks; i++) { 320562306a36Sopenharmony_ci i = find_next_bit_le(nm_i->empty_nat_bits, nm_i->nat_blocks, i); 320662306a36Sopenharmony_ci if (i >= nm_i->nat_blocks) 320762306a36Sopenharmony_ci break; 320862306a36Sopenharmony_ci 320962306a36Sopenharmony_ci __set_bit_le(i, nm_i->nat_block_bitmap); 321062306a36Sopenharmony_ci 321162306a36Sopenharmony_ci nid = i * NAT_ENTRY_PER_BLOCK; 321262306a36Sopenharmony_ci last_nid = nid + NAT_ENTRY_PER_BLOCK; 321362306a36Sopenharmony_ci 321462306a36Sopenharmony_ci spin_lock(&NM_I(sbi)->nid_list_lock); 321562306a36Sopenharmony_ci for (; nid < last_nid; nid++) 321662306a36Sopenharmony_ci update_free_nid_bitmap(sbi, nid, true, true); 321762306a36Sopenharmony_ci spin_unlock(&NM_I(sbi)->nid_list_lock); 321862306a36Sopenharmony_ci } 321962306a36Sopenharmony_ci 322062306a36Sopenharmony_ci for (i = 0; i < nm_i->nat_blocks; i++) { 322162306a36Sopenharmony_ci i = find_next_bit_le(nm_i->full_nat_bits, nm_i->nat_blocks, i); 322262306a36Sopenharmony_ci if (i >= nm_i->nat_blocks) 322362306a36Sopenharmony_ci break; 322462306a36Sopenharmony_ci 322562306a36Sopenharmony_ci __set_bit_le(i, nm_i->nat_block_bitmap); 322662306a36Sopenharmony_ci } 322762306a36Sopenharmony_ci} 322862306a36Sopenharmony_ci 322962306a36Sopenharmony_cistatic int init_node_manager(struct f2fs_sb_info *sbi) 323062306a36Sopenharmony_ci{ 323162306a36Sopenharmony_ci struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi); 323262306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 323362306a36Sopenharmony_ci unsigned char *version_bitmap; 323462306a36Sopenharmony_ci unsigned int nat_segs; 323562306a36Sopenharmony_ci int err; 323662306a36Sopenharmony_ci 323762306a36Sopenharmony_ci nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr); 323862306a36Sopenharmony_ci 323962306a36Sopenharmony_ci /* segment_count_nat includes pair segment so divide to 2. */ 324062306a36Sopenharmony_ci nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1; 324162306a36Sopenharmony_ci nm_i->nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg); 324262306a36Sopenharmony_ci nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nm_i->nat_blocks; 324362306a36Sopenharmony_ci 324462306a36Sopenharmony_ci /* not used nids: 0, node, meta, (and root counted as valid node) */ 324562306a36Sopenharmony_ci nm_i->available_nids = nm_i->max_nid - sbi->total_valid_node_count - 324662306a36Sopenharmony_ci F2FS_RESERVED_NODE_NUM; 324762306a36Sopenharmony_ci nm_i->nid_cnt[FREE_NID] = 0; 324862306a36Sopenharmony_ci nm_i->nid_cnt[PREALLOC_NID] = 0; 324962306a36Sopenharmony_ci nm_i->ram_thresh = DEF_RAM_THRESHOLD; 325062306a36Sopenharmony_ci nm_i->ra_nid_pages = DEF_RA_NID_PAGES; 325162306a36Sopenharmony_ci nm_i->dirty_nats_ratio = DEF_DIRTY_NAT_RATIO_THRESHOLD; 325262306a36Sopenharmony_ci nm_i->max_rf_node_blocks = DEF_RF_NODE_BLOCKS; 325362306a36Sopenharmony_ci 325462306a36Sopenharmony_ci INIT_RADIX_TREE(&nm_i->free_nid_root, GFP_ATOMIC); 325562306a36Sopenharmony_ci INIT_LIST_HEAD(&nm_i->free_nid_list); 325662306a36Sopenharmony_ci INIT_RADIX_TREE(&nm_i->nat_root, GFP_NOIO); 325762306a36Sopenharmony_ci INIT_RADIX_TREE(&nm_i->nat_set_root, GFP_NOIO); 325862306a36Sopenharmony_ci INIT_LIST_HEAD(&nm_i->nat_entries); 325962306a36Sopenharmony_ci spin_lock_init(&nm_i->nat_list_lock); 326062306a36Sopenharmony_ci 326162306a36Sopenharmony_ci mutex_init(&nm_i->build_lock); 326262306a36Sopenharmony_ci spin_lock_init(&nm_i->nid_list_lock); 326362306a36Sopenharmony_ci init_f2fs_rwsem(&nm_i->nat_tree_lock); 326462306a36Sopenharmony_ci 326562306a36Sopenharmony_ci nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid); 326662306a36Sopenharmony_ci nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP); 326762306a36Sopenharmony_ci version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP); 326862306a36Sopenharmony_ci nm_i->nat_bitmap = kmemdup(version_bitmap, nm_i->bitmap_size, 326962306a36Sopenharmony_ci GFP_KERNEL); 327062306a36Sopenharmony_ci if (!nm_i->nat_bitmap) 327162306a36Sopenharmony_ci return -ENOMEM; 327262306a36Sopenharmony_ci 327362306a36Sopenharmony_ci err = __get_nat_bitmaps(sbi); 327462306a36Sopenharmony_ci if (err) 327562306a36Sopenharmony_ci return err; 327662306a36Sopenharmony_ci 327762306a36Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS 327862306a36Sopenharmony_ci nm_i->nat_bitmap_mir = kmemdup(version_bitmap, nm_i->bitmap_size, 327962306a36Sopenharmony_ci GFP_KERNEL); 328062306a36Sopenharmony_ci if (!nm_i->nat_bitmap_mir) 328162306a36Sopenharmony_ci return -ENOMEM; 328262306a36Sopenharmony_ci#endif 328362306a36Sopenharmony_ci 328462306a36Sopenharmony_ci return 0; 328562306a36Sopenharmony_ci} 328662306a36Sopenharmony_ci 328762306a36Sopenharmony_cistatic int init_free_nid_cache(struct f2fs_sb_info *sbi) 328862306a36Sopenharmony_ci{ 328962306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 329062306a36Sopenharmony_ci int i; 329162306a36Sopenharmony_ci 329262306a36Sopenharmony_ci nm_i->free_nid_bitmap = 329362306a36Sopenharmony_ci f2fs_kvzalloc(sbi, array_size(sizeof(unsigned char *), 329462306a36Sopenharmony_ci nm_i->nat_blocks), 329562306a36Sopenharmony_ci GFP_KERNEL); 329662306a36Sopenharmony_ci if (!nm_i->free_nid_bitmap) 329762306a36Sopenharmony_ci return -ENOMEM; 329862306a36Sopenharmony_ci 329962306a36Sopenharmony_ci for (i = 0; i < nm_i->nat_blocks; i++) { 330062306a36Sopenharmony_ci nm_i->free_nid_bitmap[i] = f2fs_kvzalloc(sbi, 330162306a36Sopenharmony_ci f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK), GFP_KERNEL); 330262306a36Sopenharmony_ci if (!nm_i->free_nid_bitmap[i]) 330362306a36Sopenharmony_ci return -ENOMEM; 330462306a36Sopenharmony_ci } 330562306a36Sopenharmony_ci 330662306a36Sopenharmony_ci nm_i->nat_block_bitmap = f2fs_kvzalloc(sbi, nm_i->nat_blocks / 8, 330762306a36Sopenharmony_ci GFP_KERNEL); 330862306a36Sopenharmony_ci if (!nm_i->nat_block_bitmap) 330962306a36Sopenharmony_ci return -ENOMEM; 331062306a36Sopenharmony_ci 331162306a36Sopenharmony_ci nm_i->free_nid_count = 331262306a36Sopenharmony_ci f2fs_kvzalloc(sbi, array_size(sizeof(unsigned short), 331362306a36Sopenharmony_ci nm_i->nat_blocks), 331462306a36Sopenharmony_ci GFP_KERNEL); 331562306a36Sopenharmony_ci if (!nm_i->free_nid_count) 331662306a36Sopenharmony_ci return -ENOMEM; 331762306a36Sopenharmony_ci return 0; 331862306a36Sopenharmony_ci} 331962306a36Sopenharmony_ci 332062306a36Sopenharmony_ciint f2fs_build_node_manager(struct f2fs_sb_info *sbi) 332162306a36Sopenharmony_ci{ 332262306a36Sopenharmony_ci int err; 332362306a36Sopenharmony_ci 332462306a36Sopenharmony_ci sbi->nm_info = f2fs_kzalloc(sbi, sizeof(struct f2fs_nm_info), 332562306a36Sopenharmony_ci GFP_KERNEL); 332662306a36Sopenharmony_ci if (!sbi->nm_info) 332762306a36Sopenharmony_ci return -ENOMEM; 332862306a36Sopenharmony_ci 332962306a36Sopenharmony_ci err = init_node_manager(sbi); 333062306a36Sopenharmony_ci if (err) 333162306a36Sopenharmony_ci return err; 333262306a36Sopenharmony_ci 333362306a36Sopenharmony_ci err = init_free_nid_cache(sbi); 333462306a36Sopenharmony_ci if (err) 333562306a36Sopenharmony_ci return err; 333662306a36Sopenharmony_ci 333762306a36Sopenharmony_ci /* load free nid status from nat_bits table */ 333862306a36Sopenharmony_ci load_free_nid_bitmap(sbi); 333962306a36Sopenharmony_ci 334062306a36Sopenharmony_ci return f2fs_build_free_nids(sbi, true, true); 334162306a36Sopenharmony_ci} 334262306a36Sopenharmony_ci 334362306a36Sopenharmony_civoid f2fs_destroy_node_manager(struct f2fs_sb_info *sbi) 334462306a36Sopenharmony_ci{ 334562306a36Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 334662306a36Sopenharmony_ci struct free_nid *i, *next_i; 334762306a36Sopenharmony_ci void *vec[NAT_VEC_SIZE]; 334862306a36Sopenharmony_ci struct nat_entry **natvec = (struct nat_entry **)vec; 334962306a36Sopenharmony_ci struct nat_entry_set **setvec = (struct nat_entry_set **)vec; 335062306a36Sopenharmony_ci nid_t nid = 0; 335162306a36Sopenharmony_ci unsigned int found; 335262306a36Sopenharmony_ci 335362306a36Sopenharmony_ci if (!nm_i) 335462306a36Sopenharmony_ci return; 335562306a36Sopenharmony_ci 335662306a36Sopenharmony_ci /* destroy free nid list */ 335762306a36Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 335862306a36Sopenharmony_ci list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) { 335962306a36Sopenharmony_ci __remove_free_nid(sbi, i, FREE_NID); 336062306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 336162306a36Sopenharmony_ci kmem_cache_free(free_nid_slab, i); 336262306a36Sopenharmony_ci spin_lock(&nm_i->nid_list_lock); 336362306a36Sopenharmony_ci } 336462306a36Sopenharmony_ci f2fs_bug_on(sbi, nm_i->nid_cnt[FREE_NID]); 336562306a36Sopenharmony_ci f2fs_bug_on(sbi, nm_i->nid_cnt[PREALLOC_NID]); 336662306a36Sopenharmony_ci f2fs_bug_on(sbi, !list_empty(&nm_i->free_nid_list)); 336762306a36Sopenharmony_ci spin_unlock(&nm_i->nid_list_lock); 336862306a36Sopenharmony_ci 336962306a36Sopenharmony_ci /* destroy nat cache */ 337062306a36Sopenharmony_ci f2fs_down_write(&nm_i->nat_tree_lock); 337162306a36Sopenharmony_ci while ((found = __gang_lookup_nat_cache(nm_i, 337262306a36Sopenharmony_ci nid, NAT_VEC_SIZE, natvec))) { 337362306a36Sopenharmony_ci unsigned idx; 337462306a36Sopenharmony_ci 337562306a36Sopenharmony_ci nid = nat_get_nid(natvec[found - 1]) + 1; 337662306a36Sopenharmony_ci for (idx = 0; idx < found; idx++) { 337762306a36Sopenharmony_ci spin_lock(&nm_i->nat_list_lock); 337862306a36Sopenharmony_ci list_del(&natvec[idx]->list); 337962306a36Sopenharmony_ci spin_unlock(&nm_i->nat_list_lock); 338062306a36Sopenharmony_ci 338162306a36Sopenharmony_ci __del_from_nat_cache(nm_i, natvec[idx]); 338262306a36Sopenharmony_ci } 338362306a36Sopenharmony_ci } 338462306a36Sopenharmony_ci f2fs_bug_on(sbi, nm_i->nat_cnt[TOTAL_NAT]); 338562306a36Sopenharmony_ci 338662306a36Sopenharmony_ci /* destroy nat set cache */ 338762306a36Sopenharmony_ci nid = 0; 338862306a36Sopenharmony_ci memset(vec, 0, sizeof(void *) * NAT_VEC_SIZE); 338962306a36Sopenharmony_ci while ((found = __gang_lookup_nat_set(nm_i, 339062306a36Sopenharmony_ci nid, NAT_VEC_SIZE, setvec))) { 339162306a36Sopenharmony_ci unsigned idx; 339262306a36Sopenharmony_ci 339362306a36Sopenharmony_ci nid = setvec[found - 1]->set + 1; 339462306a36Sopenharmony_ci for (idx = 0; idx < found; idx++) { 339562306a36Sopenharmony_ci /* entry_cnt is not zero, when cp_error was occurred */ 339662306a36Sopenharmony_ci f2fs_bug_on(sbi, !list_empty(&setvec[idx]->entry_list)); 339762306a36Sopenharmony_ci radix_tree_delete(&nm_i->nat_set_root, setvec[idx]->set); 339862306a36Sopenharmony_ci kmem_cache_free(nat_entry_set_slab, setvec[idx]); 339962306a36Sopenharmony_ci } 340062306a36Sopenharmony_ci } 340162306a36Sopenharmony_ci f2fs_up_write(&nm_i->nat_tree_lock); 340262306a36Sopenharmony_ci 340362306a36Sopenharmony_ci kvfree(nm_i->nat_block_bitmap); 340462306a36Sopenharmony_ci if (nm_i->free_nid_bitmap) { 340562306a36Sopenharmony_ci int i; 340662306a36Sopenharmony_ci 340762306a36Sopenharmony_ci for (i = 0; i < nm_i->nat_blocks; i++) 340862306a36Sopenharmony_ci kvfree(nm_i->free_nid_bitmap[i]); 340962306a36Sopenharmony_ci kvfree(nm_i->free_nid_bitmap); 341062306a36Sopenharmony_ci } 341162306a36Sopenharmony_ci kvfree(nm_i->free_nid_count); 341262306a36Sopenharmony_ci 341362306a36Sopenharmony_ci kvfree(nm_i->nat_bitmap); 341462306a36Sopenharmony_ci kvfree(nm_i->nat_bits); 341562306a36Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS 341662306a36Sopenharmony_ci kvfree(nm_i->nat_bitmap_mir); 341762306a36Sopenharmony_ci#endif 341862306a36Sopenharmony_ci sbi->nm_info = NULL; 341962306a36Sopenharmony_ci kfree(nm_i); 342062306a36Sopenharmony_ci} 342162306a36Sopenharmony_ci 342262306a36Sopenharmony_ciint __init f2fs_create_node_manager_caches(void) 342362306a36Sopenharmony_ci{ 342462306a36Sopenharmony_ci nat_entry_slab = f2fs_kmem_cache_create("f2fs_nat_entry", 342562306a36Sopenharmony_ci sizeof(struct nat_entry)); 342662306a36Sopenharmony_ci if (!nat_entry_slab) 342762306a36Sopenharmony_ci goto fail; 342862306a36Sopenharmony_ci 342962306a36Sopenharmony_ci free_nid_slab = f2fs_kmem_cache_create("f2fs_free_nid", 343062306a36Sopenharmony_ci sizeof(struct free_nid)); 343162306a36Sopenharmony_ci if (!free_nid_slab) 343262306a36Sopenharmony_ci goto destroy_nat_entry; 343362306a36Sopenharmony_ci 343462306a36Sopenharmony_ci nat_entry_set_slab = f2fs_kmem_cache_create("f2fs_nat_entry_set", 343562306a36Sopenharmony_ci sizeof(struct nat_entry_set)); 343662306a36Sopenharmony_ci if (!nat_entry_set_slab) 343762306a36Sopenharmony_ci goto destroy_free_nid; 343862306a36Sopenharmony_ci 343962306a36Sopenharmony_ci fsync_node_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_node_entry", 344062306a36Sopenharmony_ci sizeof(struct fsync_node_entry)); 344162306a36Sopenharmony_ci if (!fsync_node_entry_slab) 344262306a36Sopenharmony_ci goto destroy_nat_entry_set; 344362306a36Sopenharmony_ci return 0; 344462306a36Sopenharmony_ci 344562306a36Sopenharmony_cidestroy_nat_entry_set: 344662306a36Sopenharmony_ci kmem_cache_destroy(nat_entry_set_slab); 344762306a36Sopenharmony_cidestroy_free_nid: 344862306a36Sopenharmony_ci kmem_cache_destroy(free_nid_slab); 344962306a36Sopenharmony_cidestroy_nat_entry: 345062306a36Sopenharmony_ci kmem_cache_destroy(nat_entry_slab); 345162306a36Sopenharmony_cifail: 345262306a36Sopenharmony_ci return -ENOMEM; 345362306a36Sopenharmony_ci} 345462306a36Sopenharmony_ci 345562306a36Sopenharmony_civoid f2fs_destroy_node_manager_caches(void) 345662306a36Sopenharmony_ci{ 345762306a36Sopenharmony_ci kmem_cache_destroy(fsync_node_entry_slab); 345862306a36Sopenharmony_ci kmem_cache_destroy(nat_entry_set_slab); 345962306a36Sopenharmony_ci kmem_cache_destroy(free_nid_slab); 346062306a36Sopenharmony_ci kmem_cache_destroy(nat_entry_slab); 346162306a36Sopenharmony_ci} 3462