xref: /openbmc/linux/fs/f2fs/inode.c (revision dcd6b38b)
17c1a000dSChao Yu // SPDX-License-Identifier: GPL-2.0
20a8165d7SJaegeuk Kim /*
319f99ceeSJaegeuk Kim  * fs/f2fs/inode.c
419f99ceeSJaegeuk Kim  *
519f99ceeSJaegeuk Kim  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
619f99ceeSJaegeuk Kim  *             http://www.samsung.com/
719f99ceeSJaegeuk Kim  */
819f99ceeSJaegeuk Kim #include <linux/fs.h>
919f99ceeSJaegeuk Kim #include <linux/f2fs_fs.h>
1019f99ceeSJaegeuk Kim #include <linux/buffer_head.h>
1119f99ceeSJaegeuk Kim #include <linux/writeback.h>
124034247aSNeilBrown #include <linux/sched/mm.h>
13698a5c8cSYangtao Li #include <linux/lz4.h>
14698a5c8cSYangtao Li #include <linux/zstd.h>
1519f99ceeSJaegeuk Kim 
1619f99ceeSJaegeuk Kim #include "f2fs.h"
1719f99ceeSJaegeuk Kim #include "node.h"
180eb0adadSChao Yu #include "segment.h"
19dd6c89b5SChao Yu #include "xattr.h"
2019f99ceeSJaegeuk Kim 
21a2a4a7e4SNamjae Jeon #include <trace/events/f2fs.h>
22a2a4a7e4SNamjae Jeon 
236ce19affSChao Yu #ifdef CONFIG_F2FS_FS_COMPRESSION
246ce19affSChao Yu extern const struct address_space_operations f2fs_compress_aops;
256ce19affSChao Yu #endif
266ce19affSChao Yu 
f2fs_mark_inode_dirty_sync(struct inode * inode,bool sync)277c45729aSJaegeuk Kim void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
28b56ab837SJaegeuk Kim {
299ac1e2d8SDaeho Jeong 	if (is_inode_flag_set(inode, FI_NEW_INODE))
309ac1e2d8SDaeho Jeong 		return;
319ac1e2d8SDaeho Jeong 
327c45729aSJaegeuk Kim 	if (f2fs_inode_dirtied(inode, sync))
33b56ab837SJaegeuk Kim 		return;
347c45729aSJaegeuk Kim 
35b56ab837SJaegeuk Kim 	mark_inode_dirty_sync(inode);
36b56ab837SJaegeuk Kim }
37b56ab837SJaegeuk Kim 
f2fs_set_inode_flags(struct inode * inode)3819f99ceeSJaegeuk Kim void f2fs_set_inode_flags(struct inode *inode)
3919f99ceeSJaegeuk Kim {
4019f99ceeSJaegeuk Kim 	unsigned int flags = F2FS_I(inode)->i_flags;
418abfb36aSZhang Zhen 	unsigned int new_fl = 0;
4219f99ceeSJaegeuk Kim 
4359c84408SChao Yu 	if (flags & F2FS_SYNC_FL)
448abfb36aSZhang Zhen 		new_fl |= S_SYNC;
4559c84408SChao Yu 	if (flags & F2FS_APPEND_FL)
468abfb36aSZhang Zhen 		new_fl |= S_APPEND;
4759c84408SChao Yu 	if (flags & F2FS_IMMUTABLE_FL)
488abfb36aSZhang Zhen 		new_fl |= S_IMMUTABLE;
4959c84408SChao Yu 	if (flags & F2FS_NOATIME_FL)
508abfb36aSZhang Zhen 		new_fl |= S_NOATIME;
5159c84408SChao Yu 	if (flags & F2FS_DIRSYNC_FL)
528abfb36aSZhang Zhen 		new_fl |= S_DIRSYNC;
5362230e0dSChandan Rajendra 	if (file_is_encrypt(inode))
542ee6a576SEric Biggers 		new_fl |= S_ENCRYPTED;
5595ae251fSEric Biggers 	if (file_is_verity(inode))
5695ae251fSEric Biggers 		new_fl |= S_VERITY;
572c2eb7a3SDaniel Rosenberg 	if (flags & F2FS_CASEFOLD_FL)
582c2eb7a3SDaniel Rosenberg 		new_fl |= S_CASEFOLD;
596a678857SZhang Zhen 	inode_set_flags(inode, new_fl,
602ee6a576SEric Biggers 			S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|
61fbc246a1SLinus Torvalds 			S_ENCRYPTED|S_VERITY|S_CASEFOLD);
6219f99ceeSJaegeuk Kim }
6319f99ceeSJaegeuk Kim 
__get_inode_rdev(struct inode * inode,struct page * node_page)64*dcd6b38bSChao Yu static void __get_inode_rdev(struct inode *inode, struct page *node_page)
653d1e3807SJaegeuk Kim {
66*dcd6b38bSChao Yu 	__le32 *addr = get_dnode_addr(inode, node_page);
677a2af766SChao Yu 
683d1e3807SJaegeuk Kim 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
693d1e3807SJaegeuk Kim 			S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
70*dcd6b38bSChao Yu 		if (addr[0])
71*dcd6b38bSChao Yu 			inode->i_rdev = old_decode_dev(le32_to_cpu(addr[0]));
723d1e3807SJaegeuk Kim 		else
73*dcd6b38bSChao Yu 			inode->i_rdev = new_decode_dev(le32_to_cpu(addr[1]));
743d1e3807SJaegeuk Kim 	}
753d1e3807SJaegeuk Kim }
763d1e3807SJaegeuk Kim 
__set_inode_rdev(struct inode * inode,struct page * node_page)77*dcd6b38bSChao Yu static void __set_inode_rdev(struct inode *inode, struct page *node_page)
783d1e3807SJaegeuk Kim {
79*dcd6b38bSChao Yu 	__le32 *addr = get_dnode_addr(inode, node_page);
807a2af766SChao Yu 
813d1e3807SJaegeuk Kim 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
823d1e3807SJaegeuk Kim 		if (old_valid_dev(inode->i_rdev)) {
83*dcd6b38bSChao Yu 			addr[0] = cpu_to_le32(old_encode_dev(inode->i_rdev));
84*dcd6b38bSChao Yu 			addr[1] = 0;
853d1e3807SJaegeuk Kim 		} else {
86*dcd6b38bSChao Yu 			addr[0] = 0;
87*dcd6b38bSChao Yu 			addr[1] = cpu_to_le32(new_encode_dev(inode->i_rdev));
88*dcd6b38bSChao Yu 			addr[2] = 0;
893d1e3807SJaegeuk Kim 		}
903d1e3807SJaegeuk Kim 	}
913d1e3807SJaegeuk Kim }
923d1e3807SJaegeuk Kim 
__recover_inline_status(struct inode * inode,struct page * ipage)939e5ba77fSChao Yu static void __recover_inline_status(struct inode *inode, struct page *ipage)
94b3d208f9SJaegeuk Kim {
95f2470371SChao Yu 	void *inline_data = inline_data_addr(inode, ipage);
969e5ba77fSChao Yu 	__le32 *start = inline_data;
97f2470371SChao Yu 	__le32 *end = start + MAX_INLINE_DATA(inode) / sizeof(__le32);
98b3d208f9SJaegeuk Kim 
999e5ba77fSChao Yu 	while (start < end) {
1009e5ba77fSChao Yu 		if (*start++) {
101bae0ee7aSChao Yu 			f2fs_wait_on_page_writeback(ipage, NODE, true, true);
102b3d208f9SJaegeuk Kim 
10391942321SJaegeuk Kim 			set_inode_flag(inode, FI_DATA_EXIST);
10491942321SJaegeuk Kim 			set_raw_inline(inode, F2FS_INODE(ipage));
105b3d208f9SJaegeuk Kim 			set_page_dirty(ipage);
1069e5ba77fSChao Yu 			return;
1079e5ba77fSChao Yu 		}
1089e5ba77fSChao Yu 	}
1099e5ba77fSChao Yu 	return;
110b3d208f9SJaegeuk Kim }
111b3d208f9SJaegeuk Kim 
f2fs_enable_inode_chksum(struct f2fs_sb_info * sbi,struct page * page)112704956ecSChao Yu static bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct page *page)
113704956ecSChao Yu {
114704956ecSChao Yu 	struct f2fs_inode *ri = &F2FS_NODE(page)->i;
115704956ecSChao Yu 
1167beb01f7SChao Yu 	if (!f2fs_sb_has_inode_chksum(sbi))
117704956ecSChao Yu 		return false;
118704956ecSChao Yu 
1194c6b56c0SChao Yu 	if (!IS_INODE(page) || !(ri->i_inline & F2FS_EXTRA_ATTR))
120704956ecSChao Yu 		return false;
121704956ecSChao Yu 
122d6964949SZhikang Zhang 	if (!F2FS_FITS_IN_INODE(ri, le16_to_cpu(ri->i_extra_isize),
123d6964949SZhikang Zhang 				i_inode_checksum))
124704956ecSChao Yu 		return false;
125704956ecSChao Yu 
126704956ecSChao Yu 	return true;
127704956ecSChao Yu }
128704956ecSChao Yu 
f2fs_inode_chksum(struct f2fs_sb_info * sbi,struct page * page)129704956ecSChao Yu static __u32 f2fs_inode_chksum(struct f2fs_sb_info *sbi, struct page *page)
130704956ecSChao Yu {
131704956ecSChao Yu 	struct f2fs_node *node = F2FS_NODE(page);
132704956ecSChao Yu 	struct f2fs_inode *ri = &node->i;
133704956ecSChao Yu 	__le32 ino = node->footer.ino;
134704956ecSChao Yu 	__le32 gen = ri->i_generation;
135704956ecSChao Yu 	__u32 chksum, chksum_seed;
136704956ecSChao Yu 	__u32 dummy_cs = 0;
137704956ecSChao Yu 	unsigned int offset = offsetof(struct f2fs_inode, i_inode_checksum);
138704956ecSChao Yu 	unsigned int cs_size = sizeof(dummy_cs);
139704956ecSChao Yu 
140704956ecSChao Yu 	chksum = f2fs_chksum(sbi, sbi->s_chksum_seed, (__u8 *)&ino,
141704956ecSChao Yu 							sizeof(ino));
142704956ecSChao Yu 	chksum_seed = f2fs_chksum(sbi, chksum, (__u8 *)&gen, sizeof(gen));
143704956ecSChao Yu 
144704956ecSChao Yu 	chksum = f2fs_chksum(sbi, chksum_seed, (__u8 *)ri, offset);
145704956ecSChao Yu 	chksum = f2fs_chksum(sbi, chksum, (__u8 *)&dummy_cs, cs_size);
146704956ecSChao Yu 	offset += cs_size;
147704956ecSChao Yu 	chksum = f2fs_chksum(sbi, chksum, (__u8 *)ri + offset,
148704956ecSChao Yu 						F2FS_BLKSIZE - offset);
149704956ecSChao Yu 	return chksum;
150704956ecSChao Yu }
151704956ecSChao Yu 
f2fs_inode_chksum_verify(struct f2fs_sb_info * sbi,struct page * page)152704956ecSChao Yu bool f2fs_inode_chksum_verify(struct f2fs_sb_info *sbi, struct page *page)
153704956ecSChao Yu {
154704956ecSChao Yu 	struct f2fs_inode *ri;
155704956ecSChao Yu 	__u32 provided, calculated;
156704956ecSChao Yu 
15783a3bfdbSJaegeuk Kim 	if (unlikely(is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)))
15883a3bfdbSJaegeuk Kim 		return true;
15983a3bfdbSJaegeuk Kim 
16054c55c4eSWeichao Guo #ifdef CONFIG_F2FS_CHECK_FS
16154c55c4eSWeichao Guo 	if (!f2fs_enable_inode_chksum(sbi, page))
16254c55c4eSWeichao Guo #else
163ee605234SJaegeuk Kim 	if (!f2fs_enable_inode_chksum(sbi, page) ||
164ee605234SJaegeuk Kim 			PageDirty(page) || PageWriteback(page))
16554c55c4eSWeichao Guo #endif
166704956ecSChao Yu 		return true;
167704956ecSChao Yu 
168704956ecSChao Yu 	ri = &F2FS_NODE(page)->i;
169704956ecSChao Yu 	provided = le32_to_cpu(ri->i_inode_checksum);
170704956ecSChao Yu 	calculated = f2fs_inode_chksum(sbi, page);
171704956ecSChao Yu 
172704956ecSChao Yu 	if (provided != calculated)
173dcbb4c10SJoe Perches 		f2fs_warn(sbi, "checksum invalid, nid = %lu, ino_of_node = %x, %x vs. %x",
174b42b179bSChao Yu 			  page->index, ino_of_node(page), provided, calculated);
175704956ecSChao Yu 
176704956ecSChao Yu 	return provided == calculated;
177704956ecSChao Yu }
178704956ecSChao Yu 
f2fs_inode_chksum_set(struct f2fs_sb_info * sbi,struct page * page)179704956ecSChao Yu void f2fs_inode_chksum_set(struct f2fs_sb_info *sbi, struct page *page)
180704956ecSChao Yu {
181704956ecSChao Yu 	struct f2fs_inode *ri = &F2FS_NODE(page)->i;
182704956ecSChao Yu 
183704956ecSChao Yu 	if (!f2fs_enable_inode_chksum(sbi, page))
184704956ecSChao Yu 		return;
185704956ecSChao Yu 
186704956ecSChao Yu 	ri->i_inode_checksum = cpu_to_le32(f2fs_inode_chksum(sbi, page));
187704956ecSChao Yu }
188704956ecSChao Yu 
sanity_check_compress_inode(struct inode * inode,struct f2fs_inode * ri)189698a5c8cSYangtao Li static bool sanity_check_compress_inode(struct inode *inode,
190698a5c8cSYangtao Li 			struct f2fs_inode *ri)
191698a5c8cSYangtao Li {
192698a5c8cSYangtao Li 	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
193698a5c8cSYangtao Li 	unsigned char clevel;
194698a5c8cSYangtao Li 
195698a5c8cSYangtao Li 	if (ri->i_compress_algorithm >= COMPRESS_MAX) {
196698a5c8cSYangtao Li 		f2fs_warn(sbi,
197698a5c8cSYangtao Li 			"%s: inode (ino=%lx) has unsupported compress algorithm: %u, run fsck to fix",
198698a5c8cSYangtao Li 			__func__, inode->i_ino, ri->i_compress_algorithm);
199c9887949SChao Yu 		return false;
200698a5c8cSYangtao Li 	}
201698a5c8cSYangtao Li 	if (le64_to_cpu(ri->i_compr_blocks) >
202698a5c8cSYangtao Li 			SECTOR_TO_BLOCK(inode->i_blocks)) {
203698a5c8cSYangtao Li 		f2fs_warn(sbi,
204698a5c8cSYangtao Li 			"%s: inode (ino=%lx) has inconsistent i_compr_blocks:%llu, i_blocks:%llu, run fsck to fix",
205698a5c8cSYangtao Li 			__func__, inode->i_ino, le64_to_cpu(ri->i_compr_blocks),
206698a5c8cSYangtao Li 			SECTOR_TO_BLOCK(inode->i_blocks));
207c9887949SChao Yu 		return false;
208698a5c8cSYangtao Li 	}
209698a5c8cSYangtao Li 	if (ri->i_log_cluster_size < MIN_COMPRESS_LOG_SIZE ||
210698a5c8cSYangtao Li 		ri->i_log_cluster_size > MAX_COMPRESS_LOG_SIZE) {
211698a5c8cSYangtao Li 		f2fs_warn(sbi,
212698a5c8cSYangtao Li 			"%s: inode (ino=%lx) has unsupported log cluster size: %u, run fsck to fix",
213698a5c8cSYangtao Li 			__func__, inode->i_ino, ri->i_log_cluster_size);
214c9887949SChao Yu 		return false;
215698a5c8cSYangtao Li 	}
216698a5c8cSYangtao Li 
217698a5c8cSYangtao Li 	clevel = le16_to_cpu(ri->i_compress_flag) >>
218698a5c8cSYangtao Li 				COMPRESS_LEVEL_OFFSET;
219698a5c8cSYangtao Li 	switch (ri->i_compress_algorithm) {
220698a5c8cSYangtao Li 	case COMPRESS_LZO:
221698a5c8cSYangtao Li #ifdef CONFIG_F2FS_FS_LZO
222698a5c8cSYangtao Li 		if (clevel)
223698a5c8cSYangtao Li 			goto err_level;
224698a5c8cSYangtao Li #endif
225698a5c8cSYangtao Li 		break;
226698a5c8cSYangtao Li 	case COMPRESS_LZORLE:
227698a5c8cSYangtao Li #ifdef CONFIG_F2FS_FS_LZORLE
228698a5c8cSYangtao Li 		if (clevel)
229698a5c8cSYangtao Li 			goto err_level;
230698a5c8cSYangtao Li #endif
231698a5c8cSYangtao Li 		break;
232698a5c8cSYangtao Li 	case COMPRESS_LZ4:
233698a5c8cSYangtao Li #ifdef CONFIG_F2FS_FS_LZ4
234698a5c8cSYangtao Li #ifdef CONFIG_F2FS_FS_LZ4HC
235698a5c8cSYangtao Li 		if (clevel &&
236698a5c8cSYangtao Li 		   (clevel < LZ4HC_MIN_CLEVEL || clevel > LZ4HC_MAX_CLEVEL))
237698a5c8cSYangtao Li 			goto err_level;
238698a5c8cSYangtao Li #else
239698a5c8cSYangtao Li 		if (clevel)
240698a5c8cSYangtao Li 			goto err_level;
241698a5c8cSYangtao Li #endif
242698a5c8cSYangtao Li #endif
243698a5c8cSYangtao Li 		break;
244698a5c8cSYangtao Li 	case COMPRESS_ZSTD:
245698a5c8cSYangtao Li #ifdef CONFIG_F2FS_FS_ZSTD
246698a5c8cSYangtao Li 		if (clevel < zstd_min_clevel() || clevel > zstd_max_clevel())
247698a5c8cSYangtao Li 			goto err_level;
248698a5c8cSYangtao Li #endif
249698a5c8cSYangtao Li 		break;
250698a5c8cSYangtao Li 	default:
251698a5c8cSYangtao Li 		goto err_level;
252698a5c8cSYangtao Li 	}
253698a5c8cSYangtao Li 
254698a5c8cSYangtao Li 	return true;
255698a5c8cSYangtao Li err_level:
256698a5c8cSYangtao Li 	f2fs_warn(sbi, "%s: inode (ino=%lx) has unsupported compress level: %u, run fsck to fix",
257698a5c8cSYangtao Li 		  __func__, inode->i_ino, clevel);
258698a5c8cSYangtao Li 	return false;
259698a5c8cSYangtao Li }
260698a5c8cSYangtao Li 
sanity_check_inode(struct inode * inode,struct page * node_page)261e34438c9SChao Yu static bool sanity_check_inode(struct inode *inode, struct page *node_page)
2625d64600dSJaegeuk Kim {
2635d64600dSJaegeuk Kim 	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
26418dd6470SChao Yu 	struct f2fs_inode_info *fi = F2FS_I(inode);
2654c8ff709SChao Yu 	struct f2fs_inode *ri = F2FS_INODE(node_page);
266e34438c9SChao Yu 	unsigned long long iblocks;
267e34438c9SChao Yu 
268e34438c9SChao Yu 	iblocks = le64_to_cpu(F2FS_INODE(node_page)->i_blocks);
269e34438c9SChao Yu 	if (!iblocks) {
270dcbb4c10SJoe Perches 		f2fs_warn(sbi, "%s: corrupted inode i_blocks i_ino=%lx iblocks=%llu, run fsck to fix.",
271e34438c9SChao Yu 			  __func__, inode->i_ino, iblocks);
272e34438c9SChao Yu 		return false;
273e34438c9SChao Yu 	}
274e34438c9SChao Yu 
275e34438c9SChao Yu 	if (ino_of_node(node_page) != nid_of_node(node_page)) {
276dcbb4c10SJoe Perches 		f2fs_warn(sbi, "%s: corrupted inode footer i_ino=%lx, ino,nid: [%u, %u] run fsck to fix.",
277e34438c9SChao Yu 			  __func__, inode->i_ino,
278e34438c9SChao Yu 			  ino_of_node(node_page), nid_of_node(node_page));
279e34438c9SChao Yu 		return false;
280e34438c9SChao Yu 	}
2815d64600dSJaegeuk Kim 
282f240d3aaSChao Yu 	if (f2fs_has_extra_attr(inode)) {
283f240d3aaSChao Yu 		if (!f2fs_sb_has_extra_attr(sbi)) {
284dcbb4c10SJoe Perches 			f2fs_warn(sbi, "%s: inode (ino=%lx) is with extra_attr, but extra_attr feature is off",
28576d56d4aSChao Yu 				  __func__, inode->i_ino);
28676d56d4aSChao Yu 			return false;
28776d56d4aSChao Yu 		}
28818dd6470SChao Yu 		if (fi->i_extra_isize > F2FS_TOTAL_EXTRA_ATTR_SIZE ||
289f240d3aaSChao Yu 			fi->i_extra_isize < F2FS_MIN_EXTRA_ATTR_SIZE ||
29018dd6470SChao Yu 			fi->i_extra_isize % sizeof(__le32)) {
291dcbb4c10SJoe Perches 			f2fs_warn(sbi, "%s: inode (ino=%lx) has corrupted i_extra_isize: %d, max: %zu",
29218dd6470SChao Yu 				  __func__, inode->i_ino, fi->i_extra_isize,
29318dd6470SChao Yu 				  F2FS_TOTAL_EXTRA_ATTR_SIZE);
29418dd6470SChao Yu 			return false;
29518dd6470SChao Yu 		}
296f240d3aaSChao Yu 		if (f2fs_sb_has_flexible_inline_xattr(sbi) &&
297dd6c89b5SChao Yu 			f2fs_has_inline_xattr(inode) &&
298dd6c89b5SChao Yu 			(!fi->i_inline_xattr_size ||
299dd6c89b5SChao Yu 			fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE)) {
300dcbb4c10SJoe Perches 			f2fs_warn(sbi, "%s: inode (ino=%lx) has corrupted i_inline_xattr_size: %d, max: %zu",
301dd6c89b5SChao Yu 				  __func__, inode->i_ino, fi->i_inline_xattr_size,
302dd6c89b5SChao Yu 				  MAX_INLINE_XATTR_SIZE);
303dd6c89b5SChao Yu 			return false;
304dd6c89b5SChao Yu 		}
305f240d3aaSChao Yu 		if (f2fs_sb_has_compression(sbi) &&
306f240d3aaSChao Yu 			fi->i_flags & F2FS_COMPR_FL &&
307f240d3aaSChao Yu 			F2FS_FITS_IN_INODE(ri, fi->i_extra_isize,
308f240d3aaSChao Yu 						i_compress_flag)) {
309f240d3aaSChao Yu 			if (!sanity_check_compress_inode(inode, ri))
310f240d3aaSChao Yu 				return false;
311f240d3aaSChao Yu 		}
312f240d3aaSChao Yu 	} else if (f2fs_sb_has_flexible_inline_xattr(sbi)) {
313f240d3aaSChao Yu 		f2fs_warn(sbi, "%s: corrupted inode ino=%lx, run fsck to fix.",
314f240d3aaSChao Yu 			  __func__, inode->i_ino);
315f240d3aaSChao Yu 		return false;
316f240d3aaSChao Yu 	}
317f240d3aaSChao Yu 
318f240d3aaSChao Yu 	if (!f2fs_sb_has_extra_attr(sbi)) {
319f240d3aaSChao Yu 		if (f2fs_sb_has_project_quota(sbi)) {
320f240d3aaSChao Yu 			f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
321f240d3aaSChao Yu 				  __func__, inode->i_ino, F2FS_FEATURE_PRJQUOTA);
322f240d3aaSChao Yu 			return false;
323f240d3aaSChao Yu 		}
324f240d3aaSChao Yu 		if (f2fs_sb_has_inode_chksum(sbi)) {
325f240d3aaSChao Yu 			f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
326f240d3aaSChao Yu 				  __func__, inode->i_ino, F2FS_FEATURE_INODE_CHKSUM);
327f240d3aaSChao Yu 			return false;
328f240d3aaSChao Yu 		}
329f240d3aaSChao Yu 		if (f2fs_sb_has_flexible_inline_xattr(sbi)) {
330f240d3aaSChao Yu 			f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
331f240d3aaSChao Yu 				  __func__, inode->i_ino, F2FS_FEATURE_FLEXIBLE_INLINE_XATTR);
332f240d3aaSChao Yu 			return false;
333f240d3aaSChao Yu 		}
334f240d3aaSChao Yu 		if (f2fs_sb_has_inode_crtime(sbi)) {
335f240d3aaSChao Yu 			f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
336f240d3aaSChao Yu 				  __func__, inode->i_ino, F2FS_FEATURE_INODE_CRTIME);
337f240d3aaSChao Yu 			return false;
338f240d3aaSChao Yu 		}
339f240d3aaSChao Yu 		if (f2fs_sb_has_compression(sbi)) {
340f240d3aaSChao Yu 			f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
341f240d3aaSChao Yu 				  __func__, inode->i_ino, F2FS_FEATURE_COMPRESSION);
342f240d3aaSChao Yu 			return false;
343f240d3aaSChao Yu 		}
344f240d3aaSChao Yu 	}
345dd6c89b5SChao Yu 
346677a82b4SChao Yu 	if (f2fs_sanity_check_inline_data(inode)) {
347dcbb4c10SJoe Perches 		f2fs_warn(sbi, "%s: inode (ino=%lx, mode=%u) should not have inline_data, run fsck to fix",
348bcbfbd60SChao Yu 			  __func__, inode->i_ino, inode->i_mode);
349bcbfbd60SChao Yu 		return false;
350bcbfbd60SChao Yu 	}
351bcbfbd60SChao Yu 
352bcbfbd60SChao Yu 	if (f2fs_has_inline_dentry(inode) && !S_ISDIR(inode->i_mode)) {
353dcbb4c10SJoe Perches 		f2fs_warn(sbi, "%s: inode (ino=%lx, mode=%u) should not have inline_dentry, run fsck to fix",
354bcbfbd60SChao Yu 			  __func__, inode->i_ino, inode->i_mode);
355bcbfbd60SChao Yu 		return false;
356bcbfbd60SChao Yu 	}
357bcbfbd60SChao Yu 
358f6322f3fSEric Biggers 	if ((fi->i_flags & F2FS_CASEFOLD_FL) && !f2fs_sb_has_casefold(sbi)) {
359f6322f3fSEric Biggers 		f2fs_warn(sbi, "%s: inode (ino=%lx) has casefold flag, but casefold feature is off",
360f6322f3fSEric Biggers 			  __func__, inode->i_ino);
361f6322f3fSEric Biggers 		return false;
362f6322f3fSEric Biggers 	}
363f6322f3fSEric Biggers 
3645d64600dSJaegeuk Kim 	return true;
3655d64600dSJaegeuk Kim }
3665d64600dSJaegeuk Kim 
init_idisk_time(struct inode * inode)367049ea86cSZhang Qilong static void init_idisk_time(struct inode *inode)
368049ea86cSZhang Qilong {
369049ea86cSZhang Qilong 	struct f2fs_inode_info *fi = F2FS_I(inode);
370049ea86cSZhang Qilong 
371049ea86cSZhang Qilong 	fi->i_disk_time[0] = inode->i_atime;
372c62ebd35SJeff Layton 	fi->i_disk_time[1] = inode_get_ctime(inode);
373049ea86cSZhang Qilong 	fi->i_disk_time[2] = inode->i_mtime;
374049ea86cSZhang Qilong }
375049ea86cSZhang Qilong 
do_read_inode(struct inode * inode)37619f99ceeSJaegeuk Kim static int do_read_inode(struct inode *inode)
37719f99ceeSJaegeuk Kim {
3784081363fSJaegeuk Kim 	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
37919f99ceeSJaegeuk Kim 	struct f2fs_inode_info *fi = F2FS_I(inode);
38019f99ceeSJaegeuk Kim 	struct page *node_page;
38119f99ceeSJaegeuk Kim 	struct f2fs_inode *ri;
3825c57132eSChao Yu 	projid_t i_projid;
38319f99ceeSJaegeuk Kim 
38419f99ceeSJaegeuk Kim 	/* Check if ino is within scope */
3854d57b86dSChao Yu 	if (f2fs_check_nid_range(sbi, inode->i_ino))
386064e0823SNamjae Jeon 		return -EINVAL;
38719f99ceeSJaegeuk Kim 
3884d57b86dSChao Yu 	node_page = f2fs_get_node_page(sbi, inode->i_ino);
38919f99ceeSJaegeuk Kim 	if (IS_ERR(node_page))
39019f99ceeSJaegeuk Kim 		return PTR_ERR(node_page);
39119f99ceeSJaegeuk Kim 
39258bfaf44SJaegeuk Kim 	ri = F2FS_INODE(node_page);
39319f99ceeSJaegeuk Kim 
39419f99ceeSJaegeuk Kim 	inode->i_mode = le16_to_cpu(ri->i_mode);
39519f99ceeSJaegeuk Kim 	i_uid_write(inode, le32_to_cpu(ri->i_uid));
39619f99ceeSJaegeuk Kim 	i_gid_write(inode, le32_to_cpu(ri->i_gid));
39719f99ceeSJaegeuk Kim 	set_nlink(inode, le32_to_cpu(ri->i_links));
39819f99ceeSJaegeuk Kim 	inode->i_size = le64_to_cpu(ri->i_size);
399000519f2SChao Yu 	inode->i_blocks = SECTOR_FROM_BLOCK(le64_to_cpu(ri->i_blocks) - 1);
40019f99ceeSJaegeuk Kim 
40119f99ceeSJaegeuk Kim 	inode->i_atime.tv_sec = le64_to_cpu(ri->i_atime);
402c62ebd35SJeff Layton 	inode_set_ctime(inode, le64_to_cpu(ri->i_ctime),
403c62ebd35SJeff Layton 			le32_to_cpu(ri->i_ctime_nsec));
40419f99ceeSJaegeuk Kim 	inode->i_mtime.tv_sec = le64_to_cpu(ri->i_mtime);
40519f99ceeSJaegeuk Kim 	inode->i_atime.tv_nsec = le32_to_cpu(ri->i_atime_nsec);
40619f99ceeSJaegeuk Kim 	inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec);
40719f99ceeSJaegeuk Kim 	inode->i_generation = le32_to_cpu(ri->i_generation);
4081c41e680SChao Yu 	if (S_ISDIR(inode->i_mode))
40919f99ceeSJaegeuk Kim 		fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
4101c41e680SChao Yu 	else if (S_ISREG(inode->i_mode))
4112ef79ecbSChao Yu 		fi->i_gc_failures[GC_FAILURE_PIN] =
4122ef79ecbSChao Yu 					le16_to_cpu(ri->i_gc_failures);
41319f99ceeSJaegeuk Kim 	fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
41419f99ceeSJaegeuk Kim 	fi->i_flags = le32_to_cpu(ri->i_flags);
4155043a964SWang Shilong 	if (S_ISREG(inode->i_mode))
4165043a964SWang Shilong 		fi->i_flags &= ~F2FS_PROJINHERIT_FL;
4177653b9d8SChao Yu 	bitmap_zero(fi->flags, FI_MAX);
41819f99ceeSJaegeuk Kim 	fi->i_advise = ri->i_advise;
4196666e6aaSJaegeuk Kim 	fi->i_pino = le32_to_cpu(ri->i_pino);
42038431545SJaegeuk Kim 	fi->i_dir_level = ri->i_dir_level;
4213d1e3807SJaegeuk Kim 
42291942321SJaegeuk Kim 	get_inline_info(inode, ri);
4233d1e3807SJaegeuk Kim 
4247a2af766SChao Yu 	fi->i_extra_isize = f2fs_has_extra_attr(inode) ?
4257a2af766SChao Yu 					le16_to_cpu(ri->i_extra_isize) : 0;
4267a2af766SChao Yu 
4277beb01f7SChao Yu 	if (f2fs_sb_has_flexible_inline_xattr(sbi)) {
4286afc662eSChao Yu 		fi->i_inline_xattr_size = le16_to_cpu(ri->i_inline_xattr_size);
4296afc662eSChao Yu 	} else if (f2fs_has_inline_xattr(inode) ||
4306afc662eSChao Yu 				f2fs_has_inline_dentry(inode)) {
4316afc662eSChao Yu 		fi->i_inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
4326afc662eSChao Yu 	} else {
4336afc662eSChao Yu 
4346afc662eSChao Yu 		/*
4356afc662eSChao Yu 		 * Previous inline data or directory always reserved 200 bytes
4366afc662eSChao Yu 		 * in inode layout, even if inline_xattr is disabled. In order
4376afc662eSChao Yu 		 * to keep inline_dentry's structure for backward compatibility,
4386afc662eSChao Yu 		 * we get the space back only from inline_data.
4396afc662eSChao Yu 		 */
4406afc662eSChao Yu 		fi->i_inline_xattr_size = 0;
4416afc662eSChao Yu 	}
4426afc662eSChao Yu 
443958ccbbfSChao Yu 	if (!sanity_check_inode(inode, node_page)) {
444958ccbbfSChao Yu 		f2fs_put_page(node_page, 1);
445c9887949SChao Yu 		set_sbi_flag(sbi, SBI_NEED_FSCK);
446958ccbbfSChao Yu 		f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
447958ccbbfSChao Yu 		return -EFSCORRUPTED;
448958ccbbfSChao Yu 	}
449958ccbbfSChao Yu 
450b3d208f9SJaegeuk Kim 	/* check data exist */
451b3d208f9SJaegeuk Kim 	if (f2fs_has_inline_data(inode) && !f2fs_exist_data(inode))
4529e5ba77fSChao Yu 		__recover_inline_status(inode, node_page);
453b3d208f9SJaegeuk Kim 
454ef2a0071SChao Yu 	/* try to recover cold bit for non-dir inode */
455ef2a0071SChao Yu 	if (!S_ISDIR(inode->i_mode) && !is_cold_node(node_page)) {
456db5ae363SWuyun Zhao 		f2fs_wait_on_page_writeback(node_page, NODE, true, true);
457ef2a0071SChao Yu 		set_cold_node(node_page, false);
458ef2a0071SChao Yu 		set_page_dirty(node_page);
459ef2a0071SChao Yu 	}
460ef2a0071SChao Yu 
4613d1e3807SJaegeuk Kim 	/* get rdev by using inline_info */
462*dcd6b38bSChao Yu 	__get_inode_rdev(inode, node_page);
4633d1e3807SJaegeuk Kim 
4644d57b86dSChao Yu 	if (!f2fs_need_inode_block_update(sbi, inode->i_ino))
46526de9b11SJaegeuk Kim 		fi->last_disk_size = inode->i_size;
46626de9b11SJaegeuk Kim 
46759c84408SChao Yu 	if (fi->i_flags & F2FS_PROJINHERIT_FL)
4685c57132eSChao Yu 		set_inode_flag(inode, FI_PROJ_INHERIT);
4695c57132eSChao Yu 
4707beb01f7SChao Yu 	if (f2fs_has_extra_attr(inode) && f2fs_sb_has_project_quota(sbi) &&
4715c57132eSChao Yu 			F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_projid))
4725c57132eSChao Yu 		i_projid = (projid_t)le32_to_cpu(ri->i_projid);
4735c57132eSChao Yu 	else
4745c57132eSChao Yu 		i_projid = F2FS_DEF_PROJID;
4755c57132eSChao Yu 	fi->i_projid = make_kprojid(&init_user_ns, i_projid);
4765c57132eSChao Yu 
4777beb01f7SChao Yu 	if (f2fs_has_extra_attr(inode) && f2fs_sb_has_inode_crtime(sbi) &&
4781c1d35dfSChao Yu 			F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_crtime)) {
4791c1d35dfSChao Yu 		fi->i_crtime.tv_sec = le64_to_cpu(ri->i_crtime);
4801c1d35dfSChao Yu 		fi->i_crtime.tv_nsec = le32_to_cpu(ri->i_crtime_nsec);
4811c1d35dfSChao Yu 	}
4821c1d35dfSChao Yu 
4834c8ff709SChao Yu 	if (f2fs_has_extra_attr(inode) && f2fs_sb_has_compression(sbi) &&
4844c8ff709SChao Yu 					(fi->i_flags & F2FS_COMPR_FL)) {
4854c8ff709SChao Yu 		if (F2FS_FITS_IN_INODE(ri, fi->i_extra_isize,
48664ee9163SChao Yu 					i_compress_flag)) {
487b90e5086SChao Yu 			unsigned short compress_flag;
488b90e5086SChao Yu 
489c2759ebaSDaeho Jeong 			atomic_set(&fi->i_compr_blocks,
490c2759ebaSDaeho Jeong 					le64_to_cpu(ri->i_compr_blocks));
4914c8ff709SChao Yu 			fi->i_compress_algorithm = ri->i_compress_algorithm;
4924c8ff709SChao Yu 			fi->i_log_cluster_size = ri->i_log_cluster_size;
493b90e5086SChao Yu 			compress_flag = le16_to_cpu(ri->i_compress_flag);
494b90e5086SChao Yu 			fi->i_compress_level = compress_flag >>
495b90e5086SChao Yu 						COMPRESS_LEVEL_OFFSET;
496b90e5086SChao Yu 			fi->i_compress_flag = compress_flag &
497447286ebSYangtao Li 					GENMASK(COMPRESS_LEVEL_OFFSET - 1, 0);
498447286ebSYangtao Li 			fi->i_cluster_size = BIT(fi->i_log_cluster_size);
4994c8ff709SChao Yu 			set_inode_flag(inode, FI_COMPRESSED_FILE);
5004c8ff709SChao Yu 		}
5014c8ff709SChao Yu 	}
5024c8ff709SChao Yu 
503049ea86cSZhang Qilong 	init_idisk_time(inode);
50472840cccSJaegeuk Kim 
50572840cccSJaegeuk Kim 	/* Need all the flag bits */
50672840cccSJaegeuk Kim 	f2fs_init_read_extent_tree(inode, node_page);
50771644dffSJaegeuk Kim 	f2fs_init_age_extent_tree(inode);
50872840cccSJaegeuk Kim 
509269d1194SChao Yu 	if (!sanity_check_extent_cache(inode)) {
510269d1194SChao Yu 		f2fs_put_page(node_page, 1);
511269d1194SChao Yu 		f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
512269d1194SChao Yu 		return -EFSCORRUPTED;
513269d1194SChao Yu 	}
514269d1194SChao Yu 
51519f99ceeSJaegeuk Kim 	f2fs_put_page(node_page, 1);
5169d1015ddSJaegeuk Kim 
517d5e8f6c9SChao Yu 	stat_inc_inline_xattr(inode);
5189d1015ddSJaegeuk Kim 	stat_inc_inline_inode(inode);
5199d1015ddSJaegeuk Kim 	stat_inc_inline_dir(inode);
5204c8ff709SChao Yu 	stat_inc_compr_inode(inode);
521c2759ebaSDaeho Jeong 	stat_add_compr_blocks(inode, atomic_read(&fi->i_compr_blocks));
5229d1015ddSJaegeuk Kim 
5239e5ba77fSChao Yu 	return 0;
52419f99ceeSJaegeuk Kim }
52519f99ceeSJaegeuk Kim 
is_meta_ino(struct f2fs_sb_info * sbi,unsigned int ino)526fcc2d8ccSChao Yu static bool is_meta_ino(struct f2fs_sb_info *sbi, unsigned int ino)
527fcc2d8ccSChao Yu {
528fcc2d8ccSChao Yu 	return ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi) ||
529fcc2d8ccSChao Yu 		ino == F2FS_COMPRESS_INO(sbi);
530fcc2d8ccSChao Yu }
531fcc2d8ccSChao Yu 
f2fs_iget(struct super_block * sb,unsigned long ino)53219f99ceeSJaegeuk Kim struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
53319f99ceeSJaegeuk Kim {
53419f99ceeSJaegeuk Kim 	struct f2fs_sb_info *sbi = F2FS_SB(sb);
53519f99ceeSJaegeuk Kim 	struct inode *inode;
536a2a4a7e4SNamjae Jeon 	int ret = 0;
53719f99ceeSJaegeuk Kim 
53819f99ceeSJaegeuk Kim 	inode = iget_locked(sb, ino);
53919f99ceeSJaegeuk Kim 	if (!inode)
54019f99ceeSJaegeuk Kim 		return ERR_PTR(-ENOMEM);
541a2a4a7e4SNamjae Jeon 
542a2a4a7e4SNamjae Jeon 	if (!(inode->i_state & I_NEW)) {
543fcc2d8ccSChao Yu 		if (is_meta_ino(sbi, ino)) {
544fcc2d8ccSChao Yu 			f2fs_err(sbi, "inaccessible inode: %lu, run fsck to repair", ino);
545fcc2d8ccSChao Yu 			set_sbi_flag(sbi, SBI_NEED_FSCK);
546fcc2d8ccSChao Yu 			ret = -EFSCORRUPTED;
547fcc2d8ccSChao Yu 			trace_f2fs_iget_exit(inode, ret);
548fcc2d8ccSChao Yu 			iput(inode);
54995fa90c9SChao Yu 			f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
550fcc2d8ccSChao Yu 			return ERR_PTR(ret);
551fcc2d8ccSChao Yu 		}
552fcc2d8ccSChao Yu 
553a2a4a7e4SNamjae Jeon 		trace_f2fs_iget(inode);
55419f99ceeSJaegeuk Kim 		return inode;
555a2a4a7e4SNamjae Jeon 	}
55619f99ceeSJaegeuk Kim 
557fcc2d8ccSChao Yu 	if (is_meta_ino(sbi, ino))
5586ce19affSChao Yu 		goto make_now;
5596ce19affSChao Yu 
56019f99ceeSJaegeuk Kim 	ret = do_read_inode(inode);
56119f99ceeSJaegeuk Kim 	if (ret)
56219f99ceeSJaegeuk Kim 		goto bad_inode;
56319f99ceeSJaegeuk Kim make_now:
56419f99ceeSJaegeuk Kim 	if (ino == F2FS_NODE_INO(sbi)) {
56519f99ceeSJaegeuk Kim 		inode->i_mapping->a_ops = &f2fs_node_aops;
56681114baaSChao Yu 		mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
56719f99ceeSJaegeuk Kim 	} else if (ino == F2FS_META_INO(sbi)) {
56819f99ceeSJaegeuk Kim 		inode->i_mapping->a_ops = &f2fs_meta_aops;
56981114baaSChao Yu 		mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
5706ce19affSChao Yu 	} else if (ino == F2FS_COMPRESS_INO(sbi)) {
5716ce19affSChao Yu #ifdef CONFIG_F2FS_FS_COMPRESSION
5726ce19affSChao Yu 		inode->i_mapping->a_ops = &f2fs_compress_aops;
573d1917865SFengnan Chang 		/*
574d1917865SFengnan Chang 		 * generic_error_remove_page only truncates pages of regular
575d1917865SFengnan Chang 		 * inode
576d1917865SFengnan Chang 		 */
577d1917865SFengnan Chang 		inode->i_mode |= S_IFREG;
5786ce19affSChao Yu #endif
5796ce19affSChao Yu 		mapping_set_gfp_mask(inode->i_mapping,
5806ce19affSChao Yu 			GFP_NOFS | __GFP_HIGHMEM | __GFP_MOVABLE);
58119f99ceeSJaegeuk Kim 	} else if (S_ISREG(inode->i_mode)) {
58219f99ceeSJaegeuk Kim 		inode->i_op = &f2fs_file_inode_operations;
58319f99ceeSJaegeuk Kim 		inode->i_fop = &f2fs_file_operations;
58419f99ceeSJaegeuk Kim 		inode->i_mapping->a_ops = &f2fs_dblock_aops;
58519f99ceeSJaegeuk Kim 	} else if (S_ISDIR(inode->i_mode)) {
58619f99ceeSJaegeuk Kim 		inode->i_op = &f2fs_dir_inode_operations;
58719f99ceeSJaegeuk Kim 		inode->i_fop = &f2fs_dir_operations;
58819f99ceeSJaegeuk Kim 		inode->i_mapping->a_ops = &f2fs_dblock_aops;
58992d602bcSJaegeuk Kim 		mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
59019f99ceeSJaegeuk Kim 	} else if (S_ISLNK(inode->i_mode)) {
59162230e0dSChandan Rajendra 		if (file_is_encrypt(inode))
592cbaf042aSJaegeuk Kim 			inode->i_op = &f2fs_encrypted_symlink_inode_operations;
593cbaf042aSJaegeuk Kim 		else
59419f99ceeSJaegeuk Kim 			inode->i_op = &f2fs_symlink_inode_operations;
59521fc61c7SAl Viro 		inode_nohighmem(inode);
59619f99ceeSJaegeuk Kim 		inode->i_mapping->a_ops = &f2fs_dblock_aops;
59719f99ceeSJaegeuk Kim 	} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
59819f99ceeSJaegeuk Kim 			S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
59919f99ceeSJaegeuk Kim 		inode->i_op = &f2fs_special_inode_operations;
60019f99ceeSJaegeuk Kim 		init_special_inode(inode, inode->i_mode, inode->i_rdev);
60119f99ceeSJaegeuk Kim 	} else {
60219f99ceeSJaegeuk Kim 		ret = -EIO;
60319f99ceeSJaegeuk Kim 		goto bad_inode;
60419f99ceeSJaegeuk Kim 	}
60593607124SJaegeuk Kim 	f2fs_set_inode_flags(inode);
606d4dd19ecSJaegeuk Kim 
6074d8ec912SJaegeuk Kim 	if (file_should_truncate(inode) &&
6084d8ec912SJaegeuk Kim 			!is_sbi_flag_set(sbi, SBI_POR_DOING)) {
609d4dd19ecSJaegeuk Kim 		ret = f2fs_truncate(inode);
610d4dd19ecSJaegeuk Kim 		if (ret)
611d4dd19ecSJaegeuk Kim 			goto bad_inode;
612d4dd19ecSJaegeuk Kim 		file_dont_truncate(inode);
613d4dd19ecSJaegeuk Kim 	}
614d4dd19ecSJaegeuk Kim 
61519f99ceeSJaegeuk Kim 	unlock_new_inode(inode);
616a2a4a7e4SNamjae Jeon 	trace_f2fs_iget(inode);
61719f99ceeSJaegeuk Kim 	return inode;
61819f99ceeSJaegeuk Kim 
61919f99ceeSJaegeuk Kim bad_inode:
620546d22f0SChao Yu 	f2fs_inode_synced(inode);
62119f99ceeSJaegeuk Kim 	iget_failed(inode);
622a2a4a7e4SNamjae Jeon 	trace_f2fs_iget_exit(inode, ret);
62319f99ceeSJaegeuk Kim 	return ERR_PTR(ret);
62419f99ceeSJaegeuk Kim }
62519f99ceeSJaegeuk Kim 
f2fs_iget_retry(struct super_block * sb,unsigned long ino)626e8ea9b3dSJaegeuk Kim struct inode *f2fs_iget_retry(struct super_block *sb, unsigned long ino)
627e8ea9b3dSJaegeuk Kim {
628e8ea9b3dSJaegeuk Kim 	struct inode *inode;
629e8ea9b3dSJaegeuk Kim retry:
630e8ea9b3dSJaegeuk Kim 	inode = f2fs_iget(sb, ino);
631e8ea9b3dSJaegeuk Kim 	if (IS_ERR(inode)) {
632e8ea9b3dSJaegeuk Kim 		if (PTR_ERR(inode) == -ENOMEM) {
6334034247aSNeilBrown 			memalloc_retry_wait(GFP_NOFS);
634e8ea9b3dSJaegeuk Kim 			goto retry;
635e8ea9b3dSJaegeuk Kim 		}
636e8ea9b3dSJaegeuk Kim 	}
637e8ea9b3dSJaegeuk Kim 	return inode;
638e8ea9b3dSJaegeuk Kim }
639e8ea9b3dSJaegeuk Kim 
f2fs_update_inode(struct inode * inode,struct page * node_page)6404d57b86dSChao Yu void f2fs_update_inode(struct inode *inode, struct page *node_page)
64119f99ceeSJaegeuk Kim {
64219f99ceeSJaegeuk Kim 	struct f2fs_inode *ri;
643e7547dacSJaegeuk Kim 	struct extent_tree *et = F2FS_I(inode)->extent_tree[EX_READ];
64419f99ceeSJaegeuk Kim 
645bae0ee7aSChao Yu 	f2fs_wait_on_page_writeback(node_page, NODE, true, true);
646211a6fa0SYunlei He 	set_page_dirty(node_page);
647211a6fa0SYunlei He 
648211a6fa0SYunlei He 	f2fs_inode_synced(inode);
64919f99ceeSJaegeuk Kim 
65058bfaf44SJaegeuk Kim 	ri = F2FS_INODE(node_page);
65119f99ceeSJaegeuk Kim 
65219f99ceeSJaegeuk Kim 	ri->i_mode = cpu_to_le16(inode->i_mode);
65319f99ceeSJaegeuk Kim 	ri->i_advise = F2FS_I(inode)->i_advise;
65419f99ceeSJaegeuk Kim 	ri->i_uid = cpu_to_le32(i_uid_read(inode));
65519f99ceeSJaegeuk Kim 	ri->i_gid = cpu_to_le32(i_gid_read(inode));
65619f99ceeSJaegeuk Kim 	ri->i_links = cpu_to_le32(inode->i_nlink);
657000519f2SChao Yu 	ri->i_blocks = cpu_to_le64(SECTOR_TO_BLOCK(inode->i_blocks) + 1);
6580c872e2dSChao Yu 
6594d8d45dfSDaeho Jeong 	if (!f2fs_is_atomic_file(inode) ||
6604d8d45dfSDaeho Jeong 			is_inode_flag_set(inode, FI_ATOMIC_COMMITTED))
6614d8d45dfSDaeho Jeong 		ri->i_size = cpu_to_le64(i_size_read(inode));
6624d8d45dfSDaeho Jeong 
663b691d98fSChao Yu 	if (et) {
664b691d98fSChao Yu 		read_lock(&et->lock);
66512607c1bSJaegeuk Kim 		set_raw_read_extent(&et->largest, &ri->i_ext);
666b691d98fSChao Yu 		read_unlock(&et->lock);
667b691d98fSChao Yu 	} else {
6683e72f721SJaegeuk Kim 		memset(&ri->i_ext, 0, sizeof(ri->i_ext));
669b691d98fSChao Yu 	}
67091942321SJaegeuk Kim 	set_raw_inline(inode, ri);
67119f99ceeSJaegeuk Kim 
67219f99ceeSJaegeuk Kim 	ri->i_atime = cpu_to_le64(inode->i_atime.tv_sec);
673c62ebd35SJeff Layton 	ri->i_ctime = cpu_to_le64(inode_get_ctime(inode).tv_sec);
67419f99ceeSJaegeuk Kim 	ri->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
67519f99ceeSJaegeuk Kim 	ri->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
676c62ebd35SJeff Layton 	ri->i_ctime_nsec = cpu_to_le32(inode_get_ctime(inode).tv_nsec);
67719f99ceeSJaegeuk Kim 	ri->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
6781c41e680SChao Yu 	if (S_ISDIR(inode->i_mode))
6791c41e680SChao Yu 		ri->i_current_depth =
6801c41e680SChao Yu 			cpu_to_le32(F2FS_I(inode)->i_current_depth);
6811c41e680SChao Yu 	else if (S_ISREG(inode->i_mode))
6822ef79ecbSChao Yu 		ri->i_gc_failures =
6832ef79ecbSChao Yu 			cpu_to_le16(F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN]);
68419f99ceeSJaegeuk Kim 	ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
68519f99ceeSJaegeuk Kim 	ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
6866666e6aaSJaegeuk Kim 	ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
68719f99ceeSJaegeuk Kim 	ri->i_generation = cpu_to_le32(inode->i_generation);
68838431545SJaegeuk Kim 	ri->i_dir_level = F2FS_I(inode)->i_dir_level;
6897d79e75fSChangman Lee 
6905c57132eSChao Yu 	if (f2fs_has_extra_attr(inode)) {
6917a2af766SChao Yu 		ri->i_extra_isize = cpu_to_le16(F2FS_I(inode)->i_extra_isize);
6927a2af766SChao Yu 
6937beb01f7SChao Yu 		if (f2fs_sb_has_flexible_inline_xattr(F2FS_I_SB(inode)))
6946afc662eSChao Yu 			ri->i_inline_xattr_size =
6956afc662eSChao Yu 				cpu_to_le16(F2FS_I(inode)->i_inline_xattr_size);
6966afc662eSChao Yu 
6977beb01f7SChao Yu 		if (f2fs_sb_has_project_quota(F2FS_I_SB(inode)) &&
6985c57132eSChao Yu 			F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize,
6995c57132eSChao Yu 								i_projid)) {
7005c57132eSChao Yu 			projid_t i_projid;
7015c57132eSChao Yu 
7025c57132eSChao Yu 			i_projid = from_kprojid(&init_user_ns,
7035c57132eSChao Yu 						F2FS_I(inode)->i_projid);
7045c57132eSChao Yu 			ri->i_projid = cpu_to_le32(i_projid);
7055c57132eSChao Yu 		}
7061c1d35dfSChao Yu 
7077beb01f7SChao Yu 		if (f2fs_sb_has_inode_crtime(F2FS_I_SB(inode)) &&
7081c1d35dfSChao Yu 			F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize,
7091c1d35dfSChao Yu 								i_crtime)) {
7101c1d35dfSChao Yu 			ri->i_crtime =
7111c1d35dfSChao Yu 				cpu_to_le64(F2FS_I(inode)->i_crtime.tv_sec);
7121c1d35dfSChao Yu 			ri->i_crtime_nsec =
7131c1d35dfSChao Yu 				cpu_to_le32(F2FS_I(inode)->i_crtime.tv_nsec);
7141c1d35dfSChao Yu 		}
7154c8ff709SChao Yu 
7164c8ff709SChao Yu 		if (f2fs_sb_has_compression(F2FS_I_SB(inode)) &&
7174c8ff709SChao Yu 			F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize,
71864ee9163SChao Yu 							i_compress_flag)) {
719b90e5086SChao Yu 			unsigned short compress_flag;
720b90e5086SChao Yu 
7214c8ff709SChao Yu 			ri->i_compr_blocks =
722c2759ebaSDaeho Jeong 				cpu_to_le64(atomic_read(
723c2759ebaSDaeho Jeong 					&F2FS_I(inode)->i_compr_blocks));
7244c8ff709SChao Yu 			ri->i_compress_algorithm =
7254c8ff709SChao Yu 				F2FS_I(inode)->i_compress_algorithm;
726b90e5086SChao Yu 			compress_flag = F2FS_I(inode)->i_compress_flag |
727b90e5086SChao Yu 				F2FS_I(inode)->i_compress_level <<
728b90e5086SChao Yu 						COMPRESS_LEVEL_OFFSET;
729b90e5086SChao Yu 			ri->i_compress_flag = cpu_to_le16(compress_flag);
7304c8ff709SChao Yu 			ri->i_log_cluster_size =
7314c8ff709SChao Yu 				F2FS_I(inode)->i_log_cluster_size;
7324c8ff709SChao Yu 		}
7335c57132eSChao Yu 	}
7345c57132eSChao Yu 
735*dcd6b38bSChao Yu 	__set_inode_rdev(inode, node_page);
73612719ae1SJaegeuk Kim 
7372049d4fcSJaegeuk Kim 	/* deleted inode */
7382049d4fcSJaegeuk Kim 	if (inode->i_nlink == 0)
739b763f3beSChao Yu 		clear_page_private_inline(node_page);
7402049d4fcSJaegeuk Kim 
741049ea86cSZhang Qilong 	init_idisk_time(inode);
74254c55c4eSWeichao Guo #ifdef CONFIG_F2FS_CHECK_FS
74354c55c4eSWeichao Guo 	f2fs_inode_chksum_set(F2FS_I_SB(inode), node_page);
74454c55c4eSWeichao Guo #endif
74519f99ceeSJaegeuk Kim }
74619f99ceeSJaegeuk Kim 
f2fs_update_inode_page(struct inode * inode)7474d57b86dSChao Yu void f2fs_update_inode_page(struct inode *inode)
74819f99ceeSJaegeuk Kim {
7494081363fSJaegeuk Kim 	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
75019f99ceeSJaegeuk Kim 	struct page *node_page;
7513aa51c61SJaegeuk Kim 	int count = 0;
752744602cfSJaegeuk Kim retry:
7534d57b86dSChao Yu 	node_page = f2fs_get_node_page(sbi, inode->i_ino);
754744602cfSJaegeuk Kim 	if (IS_ERR(node_page)) {
755744602cfSJaegeuk Kim 		int err = PTR_ERR(node_page);
7565f029c04SYi Zhuang 
7573aa51c61SJaegeuk Kim 		/* The node block was truncated. */
7583aa51c61SJaegeuk Kim 		if (err == -ENOENT)
7593aa51c61SJaegeuk Kim 			return;
7603aa51c61SJaegeuk Kim 
7613aa51c61SJaegeuk Kim 		if (err == -ENOMEM || ++count <= DEFAULT_RETRY_IO_COUNT)
762744602cfSJaegeuk Kim 			goto retry;
7633aa51c61SJaegeuk Kim 		f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_UPDATE_INODE);
764211a6fa0SYunlei He 		return;
765744602cfSJaegeuk Kim 	}
7664d57b86dSChao Yu 	f2fs_update_inode(inode, node_page);
76739936837SJaegeuk Kim 	f2fs_put_page(node_page, 1);
76839936837SJaegeuk Kim }
76939936837SJaegeuk Kim 
f2fs_write_inode(struct inode * inode,struct writeback_control * wbc)77039936837SJaegeuk Kim int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
77139936837SJaegeuk Kim {
7724081363fSJaegeuk Kim 	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
77319f99ceeSJaegeuk Kim 
77419f99ceeSJaegeuk Kim 	if (inode->i_ino == F2FS_NODE_INO(sbi) ||
77519f99ceeSJaegeuk Kim 			inode->i_ino == F2FS_META_INO(sbi))
77619f99ceeSJaegeuk Kim 		return 0;
77719f99ceeSJaegeuk Kim 
778fe1897eaSChao Yu 	/*
779fe1897eaSChao Yu 	 * atime could be updated without dirtying f2fs inode in lazytime mode
780fe1897eaSChao Yu 	 */
781fe1897eaSChao Yu 	if (f2fs_is_time_consistent(inode) &&
782fe1897eaSChao Yu 		!is_inode_flag_set(inode, FI_DIRTY_INODE))
783b3783873SJaegeuk Kim 		return 0;
784b3783873SJaegeuk Kim 
78500e09c0bSChao Yu 	if (!f2fs_is_checkpoint_ready(sbi))
7864354994fSDaniel Rosenberg 		return -ENOSPC;
7874354994fSDaniel Rosenberg 
78839936837SJaegeuk Kim 	/*
789c5cd29d2SJaegeuk Kim 	 * We need to balance fs here to prevent from producing dirty node pages
7902c718feeSRuiqi Gong 	 * during the urgent cleaning time when running out of free sections.
79139936837SJaegeuk Kim 	 */
7924d57b86dSChao Yu 	f2fs_update_inode_page(inode);
793a7881893SJaegeuk Kim 	if (wbc && wbc->nr_to_write)
7942c4db1a6SJaegeuk Kim 		f2fs_balance_fs(sbi, true);
795744602cfSJaegeuk Kim 	return 0;
79619f99ceeSJaegeuk Kim }
79719f99ceeSJaegeuk Kim 
7980a8165d7SJaegeuk Kim /*
79919f99ceeSJaegeuk Kim  * Called at the last iput() if i_nlink is zero
80019f99ceeSJaegeuk Kim  */
f2fs_evict_inode(struct inode * inode)80119f99ceeSJaegeuk Kim void f2fs_evict_inode(struct inode *inode)
80219f99ceeSJaegeuk Kim {
8034081363fSJaegeuk Kim 	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
804a46bebd5SDaeho Jeong 	struct f2fs_inode_info *fi = F2FS_I(inode);
805a46bebd5SDaeho Jeong 	nid_t xnid = fi->i_xattr_nid;
80613ec7297SChao Yu 	int err = 0;
80719f99ceeSJaegeuk Kim 
8083db1de0eSDaeho Jeong 	f2fs_abort_atomic_write(inode, true);
80988b88a66SJaegeuk Kim 
810a46bebd5SDaeho Jeong 	if (fi->cow_inode) {
811a46bebd5SDaeho Jeong 		clear_inode_flag(fi->cow_inode, FI_COW_FILE);
812a46bebd5SDaeho Jeong 		iput(fi->cow_inode);
813a46bebd5SDaeho Jeong 		fi->cow_inode = NULL;
814a46bebd5SDaeho Jeong 	}
815a46bebd5SDaeho Jeong 
816a2a4a7e4SNamjae Jeon 	trace_f2fs_evict_inode(inode);
81791b0abe3SJohannes Weiner 	truncate_inode_pages_final(&inode->i_data);
81819f99ceeSJaegeuk Kim 
8192b642898SFengnan Chang 	if ((inode->i_nlink || is_bad_inode(inode)) &&
8202b642898SFengnan Chang 		test_opt(sbi, COMPRESS_CACHE) && f2fs_compressed_file(inode))
8216ce19affSChao Yu 		f2fs_invalidate_compress_pages(sbi, inode->i_ino);
8226ce19affSChao Yu 
82319f99ceeSJaegeuk Kim 	if (inode->i_ino == F2FS_NODE_INO(sbi) ||
8246ce19affSChao Yu 			inode->i_ino == F2FS_META_INO(sbi) ||
8256ce19affSChao Yu 			inode->i_ino == F2FS_COMPRESS_INO(sbi))
826dbf20cb2SChao Yu 		goto out_clear;
82719f99ceeSJaegeuk Kim 
828a7ffdbe2SJaegeuk Kim 	f2fs_bug_on(sbi, get_dirty_pages(inode));
8294d57b86dSChao Yu 	f2fs_remove_dirty_inode(inode);
83019f99ceeSJaegeuk Kim 
8313e72f721SJaegeuk Kim 	f2fs_destroy_extent_tree(inode);
8323e72f721SJaegeuk Kim 
83319f99ceeSJaegeuk Kim 	if (inode->i_nlink || is_bad_inode(inode))
83419f99ceeSJaegeuk Kim 		goto no_delete;
83519f99ceeSJaegeuk Kim 
83610a26878SChao Yu 	err = f2fs_dquot_initialize(inode);
837af033b2aSChao Yu 	if (err) {
838af033b2aSChao Yu 		err = 0;
839af033b2aSChao Yu 		set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
840af033b2aSChao Yu 	}
8410abd675eSChao Yu 
8424d57b86dSChao Yu 	f2fs_remove_ino_entry(sbi, inode->i_ino, APPEND_INO);
8434d57b86dSChao Yu 	f2fs_remove_ino_entry(sbi, inode->i_ino, UPDATE_INO);
8444d57b86dSChao Yu 	f2fs_remove_ino_entry(sbi, inode->i_ino, FLUSH_INO);
84560dcedc9SChao Yu 
846ba900534SJaegeuk Kim 	if (!is_sbi_flag_set(sbi, SBI_IS_FREEZING))
847d6212a5fSChangman Lee 		sb_start_intwrite(inode->i_sb);
84891942321SJaegeuk Kim 	set_inode_flag(inode, FI_NO_ALLOC);
84919f99ceeSJaegeuk Kim 	i_size_write(inode, 0);
8504c0c2949SJaegeuk Kim retry:
85119f99ceeSJaegeuk Kim 	if (F2FS_HAS_BLOCKS(inode))
8529a449e9cSJaegeuk Kim 		err = f2fs_truncate(inode);
85319f99ceeSJaegeuk Kim 
854c40e15a9SYangtao Li 	if (time_to_inject(sbi, FAULT_EVICT_INODE))
8558c1b3c0fSJaegeuk Kim 		err = -EIO;
8567fa750a1SArnd Bergmann 
85713ec7297SChao Yu 	if (!err) {
858e479556bSGu Zheng 		f2fs_lock_op(sbi);
8594d57b86dSChao Yu 		err = f2fs_remove_inode_page(inode);
860e479556bSGu Zheng 		f2fs_unlock_op(sbi);
861f2db7105SChao Yu 		if (err == -ENOENT) {
862a11b9f65SChao Yu 			err = 0;
863f2db7105SChao Yu 
864f2db7105SChao Yu 			/*
865f2db7105SChao Yu 			 * in fuzzed image, another node may has the same
866f2db7105SChao Yu 			 * block address as inode's, if it was truncated
867f2db7105SChao Yu 			 * previously, truncation of inode node will fail.
868f2db7105SChao Yu 			 */
869f2db7105SChao Yu 			if (is_inode_flag_set(inode, FI_DIRTY_INODE)) {
870f2db7105SChao Yu 				f2fs_warn(F2FS_I_SB(inode),
871f2db7105SChao Yu 					"f2fs_evict_inode: inconsistent node id, ino:%lu",
872f2db7105SChao Yu 					inode->i_ino);
873f2db7105SChao Yu 				f2fs_inode_synced(inode);
874f2db7105SChao Yu 				set_sbi_flag(sbi, SBI_NEED_FSCK);
875f2db7105SChao Yu 			}
876f2db7105SChao Yu 		}
87713ec7297SChao Yu 	}
87839936837SJaegeuk Kim 
8794c0c2949SJaegeuk Kim 	/* give more chances, if ENOMEM case */
8804c0c2949SJaegeuk Kim 	if (err == -ENOMEM) {
8814c0c2949SJaegeuk Kim 		err = 0;
8824c0c2949SJaegeuk Kim 		goto retry;
8834c0c2949SJaegeuk Kim 	}
8844c0c2949SJaegeuk Kim 
885af033b2aSChao Yu 	if (err) {
8864d57b86dSChao Yu 		f2fs_update_inode_page(inode);
8870f1898f9SChao Yu 		if (dquot_initialize_needed(inode))
888af033b2aSChao Yu 			set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
889af033b2aSChao Yu 	}
890ba900534SJaegeuk Kim 	if (!is_sbi_flag_set(sbi, SBI_IS_FREEZING))
891d6212a5fSChangman Lee 		sb_end_intwrite(inode->i_sb);
89219f99ceeSJaegeuk Kim no_delete:
8930abd675eSChao Yu 	dquot_drop(inode);
8940abd675eSChao Yu 
895d5e8f6c9SChao Yu 	stat_dec_inline_xattr(inode);
8963289c061SJaegeuk Kim 	stat_dec_inline_dir(inode);
897e7a2bf22SJaegeuk Kim 	stat_dec_inline_inode(inode);
8984c8ff709SChao Yu 	stat_dec_compr_inode(inode);
899c2759ebaSDaeho Jeong 	stat_sub_compr_blocks(inode,
900a46bebd5SDaeho Jeong 			atomic_read(&fi->i_compr_blocks));
9010bdee482SChao Yu 
90233ac18a1SChao Yu 	if (likely(!f2fs_cp_error(sbi) &&
9034354994fSDaniel Rosenberg 				!is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
904ca7d802aSChao Yu 		f2fs_bug_on(sbi, is_inode_flag_set(inode, FI_DIRTY_INODE));
905943973cdSJaegeuk Kim 	else
906943973cdSJaegeuk Kim 		f2fs_inode_synced(inode);
907ca7d802aSChao Yu 
9087a88ddb5SChao Yu 	/* for the case f2fs_new_inode() was failed, .i_ino is zero, skip it */
9094f295443SJaegeuk Kim 	if (inode->i_ino)
9104f295443SJaegeuk Kim 		invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino,
9114f295443SJaegeuk Kim 							inode->i_ino);
912002a41caSChao Yu 	if (xnid)
913002a41caSChao Yu 		invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid);
91460dcedc9SChao Yu 	if (inode->i_nlink) {
91591942321SJaegeuk Kim 		if (is_inode_flag_set(inode, FI_APPEND_WRITE))
9164d57b86dSChao Yu 			f2fs_add_ino_entry(sbi, inode->i_ino, APPEND_INO);
91791942321SJaegeuk Kim 		if (is_inode_flag_set(inode, FI_UPDATE_WRITE))
9184d57b86dSChao Yu 			f2fs_add_ino_entry(sbi, inode->i_ino, UPDATE_INO);
91960dcedc9SChao Yu 	}
92091942321SJaegeuk Kim 	if (is_inode_flag_set(inode, FI_FREE_NID)) {
9214d57b86dSChao Yu 		f2fs_alloc_nid_failed(sbi, inode->i_ino);
92291942321SJaegeuk Kim 		clear_inode_flag(inode, FI_FREE_NID);
923d8c4256cSJaegeuk Kim 	} else {
924a4f843bdSJaegeuk Kim 		/*
925a4f843bdSJaegeuk Kim 		 * If xattr nid is corrupted, we can reach out error condition,
9264d57b86dSChao Yu 		 * err & !f2fs_exist_written_data(sbi, inode->i_ino, ORPHAN_INO)).
9274d57b86dSChao Yu 		 * In that case, f2fs_check_nid_range() is enough to give a clue.
928a4f843bdSJaegeuk Kim 		 */
929d8c4256cSJaegeuk Kim 	}
930dbf20cb2SChao Yu out_clear:
9313d204e24SEric Biggers 	fscrypt_put_encryption_info(inode);
93295ae251fSEric Biggers 	fsverity_cleanup_inode(inode);
933dbf20cb2SChao Yu 	clear_inode(inode);
93419f99ceeSJaegeuk Kim }
93544c16156SJaegeuk Kim 
93644c16156SJaegeuk Kim /* caller should call f2fs_lock_op() */
f2fs_handle_failed_inode(struct inode * inode)9374d57b86dSChao Yu void f2fs_handle_failed_inode(struct inode *inode)
93844c16156SJaegeuk Kim {
93944c16156SJaegeuk Kim 	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
940221149c0SJaegeuk Kim 	struct node_info ni;
9417735730dSChao Yu 	int err;
94244c16156SJaegeuk Kim 
943a11b9f65SChao Yu 	/*
944a11b9f65SChao Yu 	 * clear nlink of inode in order to release resource of inode
945a11b9f65SChao Yu 	 * immediately.
946a11b9f65SChao Yu 	 */
947a11b9f65SChao Yu 	clear_nlink(inode);
948a11b9f65SChao Yu 
949a11b9f65SChao Yu 	/*
950a11b9f65SChao Yu 	 * we must call this to avoid inode being remained as dirty, resulting
951a11b9f65SChao Yu 	 * in a panic when flushing dirty inodes in gdirty_list.
952a11b9f65SChao Yu 	 */
9534d57b86dSChao Yu 	f2fs_update_inode_page(inode);
9549bb02c36SJaegeuk Kim 	f2fs_inode_synced(inode);
955a11b9f65SChao Yu 
956221149c0SJaegeuk Kim 	/* don't make bad inode, since it becomes a regular file. */
95744c16156SJaegeuk Kim 	unlock_new_inode(inode);
95844c16156SJaegeuk Kim 
95913ec7297SChao Yu 	/*
96013ec7297SChao Yu 	 * Note: we should add inode to orphan list before f2fs_unlock_op()
96113ec7297SChao Yu 	 * so we can prevent losing this orphan when encoutering checkpoint
96213ec7297SChao Yu 	 * and following suddenly power-off.
96313ec7297SChao Yu 	 */
964a9419b63SJaegeuk Kim 	err = f2fs_get_node_info(sbi, inode->i_ino, &ni, false);
9657735730dSChao Yu 	if (err) {
9667735730dSChao Yu 		set_sbi_flag(sbi, SBI_NEED_FSCK);
9672fef99b8SJaegeuk Kim 		set_inode_flag(inode, FI_FREE_NID);
968dcbb4c10SJoe Perches 		f2fs_warn(sbi, "May loss orphan inode, run fsck to fix.");
9697735730dSChao Yu 		goto out;
9707735730dSChao Yu 	}
971221149c0SJaegeuk Kim 
972221149c0SJaegeuk Kim 	if (ni.blk_addr != NULL_ADDR) {
9737735730dSChao Yu 		err = f2fs_acquire_orphan_inode(sbi);
974221149c0SJaegeuk Kim 		if (err) {
975221149c0SJaegeuk Kim 			set_sbi_flag(sbi, SBI_NEED_FSCK);
976dcbb4c10SJoe Perches 			f2fs_warn(sbi, "Too many orphan inodes, run fsck to fix.");
977221149c0SJaegeuk Kim 		} else {
9784d57b86dSChao Yu 			f2fs_add_orphan_inode(inode);
97913ec7297SChao Yu 		}
9804d57b86dSChao Yu 		f2fs_alloc_nid_done(sbi, inode->i_ino);
981221149c0SJaegeuk Kim 	} else {
98291942321SJaegeuk Kim 		set_inode_flag(inode, FI_FREE_NID);
983221149c0SJaegeuk Kim 	}
984221149c0SJaegeuk Kim 
9857735730dSChao Yu out:
98644c16156SJaegeuk Kim 	f2fs_unlock_op(sbi);
98744c16156SJaegeuk Kim 
98844c16156SJaegeuk Kim 	/* iput will drop the inode object */
98944c16156SJaegeuk Kim 	iput(inode);
99044c16156SJaegeuk Kim }
991