18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fs/f2fs/checkpoint.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd. 68c2ecf20Sopenharmony_ci * http://www.samsung.com/ 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#include <linux/fs.h> 98c2ecf20Sopenharmony_ci#include <linux/bio.h> 108c2ecf20Sopenharmony_ci#include <linux/mpage.h> 118c2ecf20Sopenharmony_ci#include <linux/writeback.h> 128c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 138c2ecf20Sopenharmony_ci#include <linux/f2fs_fs.h> 148c2ecf20Sopenharmony_ci#include <linux/pagevec.h> 158c2ecf20Sopenharmony_ci#include <linux/swap.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "f2fs.h" 188c2ecf20Sopenharmony_ci#include "node.h" 198c2ecf20Sopenharmony_ci#include "segment.h" 208c2ecf20Sopenharmony_ci#include "trace.h" 218c2ecf20Sopenharmony_ci#include <trace/events/f2fs.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic struct kmem_cache *ino_entry_slab; 248c2ecf20Sopenharmony_cistruct kmem_cache *f2fs_inode_entry_slab; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_civoid f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci f2fs_build_fault_attr(sbi, 0, 0); 298c2ecf20Sopenharmony_ci set_ckpt_flags(sbi, CP_ERROR_FLAG); 308c2ecf20Sopenharmony_ci if (!end_io) 318c2ecf20Sopenharmony_ci f2fs_flush_merged_writes(sbi); 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* 358c2ecf20Sopenharmony_ci * We guarantee no failure on the returned page. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_cistruct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci struct address_space *mapping = META_MAPPING(sbi); 408c2ecf20Sopenharmony_ci struct page *page = NULL; 418c2ecf20Sopenharmony_cirepeat: 428c2ecf20Sopenharmony_ci page = f2fs_grab_cache_page(mapping, index, false); 438c2ecf20Sopenharmony_ci if (!page) { 448c2ecf20Sopenharmony_ci cond_resched(); 458c2ecf20Sopenharmony_ci goto repeat; 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(page, META, true, true); 488c2ecf20Sopenharmony_ci if (!PageUptodate(page)) 498c2ecf20Sopenharmony_ci SetPageUptodate(page); 508c2ecf20Sopenharmony_ci return page; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index, 548c2ecf20Sopenharmony_ci bool is_meta) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci struct address_space *mapping = META_MAPPING(sbi); 578c2ecf20Sopenharmony_ci struct page *page; 588c2ecf20Sopenharmony_ci struct f2fs_io_info fio = { 598c2ecf20Sopenharmony_ci .sbi = sbi, 608c2ecf20Sopenharmony_ci .type = META, 618c2ecf20Sopenharmony_ci .op = REQ_OP_READ, 628c2ecf20Sopenharmony_ci .op_flags = REQ_META | REQ_PRIO, 638c2ecf20Sopenharmony_ci .old_blkaddr = index, 648c2ecf20Sopenharmony_ci .new_blkaddr = index, 658c2ecf20Sopenharmony_ci .encrypted_page = NULL, 668c2ecf20Sopenharmony_ci .is_por = !is_meta, 678c2ecf20Sopenharmony_ci }; 688c2ecf20Sopenharmony_ci int err; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci if (unlikely(!is_meta)) 718c2ecf20Sopenharmony_ci fio.op_flags &= ~REQ_META; 728c2ecf20Sopenharmony_cirepeat: 738c2ecf20Sopenharmony_ci page = f2fs_grab_cache_page(mapping, index, false); 748c2ecf20Sopenharmony_ci if (!page) { 758c2ecf20Sopenharmony_ci cond_resched(); 768c2ecf20Sopenharmony_ci goto repeat; 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci if (PageUptodate(page)) 798c2ecf20Sopenharmony_ci goto out; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci fio.page = page; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci err = f2fs_submit_page_bio(&fio); 848c2ecf20Sopenharmony_ci if (err) { 858c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 868c2ecf20Sopenharmony_ci return ERR_PTR(err); 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci f2fs_update_iostat(sbi, FS_META_READ_IO, F2FS_BLKSIZE); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci lock_page(page); 928c2ecf20Sopenharmony_ci if (unlikely(page->mapping != mapping)) { 938c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 948c2ecf20Sopenharmony_ci goto repeat; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci if (unlikely(!PageUptodate(page))) { 988c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 998c2ecf20Sopenharmony_ci return ERR_PTR(-EIO); 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ciout: 1028c2ecf20Sopenharmony_ci return page; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistruct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci return __get_meta_page(sbi, index, true); 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistruct page *f2fs_get_meta_page_retry(struct f2fs_sb_info *sbi, pgoff_t index) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci struct page *page; 1138c2ecf20Sopenharmony_ci int count = 0; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciretry: 1168c2ecf20Sopenharmony_ci page = __get_meta_page(sbi, index, true); 1178c2ecf20Sopenharmony_ci if (IS_ERR(page)) { 1188c2ecf20Sopenharmony_ci if (PTR_ERR(page) == -EIO && 1198c2ecf20Sopenharmony_ci ++count <= DEFAULT_RETRY_IO_COUNT) 1208c2ecf20Sopenharmony_ci goto retry; 1218c2ecf20Sopenharmony_ci f2fs_stop_checkpoint(sbi, false); 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci return page; 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci/* for POR only */ 1278c2ecf20Sopenharmony_cistruct page *f2fs_get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci return __get_meta_page(sbi, index, false); 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic bool __is_bitmap_valid(struct f2fs_sb_info *sbi, block_t blkaddr, 1338c2ecf20Sopenharmony_ci int type) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci struct seg_entry *se; 1368c2ecf20Sopenharmony_ci unsigned int segno, offset; 1378c2ecf20Sopenharmony_ci bool exist; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci if (type == DATA_GENERIC) 1408c2ecf20Sopenharmony_ci return true; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci segno = GET_SEGNO(sbi, blkaddr); 1438c2ecf20Sopenharmony_ci offset = GET_BLKOFF_FROM_SEG0(sbi, blkaddr); 1448c2ecf20Sopenharmony_ci se = get_seg_entry(sbi, segno); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci exist = f2fs_test_bit(offset, se->cur_valid_map); 1478c2ecf20Sopenharmony_ci if (exist && type == DATA_GENERIC_ENHANCE_UPDATE) { 1488c2ecf20Sopenharmony_ci f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d", 1498c2ecf20Sopenharmony_ci blkaddr, exist); 1508c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 1518c2ecf20Sopenharmony_ci return exist; 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci if (!exist && type == DATA_GENERIC_ENHANCE) { 1558c2ecf20Sopenharmony_ci f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d", 1568c2ecf20Sopenharmony_ci blkaddr, exist); 1578c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 1588c2ecf20Sopenharmony_ci dump_stack(); 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci return exist; 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cibool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi, 1648c2ecf20Sopenharmony_ci block_t blkaddr, int type) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci switch (type) { 1678c2ecf20Sopenharmony_ci case META_NAT: 1688c2ecf20Sopenharmony_ci break; 1698c2ecf20Sopenharmony_ci case META_SIT: 1708c2ecf20Sopenharmony_ci if (unlikely(blkaddr >= SIT_BLK_CNT(sbi))) 1718c2ecf20Sopenharmony_ci return false; 1728c2ecf20Sopenharmony_ci break; 1738c2ecf20Sopenharmony_ci case META_SSA: 1748c2ecf20Sopenharmony_ci if (unlikely(blkaddr >= MAIN_BLKADDR(sbi) || 1758c2ecf20Sopenharmony_ci blkaddr < SM_I(sbi)->ssa_blkaddr)) 1768c2ecf20Sopenharmony_ci return false; 1778c2ecf20Sopenharmony_ci break; 1788c2ecf20Sopenharmony_ci case META_CP: 1798c2ecf20Sopenharmony_ci if (unlikely(blkaddr >= SIT_I(sbi)->sit_base_addr || 1808c2ecf20Sopenharmony_ci blkaddr < __start_cp_addr(sbi))) 1818c2ecf20Sopenharmony_ci return false; 1828c2ecf20Sopenharmony_ci break; 1838c2ecf20Sopenharmony_ci case META_POR: 1848c2ecf20Sopenharmony_ci if (unlikely(blkaddr >= MAX_BLKADDR(sbi) || 1858c2ecf20Sopenharmony_ci blkaddr < MAIN_BLKADDR(sbi))) 1868c2ecf20Sopenharmony_ci return false; 1878c2ecf20Sopenharmony_ci break; 1888c2ecf20Sopenharmony_ci case DATA_GENERIC: 1898c2ecf20Sopenharmony_ci case DATA_GENERIC_ENHANCE: 1908c2ecf20Sopenharmony_ci case DATA_GENERIC_ENHANCE_READ: 1918c2ecf20Sopenharmony_ci case DATA_GENERIC_ENHANCE_UPDATE: 1928c2ecf20Sopenharmony_ci if (unlikely(blkaddr >= MAX_BLKADDR(sbi) || 1938c2ecf20Sopenharmony_ci blkaddr < MAIN_BLKADDR(sbi))) { 1948c2ecf20Sopenharmony_ci f2fs_warn(sbi, "access invalid blkaddr:%u", 1958c2ecf20Sopenharmony_ci blkaddr); 1968c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 1978c2ecf20Sopenharmony_ci dump_stack(); 1988c2ecf20Sopenharmony_ci return false; 1998c2ecf20Sopenharmony_ci } else { 2008c2ecf20Sopenharmony_ci return __is_bitmap_valid(sbi, blkaddr, type); 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci break; 2038c2ecf20Sopenharmony_ci case META_GENERIC: 2048c2ecf20Sopenharmony_ci if (unlikely(blkaddr < SEG0_BLKADDR(sbi) || 2058c2ecf20Sopenharmony_ci blkaddr >= MAIN_BLKADDR(sbi))) 2068c2ecf20Sopenharmony_ci return false; 2078c2ecf20Sopenharmony_ci break; 2088c2ecf20Sopenharmony_ci default: 2098c2ecf20Sopenharmony_ci BUG(); 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci return true; 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci/* 2168c2ecf20Sopenharmony_ci * Readahead CP/NAT/SIT/SSA/POR pages 2178c2ecf20Sopenharmony_ci */ 2188c2ecf20Sopenharmony_ciint f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, 2198c2ecf20Sopenharmony_ci int type, bool sync) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci struct page *page; 2228c2ecf20Sopenharmony_ci block_t blkno = start; 2238c2ecf20Sopenharmony_ci struct f2fs_io_info fio = { 2248c2ecf20Sopenharmony_ci .sbi = sbi, 2258c2ecf20Sopenharmony_ci .type = META, 2268c2ecf20Sopenharmony_ci .op = REQ_OP_READ, 2278c2ecf20Sopenharmony_ci .op_flags = sync ? (REQ_META | REQ_PRIO) : REQ_RAHEAD, 2288c2ecf20Sopenharmony_ci .encrypted_page = NULL, 2298c2ecf20Sopenharmony_ci .in_list = false, 2308c2ecf20Sopenharmony_ci .is_por = (type == META_POR), 2318c2ecf20Sopenharmony_ci }; 2328c2ecf20Sopenharmony_ci struct blk_plug plug; 2338c2ecf20Sopenharmony_ci int err; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci if (unlikely(type == META_POR)) 2368c2ecf20Sopenharmony_ci fio.op_flags &= ~REQ_META; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci blk_start_plug(&plug); 2398c2ecf20Sopenharmony_ci for (; nrpages-- > 0; blkno++) { 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (!f2fs_is_valid_blkaddr(sbi, blkno, type)) 2428c2ecf20Sopenharmony_ci goto out; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci switch (type) { 2458c2ecf20Sopenharmony_ci case META_NAT: 2468c2ecf20Sopenharmony_ci if (unlikely(blkno >= 2478c2ecf20Sopenharmony_ci NAT_BLOCK_OFFSET(NM_I(sbi)->max_nid))) 2488c2ecf20Sopenharmony_ci blkno = 0; 2498c2ecf20Sopenharmony_ci /* get nat block addr */ 2508c2ecf20Sopenharmony_ci fio.new_blkaddr = current_nat_addr(sbi, 2518c2ecf20Sopenharmony_ci blkno * NAT_ENTRY_PER_BLOCK); 2528c2ecf20Sopenharmony_ci break; 2538c2ecf20Sopenharmony_ci case META_SIT: 2548c2ecf20Sopenharmony_ci if (unlikely(blkno >= TOTAL_SEGS(sbi))) 2558c2ecf20Sopenharmony_ci goto out; 2568c2ecf20Sopenharmony_ci /* get sit block addr */ 2578c2ecf20Sopenharmony_ci fio.new_blkaddr = current_sit_addr(sbi, 2588c2ecf20Sopenharmony_ci blkno * SIT_ENTRY_PER_BLOCK); 2598c2ecf20Sopenharmony_ci break; 2608c2ecf20Sopenharmony_ci case META_SSA: 2618c2ecf20Sopenharmony_ci case META_CP: 2628c2ecf20Sopenharmony_ci case META_POR: 2638c2ecf20Sopenharmony_ci fio.new_blkaddr = blkno; 2648c2ecf20Sopenharmony_ci break; 2658c2ecf20Sopenharmony_ci default: 2668c2ecf20Sopenharmony_ci BUG(); 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci page = f2fs_grab_cache_page(META_MAPPING(sbi), 2708c2ecf20Sopenharmony_ci fio.new_blkaddr, false); 2718c2ecf20Sopenharmony_ci if (!page) 2728c2ecf20Sopenharmony_ci continue; 2738c2ecf20Sopenharmony_ci if (PageUptodate(page)) { 2748c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 2758c2ecf20Sopenharmony_ci continue; 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci fio.page = page; 2798c2ecf20Sopenharmony_ci err = f2fs_submit_page_bio(&fio); 2808c2ecf20Sopenharmony_ci f2fs_put_page(page, err ? 1 : 0); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci if (!err) 2838c2ecf20Sopenharmony_ci f2fs_update_iostat(sbi, FS_META_READ_IO, F2FS_BLKSIZE); 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ciout: 2868c2ecf20Sopenharmony_ci blk_finish_plug(&plug); 2878c2ecf20Sopenharmony_ci return blkno - start; 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_civoid f2fs_ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci struct page *page; 2938c2ecf20Sopenharmony_ci bool readahead = false; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci page = find_get_page(META_MAPPING(sbi), index); 2968c2ecf20Sopenharmony_ci if (!page || !PageUptodate(page)) 2978c2ecf20Sopenharmony_ci readahead = true; 2988c2ecf20Sopenharmony_ci f2fs_put_page(page, 0); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci if (readahead) 3018c2ecf20Sopenharmony_ci f2fs_ra_meta_pages(sbi, index, BIO_MAX_PAGES, META_POR, true); 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic int __f2fs_write_meta_page(struct page *page, 3058c2ecf20Sopenharmony_ci struct writeback_control *wbc, 3068c2ecf20Sopenharmony_ci enum iostat_type io_type) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(page); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci trace_f2fs_writepage(page, META); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 3138c2ecf20Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_IS_CLOSE)) { 3148c2ecf20Sopenharmony_ci ClearPageUptodate(page); 3158c2ecf20Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_META); 3168c2ecf20Sopenharmony_ci unlock_page(page); 3178c2ecf20Sopenharmony_ci return 0; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci goto redirty_out; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 3228c2ecf20Sopenharmony_ci goto redirty_out; 3238c2ecf20Sopenharmony_ci if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0)) 3248c2ecf20Sopenharmony_ci goto redirty_out; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci f2fs_do_write_meta_page(sbi, page, io_type); 3278c2ecf20Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_META); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci if (wbc->for_reclaim) 3308c2ecf20Sopenharmony_ci f2fs_submit_merged_write_cond(sbi, NULL, page, 0, META); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci unlock_page(page); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) 3358c2ecf20Sopenharmony_ci f2fs_submit_merged_write(sbi, META); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci return 0; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ciredirty_out: 3408c2ecf20Sopenharmony_ci redirty_page_for_writepage(wbc, page); 3418c2ecf20Sopenharmony_ci return AOP_WRITEPAGE_ACTIVATE; 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic int f2fs_write_meta_page(struct page *page, 3458c2ecf20Sopenharmony_ci struct writeback_control *wbc) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci return __f2fs_write_meta_page(page, wbc, FS_META_IO); 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic int f2fs_write_meta_pages(struct address_space *mapping, 3518c2ecf20Sopenharmony_ci struct writeback_control *wbc) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_M_SB(mapping); 3548c2ecf20Sopenharmony_ci long diff, written; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 3578c2ecf20Sopenharmony_ci goto skip_write; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci /* collect a number of dirty meta pages and write together */ 3608c2ecf20Sopenharmony_ci if (wbc->sync_mode != WB_SYNC_ALL && 3618c2ecf20Sopenharmony_ci get_pages(sbi, F2FS_DIRTY_META) < 3628c2ecf20Sopenharmony_ci nr_pages_to_skip(sbi, META)) 3638c2ecf20Sopenharmony_ci goto skip_write; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci /* if locked failed, cp will flush dirty pages instead */ 3668c2ecf20Sopenharmony_ci if (!mutex_trylock(&sbi->cp_mutex)) 3678c2ecf20Sopenharmony_ci goto skip_write; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci trace_f2fs_writepages(mapping->host, wbc, META); 3708c2ecf20Sopenharmony_ci diff = nr_pages_to_write(sbi, META, wbc); 3718c2ecf20Sopenharmony_ci written = f2fs_sync_meta_pages(sbi, META, wbc->nr_to_write, FS_META_IO); 3728c2ecf20Sopenharmony_ci mutex_unlock(&sbi->cp_mutex); 3738c2ecf20Sopenharmony_ci wbc->nr_to_write = max((long)0, wbc->nr_to_write - written - diff); 3748c2ecf20Sopenharmony_ci return 0; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ciskip_write: 3778c2ecf20Sopenharmony_ci wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_META); 3788c2ecf20Sopenharmony_ci trace_f2fs_writepages(mapping->host, wbc, META); 3798c2ecf20Sopenharmony_ci return 0; 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cilong f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type, 3838c2ecf20Sopenharmony_ci long nr_to_write, enum iostat_type io_type) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci struct address_space *mapping = META_MAPPING(sbi); 3868c2ecf20Sopenharmony_ci pgoff_t index = 0, prev = ULONG_MAX; 3878c2ecf20Sopenharmony_ci struct pagevec pvec; 3888c2ecf20Sopenharmony_ci long nwritten = 0; 3898c2ecf20Sopenharmony_ci int nr_pages; 3908c2ecf20Sopenharmony_ci struct writeback_control wbc = { 3918c2ecf20Sopenharmony_ci .for_reclaim = 0, 3928c2ecf20Sopenharmony_ci }; 3938c2ecf20Sopenharmony_ci struct blk_plug plug; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci pagevec_init(&pvec); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci blk_start_plug(&plug); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci while ((nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, 4008c2ecf20Sopenharmony_ci PAGECACHE_TAG_DIRTY))) { 4018c2ecf20Sopenharmony_ci int i; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci for (i = 0; i < nr_pages; i++) { 4048c2ecf20Sopenharmony_ci struct page *page = pvec.pages[i]; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci if (prev == ULONG_MAX) 4078c2ecf20Sopenharmony_ci prev = page->index - 1; 4088c2ecf20Sopenharmony_ci if (nr_to_write != LONG_MAX && page->index != prev + 1) { 4098c2ecf20Sopenharmony_ci pagevec_release(&pvec); 4108c2ecf20Sopenharmony_ci goto stop; 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci lock_page(page); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci if (unlikely(page->mapping != mapping)) { 4168c2ecf20Sopenharmony_cicontinue_unlock: 4178c2ecf20Sopenharmony_ci unlock_page(page); 4188c2ecf20Sopenharmony_ci continue; 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci if (!PageDirty(page)) { 4218c2ecf20Sopenharmony_ci /* someone wrote it for us */ 4228c2ecf20Sopenharmony_ci goto continue_unlock; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(page, META, true, true); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci if (!clear_page_dirty_for_io(page)) 4288c2ecf20Sopenharmony_ci goto continue_unlock; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci if (__f2fs_write_meta_page(page, &wbc, io_type)) { 4318c2ecf20Sopenharmony_ci unlock_page(page); 4328c2ecf20Sopenharmony_ci break; 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci nwritten++; 4358c2ecf20Sopenharmony_ci prev = page->index; 4368c2ecf20Sopenharmony_ci if (unlikely(nwritten >= nr_to_write)) 4378c2ecf20Sopenharmony_ci break; 4388c2ecf20Sopenharmony_ci } 4398c2ecf20Sopenharmony_ci pagevec_release(&pvec); 4408c2ecf20Sopenharmony_ci cond_resched(); 4418c2ecf20Sopenharmony_ci } 4428c2ecf20Sopenharmony_cistop: 4438c2ecf20Sopenharmony_ci if (nwritten) 4448c2ecf20Sopenharmony_ci f2fs_submit_merged_write(sbi, type); 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci blk_finish_plug(&plug); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci return nwritten; 4498c2ecf20Sopenharmony_ci} 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_cistatic int f2fs_set_meta_page_dirty(struct page *page) 4528c2ecf20Sopenharmony_ci{ 4538c2ecf20Sopenharmony_ci trace_f2fs_set_page_dirty(page, META); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci if (!PageUptodate(page)) 4568c2ecf20Sopenharmony_ci SetPageUptodate(page); 4578c2ecf20Sopenharmony_ci if (!PageDirty(page)) { 4588c2ecf20Sopenharmony_ci __set_page_dirty_nobuffers(page); 4598c2ecf20Sopenharmony_ci inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META); 4608c2ecf20Sopenharmony_ci f2fs_set_page_private(page, 0); 4618c2ecf20Sopenharmony_ci f2fs_trace_pid(page); 4628c2ecf20Sopenharmony_ci return 1; 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci return 0; 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ciconst struct address_space_operations f2fs_meta_aops = { 4688c2ecf20Sopenharmony_ci .writepage = f2fs_write_meta_page, 4698c2ecf20Sopenharmony_ci .writepages = f2fs_write_meta_pages, 4708c2ecf20Sopenharmony_ci .set_page_dirty = f2fs_set_meta_page_dirty, 4718c2ecf20Sopenharmony_ci .invalidatepage = f2fs_invalidate_page, 4728c2ecf20Sopenharmony_ci .releasepage = f2fs_release_page, 4738c2ecf20Sopenharmony_ci#ifdef CONFIG_MIGRATION 4748c2ecf20Sopenharmony_ci .migratepage = f2fs_migrate_page, 4758c2ecf20Sopenharmony_ci#endif 4768c2ecf20Sopenharmony_ci}; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_cistatic void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, 4798c2ecf20Sopenharmony_ci unsigned int devidx, int type) 4808c2ecf20Sopenharmony_ci{ 4818c2ecf20Sopenharmony_ci struct inode_management *im = &sbi->im[type]; 4828c2ecf20Sopenharmony_ci struct ino_entry *e, *tmp; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci tmp = f2fs_kmem_cache_alloc(ino_entry_slab, GFP_NOFS); 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci radix_tree_preload(GFP_NOFS | __GFP_NOFAIL); 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci spin_lock(&im->ino_lock); 4898c2ecf20Sopenharmony_ci e = radix_tree_lookup(&im->ino_root, ino); 4908c2ecf20Sopenharmony_ci if (!e) { 4918c2ecf20Sopenharmony_ci e = tmp; 4928c2ecf20Sopenharmony_ci if (unlikely(radix_tree_insert(&im->ino_root, ino, e))) 4938c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, 1); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci memset(e, 0, sizeof(struct ino_entry)); 4968c2ecf20Sopenharmony_ci e->ino = ino; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci list_add_tail(&e->list, &im->ino_list); 4998c2ecf20Sopenharmony_ci if (type != ORPHAN_INO) 5008c2ecf20Sopenharmony_ci im->ino_num++; 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci if (type == FLUSH_INO) 5048c2ecf20Sopenharmony_ci f2fs_set_bit(devidx, (char *)&e->dirty_device); 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci spin_unlock(&im->ino_lock); 5078c2ecf20Sopenharmony_ci radix_tree_preload_end(); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci if (e != tmp) 5108c2ecf20Sopenharmony_ci kmem_cache_free(ino_entry_slab, tmp); 5118c2ecf20Sopenharmony_ci} 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_cistatic void __remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type) 5148c2ecf20Sopenharmony_ci{ 5158c2ecf20Sopenharmony_ci struct inode_management *im = &sbi->im[type]; 5168c2ecf20Sopenharmony_ci struct ino_entry *e; 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci spin_lock(&im->ino_lock); 5198c2ecf20Sopenharmony_ci e = radix_tree_lookup(&im->ino_root, ino); 5208c2ecf20Sopenharmony_ci if (e) { 5218c2ecf20Sopenharmony_ci list_del(&e->list); 5228c2ecf20Sopenharmony_ci radix_tree_delete(&im->ino_root, ino); 5238c2ecf20Sopenharmony_ci im->ino_num--; 5248c2ecf20Sopenharmony_ci spin_unlock(&im->ino_lock); 5258c2ecf20Sopenharmony_ci kmem_cache_free(ino_entry_slab, e); 5268c2ecf20Sopenharmony_ci return; 5278c2ecf20Sopenharmony_ci } 5288c2ecf20Sopenharmony_ci spin_unlock(&im->ino_lock); 5298c2ecf20Sopenharmony_ci} 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_civoid f2fs_add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type) 5328c2ecf20Sopenharmony_ci{ 5338c2ecf20Sopenharmony_ci /* add new dirty ino entry into list */ 5348c2ecf20Sopenharmony_ci __add_ino_entry(sbi, ino, 0, type); 5358c2ecf20Sopenharmony_ci} 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_civoid f2fs_remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci /* remove dirty ino entry from list */ 5408c2ecf20Sopenharmony_ci __remove_ino_entry(sbi, ino, type); 5418c2ecf20Sopenharmony_ci} 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci/* mode should be APPEND_INO, UPDATE_INO or TRANS_DIR_INO */ 5448c2ecf20Sopenharmony_cibool f2fs_exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci struct inode_management *im = &sbi->im[mode]; 5478c2ecf20Sopenharmony_ci struct ino_entry *e; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci spin_lock(&im->ino_lock); 5508c2ecf20Sopenharmony_ci e = radix_tree_lookup(&im->ino_root, ino); 5518c2ecf20Sopenharmony_ci spin_unlock(&im->ino_lock); 5528c2ecf20Sopenharmony_ci return e ? true : false; 5538c2ecf20Sopenharmony_ci} 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_civoid f2fs_release_ino_entry(struct f2fs_sb_info *sbi, bool all) 5568c2ecf20Sopenharmony_ci{ 5578c2ecf20Sopenharmony_ci struct ino_entry *e, *tmp; 5588c2ecf20Sopenharmony_ci int i; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci for (i = all ? ORPHAN_INO : APPEND_INO; i < MAX_INO_ENTRY; i++) { 5618c2ecf20Sopenharmony_ci struct inode_management *im = &sbi->im[i]; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci spin_lock(&im->ino_lock); 5648c2ecf20Sopenharmony_ci list_for_each_entry_safe(e, tmp, &im->ino_list, list) { 5658c2ecf20Sopenharmony_ci list_del(&e->list); 5668c2ecf20Sopenharmony_ci radix_tree_delete(&im->ino_root, e->ino); 5678c2ecf20Sopenharmony_ci kmem_cache_free(ino_entry_slab, e); 5688c2ecf20Sopenharmony_ci im->ino_num--; 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci spin_unlock(&im->ino_lock); 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci} 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_civoid f2fs_set_dirty_device(struct f2fs_sb_info *sbi, nid_t ino, 5758c2ecf20Sopenharmony_ci unsigned int devidx, int type) 5768c2ecf20Sopenharmony_ci{ 5778c2ecf20Sopenharmony_ci __add_ino_entry(sbi, ino, devidx, type); 5788c2ecf20Sopenharmony_ci} 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_cibool f2fs_is_dirty_device(struct f2fs_sb_info *sbi, nid_t ino, 5818c2ecf20Sopenharmony_ci unsigned int devidx, int type) 5828c2ecf20Sopenharmony_ci{ 5838c2ecf20Sopenharmony_ci struct inode_management *im = &sbi->im[type]; 5848c2ecf20Sopenharmony_ci struct ino_entry *e; 5858c2ecf20Sopenharmony_ci bool is_dirty = false; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci spin_lock(&im->ino_lock); 5888c2ecf20Sopenharmony_ci e = radix_tree_lookup(&im->ino_root, ino); 5898c2ecf20Sopenharmony_ci if (e && f2fs_test_bit(devidx, (char *)&e->dirty_device)) 5908c2ecf20Sopenharmony_ci is_dirty = true; 5918c2ecf20Sopenharmony_ci spin_unlock(&im->ino_lock); 5928c2ecf20Sopenharmony_ci return is_dirty; 5938c2ecf20Sopenharmony_ci} 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ciint f2fs_acquire_orphan_inode(struct f2fs_sb_info *sbi) 5968c2ecf20Sopenharmony_ci{ 5978c2ecf20Sopenharmony_ci struct inode_management *im = &sbi->im[ORPHAN_INO]; 5988c2ecf20Sopenharmony_ci int err = 0; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci spin_lock(&im->ino_lock); 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci if (time_to_inject(sbi, FAULT_ORPHAN)) { 6038c2ecf20Sopenharmony_ci spin_unlock(&im->ino_lock); 6048c2ecf20Sopenharmony_ci f2fs_show_injection_info(sbi, FAULT_ORPHAN); 6058c2ecf20Sopenharmony_ci return -ENOSPC; 6068c2ecf20Sopenharmony_ci } 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci if (unlikely(im->ino_num >= sbi->max_orphans)) 6098c2ecf20Sopenharmony_ci err = -ENOSPC; 6108c2ecf20Sopenharmony_ci else 6118c2ecf20Sopenharmony_ci im->ino_num++; 6128c2ecf20Sopenharmony_ci spin_unlock(&im->ino_lock); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci return err; 6158c2ecf20Sopenharmony_ci} 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_civoid f2fs_release_orphan_inode(struct f2fs_sb_info *sbi) 6188c2ecf20Sopenharmony_ci{ 6198c2ecf20Sopenharmony_ci struct inode_management *im = &sbi->im[ORPHAN_INO]; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci spin_lock(&im->ino_lock); 6228c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, im->ino_num == 0); 6238c2ecf20Sopenharmony_ci im->ino_num--; 6248c2ecf20Sopenharmony_ci spin_unlock(&im->ino_lock); 6258c2ecf20Sopenharmony_ci} 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_civoid f2fs_add_orphan_inode(struct inode *inode) 6288c2ecf20Sopenharmony_ci{ 6298c2ecf20Sopenharmony_ci /* add new orphan ino entry into list */ 6308c2ecf20Sopenharmony_ci __add_ino_entry(F2FS_I_SB(inode), inode->i_ino, 0, ORPHAN_INO); 6318c2ecf20Sopenharmony_ci f2fs_update_inode_page(inode); 6328c2ecf20Sopenharmony_ci} 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_civoid f2fs_remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) 6358c2ecf20Sopenharmony_ci{ 6368c2ecf20Sopenharmony_ci /* remove orphan entry from orphan list */ 6378c2ecf20Sopenharmony_ci __remove_ino_entry(sbi, ino, ORPHAN_INO); 6388c2ecf20Sopenharmony_ci} 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_cistatic int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) 6418c2ecf20Sopenharmony_ci{ 6428c2ecf20Sopenharmony_ci struct inode *inode; 6438c2ecf20Sopenharmony_ci struct node_info ni; 6448c2ecf20Sopenharmony_ci int err; 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci inode = f2fs_iget_retry(sbi->sb, ino); 6478c2ecf20Sopenharmony_ci if (IS_ERR(inode)) { 6488c2ecf20Sopenharmony_ci /* 6498c2ecf20Sopenharmony_ci * there should be a bug that we can't find the entry 6508c2ecf20Sopenharmony_ci * to orphan inode. 6518c2ecf20Sopenharmony_ci */ 6528c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, PTR_ERR(inode) == -ENOENT); 6538c2ecf20Sopenharmony_ci return PTR_ERR(inode); 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci err = dquot_initialize(inode); 6578c2ecf20Sopenharmony_ci if (err) { 6588c2ecf20Sopenharmony_ci iput(inode); 6598c2ecf20Sopenharmony_ci goto err_out; 6608c2ecf20Sopenharmony_ci } 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci clear_nlink(inode); 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci /* truncate all the data during iput */ 6658c2ecf20Sopenharmony_ci iput(inode); 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci err = f2fs_get_node_info(sbi, ino, &ni); 6688c2ecf20Sopenharmony_ci if (err) 6698c2ecf20Sopenharmony_ci goto err_out; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci /* ENOMEM was fully retried in f2fs_evict_inode. */ 6728c2ecf20Sopenharmony_ci if (ni.blk_addr != NULL_ADDR) { 6738c2ecf20Sopenharmony_ci err = -EIO; 6748c2ecf20Sopenharmony_ci goto err_out; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci return 0; 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_cierr_out: 6798c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_FSCK); 6808c2ecf20Sopenharmony_ci f2fs_warn(sbi, "%s: orphan failed (ino=%x), run fsck to fix.", 6818c2ecf20Sopenharmony_ci __func__, ino); 6828c2ecf20Sopenharmony_ci return err; 6838c2ecf20Sopenharmony_ci} 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ciint f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi) 6868c2ecf20Sopenharmony_ci{ 6878c2ecf20Sopenharmony_ci block_t start_blk, orphan_blocks, i, j; 6888c2ecf20Sopenharmony_ci unsigned int s_flags = sbi->sb->s_flags; 6898c2ecf20Sopenharmony_ci int err = 0; 6908c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 6918c2ecf20Sopenharmony_ci int quota_enabled; 6928c2ecf20Sopenharmony_ci#endif 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci if (!is_set_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG)) 6958c2ecf20Sopenharmony_ci return 0; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci if (bdev_read_only(sbi->sb->s_bdev)) { 6988c2ecf20Sopenharmony_ci f2fs_info(sbi, "write access unavailable, skipping orphan cleanup"); 6998c2ecf20Sopenharmony_ci return 0; 7008c2ecf20Sopenharmony_ci } 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci if (s_flags & SB_RDONLY) { 7038c2ecf20Sopenharmony_ci f2fs_info(sbi, "orphan cleanup on readonly fs"); 7048c2ecf20Sopenharmony_ci sbi->sb->s_flags &= ~SB_RDONLY; 7058c2ecf20Sopenharmony_ci } 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 7088c2ecf20Sopenharmony_ci /* Needed for iput() to work correctly and not trash data */ 7098c2ecf20Sopenharmony_ci sbi->sb->s_flags |= SB_ACTIVE; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci /* 7128c2ecf20Sopenharmony_ci * Turn on quotas which were not enabled for read-only mounts if 7138c2ecf20Sopenharmony_ci * filesystem has quota feature, so that they are updated correctly. 7148c2ecf20Sopenharmony_ci */ 7158c2ecf20Sopenharmony_ci quota_enabled = f2fs_enable_quota_files(sbi, s_flags & SB_RDONLY); 7168c2ecf20Sopenharmony_ci#endif 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci start_blk = __start_cp_addr(sbi) + 1 + __cp_payload(sbi); 7198c2ecf20Sopenharmony_ci orphan_blocks = __start_sum_addr(sbi) - 1 - __cp_payload(sbi); 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci f2fs_ra_meta_pages(sbi, start_blk, orphan_blocks, META_CP, true); 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci for (i = 0; i < orphan_blocks; i++) { 7248c2ecf20Sopenharmony_ci struct page *page; 7258c2ecf20Sopenharmony_ci struct f2fs_orphan_block *orphan_blk; 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci page = f2fs_get_meta_page(sbi, start_blk + i); 7288c2ecf20Sopenharmony_ci if (IS_ERR(page)) { 7298c2ecf20Sopenharmony_ci err = PTR_ERR(page); 7308c2ecf20Sopenharmony_ci goto out; 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci orphan_blk = (struct f2fs_orphan_block *)page_address(page); 7348c2ecf20Sopenharmony_ci for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) { 7358c2ecf20Sopenharmony_ci nid_t ino = le32_to_cpu(orphan_blk->ino[j]); 7368c2ecf20Sopenharmony_ci err = recover_orphan_inode(sbi, ino); 7378c2ecf20Sopenharmony_ci if (err) { 7388c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 7398c2ecf20Sopenharmony_ci goto out; 7408c2ecf20Sopenharmony_ci } 7418c2ecf20Sopenharmony_ci } 7428c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci /* clear Orphan Flag */ 7458c2ecf20Sopenharmony_ci clear_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG); 7468c2ecf20Sopenharmony_ciout: 7478c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_IS_RECOVERED); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci#ifdef CONFIG_QUOTA 7508c2ecf20Sopenharmony_ci /* Turn quotas off */ 7518c2ecf20Sopenharmony_ci if (quota_enabled) 7528c2ecf20Sopenharmony_ci f2fs_quota_off_umount(sbi->sb); 7538c2ecf20Sopenharmony_ci#endif 7548c2ecf20Sopenharmony_ci sbi->sb->s_flags = s_flags; /* Restore SB_RDONLY status */ 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci return err; 7578c2ecf20Sopenharmony_ci} 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_cistatic void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) 7608c2ecf20Sopenharmony_ci{ 7618c2ecf20Sopenharmony_ci struct list_head *head; 7628c2ecf20Sopenharmony_ci struct f2fs_orphan_block *orphan_blk = NULL; 7638c2ecf20Sopenharmony_ci unsigned int nentries = 0; 7648c2ecf20Sopenharmony_ci unsigned short index = 1; 7658c2ecf20Sopenharmony_ci unsigned short orphan_blocks; 7668c2ecf20Sopenharmony_ci struct page *page = NULL; 7678c2ecf20Sopenharmony_ci struct ino_entry *orphan = NULL; 7688c2ecf20Sopenharmony_ci struct inode_management *im = &sbi->im[ORPHAN_INO]; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci orphan_blocks = GET_ORPHAN_BLOCKS(im->ino_num); 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci /* 7738c2ecf20Sopenharmony_ci * we don't need to do spin_lock(&im->ino_lock) here, since all the 7748c2ecf20Sopenharmony_ci * orphan inode operations are covered under f2fs_lock_op(). 7758c2ecf20Sopenharmony_ci * And, spin_lock should be avoided due to page operations below. 7768c2ecf20Sopenharmony_ci */ 7778c2ecf20Sopenharmony_ci head = &im->ino_list; 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci /* loop for each orphan inode entry and write them in Jornal block */ 7808c2ecf20Sopenharmony_ci list_for_each_entry(orphan, head, list) { 7818c2ecf20Sopenharmony_ci if (!page) { 7828c2ecf20Sopenharmony_ci page = f2fs_grab_meta_page(sbi, start_blk++); 7838c2ecf20Sopenharmony_ci orphan_blk = 7848c2ecf20Sopenharmony_ci (struct f2fs_orphan_block *)page_address(page); 7858c2ecf20Sopenharmony_ci memset(orphan_blk, 0, sizeof(*orphan_blk)); 7868c2ecf20Sopenharmony_ci } 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci if (nentries == F2FS_ORPHANS_PER_BLOCK) { 7918c2ecf20Sopenharmony_ci /* 7928c2ecf20Sopenharmony_ci * an orphan block is full of 1020 entries, 7938c2ecf20Sopenharmony_ci * then we need to flush current orphan blocks 7948c2ecf20Sopenharmony_ci * and bring another one in memory 7958c2ecf20Sopenharmony_ci */ 7968c2ecf20Sopenharmony_ci orphan_blk->blk_addr = cpu_to_le16(index); 7978c2ecf20Sopenharmony_ci orphan_blk->blk_count = cpu_to_le16(orphan_blocks); 7988c2ecf20Sopenharmony_ci orphan_blk->entry_count = cpu_to_le32(nentries); 7998c2ecf20Sopenharmony_ci set_page_dirty(page); 8008c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 8018c2ecf20Sopenharmony_ci index++; 8028c2ecf20Sopenharmony_ci nentries = 0; 8038c2ecf20Sopenharmony_ci page = NULL; 8048c2ecf20Sopenharmony_ci } 8058c2ecf20Sopenharmony_ci } 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci if (page) { 8088c2ecf20Sopenharmony_ci orphan_blk->blk_addr = cpu_to_le16(index); 8098c2ecf20Sopenharmony_ci orphan_blk->blk_count = cpu_to_le16(orphan_blocks); 8108c2ecf20Sopenharmony_ci orphan_blk->entry_count = cpu_to_le32(nentries); 8118c2ecf20Sopenharmony_ci set_page_dirty(page); 8128c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 8138c2ecf20Sopenharmony_ci } 8148c2ecf20Sopenharmony_ci} 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_cistatic __u32 f2fs_checkpoint_chksum(struct f2fs_sb_info *sbi, 8178c2ecf20Sopenharmony_ci struct f2fs_checkpoint *ckpt) 8188c2ecf20Sopenharmony_ci{ 8198c2ecf20Sopenharmony_ci unsigned int chksum_ofs = le32_to_cpu(ckpt->checksum_offset); 8208c2ecf20Sopenharmony_ci __u32 chksum; 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci chksum = f2fs_crc32(sbi, ckpt, chksum_ofs); 8238c2ecf20Sopenharmony_ci if (chksum_ofs < CP_CHKSUM_OFFSET) { 8248c2ecf20Sopenharmony_ci chksum_ofs += sizeof(chksum); 8258c2ecf20Sopenharmony_ci chksum = f2fs_chksum(sbi, chksum, (__u8 *)ckpt + chksum_ofs, 8268c2ecf20Sopenharmony_ci F2FS_BLKSIZE - chksum_ofs); 8278c2ecf20Sopenharmony_ci } 8288c2ecf20Sopenharmony_ci return chksum; 8298c2ecf20Sopenharmony_ci} 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_cistatic int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr, 8328c2ecf20Sopenharmony_ci struct f2fs_checkpoint **cp_block, struct page **cp_page, 8338c2ecf20Sopenharmony_ci unsigned long long *version) 8348c2ecf20Sopenharmony_ci{ 8358c2ecf20Sopenharmony_ci size_t crc_offset = 0; 8368c2ecf20Sopenharmony_ci __u32 crc; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci *cp_page = f2fs_get_meta_page(sbi, cp_addr); 8398c2ecf20Sopenharmony_ci if (IS_ERR(*cp_page)) 8408c2ecf20Sopenharmony_ci return PTR_ERR(*cp_page); 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci *cp_block = (struct f2fs_checkpoint *)page_address(*cp_page); 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci crc_offset = le32_to_cpu((*cp_block)->checksum_offset); 8458c2ecf20Sopenharmony_ci if (crc_offset < CP_MIN_CHKSUM_OFFSET || 8468c2ecf20Sopenharmony_ci crc_offset > CP_CHKSUM_OFFSET) { 8478c2ecf20Sopenharmony_ci f2fs_put_page(*cp_page, 1); 8488c2ecf20Sopenharmony_ci f2fs_warn(sbi, "invalid crc_offset: %zu", crc_offset); 8498c2ecf20Sopenharmony_ci return -EINVAL; 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci crc = f2fs_checkpoint_chksum(sbi, *cp_block); 8538c2ecf20Sopenharmony_ci if (crc != cur_cp_crc(*cp_block)) { 8548c2ecf20Sopenharmony_ci f2fs_put_page(*cp_page, 1); 8558c2ecf20Sopenharmony_ci f2fs_warn(sbi, "invalid crc value"); 8568c2ecf20Sopenharmony_ci return -EINVAL; 8578c2ecf20Sopenharmony_ci } 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci *version = cur_cp_version(*cp_block); 8608c2ecf20Sopenharmony_ci return 0; 8618c2ecf20Sopenharmony_ci} 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_cistatic struct page *validate_checkpoint(struct f2fs_sb_info *sbi, 8648c2ecf20Sopenharmony_ci block_t cp_addr, unsigned long long *version) 8658c2ecf20Sopenharmony_ci{ 8668c2ecf20Sopenharmony_ci struct page *cp_page_1 = NULL, *cp_page_2 = NULL; 8678c2ecf20Sopenharmony_ci struct f2fs_checkpoint *cp_block = NULL; 8688c2ecf20Sopenharmony_ci unsigned long long cur_version = 0, pre_version = 0; 8698c2ecf20Sopenharmony_ci unsigned int cp_blocks; 8708c2ecf20Sopenharmony_ci int err; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci err = get_checkpoint_version(sbi, cp_addr, &cp_block, 8738c2ecf20Sopenharmony_ci &cp_page_1, version); 8748c2ecf20Sopenharmony_ci if (err) 8758c2ecf20Sopenharmony_ci return NULL; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci cp_blocks = le32_to_cpu(cp_block->cp_pack_total_block_count); 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci if (cp_blocks > sbi->blocks_per_seg || cp_blocks <= F2FS_CP_PACKS) { 8808c2ecf20Sopenharmony_ci f2fs_warn(sbi, "invalid cp_pack_total_block_count:%u", 8818c2ecf20Sopenharmony_ci le32_to_cpu(cp_block->cp_pack_total_block_count)); 8828c2ecf20Sopenharmony_ci goto invalid_cp; 8838c2ecf20Sopenharmony_ci } 8848c2ecf20Sopenharmony_ci pre_version = *version; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci cp_addr += cp_blocks - 1; 8878c2ecf20Sopenharmony_ci err = get_checkpoint_version(sbi, cp_addr, &cp_block, 8888c2ecf20Sopenharmony_ci &cp_page_2, version); 8898c2ecf20Sopenharmony_ci if (err) 8908c2ecf20Sopenharmony_ci goto invalid_cp; 8918c2ecf20Sopenharmony_ci cur_version = *version; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci if (cur_version == pre_version) { 8948c2ecf20Sopenharmony_ci *version = cur_version; 8958c2ecf20Sopenharmony_ci f2fs_put_page(cp_page_2, 1); 8968c2ecf20Sopenharmony_ci return cp_page_1; 8978c2ecf20Sopenharmony_ci } 8988c2ecf20Sopenharmony_ci f2fs_put_page(cp_page_2, 1); 8998c2ecf20Sopenharmony_ciinvalid_cp: 9008c2ecf20Sopenharmony_ci f2fs_put_page(cp_page_1, 1); 9018c2ecf20Sopenharmony_ci return NULL; 9028c2ecf20Sopenharmony_ci} 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ciint f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi) 9058c2ecf20Sopenharmony_ci{ 9068c2ecf20Sopenharmony_ci struct f2fs_checkpoint *cp_block; 9078c2ecf20Sopenharmony_ci struct f2fs_super_block *fsb = sbi->raw_super; 9088c2ecf20Sopenharmony_ci struct page *cp1, *cp2, *cur_page; 9098c2ecf20Sopenharmony_ci unsigned long blk_size = sbi->blocksize; 9108c2ecf20Sopenharmony_ci unsigned long long cp1_version = 0, cp2_version = 0; 9118c2ecf20Sopenharmony_ci unsigned long long cp_start_blk_no; 9128c2ecf20Sopenharmony_ci unsigned int cp_blks = 1 + __cp_payload(sbi); 9138c2ecf20Sopenharmony_ci block_t cp_blk_no; 9148c2ecf20Sopenharmony_ci int i; 9158c2ecf20Sopenharmony_ci int err; 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci sbi->ckpt = f2fs_kvzalloc(sbi, array_size(blk_size, cp_blks), 9188c2ecf20Sopenharmony_ci GFP_KERNEL); 9198c2ecf20Sopenharmony_ci if (!sbi->ckpt) 9208c2ecf20Sopenharmony_ci return -ENOMEM; 9218c2ecf20Sopenharmony_ci /* 9228c2ecf20Sopenharmony_ci * Finding out valid cp block involves read both 9238c2ecf20Sopenharmony_ci * sets( cp pack 1 and cp pack 2) 9248c2ecf20Sopenharmony_ci */ 9258c2ecf20Sopenharmony_ci cp_start_blk_no = le32_to_cpu(fsb->cp_blkaddr); 9268c2ecf20Sopenharmony_ci cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version); 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci /* The second checkpoint pack should start at the next segment */ 9298c2ecf20Sopenharmony_ci cp_start_blk_no += ((unsigned long long)1) << 9308c2ecf20Sopenharmony_ci le32_to_cpu(fsb->log_blocks_per_seg); 9318c2ecf20Sopenharmony_ci cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci if (cp1 && cp2) { 9348c2ecf20Sopenharmony_ci if (ver_after(cp2_version, cp1_version)) 9358c2ecf20Sopenharmony_ci cur_page = cp2; 9368c2ecf20Sopenharmony_ci else 9378c2ecf20Sopenharmony_ci cur_page = cp1; 9388c2ecf20Sopenharmony_ci } else if (cp1) { 9398c2ecf20Sopenharmony_ci cur_page = cp1; 9408c2ecf20Sopenharmony_ci } else if (cp2) { 9418c2ecf20Sopenharmony_ci cur_page = cp2; 9428c2ecf20Sopenharmony_ci } else { 9438c2ecf20Sopenharmony_ci err = -EFSCORRUPTED; 9448c2ecf20Sopenharmony_ci goto fail_no_cp; 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci cp_block = (struct f2fs_checkpoint *)page_address(cur_page); 9488c2ecf20Sopenharmony_ci memcpy(sbi->ckpt, cp_block, blk_size); 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci if (cur_page == cp1) 9518c2ecf20Sopenharmony_ci sbi->cur_cp_pack = 1; 9528c2ecf20Sopenharmony_ci else 9538c2ecf20Sopenharmony_ci sbi->cur_cp_pack = 2; 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci /* Sanity checking of checkpoint */ 9568c2ecf20Sopenharmony_ci if (f2fs_sanity_check_ckpt(sbi)) { 9578c2ecf20Sopenharmony_ci err = -EFSCORRUPTED; 9588c2ecf20Sopenharmony_ci goto free_fail_no_cp; 9598c2ecf20Sopenharmony_ci } 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci if (cp_blks <= 1) 9628c2ecf20Sopenharmony_ci goto done; 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci cp_blk_no = le32_to_cpu(fsb->cp_blkaddr); 9658c2ecf20Sopenharmony_ci if (cur_page == cp2) 9668c2ecf20Sopenharmony_ci cp_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg); 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci for (i = 1; i < cp_blks; i++) { 9698c2ecf20Sopenharmony_ci void *sit_bitmap_ptr; 9708c2ecf20Sopenharmony_ci unsigned char *ckpt = (unsigned char *)sbi->ckpt; 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci cur_page = f2fs_get_meta_page(sbi, cp_blk_no + i); 9738c2ecf20Sopenharmony_ci if (IS_ERR(cur_page)) { 9748c2ecf20Sopenharmony_ci err = PTR_ERR(cur_page); 9758c2ecf20Sopenharmony_ci goto free_fail_no_cp; 9768c2ecf20Sopenharmony_ci } 9778c2ecf20Sopenharmony_ci sit_bitmap_ptr = page_address(cur_page); 9788c2ecf20Sopenharmony_ci memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size); 9798c2ecf20Sopenharmony_ci f2fs_put_page(cur_page, 1); 9808c2ecf20Sopenharmony_ci } 9818c2ecf20Sopenharmony_cidone: 9828c2ecf20Sopenharmony_ci f2fs_put_page(cp1, 1); 9838c2ecf20Sopenharmony_ci f2fs_put_page(cp2, 1); 9848c2ecf20Sopenharmony_ci return 0; 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_cifree_fail_no_cp: 9878c2ecf20Sopenharmony_ci f2fs_put_page(cp1, 1); 9888c2ecf20Sopenharmony_ci f2fs_put_page(cp2, 1); 9898c2ecf20Sopenharmony_cifail_no_cp: 9908c2ecf20Sopenharmony_ci kvfree(sbi->ckpt); 9918c2ecf20Sopenharmony_ci return err; 9928c2ecf20Sopenharmony_ci} 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_cistatic void __add_dirty_inode(struct inode *inode, enum inode_type type) 9958c2ecf20Sopenharmony_ci{ 9968c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 9978c2ecf20Sopenharmony_ci int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE; 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci if (is_inode_flag_set(inode, flag)) 10008c2ecf20Sopenharmony_ci return; 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci set_inode_flag(inode, flag); 10038c2ecf20Sopenharmony_ci if (!f2fs_is_volatile_file(inode)) 10048c2ecf20Sopenharmony_ci list_add_tail(&F2FS_I(inode)->dirty_list, 10058c2ecf20Sopenharmony_ci &sbi->inode_list[type]); 10068c2ecf20Sopenharmony_ci stat_inc_dirty_inode(sbi, type); 10078c2ecf20Sopenharmony_ci} 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_cistatic void __remove_dirty_inode(struct inode *inode, enum inode_type type) 10108c2ecf20Sopenharmony_ci{ 10118c2ecf20Sopenharmony_ci int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE; 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci if (get_dirty_pages(inode) || !is_inode_flag_set(inode, flag)) 10148c2ecf20Sopenharmony_ci return; 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci list_del_init(&F2FS_I(inode)->dirty_list); 10178c2ecf20Sopenharmony_ci clear_inode_flag(inode, flag); 10188c2ecf20Sopenharmony_ci stat_dec_dirty_inode(F2FS_I_SB(inode), type); 10198c2ecf20Sopenharmony_ci} 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_civoid f2fs_update_dirty_page(struct inode *inode, struct page *page) 10228c2ecf20Sopenharmony_ci{ 10238c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 10248c2ecf20Sopenharmony_ci enum inode_type type = S_ISDIR(inode->i_mode) ? DIR_INODE : FILE_INODE; 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) && 10278c2ecf20Sopenharmony_ci !S_ISLNK(inode->i_mode)) 10288c2ecf20Sopenharmony_ci return; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci spin_lock(&sbi->inode_lock[type]); 10318c2ecf20Sopenharmony_ci if (type != FILE_INODE || test_opt(sbi, DATA_FLUSH)) 10328c2ecf20Sopenharmony_ci __add_dirty_inode(inode, type); 10338c2ecf20Sopenharmony_ci inode_inc_dirty_pages(inode); 10348c2ecf20Sopenharmony_ci spin_unlock(&sbi->inode_lock[type]); 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci f2fs_set_page_private(page, 0); 10378c2ecf20Sopenharmony_ci f2fs_trace_pid(page); 10388c2ecf20Sopenharmony_ci} 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_civoid f2fs_remove_dirty_inode(struct inode *inode) 10418c2ecf20Sopenharmony_ci{ 10428c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 10438c2ecf20Sopenharmony_ci enum inode_type type = S_ISDIR(inode->i_mode) ? DIR_INODE : FILE_INODE; 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) && 10468c2ecf20Sopenharmony_ci !S_ISLNK(inode->i_mode)) 10478c2ecf20Sopenharmony_ci return; 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci if (type == FILE_INODE && !test_opt(sbi, DATA_FLUSH)) 10508c2ecf20Sopenharmony_ci return; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci spin_lock(&sbi->inode_lock[type]); 10538c2ecf20Sopenharmony_ci __remove_dirty_inode(inode, type); 10548c2ecf20Sopenharmony_ci spin_unlock(&sbi->inode_lock[type]); 10558c2ecf20Sopenharmony_ci} 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ciint f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type, 10588c2ecf20Sopenharmony_ci bool from_cp) 10598c2ecf20Sopenharmony_ci{ 10608c2ecf20Sopenharmony_ci struct list_head *head; 10618c2ecf20Sopenharmony_ci struct inode *inode; 10628c2ecf20Sopenharmony_ci struct f2fs_inode_info *fi; 10638c2ecf20Sopenharmony_ci bool is_dir = (type == DIR_INODE); 10648c2ecf20Sopenharmony_ci unsigned long ino = 0; 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci trace_f2fs_sync_dirty_inodes_enter(sbi->sb, is_dir, 10678c2ecf20Sopenharmony_ci get_pages(sbi, is_dir ? 10688c2ecf20Sopenharmony_ci F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA)); 10698c2ecf20Sopenharmony_ciretry: 10708c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 10718c2ecf20Sopenharmony_ci trace_f2fs_sync_dirty_inodes_exit(sbi->sb, is_dir, 10728c2ecf20Sopenharmony_ci get_pages(sbi, is_dir ? 10738c2ecf20Sopenharmony_ci F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA)); 10748c2ecf20Sopenharmony_ci return -EIO; 10758c2ecf20Sopenharmony_ci } 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci spin_lock(&sbi->inode_lock[type]); 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci head = &sbi->inode_list[type]; 10808c2ecf20Sopenharmony_ci if (list_empty(head)) { 10818c2ecf20Sopenharmony_ci spin_unlock(&sbi->inode_lock[type]); 10828c2ecf20Sopenharmony_ci trace_f2fs_sync_dirty_inodes_exit(sbi->sb, is_dir, 10838c2ecf20Sopenharmony_ci get_pages(sbi, is_dir ? 10848c2ecf20Sopenharmony_ci F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA)); 10858c2ecf20Sopenharmony_ci return 0; 10868c2ecf20Sopenharmony_ci } 10878c2ecf20Sopenharmony_ci fi = list_first_entry(head, struct f2fs_inode_info, dirty_list); 10888c2ecf20Sopenharmony_ci inode = igrab(&fi->vfs_inode); 10898c2ecf20Sopenharmony_ci spin_unlock(&sbi->inode_lock[type]); 10908c2ecf20Sopenharmony_ci if (inode) { 10918c2ecf20Sopenharmony_ci unsigned long cur_ino = inode->i_ino; 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci if (from_cp) 10948c2ecf20Sopenharmony_ci F2FS_I(inode)->cp_task = current; 10958c2ecf20Sopenharmony_ci F2FS_I(inode)->wb_task = current; 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci filemap_fdatawrite(inode->i_mapping); 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci F2FS_I(inode)->wb_task = NULL; 11008c2ecf20Sopenharmony_ci if (from_cp) 11018c2ecf20Sopenharmony_ci F2FS_I(inode)->cp_task = NULL; 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci iput(inode); 11048c2ecf20Sopenharmony_ci /* We need to give cpu to another writers. */ 11058c2ecf20Sopenharmony_ci if (ino == cur_ino) 11068c2ecf20Sopenharmony_ci cond_resched(); 11078c2ecf20Sopenharmony_ci else 11088c2ecf20Sopenharmony_ci ino = cur_ino; 11098c2ecf20Sopenharmony_ci } else { 11108c2ecf20Sopenharmony_ci /* 11118c2ecf20Sopenharmony_ci * We should submit bio, since it exists several 11128c2ecf20Sopenharmony_ci * wribacking dentry pages in the freeing inode. 11138c2ecf20Sopenharmony_ci */ 11148c2ecf20Sopenharmony_ci f2fs_submit_merged_write(sbi, DATA); 11158c2ecf20Sopenharmony_ci cond_resched(); 11168c2ecf20Sopenharmony_ci } 11178c2ecf20Sopenharmony_ci goto retry; 11188c2ecf20Sopenharmony_ci} 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ciint f2fs_sync_inode_meta(struct f2fs_sb_info *sbi) 11218c2ecf20Sopenharmony_ci{ 11228c2ecf20Sopenharmony_ci struct list_head *head = &sbi->inode_list[DIRTY_META]; 11238c2ecf20Sopenharmony_ci struct inode *inode; 11248c2ecf20Sopenharmony_ci struct f2fs_inode_info *fi; 11258c2ecf20Sopenharmony_ci s64 total = get_pages(sbi, F2FS_DIRTY_IMETA); 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci while (total--) { 11288c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) 11298c2ecf20Sopenharmony_ci return -EIO; 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci spin_lock(&sbi->inode_lock[DIRTY_META]); 11328c2ecf20Sopenharmony_ci if (list_empty(head)) { 11338c2ecf20Sopenharmony_ci spin_unlock(&sbi->inode_lock[DIRTY_META]); 11348c2ecf20Sopenharmony_ci return 0; 11358c2ecf20Sopenharmony_ci } 11368c2ecf20Sopenharmony_ci fi = list_first_entry(head, struct f2fs_inode_info, 11378c2ecf20Sopenharmony_ci gdirty_list); 11388c2ecf20Sopenharmony_ci inode = igrab(&fi->vfs_inode); 11398c2ecf20Sopenharmony_ci spin_unlock(&sbi->inode_lock[DIRTY_META]); 11408c2ecf20Sopenharmony_ci if (inode) { 11418c2ecf20Sopenharmony_ci sync_inode_metadata(inode, 0); 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci /* it's on eviction */ 11448c2ecf20Sopenharmony_ci if (is_inode_flag_set(inode, FI_DIRTY_INODE)) 11458c2ecf20Sopenharmony_ci f2fs_update_inode_page(inode); 11468c2ecf20Sopenharmony_ci iput(inode); 11478c2ecf20Sopenharmony_ci } 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci return 0; 11508c2ecf20Sopenharmony_ci} 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_cistatic void __prepare_cp_block(struct f2fs_sb_info *sbi) 11538c2ecf20Sopenharmony_ci{ 11548c2ecf20Sopenharmony_ci struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); 11558c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 11568c2ecf20Sopenharmony_ci nid_t last_nid = nm_i->next_scan_nid; 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci next_free_nid(sbi, &last_nid); 11598c2ecf20Sopenharmony_ci ckpt->valid_block_count = cpu_to_le64(valid_user_blocks(sbi)); 11608c2ecf20Sopenharmony_ci ckpt->valid_node_count = cpu_to_le32(valid_node_count(sbi)); 11618c2ecf20Sopenharmony_ci ckpt->valid_inode_count = cpu_to_le32(valid_inode_count(sbi)); 11628c2ecf20Sopenharmony_ci ckpt->next_free_nid = cpu_to_le32(last_nid); 11638c2ecf20Sopenharmony_ci} 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_cistatic bool __need_flush_quota(struct f2fs_sb_info *sbi) 11668c2ecf20Sopenharmony_ci{ 11678c2ecf20Sopenharmony_ci bool ret = false; 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci if (!is_journalled_quota(sbi)) 11708c2ecf20Sopenharmony_ci return false; 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci if (!down_write_trylock(&sbi->quota_sem)) 11738c2ecf20Sopenharmony_ci return true; 11748c2ecf20Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH)) { 11758c2ecf20Sopenharmony_ci ret = false; 11768c2ecf20Sopenharmony_ci } else if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR)) { 11778c2ecf20Sopenharmony_ci ret = false; 11788c2ecf20Sopenharmony_ci } else if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_FLUSH)) { 11798c2ecf20Sopenharmony_ci clear_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH); 11808c2ecf20Sopenharmony_ci ret = true; 11818c2ecf20Sopenharmony_ci } else if (get_pages(sbi, F2FS_DIRTY_QDATA)) { 11828c2ecf20Sopenharmony_ci ret = true; 11838c2ecf20Sopenharmony_ci } 11848c2ecf20Sopenharmony_ci up_write(&sbi->quota_sem); 11858c2ecf20Sopenharmony_ci return ret; 11868c2ecf20Sopenharmony_ci} 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci/* 11898c2ecf20Sopenharmony_ci * Freeze all the FS-operations for checkpoint. 11908c2ecf20Sopenharmony_ci */ 11918c2ecf20Sopenharmony_cistatic int block_operations(struct f2fs_sb_info *sbi) 11928c2ecf20Sopenharmony_ci{ 11938c2ecf20Sopenharmony_ci struct writeback_control wbc = { 11948c2ecf20Sopenharmony_ci .sync_mode = WB_SYNC_ALL, 11958c2ecf20Sopenharmony_ci .nr_to_write = LONG_MAX, 11968c2ecf20Sopenharmony_ci .for_reclaim = 0, 11978c2ecf20Sopenharmony_ci }; 11988c2ecf20Sopenharmony_ci int err = 0, cnt = 0; 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci /* 12018c2ecf20Sopenharmony_ci * Let's flush inline_data in dirty node pages. 12028c2ecf20Sopenharmony_ci */ 12038c2ecf20Sopenharmony_ci f2fs_flush_inline_data(sbi); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ciretry_flush_quotas: 12068c2ecf20Sopenharmony_ci f2fs_lock_all(sbi); 12078c2ecf20Sopenharmony_ci if (__need_flush_quota(sbi)) { 12088c2ecf20Sopenharmony_ci int locked; 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci if (++cnt > DEFAULT_RETRY_QUOTA_FLUSH_COUNT) { 12118c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_QUOTA_SKIP_FLUSH); 12128c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH); 12138c2ecf20Sopenharmony_ci goto retry_flush_dents; 12148c2ecf20Sopenharmony_ci } 12158c2ecf20Sopenharmony_ci f2fs_unlock_all(sbi); 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci /* only failed during mount/umount/freeze/quotactl */ 12188c2ecf20Sopenharmony_ci locked = down_read_trylock(&sbi->sb->s_umount); 12198c2ecf20Sopenharmony_ci f2fs_quota_sync(sbi->sb, -1); 12208c2ecf20Sopenharmony_ci if (locked) 12218c2ecf20Sopenharmony_ci up_read(&sbi->sb->s_umount); 12228c2ecf20Sopenharmony_ci cond_resched(); 12238c2ecf20Sopenharmony_ci goto retry_flush_quotas; 12248c2ecf20Sopenharmony_ci } 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ciretry_flush_dents: 12278c2ecf20Sopenharmony_ci /* write all the dirty dentry pages */ 12288c2ecf20Sopenharmony_ci if (get_pages(sbi, F2FS_DIRTY_DENTS)) { 12298c2ecf20Sopenharmony_ci f2fs_unlock_all(sbi); 12308c2ecf20Sopenharmony_ci err = f2fs_sync_dirty_inodes(sbi, DIR_INODE, true); 12318c2ecf20Sopenharmony_ci if (err) 12328c2ecf20Sopenharmony_ci return err; 12338c2ecf20Sopenharmony_ci cond_resched(); 12348c2ecf20Sopenharmony_ci goto retry_flush_quotas; 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci /* 12388c2ecf20Sopenharmony_ci * POR: we should ensure that there are no dirty node pages 12398c2ecf20Sopenharmony_ci * until finishing nat/sit flush. inode->i_blocks can be updated. 12408c2ecf20Sopenharmony_ci */ 12418c2ecf20Sopenharmony_ci down_write(&sbi->node_change); 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci if (get_pages(sbi, F2FS_DIRTY_IMETA)) { 12448c2ecf20Sopenharmony_ci up_write(&sbi->node_change); 12458c2ecf20Sopenharmony_ci f2fs_unlock_all(sbi); 12468c2ecf20Sopenharmony_ci err = f2fs_sync_inode_meta(sbi); 12478c2ecf20Sopenharmony_ci if (err) 12488c2ecf20Sopenharmony_ci return err; 12498c2ecf20Sopenharmony_ci cond_resched(); 12508c2ecf20Sopenharmony_ci goto retry_flush_quotas; 12518c2ecf20Sopenharmony_ci } 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ciretry_flush_nodes: 12548c2ecf20Sopenharmony_ci down_write(&sbi->node_write); 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci if (get_pages(sbi, F2FS_DIRTY_NODES)) { 12578c2ecf20Sopenharmony_ci up_write(&sbi->node_write); 12588c2ecf20Sopenharmony_ci atomic_inc(&sbi->wb_sync_req[NODE]); 12598c2ecf20Sopenharmony_ci err = f2fs_sync_node_pages(sbi, &wbc, false, FS_CP_NODE_IO); 12608c2ecf20Sopenharmony_ci atomic_dec(&sbi->wb_sync_req[NODE]); 12618c2ecf20Sopenharmony_ci if (err) { 12628c2ecf20Sopenharmony_ci up_write(&sbi->node_change); 12638c2ecf20Sopenharmony_ci f2fs_unlock_all(sbi); 12648c2ecf20Sopenharmony_ci return err; 12658c2ecf20Sopenharmony_ci } 12668c2ecf20Sopenharmony_ci cond_resched(); 12678c2ecf20Sopenharmony_ci goto retry_flush_nodes; 12688c2ecf20Sopenharmony_ci } 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci /* 12718c2ecf20Sopenharmony_ci * sbi->node_change is used only for AIO write_begin path which produces 12728c2ecf20Sopenharmony_ci * dirty node blocks and some checkpoint values by block allocation. 12738c2ecf20Sopenharmony_ci */ 12748c2ecf20Sopenharmony_ci __prepare_cp_block(sbi); 12758c2ecf20Sopenharmony_ci up_write(&sbi->node_change); 12768c2ecf20Sopenharmony_ci return err; 12778c2ecf20Sopenharmony_ci} 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_cistatic void unblock_operations(struct f2fs_sb_info *sbi) 12808c2ecf20Sopenharmony_ci{ 12818c2ecf20Sopenharmony_ci up_write(&sbi->node_write); 12828c2ecf20Sopenharmony_ci f2fs_unlock_all(sbi); 12838c2ecf20Sopenharmony_ci} 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_civoid f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type) 12868c2ecf20Sopenharmony_ci{ 12878c2ecf20Sopenharmony_ci DEFINE_WAIT(wait); 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci for (;;) { 12908c2ecf20Sopenharmony_ci if (!get_pages(sbi, type)) 12918c2ecf20Sopenharmony_ci break; 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi) && 12948c2ecf20Sopenharmony_ci !is_sbi_flag_set(sbi, SBI_IS_CLOSE))) 12958c2ecf20Sopenharmony_ci break; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci if (type == F2FS_DIRTY_META) 12988c2ecf20Sopenharmony_ci f2fs_sync_meta_pages(sbi, META, LONG_MAX, 12998c2ecf20Sopenharmony_ci FS_CP_META_IO); 13008c2ecf20Sopenharmony_ci else if (type == F2FS_WB_CP_DATA) 13018c2ecf20Sopenharmony_ci f2fs_submit_merged_write(sbi, DATA); 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE); 13048c2ecf20Sopenharmony_ci io_schedule_timeout(DEFAULT_IO_TIMEOUT); 13058c2ecf20Sopenharmony_ci } 13068c2ecf20Sopenharmony_ci finish_wait(&sbi->cp_wait, &wait); 13078c2ecf20Sopenharmony_ci} 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_cistatic void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) 13108c2ecf20Sopenharmony_ci{ 13118c2ecf20Sopenharmony_ci unsigned long orphan_num = sbi->im[ORPHAN_INO].ino_num; 13128c2ecf20Sopenharmony_ci struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); 13138c2ecf20Sopenharmony_ci unsigned long flags; 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci spin_lock_irqsave(&sbi->cp_lock, flags); 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci if ((cpc->reason & CP_UMOUNT) && 13188c2ecf20Sopenharmony_ci le32_to_cpu(ckpt->cp_pack_total_block_count) > 13198c2ecf20Sopenharmony_ci sbi->blocks_per_seg - NM_I(sbi)->nat_bits_blocks) 13208c2ecf20Sopenharmony_ci disable_nat_bits(sbi, false); 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci if (cpc->reason & CP_TRIMMED) 13238c2ecf20Sopenharmony_ci __set_ckpt_flags(ckpt, CP_TRIMMED_FLAG); 13248c2ecf20Sopenharmony_ci else 13258c2ecf20Sopenharmony_ci __clear_ckpt_flags(ckpt, CP_TRIMMED_FLAG); 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci if (cpc->reason & CP_UMOUNT) 13288c2ecf20Sopenharmony_ci __set_ckpt_flags(ckpt, CP_UMOUNT_FLAG); 13298c2ecf20Sopenharmony_ci else 13308c2ecf20Sopenharmony_ci __clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG); 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci if (cpc->reason & CP_FASTBOOT) 13338c2ecf20Sopenharmony_ci __set_ckpt_flags(ckpt, CP_FASTBOOT_FLAG); 13348c2ecf20Sopenharmony_ci else 13358c2ecf20Sopenharmony_ci __clear_ckpt_flags(ckpt, CP_FASTBOOT_FLAG); 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci if (orphan_num) 13388c2ecf20Sopenharmony_ci __set_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG); 13398c2ecf20Sopenharmony_ci else 13408c2ecf20Sopenharmony_ci __clear_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG); 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) 13438c2ecf20Sopenharmony_ci __set_ckpt_flags(ckpt, CP_FSCK_FLAG); 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_IS_RESIZEFS)) 13468c2ecf20Sopenharmony_ci __set_ckpt_flags(ckpt, CP_RESIZEFS_FLAG); 13478c2ecf20Sopenharmony_ci else 13488c2ecf20Sopenharmony_ci __clear_ckpt_flags(ckpt, CP_RESIZEFS_FLAG); 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_CP_DISABLED)) 13518c2ecf20Sopenharmony_ci __set_ckpt_flags(ckpt, CP_DISABLED_FLAG); 13528c2ecf20Sopenharmony_ci else 13538c2ecf20Sopenharmony_ci __clear_ckpt_flags(ckpt, CP_DISABLED_FLAG); 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_CP_DISABLED_QUICK)) 13568c2ecf20Sopenharmony_ci __set_ckpt_flags(ckpt, CP_DISABLED_QUICK_FLAG); 13578c2ecf20Sopenharmony_ci else 13588c2ecf20Sopenharmony_ci __clear_ckpt_flags(ckpt, CP_DISABLED_QUICK_FLAG); 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH)) 13618c2ecf20Sopenharmony_ci __set_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG); 13628c2ecf20Sopenharmony_ci else 13638c2ecf20Sopenharmony_ci __clear_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG); 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR)) 13668c2ecf20Sopenharmony_ci __set_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG); 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci /* set this flag to activate crc|cp_ver for recovery */ 13698c2ecf20Sopenharmony_ci __set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG); 13708c2ecf20Sopenharmony_ci __clear_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG); 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sbi->cp_lock, flags); 13738c2ecf20Sopenharmony_ci} 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_cistatic void commit_checkpoint(struct f2fs_sb_info *sbi, 13768c2ecf20Sopenharmony_ci void *src, block_t blk_addr) 13778c2ecf20Sopenharmony_ci{ 13788c2ecf20Sopenharmony_ci struct writeback_control wbc = { 13798c2ecf20Sopenharmony_ci .for_reclaim = 0, 13808c2ecf20Sopenharmony_ci }; 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci /* 13838c2ecf20Sopenharmony_ci * pagevec_lookup_tag and lock_page again will take 13848c2ecf20Sopenharmony_ci * some extra time. Therefore, f2fs_update_meta_pages and 13858c2ecf20Sopenharmony_ci * f2fs_sync_meta_pages are combined in this function. 13868c2ecf20Sopenharmony_ci */ 13878c2ecf20Sopenharmony_ci struct page *page = f2fs_grab_meta_page(sbi, blk_addr); 13888c2ecf20Sopenharmony_ci int err; 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(page, META, true, true); 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci memcpy(page_address(page), src, PAGE_SIZE); 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci set_page_dirty(page); 13958c2ecf20Sopenharmony_ci if (unlikely(!clear_page_dirty_for_io(page))) 13968c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, 1); 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci /* writeout cp pack 2 page */ 13998c2ecf20Sopenharmony_ci err = __f2fs_write_meta_page(page, &wbc, FS_CP_META_IO); 14008c2ecf20Sopenharmony_ci if (unlikely(err && f2fs_cp_error(sbi))) { 14018c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 14028c2ecf20Sopenharmony_ci return; 14038c2ecf20Sopenharmony_ci } 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, err); 14068c2ecf20Sopenharmony_ci f2fs_put_page(page, 0); 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci /* submit checkpoint (with barrier if NOBARRIER is not set) */ 14098c2ecf20Sopenharmony_ci f2fs_submit_merged_write(sbi, META_FLUSH); 14108c2ecf20Sopenharmony_ci} 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_cistatic int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) 14138c2ecf20Sopenharmony_ci{ 14148c2ecf20Sopenharmony_ci struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); 14158c2ecf20Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 14168c2ecf20Sopenharmony_ci unsigned long orphan_num = sbi->im[ORPHAN_INO].ino_num, flags; 14178c2ecf20Sopenharmony_ci block_t start_blk; 14188c2ecf20Sopenharmony_ci unsigned int data_sum_blocks, orphan_blocks; 14198c2ecf20Sopenharmony_ci __u32 crc32 = 0; 14208c2ecf20Sopenharmony_ci int i; 14218c2ecf20Sopenharmony_ci int cp_payload_blks = __cp_payload(sbi); 14228c2ecf20Sopenharmony_ci struct super_block *sb = sbi->sb; 14238c2ecf20Sopenharmony_ci struct curseg_info *seg_i = CURSEG_I(sbi, CURSEG_HOT_NODE); 14248c2ecf20Sopenharmony_ci u64 kbytes_written; 14258c2ecf20Sopenharmony_ci int err; 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci /* Flush all the NAT/SIT pages */ 14288c2ecf20Sopenharmony_ci f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO); 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci /* start to update checkpoint, cp ver is already updated previously */ 14318c2ecf20Sopenharmony_ci ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi, true)); 14328c2ecf20Sopenharmony_ci ckpt->free_segment_count = cpu_to_le32(free_segments(sbi)); 14338c2ecf20Sopenharmony_ci for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) { 14348c2ecf20Sopenharmony_ci ckpt->cur_node_segno[i] = 14358c2ecf20Sopenharmony_ci cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_NODE)); 14368c2ecf20Sopenharmony_ci ckpt->cur_node_blkoff[i] = 14378c2ecf20Sopenharmony_ci cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_NODE)); 14388c2ecf20Sopenharmony_ci ckpt->alloc_type[i + CURSEG_HOT_NODE] = 14398c2ecf20Sopenharmony_ci curseg_alloc_type(sbi, i + CURSEG_HOT_NODE); 14408c2ecf20Sopenharmony_ci } 14418c2ecf20Sopenharmony_ci for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) { 14428c2ecf20Sopenharmony_ci ckpt->cur_data_segno[i] = 14438c2ecf20Sopenharmony_ci cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_DATA)); 14448c2ecf20Sopenharmony_ci ckpt->cur_data_blkoff[i] = 14458c2ecf20Sopenharmony_ci cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_DATA)); 14468c2ecf20Sopenharmony_ci ckpt->alloc_type[i + CURSEG_HOT_DATA] = 14478c2ecf20Sopenharmony_ci curseg_alloc_type(sbi, i + CURSEG_HOT_DATA); 14488c2ecf20Sopenharmony_ci } 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci /* 2 cp + n data seg summary + orphan inode blocks */ 14518c2ecf20Sopenharmony_ci data_sum_blocks = f2fs_npages_for_summary_flush(sbi, false); 14528c2ecf20Sopenharmony_ci spin_lock_irqsave(&sbi->cp_lock, flags); 14538c2ecf20Sopenharmony_ci if (data_sum_blocks < NR_CURSEG_DATA_TYPE) 14548c2ecf20Sopenharmony_ci __set_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG); 14558c2ecf20Sopenharmony_ci else 14568c2ecf20Sopenharmony_ci __clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG); 14578c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&sbi->cp_lock, flags); 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci orphan_blocks = GET_ORPHAN_BLOCKS(orphan_num); 14608c2ecf20Sopenharmony_ci ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks + 14618c2ecf20Sopenharmony_ci orphan_blocks); 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci if (__remain_node_summaries(cpc->reason)) 14648c2ecf20Sopenharmony_ci ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS+ 14658c2ecf20Sopenharmony_ci cp_payload_blks + data_sum_blocks + 14668c2ecf20Sopenharmony_ci orphan_blocks + NR_CURSEG_NODE_TYPE); 14678c2ecf20Sopenharmony_ci else 14688c2ecf20Sopenharmony_ci ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS + 14698c2ecf20Sopenharmony_ci cp_payload_blks + data_sum_blocks + 14708c2ecf20Sopenharmony_ci orphan_blocks); 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_ci /* update ckpt flag for checkpoint */ 14738c2ecf20Sopenharmony_ci update_ckpt_flags(sbi, cpc); 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci /* update SIT/NAT bitmap */ 14768c2ecf20Sopenharmony_ci get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP)); 14778c2ecf20Sopenharmony_ci get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP)); 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci crc32 = f2fs_checkpoint_chksum(sbi, ckpt); 14808c2ecf20Sopenharmony_ci *((__le32 *)((unsigned char *)ckpt + 14818c2ecf20Sopenharmony_ci le32_to_cpu(ckpt->checksum_offset))) 14828c2ecf20Sopenharmony_ci = cpu_to_le32(crc32); 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci start_blk = __start_cp_next_addr(sbi); 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci /* write nat bits */ 14878c2ecf20Sopenharmony_ci if (enabled_nat_bits(sbi, cpc)) { 14888c2ecf20Sopenharmony_ci __u64 cp_ver = cur_cp_version(ckpt); 14898c2ecf20Sopenharmony_ci block_t blk; 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci cp_ver |= ((__u64)crc32 << 32); 14928c2ecf20Sopenharmony_ci *(__le64 *)nm_i->nat_bits = cpu_to_le64(cp_ver); 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci blk = start_blk + sbi->blocks_per_seg - nm_i->nat_bits_blocks; 14958c2ecf20Sopenharmony_ci for (i = 0; i < nm_i->nat_bits_blocks; i++) 14968c2ecf20Sopenharmony_ci f2fs_update_meta_page(sbi, nm_i->nat_bits + 14978c2ecf20Sopenharmony_ci (i << F2FS_BLKSIZE_BITS), blk + i); 14988c2ecf20Sopenharmony_ci } 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci /* write out checkpoint buffer at block 0 */ 15018c2ecf20Sopenharmony_ci f2fs_update_meta_page(sbi, ckpt, start_blk++); 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci for (i = 1; i < 1 + cp_payload_blks; i++) 15048c2ecf20Sopenharmony_ci f2fs_update_meta_page(sbi, (char *)ckpt + i * F2FS_BLKSIZE, 15058c2ecf20Sopenharmony_ci start_blk++); 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci if (orphan_num) { 15088c2ecf20Sopenharmony_ci write_orphan_inodes(sbi, start_blk); 15098c2ecf20Sopenharmony_ci start_blk += orphan_blocks; 15108c2ecf20Sopenharmony_ci } 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci f2fs_write_data_summaries(sbi, start_blk); 15138c2ecf20Sopenharmony_ci start_blk += data_sum_blocks; 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci /* Record write statistics in the hot node summary */ 15168c2ecf20Sopenharmony_ci kbytes_written = sbi->kbytes_written; 15178c2ecf20Sopenharmony_ci if (sb->s_bdev->bd_part) 15188c2ecf20Sopenharmony_ci kbytes_written += BD_PART_WRITTEN(sbi); 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci seg_i->journal->info.kbytes_written = cpu_to_le64(kbytes_written); 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci if (__remain_node_summaries(cpc->reason)) { 15238c2ecf20Sopenharmony_ci f2fs_write_node_summaries(sbi, start_blk); 15248c2ecf20Sopenharmony_ci start_blk += NR_CURSEG_NODE_TYPE; 15258c2ecf20Sopenharmony_ci } 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci /* update user_block_counts */ 15288c2ecf20Sopenharmony_ci sbi->last_valid_block_count = sbi->total_valid_block_count; 15298c2ecf20Sopenharmony_ci percpu_counter_set(&sbi->alloc_valid_block_count, 0); 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci /* Here, we have one bio having CP pack except cp pack 2 page */ 15328c2ecf20Sopenharmony_ci f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO); 15338c2ecf20Sopenharmony_ci /* Wait for all dirty meta pages to be submitted for IO */ 15348c2ecf20Sopenharmony_ci f2fs_wait_on_all_pages(sbi, F2FS_DIRTY_META); 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci /* wait for previous submitted meta pages writeback */ 15378c2ecf20Sopenharmony_ci f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA); 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci /* flush all device cache */ 15408c2ecf20Sopenharmony_ci err = f2fs_flush_device_cache(sbi); 15418c2ecf20Sopenharmony_ci if (err) 15428c2ecf20Sopenharmony_ci return err; 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci /* barrier and flush checkpoint cp pack 2 page if it can */ 15458c2ecf20Sopenharmony_ci commit_checkpoint(sbi, ckpt, start_blk); 15468c2ecf20Sopenharmony_ci f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA); 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci /* 15498c2ecf20Sopenharmony_ci * invalidate intermediate page cache borrowed from meta inode which are 15508c2ecf20Sopenharmony_ci * used for migration of encrypted, verity or compressed inode's blocks. 15518c2ecf20Sopenharmony_ci */ 15528c2ecf20Sopenharmony_ci if (f2fs_sb_has_encrypt(sbi) || f2fs_sb_has_verity(sbi) || 15538c2ecf20Sopenharmony_ci f2fs_sb_has_compression(sbi)) 15548c2ecf20Sopenharmony_ci invalidate_mapping_pages(META_MAPPING(sbi), 15558c2ecf20Sopenharmony_ci MAIN_BLKADDR(sbi), MAX_BLKADDR(sbi) - 1); 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci f2fs_release_ino_entry(sbi, false); 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci f2fs_reset_fsync_node_info(sbi); 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_ci clear_sbi_flag(sbi, SBI_IS_DIRTY); 15628c2ecf20Sopenharmony_ci clear_sbi_flag(sbi, SBI_NEED_CP); 15638c2ecf20Sopenharmony_ci clear_sbi_flag(sbi, SBI_QUOTA_SKIP_FLUSH); 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci spin_lock(&sbi->stat_lock); 15668c2ecf20Sopenharmony_ci sbi->unusable_block_count = 0; 15678c2ecf20Sopenharmony_ci spin_unlock(&sbi->stat_lock); 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci __set_cp_next_pack(sbi); 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_ci /* 15728c2ecf20Sopenharmony_ci * redirty superblock if metadata like node page or inode cache is 15738c2ecf20Sopenharmony_ci * updated during writing checkpoint. 15748c2ecf20Sopenharmony_ci */ 15758c2ecf20Sopenharmony_ci if (get_pages(sbi, F2FS_DIRTY_NODES) || 15768c2ecf20Sopenharmony_ci get_pages(sbi, F2FS_DIRTY_IMETA)) 15778c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_IS_DIRTY); 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, get_pages(sbi, F2FS_DIRTY_DENTS)); 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci return unlikely(f2fs_cp_error(sbi)) ? -EIO : 0; 15828c2ecf20Sopenharmony_ci} 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ciint f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) 15858c2ecf20Sopenharmony_ci{ 15868c2ecf20Sopenharmony_ci struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); 15878c2ecf20Sopenharmony_ci unsigned long long ckpt_ver; 15888c2ecf20Sopenharmony_ci int err = 0; 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci if (f2fs_readonly(sbi->sb) || f2fs_hw_is_readonly(sbi)) 15918c2ecf20Sopenharmony_ci return -EROFS; 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { 15948c2ecf20Sopenharmony_ci if (cpc->reason != CP_PAUSE) 15958c2ecf20Sopenharmony_ci return 0; 15968c2ecf20Sopenharmony_ci f2fs_warn(sbi, "Start checkpoint disabled!"); 15978c2ecf20Sopenharmony_ci } 15988c2ecf20Sopenharmony_ci if (cpc->reason != CP_RESIZE) 15998c2ecf20Sopenharmony_ci mutex_lock(&sbi->cp_mutex); 16008c2ecf20Sopenharmony_ci 16018c2ecf20Sopenharmony_ci if (!is_sbi_flag_set(sbi, SBI_IS_DIRTY) && 16028c2ecf20Sopenharmony_ci ((cpc->reason & CP_FASTBOOT) || (cpc->reason & CP_SYNC) || 16038c2ecf20Sopenharmony_ci ((cpc->reason & CP_DISCARD) && !sbi->discard_blks))) 16048c2ecf20Sopenharmony_ci goto out; 16058c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 16068c2ecf20Sopenharmony_ci err = -EIO; 16078c2ecf20Sopenharmony_ci goto out; 16088c2ecf20Sopenharmony_ci } 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_ci trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "start block_ops"); 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci err = block_operations(sbi); 16138c2ecf20Sopenharmony_ci if (err) 16148c2ecf20Sopenharmony_ci goto out; 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish block_ops"); 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci f2fs_flush_merged_writes(sbi); 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci /* this is the case of multiple fstrims without any changes */ 16218c2ecf20Sopenharmony_ci if (cpc->reason & CP_DISCARD) { 16228c2ecf20Sopenharmony_ci if (!f2fs_exist_trim_candidates(sbi, cpc)) { 16238c2ecf20Sopenharmony_ci unblock_operations(sbi); 16248c2ecf20Sopenharmony_ci goto out; 16258c2ecf20Sopenharmony_ci } 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci if (NM_I(sbi)->nat_cnt[DIRTY_NAT] == 0 && 16288c2ecf20Sopenharmony_ci SIT_I(sbi)->dirty_sentries == 0 && 16298c2ecf20Sopenharmony_ci prefree_segments(sbi) == 0) { 16308c2ecf20Sopenharmony_ci f2fs_flush_sit_entries(sbi, cpc); 16318c2ecf20Sopenharmony_ci f2fs_clear_prefree_segments(sbi, cpc); 16328c2ecf20Sopenharmony_ci unblock_operations(sbi); 16338c2ecf20Sopenharmony_ci goto out; 16348c2ecf20Sopenharmony_ci } 16358c2ecf20Sopenharmony_ci } 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci /* 16388c2ecf20Sopenharmony_ci * update checkpoint pack index 16398c2ecf20Sopenharmony_ci * Increase the version number so that 16408c2ecf20Sopenharmony_ci * SIT entries and seg summaries are written at correct place 16418c2ecf20Sopenharmony_ci */ 16428c2ecf20Sopenharmony_ci ckpt_ver = cur_cp_version(ckpt); 16438c2ecf20Sopenharmony_ci ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver); 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci /* write cached NAT/SIT entries to NAT/SIT area */ 16468c2ecf20Sopenharmony_ci err = f2fs_flush_nat_entries(sbi, cpc); 16478c2ecf20Sopenharmony_ci if (err) 16488c2ecf20Sopenharmony_ci goto stop; 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci f2fs_flush_sit_entries(sbi, cpc); 16518c2ecf20Sopenharmony_ci 16528c2ecf20Sopenharmony_ci /* save inmem log status */ 16538c2ecf20Sopenharmony_ci f2fs_save_inmem_curseg(sbi); 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci err = do_checkpoint(sbi, cpc); 16568c2ecf20Sopenharmony_ci if (err) 16578c2ecf20Sopenharmony_ci f2fs_release_discard_addrs(sbi); 16588c2ecf20Sopenharmony_ci else 16598c2ecf20Sopenharmony_ci f2fs_clear_prefree_segments(sbi, cpc); 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci f2fs_restore_inmem_curseg(sbi); 16628c2ecf20Sopenharmony_cistop: 16638c2ecf20Sopenharmony_ci unblock_operations(sbi); 16648c2ecf20Sopenharmony_ci stat_inc_cp_count(sbi->stat_info); 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci if (cpc->reason & CP_RECOVERY) 16678c2ecf20Sopenharmony_ci f2fs_notice(sbi, "checkpoint: version = %llx", ckpt_ver); 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci /* update CP_TIME to trigger checkpoint periodically */ 16708c2ecf20Sopenharmony_ci f2fs_update_time(sbi, CP_TIME); 16718c2ecf20Sopenharmony_ci trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish checkpoint"); 16728c2ecf20Sopenharmony_ciout: 16738c2ecf20Sopenharmony_ci if (cpc->reason != CP_RESIZE) 16748c2ecf20Sopenharmony_ci mutex_unlock(&sbi->cp_mutex); 16758c2ecf20Sopenharmony_ci return err; 16768c2ecf20Sopenharmony_ci} 16778c2ecf20Sopenharmony_ci 16788c2ecf20Sopenharmony_civoid f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi) 16798c2ecf20Sopenharmony_ci{ 16808c2ecf20Sopenharmony_ci int i; 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci for (i = 0; i < MAX_INO_ENTRY; i++) { 16838c2ecf20Sopenharmony_ci struct inode_management *im = &sbi->im[i]; 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci INIT_RADIX_TREE(&im->ino_root, GFP_ATOMIC); 16868c2ecf20Sopenharmony_ci spin_lock_init(&im->ino_lock); 16878c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&im->ino_list); 16888c2ecf20Sopenharmony_ci im->ino_num = 0; 16898c2ecf20Sopenharmony_ci } 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci sbi->max_orphans = (sbi->blocks_per_seg - F2FS_CP_PACKS - 16928c2ecf20Sopenharmony_ci NR_CURSEG_PERSIST_TYPE - __cp_payload(sbi)) * 16938c2ecf20Sopenharmony_ci F2FS_ORPHANS_PER_BLOCK; 16948c2ecf20Sopenharmony_ci} 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ciint __init f2fs_create_checkpoint_caches(void) 16978c2ecf20Sopenharmony_ci{ 16988c2ecf20Sopenharmony_ci ino_entry_slab = f2fs_kmem_cache_create("f2fs_ino_entry", 16998c2ecf20Sopenharmony_ci sizeof(struct ino_entry)); 17008c2ecf20Sopenharmony_ci if (!ino_entry_slab) 17018c2ecf20Sopenharmony_ci return -ENOMEM; 17028c2ecf20Sopenharmony_ci f2fs_inode_entry_slab = f2fs_kmem_cache_create("f2fs_inode_entry", 17038c2ecf20Sopenharmony_ci sizeof(struct inode_entry)); 17048c2ecf20Sopenharmony_ci if (!f2fs_inode_entry_slab) { 17058c2ecf20Sopenharmony_ci kmem_cache_destroy(ino_entry_slab); 17068c2ecf20Sopenharmony_ci return -ENOMEM; 17078c2ecf20Sopenharmony_ci } 17088c2ecf20Sopenharmony_ci return 0; 17098c2ecf20Sopenharmony_ci} 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_civoid f2fs_destroy_checkpoint_caches(void) 17128c2ecf20Sopenharmony_ci{ 17138c2ecf20Sopenharmony_ci kmem_cache_destroy(ino_entry_slab); 17148c2ecf20Sopenharmony_ci kmem_cache_destroy(f2fs_inode_entry_slab); 17158c2ecf20Sopenharmony_ci} 1716