162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * fs/f2fs/checkpoint.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/bio.h>
1062306a36Sopenharmony_ci#include <linux/mpage.h>
1162306a36Sopenharmony_ci#include <linux/writeback.h>
1262306a36Sopenharmony_ci#include <linux/blkdev.h>
1362306a36Sopenharmony_ci#include <linux/f2fs_fs.h>
1462306a36Sopenharmony_ci#include <linux/pagevec.h>
1562306a36Sopenharmony_ci#include <linux/swap.h>
1662306a36Sopenharmony_ci#include <linux/kthread.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include "f2fs.h"
1962306a36Sopenharmony_ci#include "node.h"
2062306a36Sopenharmony_ci#include "segment.h"
2162306a36Sopenharmony_ci#include "iostat.h"
2262306a36Sopenharmony_ci#include <trace/events/f2fs.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define DEFAULT_CHECKPOINT_IOPRIO (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 3))
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic struct kmem_cache *ino_entry_slab;
2762306a36Sopenharmony_cistruct kmem_cache *f2fs_inode_entry_slab;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_civoid f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io,
3062306a36Sopenharmony_ci						unsigned char reason)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	f2fs_build_fault_attr(sbi, 0, 0);
3362306a36Sopenharmony_ci	if (!end_io)
3462306a36Sopenharmony_ci		f2fs_flush_merged_writes(sbi);
3562306a36Sopenharmony_ci	f2fs_handle_critical_error(sbi, reason, end_io);
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/*
3962306a36Sopenharmony_ci * We guarantee no failure on the returned page.
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_cistruct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	struct address_space *mapping = META_MAPPING(sbi);
4462306a36Sopenharmony_ci	struct page *page;
4562306a36Sopenharmony_cirepeat:
4662306a36Sopenharmony_ci	page = f2fs_grab_cache_page(mapping, index, false);
4762306a36Sopenharmony_ci	if (!page) {
4862306a36Sopenharmony_ci		cond_resched();
4962306a36Sopenharmony_ci		goto repeat;
5062306a36Sopenharmony_ci	}
5162306a36Sopenharmony_ci	f2fs_wait_on_page_writeback(page, META, true, true);
5262306a36Sopenharmony_ci	if (!PageUptodate(page))
5362306a36Sopenharmony_ci		SetPageUptodate(page);
5462306a36Sopenharmony_ci	return page;
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
5862306a36Sopenharmony_ci							bool is_meta)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	struct address_space *mapping = META_MAPPING(sbi);
6162306a36Sopenharmony_ci	struct page *page;
6262306a36Sopenharmony_ci	struct f2fs_io_info fio = {
6362306a36Sopenharmony_ci		.sbi = sbi,
6462306a36Sopenharmony_ci		.type = META,
6562306a36Sopenharmony_ci		.op = REQ_OP_READ,
6662306a36Sopenharmony_ci		.op_flags = REQ_META | REQ_PRIO,
6762306a36Sopenharmony_ci		.old_blkaddr = index,
6862306a36Sopenharmony_ci		.new_blkaddr = index,
6962306a36Sopenharmony_ci		.encrypted_page = NULL,
7062306a36Sopenharmony_ci		.is_por = !is_meta ? 1 : 0,
7162306a36Sopenharmony_ci	};
7262306a36Sopenharmony_ci	int err;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	if (unlikely(!is_meta))
7562306a36Sopenharmony_ci		fio.op_flags &= ~REQ_META;
7662306a36Sopenharmony_cirepeat:
7762306a36Sopenharmony_ci	page = f2fs_grab_cache_page(mapping, index, false);
7862306a36Sopenharmony_ci	if (!page) {
7962306a36Sopenharmony_ci		cond_resched();
8062306a36Sopenharmony_ci		goto repeat;
8162306a36Sopenharmony_ci	}
8262306a36Sopenharmony_ci	if (PageUptodate(page))
8362306a36Sopenharmony_ci		goto out;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	fio.page = page;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	err = f2fs_submit_page_bio(&fio);
8862306a36Sopenharmony_ci	if (err) {
8962306a36Sopenharmony_ci		f2fs_put_page(page, 1);
9062306a36Sopenharmony_ci		return ERR_PTR(err);
9162306a36Sopenharmony_ci	}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	f2fs_update_iostat(sbi, NULL, FS_META_READ_IO, F2FS_BLKSIZE);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	lock_page(page);
9662306a36Sopenharmony_ci	if (unlikely(page->mapping != mapping)) {
9762306a36Sopenharmony_ci		f2fs_put_page(page, 1);
9862306a36Sopenharmony_ci		goto repeat;
9962306a36Sopenharmony_ci	}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	if (unlikely(!PageUptodate(page))) {
10262306a36Sopenharmony_ci		f2fs_handle_page_eio(sbi, page->index, META);
10362306a36Sopenharmony_ci		f2fs_put_page(page, 1);
10462306a36Sopenharmony_ci		return ERR_PTR(-EIO);
10562306a36Sopenharmony_ci	}
10662306a36Sopenharmony_ciout:
10762306a36Sopenharmony_ci	return page;
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cistruct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	return __get_meta_page(sbi, index, true);
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistruct page *f2fs_get_meta_page_retry(struct f2fs_sb_info *sbi, pgoff_t index)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	struct page *page;
11862306a36Sopenharmony_ci	int count = 0;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ciretry:
12162306a36Sopenharmony_ci	page = __get_meta_page(sbi, index, true);
12262306a36Sopenharmony_ci	if (IS_ERR(page)) {
12362306a36Sopenharmony_ci		if (PTR_ERR(page) == -EIO &&
12462306a36Sopenharmony_ci				++count <= DEFAULT_RETRY_IO_COUNT)
12562306a36Sopenharmony_ci			goto retry;
12662306a36Sopenharmony_ci		f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_META_PAGE);
12762306a36Sopenharmony_ci	}
12862306a36Sopenharmony_ci	return page;
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci/* for POR only */
13262306a36Sopenharmony_cistruct page *f2fs_get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	return __get_meta_page(sbi, index, false);
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic bool __is_bitmap_valid(struct f2fs_sb_info *sbi, block_t blkaddr,
13862306a36Sopenharmony_ci							int type)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	struct seg_entry *se;
14162306a36Sopenharmony_ci	unsigned int segno, offset;
14262306a36Sopenharmony_ci	bool exist;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	if (type == DATA_GENERIC)
14562306a36Sopenharmony_ci		return true;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	segno = GET_SEGNO(sbi, blkaddr);
14862306a36Sopenharmony_ci	offset = GET_BLKOFF_FROM_SEG0(sbi, blkaddr);
14962306a36Sopenharmony_ci	se = get_seg_entry(sbi, segno);
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	exist = f2fs_test_bit(offset, se->cur_valid_map);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	/* skip data, if we already have an error in checkpoint. */
15462306a36Sopenharmony_ci	if (unlikely(f2fs_cp_error(sbi)))
15562306a36Sopenharmony_ci		return exist;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	if (exist && type == DATA_GENERIC_ENHANCE_UPDATE) {
15862306a36Sopenharmony_ci		f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d",
15962306a36Sopenharmony_ci			 blkaddr, exist);
16062306a36Sopenharmony_ci		set_sbi_flag(sbi, SBI_NEED_FSCK);
16162306a36Sopenharmony_ci		return exist;
16262306a36Sopenharmony_ci	}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	if (!exist && type == DATA_GENERIC_ENHANCE) {
16562306a36Sopenharmony_ci		f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d",
16662306a36Sopenharmony_ci			 blkaddr, exist);
16762306a36Sopenharmony_ci		set_sbi_flag(sbi, SBI_NEED_FSCK);
16862306a36Sopenharmony_ci		dump_stack();
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci	return exist;
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cibool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
17462306a36Sopenharmony_ci					block_t blkaddr, int type)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	if (time_to_inject(sbi, FAULT_BLKADDR))
17762306a36Sopenharmony_ci		return false;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	switch (type) {
18062306a36Sopenharmony_ci	case META_NAT:
18162306a36Sopenharmony_ci		break;
18262306a36Sopenharmony_ci	case META_SIT:
18362306a36Sopenharmony_ci		if (unlikely(blkaddr >= SIT_BLK_CNT(sbi)))
18462306a36Sopenharmony_ci			return false;
18562306a36Sopenharmony_ci		break;
18662306a36Sopenharmony_ci	case META_SSA:
18762306a36Sopenharmony_ci		if (unlikely(blkaddr >= MAIN_BLKADDR(sbi) ||
18862306a36Sopenharmony_ci			blkaddr < SM_I(sbi)->ssa_blkaddr))
18962306a36Sopenharmony_ci			return false;
19062306a36Sopenharmony_ci		break;
19162306a36Sopenharmony_ci	case META_CP:
19262306a36Sopenharmony_ci		if (unlikely(blkaddr >= SIT_I(sbi)->sit_base_addr ||
19362306a36Sopenharmony_ci			blkaddr < __start_cp_addr(sbi)))
19462306a36Sopenharmony_ci			return false;
19562306a36Sopenharmony_ci		break;
19662306a36Sopenharmony_ci	case META_POR:
19762306a36Sopenharmony_ci		if (unlikely(blkaddr >= MAX_BLKADDR(sbi) ||
19862306a36Sopenharmony_ci			blkaddr < MAIN_BLKADDR(sbi)))
19962306a36Sopenharmony_ci			return false;
20062306a36Sopenharmony_ci		break;
20162306a36Sopenharmony_ci	case DATA_GENERIC:
20262306a36Sopenharmony_ci	case DATA_GENERIC_ENHANCE:
20362306a36Sopenharmony_ci	case DATA_GENERIC_ENHANCE_READ:
20462306a36Sopenharmony_ci	case DATA_GENERIC_ENHANCE_UPDATE:
20562306a36Sopenharmony_ci		if (unlikely(blkaddr >= MAX_BLKADDR(sbi) ||
20662306a36Sopenharmony_ci				blkaddr < MAIN_BLKADDR(sbi))) {
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci			/* Skip to emit an error message. */
20962306a36Sopenharmony_ci			if (unlikely(f2fs_cp_error(sbi)))
21062306a36Sopenharmony_ci				return false;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci			f2fs_warn(sbi, "access invalid blkaddr:%u",
21362306a36Sopenharmony_ci				  blkaddr);
21462306a36Sopenharmony_ci			set_sbi_flag(sbi, SBI_NEED_FSCK);
21562306a36Sopenharmony_ci			dump_stack();
21662306a36Sopenharmony_ci			return false;
21762306a36Sopenharmony_ci		} else {
21862306a36Sopenharmony_ci			return __is_bitmap_valid(sbi, blkaddr, type);
21962306a36Sopenharmony_ci		}
22062306a36Sopenharmony_ci		break;
22162306a36Sopenharmony_ci	case META_GENERIC:
22262306a36Sopenharmony_ci		if (unlikely(blkaddr < SEG0_BLKADDR(sbi) ||
22362306a36Sopenharmony_ci			blkaddr >= MAIN_BLKADDR(sbi)))
22462306a36Sopenharmony_ci			return false;
22562306a36Sopenharmony_ci		break;
22662306a36Sopenharmony_ci	default:
22762306a36Sopenharmony_ci		BUG();
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	return true;
23162306a36Sopenharmony_ci}
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci/*
23462306a36Sopenharmony_ci * Readahead CP/NAT/SIT/SSA/POR pages
23562306a36Sopenharmony_ci */
23662306a36Sopenharmony_ciint f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
23762306a36Sopenharmony_ci							int type, bool sync)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	struct page *page;
24062306a36Sopenharmony_ci	block_t blkno = start;
24162306a36Sopenharmony_ci	struct f2fs_io_info fio = {
24262306a36Sopenharmony_ci		.sbi = sbi,
24362306a36Sopenharmony_ci		.type = META,
24462306a36Sopenharmony_ci		.op = REQ_OP_READ,
24562306a36Sopenharmony_ci		.op_flags = sync ? (REQ_META | REQ_PRIO) : REQ_RAHEAD,
24662306a36Sopenharmony_ci		.encrypted_page = NULL,
24762306a36Sopenharmony_ci		.in_list = 0,
24862306a36Sopenharmony_ci		.is_por = (type == META_POR) ? 1 : 0,
24962306a36Sopenharmony_ci	};
25062306a36Sopenharmony_ci	struct blk_plug plug;
25162306a36Sopenharmony_ci	int err;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	if (unlikely(type == META_POR))
25462306a36Sopenharmony_ci		fio.op_flags &= ~REQ_META;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	blk_start_plug(&plug);
25762306a36Sopenharmony_ci	for (; nrpages-- > 0; blkno++) {
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci		if (!f2fs_is_valid_blkaddr(sbi, blkno, type))
26062306a36Sopenharmony_ci			goto out;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci		switch (type) {
26362306a36Sopenharmony_ci		case META_NAT:
26462306a36Sopenharmony_ci			if (unlikely(blkno >=
26562306a36Sopenharmony_ci					NAT_BLOCK_OFFSET(NM_I(sbi)->max_nid)))
26662306a36Sopenharmony_ci				blkno = 0;
26762306a36Sopenharmony_ci			/* get nat block addr */
26862306a36Sopenharmony_ci			fio.new_blkaddr = current_nat_addr(sbi,
26962306a36Sopenharmony_ci					blkno * NAT_ENTRY_PER_BLOCK);
27062306a36Sopenharmony_ci			break;
27162306a36Sopenharmony_ci		case META_SIT:
27262306a36Sopenharmony_ci			if (unlikely(blkno >= TOTAL_SEGS(sbi)))
27362306a36Sopenharmony_ci				goto out;
27462306a36Sopenharmony_ci			/* get sit block addr */
27562306a36Sopenharmony_ci			fio.new_blkaddr = current_sit_addr(sbi,
27662306a36Sopenharmony_ci					blkno * SIT_ENTRY_PER_BLOCK);
27762306a36Sopenharmony_ci			break;
27862306a36Sopenharmony_ci		case META_SSA:
27962306a36Sopenharmony_ci		case META_CP:
28062306a36Sopenharmony_ci		case META_POR:
28162306a36Sopenharmony_ci			fio.new_blkaddr = blkno;
28262306a36Sopenharmony_ci			break;
28362306a36Sopenharmony_ci		default:
28462306a36Sopenharmony_ci			BUG();
28562306a36Sopenharmony_ci		}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci		page = f2fs_grab_cache_page(META_MAPPING(sbi),
28862306a36Sopenharmony_ci						fio.new_blkaddr, false);
28962306a36Sopenharmony_ci		if (!page)
29062306a36Sopenharmony_ci			continue;
29162306a36Sopenharmony_ci		if (PageUptodate(page)) {
29262306a36Sopenharmony_ci			f2fs_put_page(page, 1);
29362306a36Sopenharmony_ci			continue;
29462306a36Sopenharmony_ci		}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci		fio.page = page;
29762306a36Sopenharmony_ci		err = f2fs_submit_page_bio(&fio);
29862306a36Sopenharmony_ci		f2fs_put_page(page, err ? 1 : 0);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci		if (!err)
30162306a36Sopenharmony_ci			f2fs_update_iostat(sbi, NULL, FS_META_READ_IO,
30262306a36Sopenharmony_ci							F2FS_BLKSIZE);
30362306a36Sopenharmony_ci	}
30462306a36Sopenharmony_ciout:
30562306a36Sopenharmony_ci	blk_finish_plug(&plug);
30662306a36Sopenharmony_ci	return blkno - start;
30762306a36Sopenharmony_ci}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_civoid f2fs_ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index,
31062306a36Sopenharmony_ci							unsigned int ra_blocks)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	struct page *page;
31362306a36Sopenharmony_ci	bool readahead = false;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	if (ra_blocks == RECOVERY_MIN_RA_BLOCKS)
31662306a36Sopenharmony_ci		return;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	page = find_get_page(META_MAPPING(sbi), index);
31962306a36Sopenharmony_ci	if (!page || !PageUptodate(page))
32062306a36Sopenharmony_ci		readahead = true;
32162306a36Sopenharmony_ci	f2fs_put_page(page, 0);
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	if (readahead)
32462306a36Sopenharmony_ci		f2fs_ra_meta_pages(sbi, index, ra_blocks, META_POR, true);
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cistatic int __f2fs_write_meta_page(struct page *page,
32862306a36Sopenharmony_ci				struct writeback_control *wbc,
32962306a36Sopenharmony_ci				enum iostat_type io_type)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_P_SB(page);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	trace_f2fs_writepage(page, META);
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	if (unlikely(f2fs_cp_error(sbi))) {
33662306a36Sopenharmony_ci		if (is_sbi_flag_set(sbi, SBI_IS_CLOSE)) {
33762306a36Sopenharmony_ci			ClearPageUptodate(page);
33862306a36Sopenharmony_ci			dec_page_count(sbi, F2FS_DIRTY_META);
33962306a36Sopenharmony_ci			unlock_page(page);
34062306a36Sopenharmony_ci			return 0;
34162306a36Sopenharmony_ci		}
34262306a36Sopenharmony_ci		goto redirty_out;
34362306a36Sopenharmony_ci	}
34462306a36Sopenharmony_ci	if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
34562306a36Sopenharmony_ci		goto redirty_out;
34662306a36Sopenharmony_ci	if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0))
34762306a36Sopenharmony_ci		goto redirty_out;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	f2fs_do_write_meta_page(sbi, page, io_type);
35062306a36Sopenharmony_ci	dec_page_count(sbi, F2FS_DIRTY_META);
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	if (wbc->for_reclaim)
35362306a36Sopenharmony_ci		f2fs_submit_merged_write_cond(sbi, NULL, page, 0, META);
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	unlock_page(page);
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	if (unlikely(f2fs_cp_error(sbi)))
35862306a36Sopenharmony_ci		f2fs_submit_merged_write(sbi, META);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	return 0;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ciredirty_out:
36362306a36Sopenharmony_ci	redirty_page_for_writepage(wbc, page);
36462306a36Sopenharmony_ci	return AOP_WRITEPAGE_ACTIVATE;
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic int f2fs_write_meta_page(struct page *page,
36862306a36Sopenharmony_ci				struct writeback_control *wbc)
36962306a36Sopenharmony_ci{
37062306a36Sopenharmony_ci	return __f2fs_write_meta_page(page, wbc, FS_META_IO);
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic int f2fs_write_meta_pages(struct address_space *mapping,
37462306a36Sopenharmony_ci				struct writeback_control *wbc)
37562306a36Sopenharmony_ci{
37662306a36Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
37762306a36Sopenharmony_ci	long diff, written;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
38062306a36Sopenharmony_ci		goto skip_write;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	/* collect a number of dirty meta pages and write together */
38362306a36Sopenharmony_ci	if (wbc->sync_mode != WB_SYNC_ALL &&
38462306a36Sopenharmony_ci			get_pages(sbi, F2FS_DIRTY_META) <
38562306a36Sopenharmony_ci					nr_pages_to_skip(sbi, META))
38662306a36Sopenharmony_ci		goto skip_write;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	/* if locked failed, cp will flush dirty pages instead */
38962306a36Sopenharmony_ci	if (!f2fs_down_write_trylock(&sbi->cp_global_sem))
39062306a36Sopenharmony_ci		goto skip_write;
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	trace_f2fs_writepages(mapping->host, wbc, META);
39362306a36Sopenharmony_ci	diff = nr_pages_to_write(sbi, META, wbc);
39462306a36Sopenharmony_ci	written = f2fs_sync_meta_pages(sbi, META, wbc->nr_to_write, FS_META_IO);
39562306a36Sopenharmony_ci	f2fs_up_write(&sbi->cp_global_sem);
39662306a36Sopenharmony_ci	wbc->nr_to_write = max((long)0, wbc->nr_to_write - written - diff);
39762306a36Sopenharmony_ci	return 0;
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ciskip_write:
40062306a36Sopenharmony_ci	wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_META);
40162306a36Sopenharmony_ci	trace_f2fs_writepages(mapping->host, wbc, META);
40262306a36Sopenharmony_ci	return 0;
40362306a36Sopenharmony_ci}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_cilong f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
40662306a36Sopenharmony_ci				long nr_to_write, enum iostat_type io_type)
40762306a36Sopenharmony_ci{
40862306a36Sopenharmony_ci	struct address_space *mapping = META_MAPPING(sbi);
40962306a36Sopenharmony_ci	pgoff_t index = 0, prev = ULONG_MAX;
41062306a36Sopenharmony_ci	struct folio_batch fbatch;
41162306a36Sopenharmony_ci	long nwritten = 0;
41262306a36Sopenharmony_ci	int nr_folios;
41362306a36Sopenharmony_ci	struct writeback_control wbc = {
41462306a36Sopenharmony_ci		.for_reclaim = 0,
41562306a36Sopenharmony_ci	};
41662306a36Sopenharmony_ci	struct blk_plug plug;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	folio_batch_init(&fbatch);
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	blk_start_plug(&plug);
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	while ((nr_folios = filemap_get_folios_tag(mapping, &index,
42362306a36Sopenharmony_ci					(pgoff_t)-1,
42462306a36Sopenharmony_ci					PAGECACHE_TAG_DIRTY, &fbatch))) {
42562306a36Sopenharmony_ci		int i;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci		for (i = 0; i < nr_folios; i++) {
42862306a36Sopenharmony_ci			struct folio *folio = fbatch.folios[i];
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci			if (nr_to_write != LONG_MAX && i != 0 &&
43162306a36Sopenharmony_ci					folio->index != prev +
43262306a36Sopenharmony_ci					folio_nr_pages(fbatch.folios[i-1])) {
43362306a36Sopenharmony_ci				folio_batch_release(&fbatch);
43462306a36Sopenharmony_ci				goto stop;
43562306a36Sopenharmony_ci			}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci			folio_lock(folio);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci			if (unlikely(folio->mapping != mapping)) {
44062306a36Sopenharmony_cicontinue_unlock:
44162306a36Sopenharmony_ci				folio_unlock(folio);
44262306a36Sopenharmony_ci				continue;
44362306a36Sopenharmony_ci			}
44462306a36Sopenharmony_ci			if (!folio_test_dirty(folio)) {
44562306a36Sopenharmony_ci				/* someone wrote it for us */
44662306a36Sopenharmony_ci				goto continue_unlock;
44762306a36Sopenharmony_ci			}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci			f2fs_wait_on_page_writeback(&folio->page, META,
45062306a36Sopenharmony_ci					true, true);
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci			if (!folio_clear_dirty_for_io(folio))
45362306a36Sopenharmony_ci				goto continue_unlock;
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci			if (__f2fs_write_meta_page(&folio->page, &wbc,
45662306a36Sopenharmony_ci						io_type)) {
45762306a36Sopenharmony_ci				folio_unlock(folio);
45862306a36Sopenharmony_ci				break;
45962306a36Sopenharmony_ci			}
46062306a36Sopenharmony_ci			nwritten += folio_nr_pages(folio);
46162306a36Sopenharmony_ci			prev = folio->index;
46262306a36Sopenharmony_ci			if (unlikely(nwritten >= nr_to_write))
46362306a36Sopenharmony_ci				break;
46462306a36Sopenharmony_ci		}
46562306a36Sopenharmony_ci		folio_batch_release(&fbatch);
46662306a36Sopenharmony_ci		cond_resched();
46762306a36Sopenharmony_ci	}
46862306a36Sopenharmony_cistop:
46962306a36Sopenharmony_ci	if (nwritten)
47062306a36Sopenharmony_ci		f2fs_submit_merged_write(sbi, type);
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	blk_finish_plug(&plug);
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	return nwritten;
47562306a36Sopenharmony_ci}
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_cistatic bool f2fs_dirty_meta_folio(struct address_space *mapping,
47862306a36Sopenharmony_ci		struct folio *folio)
47962306a36Sopenharmony_ci{
48062306a36Sopenharmony_ci	trace_f2fs_set_page_dirty(&folio->page, META);
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	if (!folio_test_uptodate(folio))
48362306a36Sopenharmony_ci		folio_mark_uptodate(folio);
48462306a36Sopenharmony_ci	if (filemap_dirty_folio(mapping, folio)) {
48562306a36Sopenharmony_ci		inc_page_count(F2FS_M_SB(mapping), F2FS_DIRTY_META);
48662306a36Sopenharmony_ci		set_page_private_reference(&folio->page);
48762306a36Sopenharmony_ci		return true;
48862306a36Sopenharmony_ci	}
48962306a36Sopenharmony_ci	return false;
49062306a36Sopenharmony_ci}
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ciconst struct address_space_operations f2fs_meta_aops = {
49362306a36Sopenharmony_ci	.writepage	= f2fs_write_meta_page,
49462306a36Sopenharmony_ci	.writepages	= f2fs_write_meta_pages,
49562306a36Sopenharmony_ci	.dirty_folio	= f2fs_dirty_meta_folio,
49662306a36Sopenharmony_ci	.invalidate_folio = f2fs_invalidate_folio,
49762306a36Sopenharmony_ci	.release_folio	= f2fs_release_folio,
49862306a36Sopenharmony_ci	.migrate_folio	= filemap_migrate_folio,
49962306a36Sopenharmony_ci};
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_cistatic void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino,
50262306a36Sopenharmony_ci						unsigned int devidx, int type)
50362306a36Sopenharmony_ci{
50462306a36Sopenharmony_ci	struct inode_management *im = &sbi->im[type];
50562306a36Sopenharmony_ci	struct ino_entry *e = NULL, *new = NULL;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	if (type == FLUSH_INO) {
50862306a36Sopenharmony_ci		rcu_read_lock();
50962306a36Sopenharmony_ci		e = radix_tree_lookup(&im->ino_root, ino);
51062306a36Sopenharmony_ci		rcu_read_unlock();
51162306a36Sopenharmony_ci	}
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ciretry:
51462306a36Sopenharmony_ci	if (!e)
51562306a36Sopenharmony_ci		new = f2fs_kmem_cache_alloc(ino_entry_slab,
51662306a36Sopenharmony_ci						GFP_NOFS, true, NULL);
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	spin_lock(&im->ino_lock);
52162306a36Sopenharmony_ci	e = radix_tree_lookup(&im->ino_root, ino);
52262306a36Sopenharmony_ci	if (!e) {
52362306a36Sopenharmony_ci		if (!new) {
52462306a36Sopenharmony_ci			spin_unlock(&im->ino_lock);
52562306a36Sopenharmony_ci			radix_tree_preload_end();
52662306a36Sopenharmony_ci			goto retry;
52762306a36Sopenharmony_ci		}
52862306a36Sopenharmony_ci		e = new;
52962306a36Sopenharmony_ci		if (unlikely(radix_tree_insert(&im->ino_root, ino, e)))
53062306a36Sopenharmony_ci			f2fs_bug_on(sbi, 1);
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci		memset(e, 0, sizeof(struct ino_entry));
53362306a36Sopenharmony_ci		e->ino = ino;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci		list_add_tail(&e->list, &im->ino_list);
53662306a36Sopenharmony_ci		if (type != ORPHAN_INO)
53762306a36Sopenharmony_ci			im->ino_num++;
53862306a36Sopenharmony_ci	}
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	if (type == FLUSH_INO)
54162306a36Sopenharmony_ci		f2fs_set_bit(devidx, (char *)&e->dirty_device);
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	spin_unlock(&im->ino_lock);
54462306a36Sopenharmony_ci	radix_tree_preload_end();
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	if (new && e != new)
54762306a36Sopenharmony_ci		kmem_cache_free(ino_entry_slab, new);
54862306a36Sopenharmony_ci}
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_cistatic void __remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
55162306a36Sopenharmony_ci{
55262306a36Sopenharmony_ci	struct inode_management *im = &sbi->im[type];
55362306a36Sopenharmony_ci	struct ino_entry *e;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	spin_lock(&im->ino_lock);
55662306a36Sopenharmony_ci	e = radix_tree_lookup(&im->ino_root, ino);
55762306a36Sopenharmony_ci	if (e) {
55862306a36Sopenharmony_ci		list_del(&e->list);
55962306a36Sopenharmony_ci		radix_tree_delete(&im->ino_root, ino);
56062306a36Sopenharmony_ci		im->ino_num--;
56162306a36Sopenharmony_ci		spin_unlock(&im->ino_lock);
56262306a36Sopenharmony_ci		kmem_cache_free(ino_entry_slab, e);
56362306a36Sopenharmony_ci		return;
56462306a36Sopenharmony_ci	}
56562306a36Sopenharmony_ci	spin_unlock(&im->ino_lock);
56662306a36Sopenharmony_ci}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_civoid f2fs_add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
56962306a36Sopenharmony_ci{
57062306a36Sopenharmony_ci	/* add new dirty ino entry into list */
57162306a36Sopenharmony_ci	__add_ino_entry(sbi, ino, 0, type);
57262306a36Sopenharmony_ci}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_civoid f2fs_remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
57562306a36Sopenharmony_ci{
57662306a36Sopenharmony_ci	/* remove dirty ino entry from list */
57762306a36Sopenharmony_ci	__remove_ino_entry(sbi, ino, type);
57862306a36Sopenharmony_ci}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci/* mode should be APPEND_INO, UPDATE_INO or TRANS_DIR_INO */
58162306a36Sopenharmony_cibool f2fs_exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode)
58262306a36Sopenharmony_ci{
58362306a36Sopenharmony_ci	struct inode_management *im = &sbi->im[mode];
58462306a36Sopenharmony_ci	struct ino_entry *e;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	spin_lock(&im->ino_lock);
58762306a36Sopenharmony_ci	e = radix_tree_lookup(&im->ino_root, ino);
58862306a36Sopenharmony_ci	spin_unlock(&im->ino_lock);
58962306a36Sopenharmony_ci	return e ? true : false;
59062306a36Sopenharmony_ci}
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_civoid f2fs_release_ino_entry(struct f2fs_sb_info *sbi, bool all)
59362306a36Sopenharmony_ci{
59462306a36Sopenharmony_ci	struct ino_entry *e, *tmp;
59562306a36Sopenharmony_ci	int i;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	for (i = all ? ORPHAN_INO : APPEND_INO; i < MAX_INO_ENTRY; i++) {
59862306a36Sopenharmony_ci		struct inode_management *im = &sbi->im[i];
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci		spin_lock(&im->ino_lock);
60162306a36Sopenharmony_ci		list_for_each_entry_safe(e, tmp, &im->ino_list, list) {
60262306a36Sopenharmony_ci			list_del(&e->list);
60362306a36Sopenharmony_ci			radix_tree_delete(&im->ino_root, e->ino);
60462306a36Sopenharmony_ci			kmem_cache_free(ino_entry_slab, e);
60562306a36Sopenharmony_ci			im->ino_num--;
60662306a36Sopenharmony_ci		}
60762306a36Sopenharmony_ci		spin_unlock(&im->ino_lock);
60862306a36Sopenharmony_ci	}
60962306a36Sopenharmony_ci}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_civoid f2fs_set_dirty_device(struct f2fs_sb_info *sbi, nid_t ino,
61262306a36Sopenharmony_ci					unsigned int devidx, int type)
61362306a36Sopenharmony_ci{
61462306a36Sopenharmony_ci	__add_ino_entry(sbi, ino, devidx, type);
61562306a36Sopenharmony_ci}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_cibool f2fs_is_dirty_device(struct f2fs_sb_info *sbi, nid_t ino,
61862306a36Sopenharmony_ci					unsigned int devidx, int type)
61962306a36Sopenharmony_ci{
62062306a36Sopenharmony_ci	struct inode_management *im = &sbi->im[type];
62162306a36Sopenharmony_ci	struct ino_entry *e;
62262306a36Sopenharmony_ci	bool is_dirty = false;
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	spin_lock(&im->ino_lock);
62562306a36Sopenharmony_ci	e = radix_tree_lookup(&im->ino_root, ino);
62662306a36Sopenharmony_ci	if (e && f2fs_test_bit(devidx, (char *)&e->dirty_device))
62762306a36Sopenharmony_ci		is_dirty = true;
62862306a36Sopenharmony_ci	spin_unlock(&im->ino_lock);
62962306a36Sopenharmony_ci	return is_dirty;
63062306a36Sopenharmony_ci}
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ciint f2fs_acquire_orphan_inode(struct f2fs_sb_info *sbi)
63362306a36Sopenharmony_ci{
63462306a36Sopenharmony_ci	struct inode_management *im = &sbi->im[ORPHAN_INO];
63562306a36Sopenharmony_ci	int err = 0;
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	spin_lock(&im->ino_lock);
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	if (time_to_inject(sbi, FAULT_ORPHAN)) {
64062306a36Sopenharmony_ci		spin_unlock(&im->ino_lock);
64162306a36Sopenharmony_ci		return -ENOSPC;
64262306a36Sopenharmony_ci	}
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	if (unlikely(im->ino_num >= sbi->max_orphans))
64562306a36Sopenharmony_ci		err = -ENOSPC;
64662306a36Sopenharmony_ci	else
64762306a36Sopenharmony_ci		im->ino_num++;
64862306a36Sopenharmony_ci	spin_unlock(&im->ino_lock);
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	return err;
65162306a36Sopenharmony_ci}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_civoid f2fs_release_orphan_inode(struct f2fs_sb_info *sbi)
65462306a36Sopenharmony_ci{
65562306a36Sopenharmony_ci	struct inode_management *im = &sbi->im[ORPHAN_INO];
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	spin_lock(&im->ino_lock);
65862306a36Sopenharmony_ci	f2fs_bug_on(sbi, im->ino_num == 0);
65962306a36Sopenharmony_ci	im->ino_num--;
66062306a36Sopenharmony_ci	spin_unlock(&im->ino_lock);
66162306a36Sopenharmony_ci}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_civoid f2fs_add_orphan_inode(struct inode *inode)
66462306a36Sopenharmony_ci{
66562306a36Sopenharmony_ci	/* add new orphan ino entry into list */
66662306a36Sopenharmony_ci	__add_ino_entry(F2FS_I_SB(inode), inode->i_ino, 0, ORPHAN_INO);
66762306a36Sopenharmony_ci	f2fs_update_inode_page(inode);
66862306a36Sopenharmony_ci}
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_civoid f2fs_remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
67162306a36Sopenharmony_ci{
67262306a36Sopenharmony_ci	/* remove orphan entry from orphan list */
67362306a36Sopenharmony_ci	__remove_ino_entry(sbi, ino, ORPHAN_INO);
67462306a36Sopenharmony_ci}
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_cistatic int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
67762306a36Sopenharmony_ci{
67862306a36Sopenharmony_ci	struct inode *inode;
67962306a36Sopenharmony_ci	struct node_info ni;
68062306a36Sopenharmony_ci	int err;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	inode = f2fs_iget_retry(sbi->sb, ino);
68362306a36Sopenharmony_ci	if (IS_ERR(inode)) {
68462306a36Sopenharmony_ci		/*
68562306a36Sopenharmony_ci		 * there should be a bug that we can't find the entry
68662306a36Sopenharmony_ci		 * to orphan inode.
68762306a36Sopenharmony_ci		 */
68862306a36Sopenharmony_ci		f2fs_bug_on(sbi, PTR_ERR(inode) == -ENOENT);
68962306a36Sopenharmony_ci		return PTR_ERR(inode);
69062306a36Sopenharmony_ci	}
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci	err = f2fs_dquot_initialize(inode);
69362306a36Sopenharmony_ci	if (err) {
69462306a36Sopenharmony_ci		iput(inode);
69562306a36Sopenharmony_ci		goto err_out;
69662306a36Sopenharmony_ci	}
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	clear_nlink(inode);
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	/* truncate all the data during iput */
70162306a36Sopenharmony_ci	iput(inode);
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	err = f2fs_get_node_info(sbi, ino, &ni, false);
70462306a36Sopenharmony_ci	if (err)
70562306a36Sopenharmony_ci		goto err_out;
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	/* ENOMEM was fully retried in f2fs_evict_inode. */
70862306a36Sopenharmony_ci	if (ni.blk_addr != NULL_ADDR) {
70962306a36Sopenharmony_ci		err = -EIO;
71062306a36Sopenharmony_ci		goto err_out;
71162306a36Sopenharmony_ci	}
71262306a36Sopenharmony_ci	return 0;
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_cierr_out:
71562306a36Sopenharmony_ci	set_sbi_flag(sbi, SBI_NEED_FSCK);
71662306a36Sopenharmony_ci	f2fs_warn(sbi, "%s: orphan failed (ino=%x), run fsck to fix.",
71762306a36Sopenharmony_ci		  __func__, ino);
71862306a36Sopenharmony_ci	return err;
71962306a36Sopenharmony_ci}
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ciint f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
72262306a36Sopenharmony_ci{
72362306a36Sopenharmony_ci	block_t start_blk, orphan_blocks, i, j;
72462306a36Sopenharmony_ci	int err = 0;
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	if (!is_set_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG))
72762306a36Sopenharmony_ci		return 0;
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	if (f2fs_hw_is_readonly(sbi)) {
73062306a36Sopenharmony_ci		f2fs_info(sbi, "write access unavailable, skipping orphan cleanup");
73162306a36Sopenharmony_ci		return 0;
73262306a36Sopenharmony_ci	}
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	if (is_sbi_flag_set(sbi, SBI_IS_WRITABLE))
73562306a36Sopenharmony_ci		f2fs_info(sbi, "orphan cleanup on readonly fs");
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	start_blk = __start_cp_addr(sbi) + 1 + __cp_payload(sbi);
73862306a36Sopenharmony_ci	orphan_blocks = __start_sum_addr(sbi) - 1 - __cp_payload(sbi);
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	f2fs_ra_meta_pages(sbi, start_blk, orphan_blocks, META_CP, true);
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	for (i = 0; i < orphan_blocks; i++) {
74362306a36Sopenharmony_ci		struct page *page;
74462306a36Sopenharmony_ci		struct f2fs_orphan_block *orphan_blk;
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci		page = f2fs_get_meta_page(sbi, start_blk + i);
74762306a36Sopenharmony_ci		if (IS_ERR(page)) {
74862306a36Sopenharmony_ci			err = PTR_ERR(page);
74962306a36Sopenharmony_ci			goto out;
75062306a36Sopenharmony_ci		}
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci		orphan_blk = (struct f2fs_orphan_block *)page_address(page);
75362306a36Sopenharmony_ci		for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) {
75462306a36Sopenharmony_ci			nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci			err = recover_orphan_inode(sbi, ino);
75762306a36Sopenharmony_ci			if (err) {
75862306a36Sopenharmony_ci				f2fs_put_page(page, 1);
75962306a36Sopenharmony_ci				goto out;
76062306a36Sopenharmony_ci			}
76162306a36Sopenharmony_ci		}
76262306a36Sopenharmony_ci		f2fs_put_page(page, 1);
76362306a36Sopenharmony_ci	}
76462306a36Sopenharmony_ci	/* clear Orphan Flag */
76562306a36Sopenharmony_ci	clear_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG);
76662306a36Sopenharmony_ciout:
76762306a36Sopenharmony_ci	set_sbi_flag(sbi, SBI_IS_RECOVERED);
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	return err;
77062306a36Sopenharmony_ci}
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_cistatic void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
77362306a36Sopenharmony_ci{
77462306a36Sopenharmony_ci	struct list_head *head;
77562306a36Sopenharmony_ci	struct f2fs_orphan_block *orphan_blk = NULL;
77662306a36Sopenharmony_ci	unsigned int nentries = 0;
77762306a36Sopenharmony_ci	unsigned short index = 1;
77862306a36Sopenharmony_ci	unsigned short orphan_blocks;
77962306a36Sopenharmony_ci	struct page *page = NULL;
78062306a36Sopenharmony_ci	struct ino_entry *orphan = NULL;
78162306a36Sopenharmony_ci	struct inode_management *im = &sbi->im[ORPHAN_INO];
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	orphan_blocks = GET_ORPHAN_BLOCKS(im->ino_num);
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	/*
78662306a36Sopenharmony_ci	 * we don't need to do spin_lock(&im->ino_lock) here, since all the
78762306a36Sopenharmony_ci	 * orphan inode operations are covered under f2fs_lock_op().
78862306a36Sopenharmony_ci	 * And, spin_lock should be avoided due to page operations below.
78962306a36Sopenharmony_ci	 */
79062306a36Sopenharmony_ci	head = &im->ino_list;
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	/* loop for each orphan inode entry and write them in journal block */
79362306a36Sopenharmony_ci	list_for_each_entry(orphan, head, list) {
79462306a36Sopenharmony_ci		if (!page) {
79562306a36Sopenharmony_ci			page = f2fs_grab_meta_page(sbi, start_blk++);
79662306a36Sopenharmony_ci			orphan_blk =
79762306a36Sopenharmony_ci				(struct f2fs_orphan_block *)page_address(page);
79862306a36Sopenharmony_ci			memset(orphan_blk, 0, sizeof(*orphan_blk));
79962306a36Sopenharmony_ci		}
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci		orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino);
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci		if (nentries == F2FS_ORPHANS_PER_BLOCK) {
80462306a36Sopenharmony_ci			/*
80562306a36Sopenharmony_ci			 * an orphan block is full of 1020 entries,
80662306a36Sopenharmony_ci			 * then we need to flush current orphan blocks
80762306a36Sopenharmony_ci			 * and bring another one in memory
80862306a36Sopenharmony_ci			 */
80962306a36Sopenharmony_ci			orphan_blk->blk_addr = cpu_to_le16(index);
81062306a36Sopenharmony_ci			orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
81162306a36Sopenharmony_ci			orphan_blk->entry_count = cpu_to_le32(nentries);
81262306a36Sopenharmony_ci			set_page_dirty(page);
81362306a36Sopenharmony_ci			f2fs_put_page(page, 1);
81462306a36Sopenharmony_ci			index++;
81562306a36Sopenharmony_ci			nentries = 0;
81662306a36Sopenharmony_ci			page = NULL;
81762306a36Sopenharmony_ci		}
81862306a36Sopenharmony_ci	}
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	if (page) {
82162306a36Sopenharmony_ci		orphan_blk->blk_addr = cpu_to_le16(index);
82262306a36Sopenharmony_ci		orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
82362306a36Sopenharmony_ci		orphan_blk->entry_count = cpu_to_le32(nentries);
82462306a36Sopenharmony_ci		set_page_dirty(page);
82562306a36Sopenharmony_ci		f2fs_put_page(page, 1);
82662306a36Sopenharmony_ci	}
82762306a36Sopenharmony_ci}
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_cistatic __u32 f2fs_checkpoint_chksum(struct f2fs_sb_info *sbi,
83062306a36Sopenharmony_ci						struct f2fs_checkpoint *ckpt)
83162306a36Sopenharmony_ci{
83262306a36Sopenharmony_ci	unsigned int chksum_ofs = le32_to_cpu(ckpt->checksum_offset);
83362306a36Sopenharmony_ci	__u32 chksum;
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ci	chksum = f2fs_crc32(sbi, ckpt, chksum_ofs);
83662306a36Sopenharmony_ci	if (chksum_ofs < CP_CHKSUM_OFFSET) {
83762306a36Sopenharmony_ci		chksum_ofs += sizeof(chksum);
83862306a36Sopenharmony_ci		chksum = f2fs_chksum(sbi, chksum, (__u8 *)ckpt + chksum_ofs,
83962306a36Sopenharmony_ci						F2FS_BLKSIZE - chksum_ofs);
84062306a36Sopenharmony_ci	}
84162306a36Sopenharmony_ci	return chksum;
84262306a36Sopenharmony_ci}
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_cistatic int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
84562306a36Sopenharmony_ci		struct f2fs_checkpoint **cp_block, struct page **cp_page,
84662306a36Sopenharmony_ci		unsigned long long *version)
84762306a36Sopenharmony_ci{
84862306a36Sopenharmony_ci	size_t crc_offset = 0;
84962306a36Sopenharmony_ci	__u32 crc;
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	*cp_page = f2fs_get_meta_page(sbi, cp_addr);
85262306a36Sopenharmony_ci	if (IS_ERR(*cp_page))
85362306a36Sopenharmony_ci		return PTR_ERR(*cp_page);
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	*cp_block = (struct f2fs_checkpoint *)page_address(*cp_page);
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	crc_offset = le32_to_cpu((*cp_block)->checksum_offset);
85862306a36Sopenharmony_ci	if (crc_offset < CP_MIN_CHKSUM_OFFSET ||
85962306a36Sopenharmony_ci			crc_offset > CP_CHKSUM_OFFSET) {
86062306a36Sopenharmony_ci		f2fs_put_page(*cp_page, 1);
86162306a36Sopenharmony_ci		f2fs_warn(sbi, "invalid crc_offset: %zu", crc_offset);
86262306a36Sopenharmony_ci		return -EINVAL;
86362306a36Sopenharmony_ci	}
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	crc = f2fs_checkpoint_chksum(sbi, *cp_block);
86662306a36Sopenharmony_ci	if (crc != cur_cp_crc(*cp_block)) {
86762306a36Sopenharmony_ci		f2fs_put_page(*cp_page, 1);
86862306a36Sopenharmony_ci		f2fs_warn(sbi, "invalid crc value");
86962306a36Sopenharmony_ci		return -EINVAL;
87062306a36Sopenharmony_ci	}
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	*version = cur_cp_version(*cp_block);
87362306a36Sopenharmony_ci	return 0;
87462306a36Sopenharmony_ci}
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_cistatic struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
87762306a36Sopenharmony_ci				block_t cp_addr, unsigned long long *version)
87862306a36Sopenharmony_ci{
87962306a36Sopenharmony_ci	struct page *cp_page_1 = NULL, *cp_page_2 = NULL;
88062306a36Sopenharmony_ci	struct f2fs_checkpoint *cp_block = NULL;
88162306a36Sopenharmony_ci	unsigned long long cur_version = 0, pre_version = 0;
88262306a36Sopenharmony_ci	unsigned int cp_blocks;
88362306a36Sopenharmony_ci	int err;
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci	err = get_checkpoint_version(sbi, cp_addr, &cp_block,
88662306a36Sopenharmony_ci					&cp_page_1, version);
88762306a36Sopenharmony_ci	if (err)
88862306a36Sopenharmony_ci		return NULL;
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	cp_blocks = le32_to_cpu(cp_block->cp_pack_total_block_count);
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	if (cp_blocks > sbi->blocks_per_seg || cp_blocks <= F2FS_CP_PACKS) {
89362306a36Sopenharmony_ci		f2fs_warn(sbi, "invalid cp_pack_total_block_count:%u",
89462306a36Sopenharmony_ci			  le32_to_cpu(cp_block->cp_pack_total_block_count));
89562306a36Sopenharmony_ci		goto invalid_cp;
89662306a36Sopenharmony_ci	}
89762306a36Sopenharmony_ci	pre_version = *version;
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci	cp_addr += cp_blocks - 1;
90062306a36Sopenharmony_ci	err = get_checkpoint_version(sbi, cp_addr, &cp_block,
90162306a36Sopenharmony_ci					&cp_page_2, version);
90262306a36Sopenharmony_ci	if (err)
90362306a36Sopenharmony_ci		goto invalid_cp;
90462306a36Sopenharmony_ci	cur_version = *version;
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	if (cur_version == pre_version) {
90762306a36Sopenharmony_ci		*version = cur_version;
90862306a36Sopenharmony_ci		f2fs_put_page(cp_page_2, 1);
90962306a36Sopenharmony_ci		return cp_page_1;
91062306a36Sopenharmony_ci	}
91162306a36Sopenharmony_ci	f2fs_put_page(cp_page_2, 1);
91262306a36Sopenharmony_ciinvalid_cp:
91362306a36Sopenharmony_ci	f2fs_put_page(cp_page_1, 1);
91462306a36Sopenharmony_ci	return NULL;
91562306a36Sopenharmony_ci}
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ciint f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
91862306a36Sopenharmony_ci{
91962306a36Sopenharmony_ci	struct f2fs_checkpoint *cp_block;
92062306a36Sopenharmony_ci	struct f2fs_super_block *fsb = sbi->raw_super;
92162306a36Sopenharmony_ci	struct page *cp1, *cp2, *cur_page;
92262306a36Sopenharmony_ci	unsigned long blk_size = sbi->blocksize;
92362306a36Sopenharmony_ci	unsigned long long cp1_version = 0, cp2_version = 0;
92462306a36Sopenharmony_ci	unsigned long long cp_start_blk_no;
92562306a36Sopenharmony_ci	unsigned int cp_blks = 1 + __cp_payload(sbi);
92662306a36Sopenharmony_ci	block_t cp_blk_no;
92762306a36Sopenharmony_ci	int i;
92862306a36Sopenharmony_ci	int err;
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	sbi->ckpt = f2fs_kvzalloc(sbi, array_size(blk_size, cp_blks),
93162306a36Sopenharmony_ci				  GFP_KERNEL);
93262306a36Sopenharmony_ci	if (!sbi->ckpt)
93362306a36Sopenharmony_ci		return -ENOMEM;
93462306a36Sopenharmony_ci	/*
93562306a36Sopenharmony_ci	 * Finding out valid cp block involves read both
93662306a36Sopenharmony_ci	 * sets( cp pack 1 and cp pack 2)
93762306a36Sopenharmony_ci	 */
93862306a36Sopenharmony_ci	cp_start_blk_no = le32_to_cpu(fsb->cp_blkaddr);
93962306a36Sopenharmony_ci	cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version);
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci	/* The second checkpoint pack should start at the next segment */
94262306a36Sopenharmony_ci	cp_start_blk_no += ((unsigned long long)1) <<
94362306a36Sopenharmony_ci				le32_to_cpu(fsb->log_blocks_per_seg);
94462306a36Sopenharmony_ci	cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version);
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	if (cp1 && cp2) {
94762306a36Sopenharmony_ci		if (ver_after(cp2_version, cp1_version))
94862306a36Sopenharmony_ci			cur_page = cp2;
94962306a36Sopenharmony_ci		else
95062306a36Sopenharmony_ci			cur_page = cp1;
95162306a36Sopenharmony_ci	} else if (cp1) {
95262306a36Sopenharmony_ci		cur_page = cp1;
95362306a36Sopenharmony_ci	} else if (cp2) {
95462306a36Sopenharmony_ci		cur_page = cp2;
95562306a36Sopenharmony_ci	} else {
95662306a36Sopenharmony_ci		err = -EFSCORRUPTED;
95762306a36Sopenharmony_ci		goto fail_no_cp;
95862306a36Sopenharmony_ci	}
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	cp_block = (struct f2fs_checkpoint *)page_address(cur_page);
96162306a36Sopenharmony_ci	memcpy(sbi->ckpt, cp_block, blk_size);
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci	if (cur_page == cp1)
96462306a36Sopenharmony_ci		sbi->cur_cp_pack = 1;
96562306a36Sopenharmony_ci	else
96662306a36Sopenharmony_ci		sbi->cur_cp_pack = 2;
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	/* Sanity checking of checkpoint */
96962306a36Sopenharmony_ci	if (f2fs_sanity_check_ckpt(sbi)) {
97062306a36Sopenharmony_ci		err = -EFSCORRUPTED;
97162306a36Sopenharmony_ci		goto free_fail_no_cp;
97262306a36Sopenharmony_ci	}
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	if (cp_blks <= 1)
97562306a36Sopenharmony_ci		goto done;
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	cp_blk_no = le32_to_cpu(fsb->cp_blkaddr);
97862306a36Sopenharmony_ci	if (cur_page == cp2)
97962306a36Sopenharmony_ci		cp_blk_no += BIT(le32_to_cpu(fsb->log_blocks_per_seg));
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	for (i = 1; i < cp_blks; i++) {
98262306a36Sopenharmony_ci		void *sit_bitmap_ptr;
98362306a36Sopenharmony_ci		unsigned char *ckpt = (unsigned char *)sbi->ckpt;
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci		cur_page = f2fs_get_meta_page(sbi, cp_blk_no + i);
98662306a36Sopenharmony_ci		if (IS_ERR(cur_page)) {
98762306a36Sopenharmony_ci			err = PTR_ERR(cur_page);
98862306a36Sopenharmony_ci			goto free_fail_no_cp;
98962306a36Sopenharmony_ci		}
99062306a36Sopenharmony_ci		sit_bitmap_ptr = page_address(cur_page);
99162306a36Sopenharmony_ci		memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size);
99262306a36Sopenharmony_ci		f2fs_put_page(cur_page, 1);
99362306a36Sopenharmony_ci	}
99462306a36Sopenharmony_cidone:
99562306a36Sopenharmony_ci	f2fs_put_page(cp1, 1);
99662306a36Sopenharmony_ci	f2fs_put_page(cp2, 1);
99762306a36Sopenharmony_ci	return 0;
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_cifree_fail_no_cp:
100062306a36Sopenharmony_ci	f2fs_put_page(cp1, 1);
100162306a36Sopenharmony_ci	f2fs_put_page(cp2, 1);
100262306a36Sopenharmony_cifail_no_cp:
100362306a36Sopenharmony_ci	kvfree(sbi->ckpt);
100462306a36Sopenharmony_ci	return err;
100562306a36Sopenharmony_ci}
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_cistatic void __add_dirty_inode(struct inode *inode, enum inode_type type)
100862306a36Sopenharmony_ci{
100962306a36Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
101062306a36Sopenharmony_ci	int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE;
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	if (is_inode_flag_set(inode, flag))
101362306a36Sopenharmony_ci		return;
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci	set_inode_flag(inode, flag);
101662306a36Sopenharmony_ci	list_add_tail(&F2FS_I(inode)->dirty_list, &sbi->inode_list[type]);
101762306a36Sopenharmony_ci	stat_inc_dirty_inode(sbi, type);
101862306a36Sopenharmony_ci}
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_cistatic void __remove_dirty_inode(struct inode *inode, enum inode_type type)
102162306a36Sopenharmony_ci{
102262306a36Sopenharmony_ci	int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE;
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	if (get_dirty_pages(inode) || !is_inode_flag_set(inode, flag))
102562306a36Sopenharmony_ci		return;
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	list_del_init(&F2FS_I(inode)->dirty_list);
102862306a36Sopenharmony_ci	clear_inode_flag(inode, flag);
102962306a36Sopenharmony_ci	stat_dec_dirty_inode(F2FS_I_SB(inode), type);
103062306a36Sopenharmony_ci}
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_civoid f2fs_update_dirty_folio(struct inode *inode, struct folio *folio)
103362306a36Sopenharmony_ci{
103462306a36Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
103562306a36Sopenharmony_ci	enum inode_type type = S_ISDIR(inode->i_mode) ? DIR_INODE : FILE_INODE;
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
103862306a36Sopenharmony_ci			!S_ISLNK(inode->i_mode))
103962306a36Sopenharmony_ci		return;
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	spin_lock(&sbi->inode_lock[type]);
104262306a36Sopenharmony_ci	if (type != FILE_INODE || test_opt(sbi, DATA_FLUSH))
104362306a36Sopenharmony_ci		__add_dirty_inode(inode, type);
104462306a36Sopenharmony_ci	inode_inc_dirty_pages(inode);
104562306a36Sopenharmony_ci	spin_unlock(&sbi->inode_lock[type]);
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	set_page_private_reference(&folio->page);
104862306a36Sopenharmony_ci}
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_civoid f2fs_remove_dirty_inode(struct inode *inode)
105162306a36Sopenharmony_ci{
105262306a36Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
105362306a36Sopenharmony_ci	enum inode_type type = S_ISDIR(inode->i_mode) ? DIR_INODE : FILE_INODE;
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci	if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
105662306a36Sopenharmony_ci			!S_ISLNK(inode->i_mode))
105762306a36Sopenharmony_ci		return;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	if (type == FILE_INODE && !test_opt(sbi, DATA_FLUSH))
106062306a36Sopenharmony_ci		return;
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	spin_lock(&sbi->inode_lock[type]);
106362306a36Sopenharmony_ci	__remove_dirty_inode(inode, type);
106462306a36Sopenharmony_ci	spin_unlock(&sbi->inode_lock[type]);
106562306a36Sopenharmony_ci}
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ciint f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type,
106862306a36Sopenharmony_ci						bool from_cp)
106962306a36Sopenharmony_ci{
107062306a36Sopenharmony_ci	struct list_head *head;
107162306a36Sopenharmony_ci	struct inode *inode;
107262306a36Sopenharmony_ci	struct f2fs_inode_info *fi;
107362306a36Sopenharmony_ci	bool is_dir = (type == DIR_INODE);
107462306a36Sopenharmony_ci	unsigned long ino = 0;
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci	trace_f2fs_sync_dirty_inodes_enter(sbi->sb, is_dir,
107762306a36Sopenharmony_ci				get_pages(sbi, is_dir ?
107862306a36Sopenharmony_ci				F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA));
107962306a36Sopenharmony_ciretry:
108062306a36Sopenharmony_ci	if (unlikely(f2fs_cp_error(sbi))) {
108162306a36Sopenharmony_ci		trace_f2fs_sync_dirty_inodes_exit(sbi->sb, is_dir,
108262306a36Sopenharmony_ci				get_pages(sbi, is_dir ?
108362306a36Sopenharmony_ci				F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA));
108462306a36Sopenharmony_ci		return -EIO;
108562306a36Sopenharmony_ci	}
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci	spin_lock(&sbi->inode_lock[type]);
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	head = &sbi->inode_list[type];
109062306a36Sopenharmony_ci	if (list_empty(head)) {
109162306a36Sopenharmony_ci		spin_unlock(&sbi->inode_lock[type]);
109262306a36Sopenharmony_ci		trace_f2fs_sync_dirty_inodes_exit(sbi->sb, is_dir,
109362306a36Sopenharmony_ci				get_pages(sbi, is_dir ?
109462306a36Sopenharmony_ci				F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA));
109562306a36Sopenharmony_ci		return 0;
109662306a36Sopenharmony_ci	}
109762306a36Sopenharmony_ci	fi = list_first_entry(head, struct f2fs_inode_info, dirty_list);
109862306a36Sopenharmony_ci	inode = igrab(&fi->vfs_inode);
109962306a36Sopenharmony_ci	spin_unlock(&sbi->inode_lock[type]);
110062306a36Sopenharmony_ci	if (inode) {
110162306a36Sopenharmony_ci		unsigned long cur_ino = inode->i_ino;
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci		if (from_cp)
110462306a36Sopenharmony_ci			F2FS_I(inode)->cp_task = current;
110562306a36Sopenharmony_ci		F2FS_I(inode)->wb_task = current;
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci		filemap_fdatawrite(inode->i_mapping);
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci		F2FS_I(inode)->wb_task = NULL;
111062306a36Sopenharmony_ci		if (from_cp)
111162306a36Sopenharmony_ci			F2FS_I(inode)->cp_task = NULL;
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci		iput(inode);
111462306a36Sopenharmony_ci		/* We need to give cpu to another writers. */
111562306a36Sopenharmony_ci		if (ino == cur_ino)
111662306a36Sopenharmony_ci			cond_resched();
111762306a36Sopenharmony_ci		else
111862306a36Sopenharmony_ci			ino = cur_ino;
111962306a36Sopenharmony_ci	} else {
112062306a36Sopenharmony_ci		/*
112162306a36Sopenharmony_ci		 * We should submit bio, since it exists several
112262306a36Sopenharmony_ci		 * writebacking dentry pages in the freeing inode.
112362306a36Sopenharmony_ci		 */
112462306a36Sopenharmony_ci		f2fs_submit_merged_write(sbi, DATA);
112562306a36Sopenharmony_ci		cond_resched();
112662306a36Sopenharmony_ci	}
112762306a36Sopenharmony_ci	goto retry;
112862306a36Sopenharmony_ci}
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_cistatic int f2fs_sync_inode_meta(struct f2fs_sb_info *sbi)
113162306a36Sopenharmony_ci{
113262306a36Sopenharmony_ci	struct list_head *head = &sbi->inode_list[DIRTY_META];
113362306a36Sopenharmony_ci	struct inode *inode;
113462306a36Sopenharmony_ci	struct f2fs_inode_info *fi;
113562306a36Sopenharmony_ci	s64 total = get_pages(sbi, F2FS_DIRTY_IMETA);
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	while (total--) {
113862306a36Sopenharmony_ci		if (unlikely(f2fs_cp_error(sbi)))
113962306a36Sopenharmony_ci			return -EIO;
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci		spin_lock(&sbi->inode_lock[DIRTY_META]);
114262306a36Sopenharmony_ci		if (list_empty(head)) {
114362306a36Sopenharmony_ci			spin_unlock(&sbi->inode_lock[DIRTY_META]);
114462306a36Sopenharmony_ci			return 0;
114562306a36Sopenharmony_ci		}
114662306a36Sopenharmony_ci		fi = list_first_entry(head, struct f2fs_inode_info,
114762306a36Sopenharmony_ci							gdirty_list);
114862306a36Sopenharmony_ci		inode = igrab(&fi->vfs_inode);
114962306a36Sopenharmony_ci		spin_unlock(&sbi->inode_lock[DIRTY_META]);
115062306a36Sopenharmony_ci		if (inode) {
115162306a36Sopenharmony_ci			sync_inode_metadata(inode, 0);
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci			/* it's on eviction */
115462306a36Sopenharmony_ci			if (is_inode_flag_set(inode, FI_DIRTY_INODE))
115562306a36Sopenharmony_ci				f2fs_update_inode_page(inode);
115662306a36Sopenharmony_ci			iput(inode);
115762306a36Sopenharmony_ci		}
115862306a36Sopenharmony_ci	}
115962306a36Sopenharmony_ci	return 0;
116062306a36Sopenharmony_ci}
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_cistatic void __prepare_cp_block(struct f2fs_sb_info *sbi)
116362306a36Sopenharmony_ci{
116462306a36Sopenharmony_ci	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
116562306a36Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
116662306a36Sopenharmony_ci	nid_t last_nid = nm_i->next_scan_nid;
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	next_free_nid(sbi, &last_nid);
116962306a36Sopenharmony_ci	ckpt->valid_block_count = cpu_to_le64(valid_user_blocks(sbi));
117062306a36Sopenharmony_ci	ckpt->valid_node_count = cpu_to_le32(valid_node_count(sbi));
117162306a36Sopenharmony_ci	ckpt->valid_inode_count = cpu_to_le32(valid_inode_count(sbi));
117262306a36Sopenharmony_ci	ckpt->next_free_nid = cpu_to_le32(last_nid);
117362306a36Sopenharmony_ci}
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_cistatic bool __need_flush_quota(struct f2fs_sb_info *sbi)
117662306a36Sopenharmony_ci{
117762306a36Sopenharmony_ci	bool ret = false;
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	if (!is_journalled_quota(sbi))
118062306a36Sopenharmony_ci		return false;
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	if (!f2fs_down_write_trylock(&sbi->quota_sem))
118362306a36Sopenharmony_ci		return true;
118462306a36Sopenharmony_ci	if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH)) {
118562306a36Sopenharmony_ci		ret = false;
118662306a36Sopenharmony_ci	} else if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR)) {
118762306a36Sopenharmony_ci		ret = false;
118862306a36Sopenharmony_ci	} else if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_FLUSH)) {
118962306a36Sopenharmony_ci		clear_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH);
119062306a36Sopenharmony_ci		ret = true;
119162306a36Sopenharmony_ci	} else if (get_pages(sbi, F2FS_DIRTY_QDATA)) {
119262306a36Sopenharmony_ci		ret = true;
119362306a36Sopenharmony_ci	}
119462306a36Sopenharmony_ci	f2fs_up_write(&sbi->quota_sem);
119562306a36Sopenharmony_ci	return ret;
119662306a36Sopenharmony_ci}
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci/*
119962306a36Sopenharmony_ci * Freeze all the FS-operations for checkpoint.
120062306a36Sopenharmony_ci */
120162306a36Sopenharmony_cistatic int block_operations(struct f2fs_sb_info *sbi)
120262306a36Sopenharmony_ci{
120362306a36Sopenharmony_ci	struct writeback_control wbc = {
120462306a36Sopenharmony_ci		.sync_mode = WB_SYNC_ALL,
120562306a36Sopenharmony_ci		.nr_to_write = LONG_MAX,
120662306a36Sopenharmony_ci		.for_reclaim = 0,
120762306a36Sopenharmony_ci	};
120862306a36Sopenharmony_ci	int err = 0, cnt = 0;
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	/*
121162306a36Sopenharmony_ci	 * Let's flush inline_data in dirty node pages.
121262306a36Sopenharmony_ci	 */
121362306a36Sopenharmony_ci	f2fs_flush_inline_data(sbi);
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ciretry_flush_quotas:
121662306a36Sopenharmony_ci	f2fs_lock_all(sbi);
121762306a36Sopenharmony_ci	if (__need_flush_quota(sbi)) {
121862306a36Sopenharmony_ci		int locked;
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci		if (++cnt > DEFAULT_RETRY_QUOTA_FLUSH_COUNT) {
122162306a36Sopenharmony_ci			set_sbi_flag(sbi, SBI_QUOTA_SKIP_FLUSH);
122262306a36Sopenharmony_ci			set_sbi_flag(sbi, SBI_QUOTA_NEED_FLUSH);
122362306a36Sopenharmony_ci			goto retry_flush_dents;
122462306a36Sopenharmony_ci		}
122562306a36Sopenharmony_ci		f2fs_unlock_all(sbi);
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci		/* only failed during mount/umount/freeze/quotactl */
122862306a36Sopenharmony_ci		locked = down_read_trylock(&sbi->sb->s_umount);
122962306a36Sopenharmony_ci		f2fs_quota_sync(sbi->sb, -1);
123062306a36Sopenharmony_ci		if (locked)
123162306a36Sopenharmony_ci			up_read(&sbi->sb->s_umount);
123262306a36Sopenharmony_ci		cond_resched();
123362306a36Sopenharmony_ci		goto retry_flush_quotas;
123462306a36Sopenharmony_ci	}
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ciretry_flush_dents:
123762306a36Sopenharmony_ci	/* write all the dirty dentry pages */
123862306a36Sopenharmony_ci	if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
123962306a36Sopenharmony_ci		f2fs_unlock_all(sbi);
124062306a36Sopenharmony_ci		err = f2fs_sync_dirty_inodes(sbi, DIR_INODE, true);
124162306a36Sopenharmony_ci		if (err)
124262306a36Sopenharmony_ci			return err;
124362306a36Sopenharmony_ci		cond_resched();
124462306a36Sopenharmony_ci		goto retry_flush_quotas;
124562306a36Sopenharmony_ci	}
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	/*
124862306a36Sopenharmony_ci	 * POR: we should ensure that there are no dirty node pages
124962306a36Sopenharmony_ci	 * until finishing nat/sit flush. inode->i_blocks can be updated.
125062306a36Sopenharmony_ci	 */
125162306a36Sopenharmony_ci	f2fs_down_write(&sbi->node_change);
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci	if (get_pages(sbi, F2FS_DIRTY_IMETA)) {
125462306a36Sopenharmony_ci		f2fs_up_write(&sbi->node_change);
125562306a36Sopenharmony_ci		f2fs_unlock_all(sbi);
125662306a36Sopenharmony_ci		err = f2fs_sync_inode_meta(sbi);
125762306a36Sopenharmony_ci		if (err)
125862306a36Sopenharmony_ci			return err;
125962306a36Sopenharmony_ci		cond_resched();
126062306a36Sopenharmony_ci		goto retry_flush_quotas;
126162306a36Sopenharmony_ci	}
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ciretry_flush_nodes:
126462306a36Sopenharmony_ci	f2fs_down_write(&sbi->node_write);
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci	if (get_pages(sbi, F2FS_DIRTY_NODES)) {
126762306a36Sopenharmony_ci		f2fs_up_write(&sbi->node_write);
126862306a36Sopenharmony_ci		atomic_inc(&sbi->wb_sync_req[NODE]);
126962306a36Sopenharmony_ci		err = f2fs_sync_node_pages(sbi, &wbc, false, FS_CP_NODE_IO);
127062306a36Sopenharmony_ci		atomic_dec(&sbi->wb_sync_req[NODE]);
127162306a36Sopenharmony_ci		if (err) {
127262306a36Sopenharmony_ci			f2fs_up_write(&sbi->node_change);
127362306a36Sopenharmony_ci			f2fs_unlock_all(sbi);
127462306a36Sopenharmony_ci			return err;
127562306a36Sopenharmony_ci		}
127662306a36Sopenharmony_ci		cond_resched();
127762306a36Sopenharmony_ci		goto retry_flush_nodes;
127862306a36Sopenharmony_ci	}
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_ci	/*
128162306a36Sopenharmony_ci	 * sbi->node_change is used only for AIO write_begin path which produces
128262306a36Sopenharmony_ci	 * dirty node blocks and some checkpoint values by block allocation.
128362306a36Sopenharmony_ci	 */
128462306a36Sopenharmony_ci	__prepare_cp_block(sbi);
128562306a36Sopenharmony_ci	f2fs_up_write(&sbi->node_change);
128662306a36Sopenharmony_ci	return err;
128762306a36Sopenharmony_ci}
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_cistatic void unblock_operations(struct f2fs_sb_info *sbi)
129062306a36Sopenharmony_ci{
129162306a36Sopenharmony_ci	f2fs_up_write(&sbi->node_write);
129262306a36Sopenharmony_ci	f2fs_unlock_all(sbi);
129362306a36Sopenharmony_ci}
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_civoid f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type)
129662306a36Sopenharmony_ci{
129762306a36Sopenharmony_ci	DEFINE_WAIT(wait);
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	for (;;) {
130062306a36Sopenharmony_ci		if (!get_pages(sbi, type))
130162306a36Sopenharmony_ci			break;
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci		if (unlikely(f2fs_cp_error(sbi) &&
130462306a36Sopenharmony_ci			!is_sbi_flag_set(sbi, SBI_IS_CLOSE)))
130562306a36Sopenharmony_ci			break;
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci		if (type == F2FS_DIRTY_META)
130862306a36Sopenharmony_ci			f2fs_sync_meta_pages(sbi, META, LONG_MAX,
130962306a36Sopenharmony_ci							FS_CP_META_IO);
131062306a36Sopenharmony_ci		else if (type == F2FS_WB_CP_DATA)
131162306a36Sopenharmony_ci			f2fs_submit_merged_write(sbi, DATA);
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_ci		prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE);
131462306a36Sopenharmony_ci		io_schedule_timeout(DEFAULT_IO_TIMEOUT);
131562306a36Sopenharmony_ci	}
131662306a36Sopenharmony_ci	finish_wait(&sbi->cp_wait, &wait);
131762306a36Sopenharmony_ci}
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_cistatic void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
132062306a36Sopenharmony_ci{
132162306a36Sopenharmony_ci	unsigned long orphan_num = sbi->im[ORPHAN_INO].ino_num;
132262306a36Sopenharmony_ci	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
132362306a36Sopenharmony_ci	unsigned long flags;
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	if (cpc->reason & CP_UMOUNT) {
132662306a36Sopenharmony_ci		if (le32_to_cpu(ckpt->cp_pack_total_block_count) +
132762306a36Sopenharmony_ci			NM_I(sbi)->nat_bits_blocks > sbi->blocks_per_seg) {
132862306a36Sopenharmony_ci			clear_ckpt_flags(sbi, CP_NAT_BITS_FLAG);
132962306a36Sopenharmony_ci			f2fs_notice(sbi, "Disable nat_bits due to no space");
133062306a36Sopenharmony_ci		} else if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG) &&
133162306a36Sopenharmony_ci						f2fs_nat_bitmap_enabled(sbi)) {
133262306a36Sopenharmony_ci			f2fs_enable_nat_bits(sbi);
133362306a36Sopenharmony_ci			set_ckpt_flags(sbi, CP_NAT_BITS_FLAG);
133462306a36Sopenharmony_ci			f2fs_notice(sbi, "Rebuild and enable nat_bits");
133562306a36Sopenharmony_ci		}
133662306a36Sopenharmony_ci	}
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_ci	spin_lock_irqsave(&sbi->cp_lock, flags);
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	if (cpc->reason & CP_TRIMMED)
134162306a36Sopenharmony_ci		__set_ckpt_flags(ckpt, CP_TRIMMED_FLAG);
134262306a36Sopenharmony_ci	else
134362306a36Sopenharmony_ci		__clear_ckpt_flags(ckpt, CP_TRIMMED_FLAG);
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	if (cpc->reason & CP_UMOUNT)
134662306a36Sopenharmony_ci		__set_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
134762306a36Sopenharmony_ci	else
134862306a36Sopenharmony_ci		__clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci	if (cpc->reason & CP_FASTBOOT)
135162306a36Sopenharmony_ci		__set_ckpt_flags(ckpt, CP_FASTBOOT_FLAG);
135262306a36Sopenharmony_ci	else
135362306a36Sopenharmony_ci		__clear_ckpt_flags(ckpt, CP_FASTBOOT_FLAG);
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci	if (orphan_num)
135662306a36Sopenharmony_ci		__set_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG);
135762306a36Sopenharmony_ci	else
135862306a36Sopenharmony_ci		__clear_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG);
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	if (is_sbi_flag_set(sbi, SBI_NEED_FSCK))
136162306a36Sopenharmony_ci		__set_ckpt_flags(ckpt, CP_FSCK_FLAG);
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	if (is_sbi_flag_set(sbi, SBI_IS_RESIZEFS))
136462306a36Sopenharmony_ci		__set_ckpt_flags(ckpt, CP_RESIZEFS_FLAG);
136562306a36Sopenharmony_ci	else
136662306a36Sopenharmony_ci		__clear_ckpt_flags(ckpt, CP_RESIZEFS_FLAG);
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci	if (is_sbi_flag_set(sbi, SBI_CP_DISABLED))
136962306a36Sopenharmony_ci		__set_ckpt_flags(ckpt, CP_DISABLED_FLAG);
137062306a36Sopenharmony_ci	else
137162306a36Sopenharmony_ci		__clear_ckpt_flags(ckpt, CP_DISABLED_FLAG);
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci	if (is_sbi_flag_set(sbi, SBI_CP_DISABLED_QUICK))
137462306a36Sopenharmony_ci		__set_ckpt_flags(ckpt, CP_DISABLED_QUICK_FLAG);
137562306a36Sopenharmony_ci	else
137662306a36Sopenharmony_ci		__clear_ckpt_flags(ckpt, CP_DISABLED_QUICK_FLAG);
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH))
137962306a36Sopenharmony_ci		__set_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG);
138062306a36Sopenharmony_ci	else
138162306a36Sopenharmony_ci		__clear_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG);
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR))
138462306a36Sopenharmony_ci		__set_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG);
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci	/* set this flag to activate crc|cp_ver for recovery */
138762306a36Sopenharmony_ci	__set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG);
138862306a36Sopenharmony_ci	__clear_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG);
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	spin_unlock_irqrestore(&sbi->cp_lock, flags);
139162306a36Sopenharmony_ci}
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_cistatic void commit_checkpoint(struct f2fs_sb_info *sbi,
139462306a36Sopenharmony_ci	void *src, block_t blk_addr)
139562306a36Sopenharmony_ci{
139662306a36Sopenharmony_ci	struct writeback_control wbc = {
139762306a36Sopenharmony_ci		.for_reclaim = 0,
139862306a36Sopenharmony_ci	};
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci	/*
140162306a36Sopenharmony_ci	 * filemap_get_folios_tag and lock_page again will take
140262306a36Sopenharmony_ci	 * some extra time. Therefore, f2fs_update_meta_pages and
140362306a36Sopenharmony_ci	 * f2fs_sync_meta_pages are combined in this function.
140462306a36Sopenharmony_ci	 */
140562306a36Sopenharmony_ci	struct page *page = f2fs_grab_meta_page(sbi, blk_addr);
140662306a36Sopenharmony_ci	int err;
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci	f2fs_wait_on_page_writeback(page, META, true, true);
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci	memcpy(page_address(page), src, PAGE_SIZE);
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ci	set_page_dirty(page);
141362306a36Sopenharmony_ci	if (unlikely(!clear_page_dirty_for_io(page)))
141462306a36Sopenharmony_ci		f2fs_bug_on(sbi, 1);
141562306a36Sopenharmony_ci
141662306a36Sopenharmony_ci	/* writeout cp pack 2 page */
141762306a36Sopenharmony_ci	err = __f2fs_write_meta_page(page, &wbc, FS_CP_META_IO);
141862306a36Sopenharmony_ci	if (unlikely(err && f2fs_cp_error(sbi))) {
141962306a36Sopenharmony_ci		f2fs_put_page(page, 1);
142062306a36Sopenharmony_ci		return;
142162306a36Sopenharmony_ci	}
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	f2fs_bug_on(sbi, err);
142462306a36Sopenharmony_ci	f2fs_put_page(page, 0);
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci	/* submit checkpoint (with barrier if NOBARRIER is not set) */
142762306a36Sopenharmony_ci	f2fs_submit_merged_write(sbi, META_FLUSH);
142862306a36Sopenharmony_ci}
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_cistatic inline u64 get_sectors_written(struct block_device *bdev)
143162306a36Sopenharmony_ci{
143262306a36Sopenharmony_ci	return (u64)part_stat_read(bdev, sectors[STAT_WRITE]);
143362306a36Sopenharmony_ci}
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_ciu64 f2fs_get_sectors_written(struct f2fs_sb_info *sbi)
143662306a36Sopenharmony_ci{
143762306a36Sopenharmony_ci	if (f2fs_is_multi_device(sbi)) {
143862306a36Sopenharmony_ci		u64 sectors = 0;
143962306a36Sopenharmony_ci		int i;
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci		for (i = 0; i < sbi->s_ndevs; i++)
144262306a36Sopenharmony_ci			sectors += get_sectors_written(FDEV(i).bdev);
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci		return sectors;
144562306a36Sopenharmony_ci	}
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci	return get_sectors_written(sbi->sb->s_bdev);
144862306a36Sopenharmony_ci}
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_cistatic int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
145162306a36Sopenharmony_ci{
145262306a36Sopenharmony_ci	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
145362306a36Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
145462306a36Sopenharmony_ci	unsigned long orphan_num = sbi->im[ORPHAN_INO].ino_num, flags;
145562306a36Sopenharmony_ci	block_t start_blk;
145662306a36Sopenharmony_ci	unsigned int data_sum_blocks, orphan_blocks;
145762306a36Sopenharmony_ci	__u32 crc32 = 0;
145862306a36Sopenharmony_ci	int i;
145962306a36Sopenharmony_ci	int cp_payload_blks = __cp_payload(sbi);
146062306a36Sopenharmony_ci	struct curseg_info *seg_i = CURSEG_I(sbi, CURSEG_HOT_NODE);
146162306a36Sopenharmony_ci	u64 kbytes_written;
146262306a36Sopenharmony_ci	int err;
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	/* Flush all the NAT/SIT pages */
146562306a36Sopenharmony_ci	f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	/* start to update checkpoint, cp ver is already updated previously */
146862306a36Sopenharmony_ci	ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi, true));
146962306a36Sopenharmony_ci	ckpt->free_segment_count = cpu_to_le32(free_segments(sbi));
147062306a36Sopenharmony_ci	for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) {
147162306a36Sopenharmony_ci		struct curseg_info *curseg = CURSEG_I(sbi, i + CURSEG_HOT_NODE);
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci		ckpt->cur_node_segno[i] = cpu_to_le32(curseg->segno);
147462306a36Sopenharmony_ci		ckpt->cur_node_blkoff[i] = cpu_to_le16(curseg->next_blkoff);
147562306a36Sopenharmony_ci		ckpt->alloc_type[i + CURSEG_HOT_NODE] = curseg->alloc_type;
147662306a36Sopenharmony_ci	}
147762306a36Sopenharmony_ci	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
147862306a36Sopenharmony_ci		struct curseg_info *curseg = CURSEG_I(sbi, i + CURSEG_HOT_DATA);
147962306a36Sopenharmony_ci
148062306a36Sopenharmony_ci		ckpt->cur_data_segno[i] = cpu_to_le32(curseg->segno);
148162306a36Sopenharmony_ci		ckpt->cur_data_blkoff[i] = cpu_to_le16(curseg->next_blkoff);
148262306a36Sopenharmony_ci		ckpt->alloc_type[i + CURSEG_HOT_DATA] = curseg->alloc_type;
148362306a36Sopenharmony_ci	}
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	/* 2 cp + n data seg summary + orphan inode blocks */
148662306a36Sopenharmony_ci	data_sum_blocks = f2fs_npages_for_summary_flush(sbi, false);
148762306a36Sopenharmony_ci	spin_lock_irqsave(&sbi->cp_lock, flags);
148862306a36Sopenharmony_ci	if (data_sum_blocks < NR_CURSEG_DATA_TYPE)
148962306a36Sopenharmony_ci		__set_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
149062306a36Sopenharmony_ci	else
149162306a36Sopenharmony_ci		__clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
149262306a36Sopenharmony_ci	spin_unlock_irqrestore(&sbi->cp_lock, flags);
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_ci	orphan_blocks = GET_ORPHAN_BLOCKS(orphan_num);
149562306a36Sopenharmony_ci	ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks +
149662306a36Sopenharmony_ci			orphan_blocks);
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci	if (__remain_node_summaries(cpc->reason))
149962306a36Sopenharmony_ci		ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS +
150062306a36Sopenharmony_ci				cp_payload_blks + data_sum_blocks +
150162306a36Sopenharmony_ci				orphan_blocks + NR_CURSEG_NODE_TYPE);
150262306a36Sopenharmony_ci	else
150362306a36Sopenharmony_ci		ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS +
150462306a36Sopenharmony_ci				cp_payload_blks + data_sum_blocks +
150562306a36Sopenharmony_ci				orphan_blocks);
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	/* update ckpt flag for checkpoint */
150862306a36Sopenharmony_ci	update_ckpt_flags(sbi, cpc);
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_ci	/* update SIT/NAT bitmap */
151162306a36Sopenharmony_ci	get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP));
151262306a36Sopenharmony_ci	get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP));
151362306a36Sopenharmony_ci
151462306a36Sopenharmony_ci	crc32 = f2fs_checkpoint_chksum(sbi, ckpt);
151562306a36Sopenharmony_ci	*((__le32 *)((unsigned char *)ckpt +
151662306a36Sopenharmony_ci				le32_to_cpu(ckpt->checksum_offset)))
151762306a36Sopenharmony_ci				= cpu_to_le32(crc32);
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci	start_blk = __start_cp_next_addr(sbi);
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci	/* write nat bits */
152262306a36Sopenharmony_ci	if ((cpc->reason & CP_UMOUNT) &&
152362306a36Sopenharmony_ci			is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG)) {
152462306a36Sopenharmony_ci		__u64 cp_ver = cur_cp_version(ckpt);
152562306a36Sopenharmony_ci		block_t blk;
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci		cp_ver |= ((__u64)crc32 << 32);
152862306a36Sopenharmony_ci		*(__le64 *)nm_i->nat_bits = cpu_to_le64(cp_ver);
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci		blk = start_blk + sbi->blocks_per_seg - nm_i->nat_bits_blocks;
153162306a36Sopenharmony_ci		for (i = 0; i < nm_i->nat_bits_blocks; i++)
153262306a36Sopenharmony_ci			f2fs_update_meta_page(sbi, nm_i->nat_bits +
153362306a36Sopenharmony_ci					(i << F2FS_BLKSIZE_BITS), blk + i);
153462306a36Sopenharmony_ci	}
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_ci	/* write out checkpoint buffer at block 0 */
153762306a36Sopenharmony_ci	f2fs_update_meta_page(sbi, ckpt, start_blk++);
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_ci	for (i = 1; i < 1 + cp_payload_blks; i++)
154062306a36Sopenharmony_ci		f2fs_update_meta_page(sbi, (char *)ckpt + i * F2FS_BLKSIZE,
154162306a36Sopenharmony_ci							start_blk++);
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci	if (orphan_num) {
154462306a36Sopenharmony_ci		write_orphan_inodes(sbi, start_blk);
154562306a36Sopenharmony_ci		start_blk += orphan_blocks;
154662306a36Sopenharmony_ci	}
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci	f2fs_write_data_summaries(sbi, start_blk);
154962306a36Sopenharmony_ci	start_blk += data_sum_blocks;
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	/* Record write statistics in the hot node summary */
155262306a36Sopenharmony_ci	kbytes_written = sbi->kbytes_written;
155362306a36Sopenharmony_ci	kbytes_written += (f2fs_get_sectors_written(sbi) -
155462306a36Sopenharmony_ci				sbi->sectors_written_start) >> 1;
155562306a36Sopenharmony_ci	seg_i->journal->info.kbytes_written = cpu_to_le64(kbytes_written);
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci	if (__remain_node_summaries(cpc->reason)) {
155862306a36Sopenharmony_ci		f2fs_write_node_summaries(sbi, start_blk);
155962306a36Sopenharmony_ci		start_blk += NR_CURSEG_NODE_TYPE;
156062306a36Sopenharmony_ci	}
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci	/* update user_block_counts */
156362306a36Sopenharmony_ci	sbi->last_valid_block_count = sbi->total_valid_block_count;
156462306a36Sopenharmony_ci	percpu_counter_set(&sbi->alloc_valid_block_count, 0);
156562306a36Sopenharmony_ci	percpu_counter_set(&sbi->rf_node_block_count, 0);
156662306a36Sopenharmony_ci
156762306a36Sopenharmony_ci	/* Here, we have one bio having CP pack except cp pack 2 page */
156862306a36Sopenharmony_ci	f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
156962306a36Sopenharmony_ci	/* Wait for all dirty meta pages to be submitted for IO */
157062306a36Sopenharmony_ci	f2fs_wait_on_all_pages(sbi, F2FS_DIRTY_META);
157162306a36Sopenharmony_ci
157262306a36Sopenharmony_ci	/* wait for previous submitted meta pages writeback */
157362306a36Sopenharmony_ci	f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA);
157462306a36Sopenharmony_ci
157562306a36Sopenharmony_ci	/* flush all device cache */
157662306a36Sopenharmony_ci	err = f2fs_flush_device_cache(sbi);
157762306a36Sopenharmony_ci	if (err)
157862306a36Sopenharmony_ci		return err;
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci	/* barrier and flush checkpoint cp pack 2 page if it can */
158162306a36Sopenharmony_ci	commit_checkpoint(sbi, ckpt, start_blk);
158262306a36Sopenharmony_ci	f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA);
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	/*
158562306a36Sopenharmony_ci	 * invalidate intermediate page cache borrowed from meta inode which are
158662306a36Sopenharmony_ci	 * used for migration of encrypted, verity or compressed inode's blocks.
158762306a36Sopenharmony_ci	 */
158862306a36Sopenharmony_ci	if (f2fs_sb_has_encrypt(sbi) || f2fs_sb_has_verity(sbi) ||
158962306a36Sopenharmony_ci		f2fs_sb_has_compression(sbi))
159062306a36Sopenharmony_ci		f2fs_bug_on(sbi,
159162306a36Sopenharmony_ci			invalidate_inode_pages2_range(META_MAPPING(sbi),
159262306a36Sopenharmony_ci				MAIN_BLKADDR(sbi), MAX_BLKADDR(sbi) - 1));
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	f2fs_release_ino_entry(sbi, false);
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	f2fs_reset_fsync_node_info(sbi);
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	clear_sbi_flag(sbi, SBI_IS_DIRTY);
159962306a36Sopenharmony_ci	clear_sbi_flag(sbi, SBI_NEED_CP);
160062306a36Sopenharmony_ci	clear_sbi_flag(sbi, SBI_QUOTA_SKIP_FLUSH);
160162306a36Sopenharmony_ci
160262306a36Sopenharmony_ci	spin_lock(&sbi->stat_lock);
160362306a36Sopenharmony_ci	sbi->unusable_block_count = 0;
160462306a36Sopenharmony_ci	spin_unlock(&sbi->stat_lock);
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	__set_cp_next_pack(sbi);
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci	/*
160962306a36Sopenharmony_ci	 * redirty superblock if metadata like node page or inode cache is
161062306a36Sopenharmony_ci	 * updated during writing checkpoint.
161162306a36Sopenharmony_ci	 */
161262306a36Sopenharmony_ci	if (get_pages(sbi, F2FS_DIRTY_NODES) ||
161362306a36Sopenharmony_ci			get_pages(sbi, F2FS_DIRTY_IMETA))
161462306a36Sopenharmony_ci		set_sbi_flag(sbi, SBI_IS_DIRTY);
161562306a36Sopenharmony_ci
161662306a36Sopenharmony_ci	f2fs_bug_on(sbi, get_pages(sbi, F2FS_DIRTY_DENTS));
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci	return unlikely(f2fs_cp_error(sbi)) ? -EIO : 0;
161962306a36Sopenharmony_ci}
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ciint f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
162262306a36Sopenharmony_ci{
162362306a36Sopenharmony_ci	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
162462306a36Sopenharmony_ci	unsigned long long ckpt_ver;
162562306a36Sopenharmony_ci	int err = 0;
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci	if (f2fs_readonly(sbi->sb) || f2fs_hw_is_readonly(sbi))
162862306a36Sopenharmony_ci		return -EROFS;
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_ci	if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
163162306a36Sopenharmony_ci		if (cpc->reason != CP_PAUSE)
163262306a36Sopenharmony_ci			return 0;
163362306a36Sopenharmony_ci		f2fs_warn(sbi, "Start checkpoint disabled!");
163462306a36Sopenharmony_ci	}
163562306a36Sopenharmony_ci	if (cpc->reason != CP_RESIZE)
163662306a36Sopenharmony_ci		f2fs_down_write(&sbi->cp_global_sem);
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_ci	if (!is_sbi_flag_set(sbi, SBI_IS_DIRTY) &&
163962306a36Sopenharmony_ci		((cpc->reason & CP_FASTBOOT) || (cpc->reason & CP_SYNC) ||
164062306a36Sopenharmony_ci		((cpc->reason & CP_DISCARD) && !sbi->discard_blks)))
164162306a36Sopenharmony_ci		goto out;
164262306a36Sopenharmony_ci	if (unlikely(f2fs_cp_error(sbi))) {
164362306a36Sopenharmony_ci		err = -EIO;
164462306a36Sopenharmony_ci		goto out;
164562306a36Sopenharmony_ci	}
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_ci	trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "start block_ops");
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci	err = block_operations(sbi);
165062306a36Sopenharmony_ci	if (err)
165162306a36Sopenharmony_ci		goto out;
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci	trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish block_ops");
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci	f2fs_flush_merged_writes(sbi);
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_ci	/* this is the case of multiple fstrims without any changes */
165862306a36Sopenharmony_ci	if (cpc->reason & CP_DISCARD) {
165962306a36Sopenharmony_ci		if (!f2fs_exist_trim_candidates(sbi, cpc)) {
166062306a36Sopenharmony_ci			unblock_operations(sbi);
166162306a36Sopenharmony_ci			goto out;
166262306a36Sopenharmony_ci		}
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci		if (NM_I(sbi)->nat_cnt[DIRTY_NAT] == 0 &&
166562306a36Sopenharmony_ci				SIT_I(sbi)->dirty_sentries == 0 &&
166662306a36Sopenharmony_ci				prefree_segments(sbi) == 0) {
166762306a36Sopenharmony_ci			f2fs_flush_sit_entries(sbi, cpc);
166862306a36Sopenharmony_ci			f2fs_clear_prefree_segments(sbi, cpc);
166962306a36Sopenharmony_ci			unblock_operations(sbi);
167062306a36Sopenharmony_ci			goto out;
167162306a36Sopenharmony_ci		}
167262306a36Sopenharmony_ci	}
167362306a36Sopenharmony_ci
167462306a36Sopenharmony_ci	/*
167562306a36Sopenharmony_ci	 * update checkpoint pack index
167662306a36Sopenharmony_ci	 * Increase the version number so that
167762306a36Sopenharmony_ci	 * SIT entries and seg summaries are written at correct place
167862306a36Sopenharmony_ci	 */
167962306a36Sopenharmony_ci	ckpt_ver = cur_cp_version(ckpt);
168062306a36Sopenharmony_ci	ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver);
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	/* write cached NAT/SIT entries to NAT/SIT area */
168362306a36Sopenharmony_ci	err = f2fs_flush_nat_entries(sbi, cpc);
168462306a36Sopenharmony_ci	if (err) {
168562306a36Sopenharmony_ci		f2fs_err(sbi, "f2fs_flush_nat_entries failed err:%d, stop checkpoint", err);
168662306a36Sopenharmony_ci		f2fs_bug_on(sbi, !f2fs_cp_error(sbi));
168762306a36Sopenharmony_ci		goto stop;
168862306a36Sopenharmony_ci	}
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci	f2fs_flush_sit_entries(sbi, cpc);
169162306a36Sopenharmony_ci
169262306a36Sopenharmony_ci	/* save inmem log status */
169362306a36Sopenharmony_ci	f2fs_save_inmem_curseg(sbi);
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_ci	err = do_checkpoint(sbi, cpc);
169662306a36Sopenharmony_ci	if (err) {
169762306a36Sopenharmony_ci		f2fs_err(sbi, "do_checkpoint failed err:%d, stop checkpoint", err);
169862306a36Sopenharmony_ci		f2fs_bug_on(sbi, !f2fs_cp_error(sbi));
169962306a36Sopenharmony_ci		f2fs_release_discard_addrs(sbi);
170062306a36Sopenharmony_ci	} else {
170162306a36Sopenharmony_ci		f2fs_clear_prefree_segments(sbi, cpc);
170262306a36Sopenharmony_ci	}
170362306a36Sopenharmony_ci
170462306a36Sopenharmony_ci	f2fs_restore_inmem_curseg(sbi);
170562306a36Sopenharmony_ci	stat_inc_cp_count(sbi);
170662306a36Sopenharmony_cistop:
170762306a36Sopenharmony_ci	unblock_operations(sbi);
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	if (cpc->reason & CP_RECOVERY)
171062306a36Sopenharmony_ci		f2fs_notice(sbi, "checkpoint: version = %llx", ckpt_ver);
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ci	/* update CP_TIME to trigger checkpoint periodically */
171362306a36Sopenharmony_ci	f2fs_update_time(sbi, CP_TIME);
171462306a36Sopenharmony_ci	trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish checkpoint");
171562306a36Sopenharmony_ciout:
171662306a36Sopenharmony_ci	if (cpc->reason != CP_RESIZE)
171762306a36Sopenharmony_ci		f2fs_up_write(&sbi->cp_global_sem);
171862306a36Sopenharmony_ci	return err;
171962306a36Sopenharmony_ci}
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_civoid f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi)
172262306a36Sopenharmony_ci{
172362306a36Sopenharmony_ci	int i;
172462306a36Sopenharmony_ci
172562306a36Sopenharmony_ci	for (i = 0; i < MAX_INO_ENTRY; i++) {
172662306a36Sopenharmony_ci		struct inode_management *im = &sbi->im[i];
172762306a36Sopenharmony_ci
172862306a36Sopenharmony_ci		INIT_RADIX_TREE(&im->ino_root, GFP_ATOMIC);
172962306a36Sopenharmony_ci		spin_lock_init(&im->ino_lock);
173062306a36Sopenharmony_ci		INIT_LIST_HEAD(&im->ino_list);
173162306a36Sopenharmony_ci		im->ino_num = 0;
173262306a36Sopenharmony_ci	}
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_ci	sbi->max_orphans = (sbi->blocks_per_seg - F2FS_CP_PACKS -
173562306a36Sopenharmony_ci			NR_CURSEG_PERSIST_TYPE - __cp_payload(sbi)) *
173662306a36Sopenharmony_ci				F2FS_ORPHANS_PER_BLOCK;
173762306a36Sopenharmony_ci}
173862306a36Sopenharmony_ci
173962306a36Sopenharmony_ciint __init f2fs_create_checkpoint_caches(void)
174062306a36Sopenharmony_ci{
174162306a36Sopenharmony_ci	ino_entry_slab = f2fs_kmem_cache_create("f2fs_ino_entry",
174262306a36Sopenharmony_ci			sizeof(struct ino_entry));
174362306a36Sopenharmony_ci	if (!ino_entry_slab)
174462306a36Sopenharmony_ci		return -ENOMEM;
174562306a36Sopenharmony_ci	f2fs_inode_entry_slab = f2fs_kmem_cache_create("f2fs_inode_entry",
174662306a36Sopenharmony_ci			sizeof(struct inode_entry));
174762306a36Sopenharmony_ci	if (!f2fs_inode_entry_slab) {
174862306a36Sopenharmony_ci		kmem_cache_destroy(ino_entry_slab);
174962306a36Sopenharmony_ci		return -ENOMEM;
175062306a36Sopenharmony_ci	}
175162306a36Sopenharmony_ci	return 0;
175262306a36Sopenharmony_ci}
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_civoid f2fs_destroy_checkpoint_caches(void)
175562306a36Sopenharmony_ci{
175662306a36Sopenharmony_ci	kmem_cache_destroy(ino_entry_slab);
175762306a36Sopenharmony_ci	kmem_cache_destroy(f2fs_inode_entry_slab);
175862306a36Sopenharmony_ci}
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_cistatic int __write_checkpoint_sync(struct f2fs_sb_info *sbi)
176162306a36Sopenharmony_ci{
176262306a36Sopenharmony_ci	struct cp_control cpc = { .reason = CP_SYNC, };
176362306a36Sopenharmony_ci	int err;
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci	f2fs_down_write(&sbi->gc_lock);
176662306a36Sopenharmony_ci	err = f2fs_write_checkpoint(sbi, &cpc);
176762306a36Sopenharmony_ci	f2fs_up_write(&sbi->gc_lock);
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci	return err;
177062306a36Sopenharmony_ci}
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_cistatic void __checkpoint_and_complete_reqs(struct f2fs_sb_info *sbi)
177362306a36Sopenharmony_ci{
177462306a36Sopenharmony_ci	struct ckpt_req_control *cprc = &sbi->cprc_info;
177562306a36Sopenharmony_ci	struct ckpt_req *req, *next;
177662306a36Sopenharmony_ci	struct llist_node *dispatch_list;
177762306a36Sopenharmony_ci	u64 sum_diff = 0, diff, count = 0;
177862306a36Sopenharmony_ci	int ret;
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_ci	dispatch_list = llist_del_all(&cprc->issue_list);
178162306a36Sopenharmony_ci	if (!dispatch_list)
178262306a36Sopenharmony_ci		return;
178362306a36Sopenharmony_ci	dispatch_list = llist_reverse_order(dispatch_list);
178462306a36Sopenharmony_ci
178562306a36Sopenharmony_ci	ret = __write_checkpoint_sync(sbi);
178662306a36Sopenharmony_ci	atomic_inc(&cprc->issued_ckpt);
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_ci	llist_for_each_entry_safe(req, next, dispatch_list, llnode) {
178962306a36Sopenharmony_ci		diff = (u64)ktime_ms_delta(ktime_get(), req->queue_time);
179062306a36Sopenharmony_ci		req->ret = ret;
179162306a36Sopenharmony_ci		complete(&req->wait);
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ci		sum_diff += diff;
179462306a36Sopenharmony_ci		count++;
179562306a36Sopenharmony_ci	}
179662306a36Sopenharmony_ci	atomic_sub(count, &cprc->queued_ckpt);
179762306a36Sopenharmony_ci	atomic_add(count, &cprc->total_ckpt);
179862306a36Sopenharmony_ci
179962306a36Sopenharmony_ci	spin_lock(&cprc->stat_lock);
180062306a36Sopenharmony_ci	cprc->cur_time = (unsigned int)div64_u64(sum_diff, count);
180162306a36Sopenharmony_ci	if (cprc->peak_time < cprc->cur_time)
180262306a36Sopenharmony_ci		cprc->peak_time = cprc->cur_time;
180362306a36Sopenharmony_ci	spin_unlock(&cprc->stat_lock);
180462306a36Sopenharmony_ci}
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_cistatic int issue_checkpoint_thread(void *data)
180762306a36Sopenharmony_ci{
180862306a36Sopenharmony_ci	struct f2fs_sb_info *sbi = data;
180962306a36Sopenharmony_ci	struct ckpt_req_control *cprc = &sbi->cprc_info;
181062306a36Sopenharmony_ci	wait_queue_head_t *q = &cprc->ckpt_wait_queue;
181162306a36Sopenharmony_cirepeat:
181262306a36Sopenharmony_ci	if (kthread_should_stop())
181362306a36Sopenharmony_ci		return 0;
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci	if (!llist_empty(&cprc->issue_list))
181662306a36Sopenharmony_ci		__checkpoint_and_complete_reqs(sbi);
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_ci	wait_event_interruptible(*q,
181962306a36Sopenharmony_ci		kthread_should_stop() || !llist_empty(&cprc->issue_list));
182062306a36Sopenharmony_ci	goto repeat;
182162306a36Sopenharmony_ci}
182262306a36Sopenharmony_ci
182362306a36Sopenharmony_cistatic void flush_remained_ckpt_reqs(struct f2fs_sb_info *sbi,
182462306a36Sopenharmony_ci		struct ckpt_req *wait_req)
182562306a36Sopenharmony_ci{
182662306a36Sopenharmony_ci	struct ckpt_req_control *cprc = &sbi->cprc_info;
182762306a36Sopenharmony_ci
182862306a36Sopenharmony_ci	if (!llist_empty(&cprc->issue_list)) {
182962306a36Sopenharmony_ci		__checkpoint_and_complete_reqs(sbi);
183062306a36Sopenharmony_ci	} else {
183162306a36Sopenharmony_ci		/* already dispatched by issue_checkpoint_thread */
183262306a36Sopenharmony_ci		if (wait_req)
183362306a36Sopenharmony_ci			wait_for_completion(&wait_req->wait);
183462306a36Sopenharmony_ci	}
183562306a36Sopenharmony_ci}
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_cistatic void init_ckpt_req(struct ckpt_req *req)
183862306a36Sopenharmony_ci{
183962306a36Sopenharmony_ci	memset(req, 0, sizeof(struct ckpt_req));
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci	init_completion(&req->wait);
184262306a36Sopenharmony_ci	req->queue_time = ktime_get();
184362306a36Sopenharmony_ci}
184462306a36Sopenharmony_ci
184562306a36Sopenharmony_ciint f2fs_issue_checkpoint(struct f2fs_sb_info *sbi)
184662306a36Sopenharmony_ci{
184762306a36Sopenharmony_ci	struct ckpt_req_control *cprc = &sbi->cprc_info;
184862306a36Sopenharmony_ci	struct ckpt_req req;
184962306a36Sopenharmony_ci	struct cp_control cpc;
185062306a36Sopenharmony_ci
185162306a36Sopenharmony_ci	cpc.reason = __get_cp_reason(sbi);
185262306a36Sopenharmony_ci	if (!test_opt(sbi, MERGE_CHECKPOINT) || cpc.reason != CP_SYNC) {
185362306a36Sopenharmony_ci		int ret;
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci		f2fs_down_write(&sbi->gc_lock);
185662306a36Sopenharmony_ci		ret = f2fs_write_checkpoint(sbi, &cpc);
185762306a36Sopenharmony_ci		f2fs_up_write(&sbi->gc_lock);
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_ci		return ret;
186062306a36Sopenharmony_ci	}
186162306a36Sopenharmony_ci
186262306a36Sopenharmony_ci	if (!cprc->f2fs_issue_ckpt)
186362306a36Sopenharmony_ci		return __write_checkpoint_sync(sbi);
186462306a36Sopenharmony_ci
186562306a36Sopenharmony_ci	init_ckpt_req(&req);
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci	llist_add(&req.llnode, &cprc->issue_list);
186862306a36Sopenharmony_ci	atomic_inc(&cprc->queued_ckpt);
186962306a36Sopenharmony_ci
187062306a36Sopenharmony_ci	/*
187162306a36Sopenharmony_ci	 * update issue_list before we wake up issue_checkpoint thread,
187262306a36Sopenharmony_ci	 * this smp_mb() pairs with another barrier in ___wait_event(),
187362306a36Sopenharmony_ci	 * see more details in comments of waitqueue_active().
187462306a36Sopenharmony_ci	 */
187562306a36Sopenharmony_ci	smp_mb();
187662306a36Sopenharmony_ci
187762306a36Sopenharmony_ci	if (waitqueue_active(&cprc->ckpt_wait_queue))
187862306a36Sopenharmony_ci		wake_up(&cprc->ckpt_wait_queue);
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_ci	if (cprc->f2fs_issue_ckpt)
188162306a36Sopenharmony_ci		wait_for_completion(&req.wait);
188262306a36Sopenharmony_ci	else
188362306a36Sopenharmony_ci		flush_remained_ckpt_reqs(sbi, &req);
188462306a36Sopenharmony_ci
188562306a36Sopenharmony_ci	return req.ret;
188662306a36Sopenharmony_ci}
188762306a36Sopenharmony_ci
188862306a36Sopenharmony_ciint f2fs_start_ckpt_thread(struct f2fs_sb_info *sbi)
188962306a36Sopenharmony_ci{
189062306a36Sopenharmony_ci	dev_t dev = sbi->sb->s_bdev->bd_dev;
189162306a36Sopenharmony_ci	struct ckpt_req_control *cprc = &sbi->cprc_info;
189262306a36Sopenharmony_ci
189362306a36Sopenharmony_ci	if (cprc->f2fs_issue_ckpt)
189462306a36Sopenharmony_ci		return 0;
189562306a36Sopenharmony_ci
189662306a36Sopenharmony_ci	cprc->f2fs_issue_ckpt = kthread_run(issue_checkpoint_thread, sbi,
189762306a36Sopenharmony_ci			"f2fs_ckpt-%u:%u", MAJOR(dev), MINOR(dev));
189862306a36Sopenharmony_ci	if (IS_ERR(cprc->f2fs_issue_ckpt)) {
189962306a36Sopenharmony_ci		int err = PTR_ERR(cprc->f2fs_issue_ckpt);
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci		cprc->f2fs_issue_ckpt = NULL;
190262306a36Sopenharmony_ci		return err;
190362306a36Sopenharmony_ci	}
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_ci	set_task_ioprio(cprc->f2fs_issue_ckpt, cprc->ckpt_thread_ioprio);
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	return 0;
190862306a36Sopenharmony_ci}
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_civoid f2fs_stop_ckpt_thread(struct f2fs_sb_info *sbi)
191162306a36Sopenharmony_ci{
191262306a36Sopenharmony_ci	struct ckpt_req_control *cprc = &sbi->cprc_info;
191362306a36Sopenharmony_ci	struct task_struct *ckpt_task;
191462306a36Sopenharmony_ci
191562306a36Sopenharmony_ci	if (!cprc->f2fs_issue_ckpt)
191662306a36Sopenharmony_ci		return;
191762306a36Sopenharmony_ci
191862306a36Sopenharmony_ci	ckpt_task = cprc->f2fs_issue_ckpt;
191962306a36Sopenharmony_ci	cprc->f2fs_issue_ckpt = NULL;
192062306a36Sopenharmony_ci	kthread_stop(ckpt_task);
192162306a36Sopenharmony_ci
192262306a36Sopenharmony_ci	f2fs_flush_ckpt_thread(sbi);
192362306a36Sopenharmony_ci}
192462306a36Sopenharmony_ci
192562306a36Sopenharmony_civoid f2fs_flush_ckpt_thread(struct f2fs_sb_info *sbi)
192662306a36Sopenharmony_ci{
192762306a36Sopenharmony_ci	struct ckpt_req_control *cprc = &sbi->cprc_info;
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ci	flush_remained_ckpt_reqs(sbi, NULL);
193062306a36Sopenharmony_ci
193162306a36Sopenharmony_ci	/* Let's wait for the previous dispatched checkpoint. */
193262306a36Sopenharmony_ci	while (atomic_read(&cprc->queued_ckpt))
193362306a36Sopenharmony_ci		io_schedule_timeout(DEFAULT_IO_TIMEOUT);
193462306a36Sopenharmony_ci}
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_civoid f2fs_init_ckpt_req_control(struct f2fs_sb_info *sbi)
193762306a36Sopenharmony_ci{
193862306a36Sopenharmony_ci	struct ckpt_req_control *cprc = &sbi->cprc_info;
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci	atomic_set(&cprc->issued_ckpt, 0);
194162306a36Sopenharmony_ci	atomic_set(&cprc->total_ckpt, 0);
194262306a36Sopenharmony_ci	atomic_set(&cprc->queued_ckpt, 0);
194362306a36Sopenharmony_ci	cprc->ckpt_thread_ioprio = DEFAULT_CHECKPOINT_IOPRIO;
194462306a36Sopenharmony_ci	init_waitqueue_head(&cprc->ckpt_wait_queue);
194562306a36Sopenharmony_ci	init_llist_head(&cprc->issue_list);
194662306a36Sopenharmony_ci	spin_lock_init(&cprc->stat_lock);
194762306a36Sopenharmony_ci}
1948