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
32e62ff092SChao Yu if (f2fs_readonly(F2FS_I_SB(inode)->sb))
33e62ff092SChao Yu return;
34e62ff092SChao Yu
357c45729aSJaegeuk Kim if (f2fs_inode_dirtied(inode, sync))
36b56ab837SJaegeuk Kim return;
377c45729aSJaegeuk Kim
38364afd8aSDaeho Jeong if (f2fs_is_atomic_file(inode)) {
39364afd8aSDaeho Jeong set_inode_flag(inode, FI_ATOMIC_DIRTIED);
40364afd8aSDaeho Jeong return;
41364afd8aSDaeho Jeong }
42364afd8aSDaeho Jeong
43b56ab837SJaegeuk Kim mark_inode_dirty_sync(inode);
44b56ab837SJaegeuk Kim }
45b56ab837SJaegeuk Kim
f2fs_set_inode_flags(struct inode * inode)4619f99ceeSJaegeuk Kim void f2fs_set_inode_flags(struct inode *inode)
4719f99ceeSJaegeuk Kim {
4819f99ceeSJaegeuk Kim unsigned int flags = F2FS_I(inode)->i_flags;
498abfb36aSZhang Zhen unsigned int new_fl = 0;
5019f99ceeSJaegeuk Kim
5159c84408SChao Yu if (flags & F2FS_SYNC_FL)
528abfb36aSZhang Zhen new_fl |= S_SYNC;
5359c84408SChao Yu if (flags & F2FS_APPEND_FL)
548abfb36aSZhang Zhen new_fl |= S_APPEND;
5559c84408SChao Yu if (flags & F2FS_IMMUTABLE_FL)
568abfb36aSZhang Zhen new_fl |= S_IMMUTABLE;
5759c84408SChao Yu if (flags & F2FS_NOATIME_FL)
588abfb36aSZhang Zhen new_fl |= S_NOATIME;
5959c84408SChao Yu if (flags & F2FS_DIRSYNC_FL)
608abfb36aSZhang Zhen new_fl |= S_DIRSYNC;
6162230e0dSChandan Rajendra if (file_is_encrypt(inode))
622ee6a576SEric Biggers new_fl |= S_ENCRYPTED;
6395ae251fSEric Biggers if (file_is_verity(inode))
6495ae251fSEric Biggers new_fl |= S_VERITY;
652c2eb7a3SDaniel Rosenberg if (flags & F2FS_CASEFOLD_FL)
662c2eb7a3SDaniel Rosenberg new_fl |= S_CASEFOLD;
676a678857SZhang Zhen inode_set_flags(inode, new_fl,
682ee6a576SEric Biggers S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|
69fbc246a1SLinus Torvalds S_ENCRYPTED|S_VERITY|S_CASEFOLD);
7019f99ceeSJaegeuk Kim }
7119f99ceeSJaegeuk Kim
__get_inode_rdev(struct inode * inode,struct page * node_page)72dcd6b38bSChao Yu static void __get_inode_rdev(struct inode *inode, struct page *node_page)
733d1e3807SJaegeuk Kim {
74dcd6b38bSChao Yu __le32 *addr = get_dnode_addr(inode, node_page);
757a2af766SChao Yu
763d1e3807SJaegeuk Kim if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
773d1e3807SJaegeuk Kim S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
78dcd6b38bSChao Yu if (addr[0])
79dcd6b38bSChao Yu inode->i_rdev = old_decode_dev(le32_to_cpu(addr[0]));
803d1e3807SJaegeuk Kim else
81dcd6b38bSChao Yu inode->i_rdev = new_decode_dev(le32_to_cpu(addr[1]));
823d1e3807SJaegeuk Kim }
833d1e3807SJaegeuk Kim }
843d1e3807SJaegeuk Kim
__set_inode_rdev(struct inode * inode,struct page * node_page)85dcd6b38bSChao Yu static void __set_inode_rdev(struct inode *inode, struct page *node_page)
863d1e3807SJaegeuk Kim {
87dcd6b38bSChao Yu __le32 *addr = get_dnode_addr(inode, node_page);
887a2af766SChao Yu
893d1e3807SJaegeuk Kim if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
903d1e3807SJaegeuk Kim if (old_valid_dev(inode->i_rdev)) {
91dcd6b38bSChao Yu addr[0] = cpu_to_le32(old_encode_dev(inode->i_rdev));
92dcd6b38bSChao Yu addr[1] = 0;
933d1e3807SJaegeuk Kim } else {
94dcd6b38bSChao Yu addr[0] = 0;
95dcd6b38bSChao Yu addr[1] = cpu_to_le32(new_encode_dev(inode->i_rdev));
96dcd6b38bSChao Yu addr[2] = 0;
973d1e3807SJaegeuk Kim }
983d1e3807SJaegeuk Kim }
993d1e3807SJaegeuk Kim }
1003d1e3807SJaegeuk Kim
__recover_inline_status(struct inode * inode,struct page * ipage)1019e5ba77fSChao Yu static void __recover_inline_status(struct inode *inode, struct page *ipage)
102b3d208f9SJaegeuk Kim {
103f2470371SChao Yu void *inline_data = inline_data_addr(inode, ipage);
1049e5ba77fSChao Yu __le32 *start = inline_data;
105f2470371SChao Yu __le32 *end = start + MAX_INLINE_DATA(inode) / sizeof(__le32);
106b3d208f9SJaegeuk Kim
1079e5ba77fSChao Yu while (start < end) {
1089e5ba77fSChao Yu if (*start++) {
109bae0ee7aSChao Yu f2fs_wait_on_page_writeback(ipage, NODE, true, true);
110b3d208f9SJaegeuk Kim
11191942321SJaegeuk Kim set_inode_flag(inode, FI_DATA_EXIST);
11291942321SJaegeuk Kim set_raw_inline(inode, F2FS_INODE(ipage));
113b3d208f9SJaegeuk Kim set_page_dirty(ipage);
1149e5ba77fSChao Yu return;
1159e5ba77fSChao Yu }
1169e5ba77fSChao Yu }
1179e5ba77fSChao Yu return;
118b3d208f9SJaegeuk Kim }
119b3d208f9SJaegeuk Kim
f2fs_enable_inode_chksum(struct f2fs_sb_info * sbi,struct page * page)120704956ecSChao Yu static bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct page *page)
121704956ecSChao Yu {
122704956ecSChao Yu struct f2fs_inode *ri = &F2FS_NODE(page)->i;
123704956ecSChao Yu
1247beb01f7SChao Yu if (!f2fs_sb_has_inode_chksum(sbi))
125704956ecSChao Yu return false;
126704956ecSChao Yu
1274c6b56c0SChao Yu if (!IS_INODE(page) || !(ri->i_inline & F2FS_EXTRA_ATTR))
128704956ecSChao Yu return false;
129704956ecSChao Yu
130d6964949SZhikang Zhang if (!F2FS_FITS_IN_INODE(ri, le16_to_cpu(ri->i_extra_isize),
131d6964949SZhikang Zhang i_inode_checksum))
132704956ecSChao Yu return false;
133704956ecSChao Yu
134704956ecSChao Yu return true;
135704956ecSChao Yu }
136704956ecSChao Yu
f2fs_inode_chksum(struct f2fs_sb_info * sbi,struct page * page)137704956ecSChao Yu static __u32 f2fs_inode_chksum(struct f2fs_sb_info *sbi, struct page *page)
138704956ecSChao Yu {
139704956ecSChao Yu struct f2fs_node *node = F2FS_NODE(page);
140704956ecSChao Yu struct f2fs_inode *ri = &node->i;
141704956ecSChao Yu __le32 ino = node->footer.ino;
142704956ecSChao Yu __le32 gen = ri->i_generation;
143704956ecSChao Yu __u32 chksum, chksum_seed;
144704956ecSChao Yu __u32 dummy_cs = 0;
145704956ecSChao Yu unsigned int offset = offsetof(struct f2fs_inode, i_inode_checksum);
146704956ecSChao Yu unsigned int cs_size = sizeof(dummy_cs);
147704956ecSChao Yu
148704956ecSChao Yu chksum = f2fs_chksum(sbi, sbi->s_chksum_seed, (__u8 *)&ino,
149704956ecSChao Yu sizeof(ino));
150704956ecSChao Yu chksum_seed = f2fs_chksum(sbi, chksum, (__u8 *)&gen, sizeof(gen));
151704956ecSChao Yu
152704956ecSChao Yu chksum = f2fs_chksum(sbi, chksum_seed, (__u8 *)ri, offset);
153704956ecSChao Yu chksum = f2fs_chksum(sbi, chksum, (__u8 *)&dummy_cs, cs_size);
154704956ecSChao Yu offset += cs_size;
155704956ecSChao Yu chksum = f2fs_chksum(sbi, chksum, (__u8 *)ri + offset,
156704956ecSChao Yu F2FS_BLKSIZE - offset);
157704956ecSChao Yu return chksum;
158704956ecSChao Yu }
159704956ecSChao Yu
f2fs_inode_chksum_verify(struct f2fs_sb_info * sbi,struct page * page)160704956ecSChao Yu bool f2fs_inode_chksum_verify(struct f2fs_sb_info *sbi, struct page *page)
161704956ecSChao Yu {
162704956ecSChao Yu struct f2fs_inode *ri;
163704956ecSChao Yu __u32 provided, calculated;
164704956ecSChao Yu
16583a3bfdbSJaegeuk Kim if (unlikely(is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)))
16683a3bfdbSJaegeuk Kim return true;
16783a3bfdbSJaegeuk Kim
16854c55c4eSWeichao Guo #ifdef CONFIG_F2FS_CHECK_FS
16954c55c4eSWeichao Guo if (!f2fs_enable_inode_chksum(sbi, page))
17054c55c4eSWeichao Guo #else
171ee605234SJaegeuk Kim if (!f2fs_enable_inode_chksum(sbi, page) ||
172ee605234SJaegeuk Kim PageDirty(page) || PageWriteback(page))
17354c55c4eSWeichao Guo #endif
174704956ecSChao Yu return true;
175704956ecSChao Yu
176704956ecSChao Yu ri = &F2FS_NODE(page)->i;
177704956ecSChao Yu provided = le32_to_cpu(ri->i_inode_checksum);
178704956ecSChao Yu calculated = f2fs_inode_chksum(sbi, page);
179704956ecSChao Yu
180704956ecSChao Yu if (provided != calculated)
181dcbb4c10SJoe Perches f2fs_warn(sbi, "checksum invalid, nid = %lu, ino_of_node = %x, %x vs. %x",
182b42b179bSChao Yu page->index, ino_of_node(page), provided, calculated);
183704956ecSChao Yu
184704956ecSChao Yu return provided == calculated;
185704956ecSChao Yu }
186704956ecSChao Yu
f2fs_inode_chksum_set(struct f2fs_sb_info * sbi,struct page * page)187704956ecSChao Yu void f2fs_inode_chksum_set(struct f2fs_sb_info *sbi, struct page *page)
188704956ecSChao Yu {
189704956ecSChao Yu struct f2fs_inode *ri = &F2FS_NODE(page)->i;
190704956ecSChao Yu
191704956ecSChao Yu if (!f2fs_enable_inode_chksum(sbi, page))
192704956ecSChao Yu return;
193704956ecSChao Yu
194704956ecSChao Yu ri->i_inode_checksum = cpu_to_le32(f2fs_inode_chksum(sbi, page));
195704956ecSChao Yu }
196704956ecSChao Yu
sanity_check_compress_inode(struct inode * inode,struct f2fs_inode * ri)197698a5c8cSYangtao Li static bool sanity_check_compress_inode(struct inode *inode,
198698a5c8cSYangtao Li struct f2fs_inode *ri)
199698a5c8cSYangtao Li {
200698a5c8cSYangtao Li struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
201698a5c8cSYangtao Li unsigned char clevel;
202698a5c8cSYangtao Li
203698a5c8cSYangtao Li if (ri->i_compress_algorithm >= COMPRESS_MAX) {
204698a5c8cSYangtao Li f2fs_warn(sbi,
205698a5c8cSYangtao Li "%s: inode (ino=%lx) has unsupported compress algorithm: %u, run fsck to fix",
206698a5c8cSYangtao Li __func__, inode->i_ino, ri->i_compress_algorithm);
207c9887949SChao Yu return false;
208698a5c8cSYangtao Li }
209698a5c8cSYangtao Li if (le64_to_cpu(ri->i_compr_blocks) >
210698a5c8cSYangtao Li SECTOR_TO_BLOCK(inode->i_blocks)) {
211698a5c8cSYangtao Li f2fs_warn(sbi,
212698a5c8cSYangtao Li "%s: inode (ino=%lx) has inconsistent i_compr_blocks:%llu, i_blocks:%llu, run fsck to fix",
213698a5c8cSYangtao Li __func__, inode->i_ino, le64_to_cpu(ri->i_compr_blocks),
214698a5c8cSYangtao Li SECTOR_TO_BLOCK(inode->i_blocks));
215c9887949SChao Yu return false;
216698a5c8cSYangtao Li }
217698a5c8cSYangtao Li if (ri->i_log_cluster_size < MIN_COMPRESS_LOG_SIZE ||
218698a5c8cSYangtao Li ri->i_log_cluster_size > MAX_COMPRESS_LOG_SIZE) {
219698a5c8cSYangtao Li f2fs_warn(sbi,
220698a5c8cSYangtao Li "%s: inode (ino=%lx) has unsupported log cluster size: %u, run fsck to fix",
221698a5c8cSYangtao Li __func__, inode->i_ino, ri->i_log_cluster_size);
222c9887949SChao Yu return false;
223698a5c8cSYangtao Li }
224698a5c8cSYangtao Li
225698a5c8cSYangtao Li clevel = le16_to_cpu(ri->i_compress_flag) >>
226698a5c8cSYangtao Li COMPRESS_LEVEL_OFFSET;
227698a5c8cSYangtao Li switch (ri->i_compress_algorithm) {
228698a5c8cSYangtao Li case COMPRESS_LZO:
229698a5c8cSYangtao Li #ifdef CONFIG_F2FS_FS_LZO
230698a5c8cSYangtao Li if (clevel)
231698a5c8cSYangtao Li goto err_level;
232698a5c8cSYangtao Li #endif
233698a5c8cSYangtao Li break;
234698a5c8cSYangtao Li case COMPRESS_LZORLE:
235698a5c8cSYangtao Li #ifdef CONFIG_F2FS_FS_LZORLE
236698a5c8cSYangtao Li if (clevel)
237698a5c8cSYangtao Li goto err_level;
238698a5c8cSYangtao Li #endif
239698a5c8cSYangtao Li break;
240698a5c8cSYangtao Li case COMPRESS_LZ4:
241698a5c8cSYangtao Li #ifdef CONFIG_F2FS_FS_LZ4
242698a5c8cSYangtao Li #ifdef CONFIG_F2FS_FS_LZ4HC
243698a5c8cSYangtao Li if (clevel &&
244698a5c8cSYangtao Li (clevel < LZ4HC_MIN_CLEVEL || clevel > LZ4HC_MAX_CLEVEL))
245698a5c8cSYangtao Li goto err_level;
246698a5c8cSYangtao Li #else
247698a5c8cSYangtao Li if (clevel)
248698a5c8cSYangtao Li goto err_level;
249698a5c8cSYangtao Li #endif
250698a5c8cSYangtao Li #endif
251698a5c8cSYangtao Li break;
252698a5c8cSYangtao Li case COMPRESS_ZSTD:
253698a5c8cSYangtao Li #ifdef CONFIG_F2FS_FS_ZSTD
254698a5c8cSYangtao Li if (clevel < zstd_min_clevel() || clevel > zstd_max_clevel())
255698a5c8cSYangtao Li goto err_level;
256698a5c8cSYangtao Li #endif
257698a5c8cSYangtao Li break;
258698a5c8cSYangtao Li default:
259698a5c8cSYangtao Li goto err_level;
260698a5c8cSYangtao Li }
261698a5c8cSYangtao Li
262698a5c8cSYangtao Li return true;
263698a5c8cSYangtao Li err_level:
264698a5c8cSYangtao Li f2fs_warn(sbi, "%s: inode (ino=%lx) has unsupported compress level: %u, run fsck to fix",
265698a5c8cSYangtao Li __func__, inode->i_ino, clevel);
266698a5c8cSYangtao Li return false;
267698a5c8cSYangtao Li }
268698a5c8cSYangtao Li
sanity_check_inode(struct inode * inode,struct page * node_page)269e34438c9SChao Yu static bool sanity_check_inode(struct inode *inode, struct page *node_page)
2705d64600dSJaegeuk Kim {
2715d64600dSJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
27218dd6470SChao Yu struct f2fs_inode_info *fi = F2FS_I(inode);
2734c8ff709SChao Yu struct f2fs_inode *ri = F2FS_INODE(node_page);
274e34438c9SChao Yu unsigned long long iblocks;
275e34438c9SChao Yu
276e34438c9SChao Yu iblocks = le64_to_cpu(F2FS_INODE(node_page)->i_blocks);
277e34438c9SChao Yu if (!iblocks) {
278dcbb4c10SJoe Perches f2fs_warn(sbi, "%s: corrupted inode i_blocks i_ino=%lx iblocks=%llu, run fsck to fix.",
279e34438c9SChao Yu __func__, inode->i_ino, iblocks);
280e34438c9SChao Yu return false;
281e34438c9SChao Yu }
282e34438c9SChao Yu
283e34438c9SChao Yu if (ino_of_node(node_page) != nid_of_node(node_page)) {
284dcbb4c10SJoe Perches f2fs_warn(sbi, "%s: corrupted inode footer i_ino=%lx, ino,nid: [%u, %u] run fsck to fix.",
285e34438c9SChao Yu __func__, inode->i_ino,
286e34438c9SChao Yu ino_of_node(node_page), nid_of_node(node_page));
287e34438c9SChao Yu return false;
288e34438c9SChao Yu }
2895d64600dSJaegeuk Kim
290f240d3aaSChao Yu if (f2fs_has_extra_attr(inode)) {
291f240d3aaSChao Yu if (!f2fs_sb_has_extra_attr(sbi)) {
292dcbb4c10SJoe Perches f2fs_warn(sbi, "%s: inode (ino=%lx) is with extra_attr, but extra_attr feature is off",
29376d56d4aSChao Yu __func__, inode->i_ino);
29476d56d4aSChao Yu return false;
29576d56d4aSChao Yu }
29618dd6470SChao Yu if (fi->i_extra_isize > F2FS_TOTAL_EXTRA_ATTR_SIZE ||
297f240d3aaSChao Yu fi->i_extra_isize < F2FS_MIN_EXTRA_ATTR_SIZE ||
29818dd6470SChao Yu fi->i_extra_isize % sizeof(__le32)) {
299dcbb4c10SJoe Perches f2fs_warn(sbi, "%s: inode (ino=%lx) has corrupted i_extra_isize: %d, max: %zu",
30018dd6470SChao Yu __func__, inode->i_ino, fi->i_extra_isize,
30118dd6470SChao Yu F2FS_TOTAL_EXTRA_ATTR_SIZE);
30218dd6470SChao Yu return false;
30318dd6470SChao Yu }
304f240d3aaSChao Yu if (f2fs_sb_has_flexible_inline_xattr(sbi) &&
305dd6c89b5SChao Yu f2fs_has_inline_xattr(inode) &&
306dd6c89b5SChao Yu (!fi->i_inline_xattr_size ||
307dd6c89b5SChao Yu fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE)) {
308dcbb4c10SJoe Perches f2fs_warn(sbi, "%s: inode (ino=%lx) has corrupted i_inline_xattr_size: %d, max: %zu",
309dd6c89b5SChao Yu __func__, inode->i_ino, fi->i_inline_xattr_size,
310dd6c89b5SChao Yu MAX_INLINE_XATTR_SIZE);
311dd6c89b5SChao Yu return false;
312dd6c89b5SChao Yu }
313f240d3aaSChao Yu if (f2fs_sb_has_compression(sbi) &&
314f240d3aaSChao Yu fi->i_flags & F2FS_COMPR_FL &&
315f240d3aaSChao Yu F2FS_FITS_IN_INODE(ri, fi->i_extra_isize,
316f240d3aaSChao Yu i_compress_flag)) {
317f240d3aaSChao Yu if (!sanity_check_compress_inode(inode, ri))
318f240d3aaSChao Yu return false;
319f240d3aaSChao Yu }
320f240d3aaSChao Yu } else if (f2fs_sb_has_flexible_inline_xattr(sbi)) {
321f240d3aaSChao Yu f2fs_warn(sbi, "%s: corrupted inode ino=%lx, run fsck to fix.",
322f240d3aaSChao Yu __func__, inode->i_ino);
323f240d3aaSChao Yu return false;
324f240d3aaSChao Yu }
325f240d3aaSChao Yu
326f240d3aaSChao Yu if (!f2fs_sb_has_extra_attr(sbi)) {
327f240d3aaSChao Yu if (f2fs_sb_has_project_quota(sbi)) {
328f240d3aaSChao Yu f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
329f240d3aaSChao Yu __func__, inode->i_ino, F2FS_FEATURE_PRJQUOTA);
330f240d3aaSChao Yu return false;
331f240d3aaSChao Yu }
332f240d3aaSChao Yu if (f2fs_sb_has_inode_chksum(sbi)) {
333f240d3aaSChao Yu f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
334f240d3aaSChao Yu __func__, inode->i_ino, F2FS_FEATURE_INODE_CHKSUM);
335f240d3aaSChao Yu return false;
336f240d3aaSChao Yu }
337f240d3aaSChao Yu if (f2fs_sb_has_flexible_inline_xattr(sbi)) {
338f240d3aaSChao Yu f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
339f240d3aaSChao Yu __func__, inode->i_ino, F2FS_FEATURE_FLEXIBLE_INLINE_XATTR);
340f240d3aaSChao Yu return false;
341f240d3aaSChao Yu }
342f240d3aaSChao Yu if (f2fs_sb_has_inode_crtime(sbi)) {
343f240d3aaSChao Yu f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
344f240d3aaSChao Yu __func__, inode->i_ino, F2FS_FEATURE_INODE_CRTIME);
345f240d3aaSChao Yu return false;
346f240d3aaSChao Yu }
347f240d3aaSChao Yu if (f2fs_sb_has_compression(sbi)) {
348f240d3aaSChao Yu f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.",
349f240d3aaSChao Yu __func__, inode->i_ino, F2FS_FEATURE_COMPRESSION);
350f240d3aaSChao Yu return false;
351f240d3aaSChao Yu }
352f240d3aaSChao Yu }
353dd6c89b5SChao Yu
3546290d3f5SChao Yu if (f2fs_sanity_check_inline_data(inode, node_page)) {
355dcbb4c10SJoe Perches f2fs_warn(sbi, "%s: inode (ino=%lx, mode=%u) should not have inline_data, run fsck to fix",
356bcbfbd60SChao Yu __func__, inode->i_ino, inode->i_mode);
357bcbfbd60SChao Yu return false;
358bcbfbd60SChao Yu }
359bcbfbd60SChao Yu
360bcbfbd60SChao Yu if (f2fs_has_inline_dentry(inode) && !S_ISDIR(inode->i_mode)) {
361dcbb4c10SJoe Perches f2fs_warn(sbi, "%s: inode (ino=%lx, mode=%u) should not have inline_dentry, run fsck to fix",
362bcbfbd60SChao Yu __func__, inode->i_ino, inode->i_mode);
363bcbfbd60SChao Yu return false;
364bcbfbd60SChao Yu }
365bcbfbd60SChao Yu
366f6322f3fSEric Biggers if ((fi->i_flags & F2FS_CASEFOLD_FL) && !f2fs_sb_has_casefold(sbi)) {
367f6322f3fSEric Biggers f2fs_warn(sbi, "%s: inode (ino=%lx) has casefold flag, but casefold feature is off",
368f6322f3fSEric Biggers __func__, inode->i_ino);
369f6322f3fSEric Biggers return false;
370f6322f3fSEric Biggers }
371f6322f3fSEric Biggers
372be015520SChao Yu if (fi->i_xattr_nid && f2fs_check_nid_range(sbi, fi->i_xattr_nid)) {
373be015520SChao Yu f2fs_warn(sbi, "%s: inode (ino=%lx) has corrupted i_xattr_nid: %u, run fsck to fix.",
374be015520SChao Yu __func__, inode->i_ino, fi->i_xattr_nid);
375be015520SChao Yu return false;
376be015520SChao Yu }
377be015520SChao Yu
3785d64600dSJaegeuk Kim return true;
3795d64600dSJaegeuk Kim }
3805d64600dSJaegeuk Kim
init_idisk_time(struct inode * inode)381049ea86cSZhang Qilong static void init_idisk_time(struct inode *inode)
382049ea86cSZhang Qilong {
383049ea86cSZhang Qilong struct f2fs_inode_info *fi = F2FS_I(inode);
384049ea86cSZhang Qilong
385049ea86cSZhang Qilong fi->i_disk_time[0] = inode->i_atime;
386c62ebd35SJeff Layton fi->i_disk_time[1] = inode_get_ctime(inode);
387049ea86cSZhang Qilong fi->i_disk_time[2] = inode->i_mtime;
388049ea86cSZhang Qilong }
389049ea86cSZhang Qilong
do_read_inode(struct inode * inode)39019f99ceeSJaegeuk Kim static int do_read_inode(struct inode *inode)
39119f99ceeSJaegeuk Kim {
3924081363fSJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
39319f99ceeSJaegeuk Kim struct f2fs_inode_info *fi = F2FS_I(inode);
39419f99ceeSJaegeuk Kim struct page *node_page;
39519f99ceeSJaegeuk Kim struct f2fs_inode *ri;
3965c57132eSChao Yu projid_t i_projid;
39719f99ceeSJaegeuk Kim
39819f99ceeSJaegeuk Kim /* Check if ino is within scope */
3994d57b86dSChao Yu if (f2fs_check_nid_range(sbi, inode->i_ino))
400064e0823SNamjae Jeon return -EINVAL;
40119f99ceeSJaegeuk Kim
4024d57b86dSChao Yu node_page = f2fs_get_node_page(sbi, inode->i_ino);
40319f99ceeSJaegeuk Kim if (IS_ERR(node_page))
40419f99ceeSJaegeuk Kim return PTR_ERR(node_page);
40519f99ceeSJaegeuk Kim
40658bfaf44SJaegeuk Kim ri = F2FS_INODE(node_page);
40719f99ceeSJaegeuk Kim
40819f99ceeSJaegeuk Kim inode->i_mode = le16_to_cpu(ri->i_mode);
40919f99ceeSJaegeuk Kim i_uid_write(inode, le32_to_cpu(ri->i_uid));
41019f99ceeSJaegeuk Kim i_gid_write(inode, le32_to_cpu(ri->i_gid));
41119f99ceeSJaegeuk Kim set_nlink(inode, le32_to_cpu(ri->i_links));
41219f99ceeSJaegeuk Kim inode->i_size = le64_to_cpu(ri->i_size);
413000519f2SChao Yu inode->i_blocks = SECTOR_FROM_BLOCK(le64_to_cpu(ri->i_blocks) - 1);
41419f99ceeSJaegeuk Kim
41519f99ceeSJaegeuk Kim inode->i_atime.tv_sec = le64_to_cpu(ri->i_atime);
416c62ebd35SJeff Layton inode_set_ctime(inode, le64_to_cpu(ri->i_ctime),
417c62ebd35SJeff Layton le32_to_cpu(ri->i_ctime_nsec));
41819f99ceeSJaegeuk Kim inode->i_mtime.tv_sec = le64_to_cpu(ri->i_mtime);
41919f99ceeSJaegeuk Kim inode->i_atime.tv_nsec = le32_to_cpu(ri->i_atime_nsec);
42019f99ceeSJaegeuk Kim inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec);
42119f99ceeSJaegeuk Kim inode->i_generation = le32_to_cpu(ri->i_generation);
4221c41e680SChao Yu if (S_ISDIR(inode->i_mode))
42319f99ceeSJaegeuk Kim fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
4241c41e680SChao Yu else if (S_ISREG(inode->i_mode))
4252ef79ecbSChao Yu fi->i_gc_failures[GC_FAILURE_PIN] =
4262ef79ecbSChao Yu le16_to_cpu(ri->i_gc_failures);
42719f99ceeSJaegeuk Kim fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
42819f99ceeSJaegeuk Kim fi->i_flags = le32_to_cpu(ri->i_flags);
4295043a964SWang Shilong if (S_ISREG(inode->i_mode))
4305043a964SWang Shilong fi->i_flags &= ~F2FS_PROJINHERIT_FL;
4317653b9d8SChao Yu bitmap_zero(fi->flags, FI_MAX);
43219f99ceeSJaegeuk Kim fi->i_advise = ri->i_advise;
4336666e6aaSJaegeuk Kim fi->i_pino = le32_to_cpu(ri->i_pino);
43438431545SJaegeuk Kim fi->i_dir_level = ri->i_dir_level;
4353d1e3807SJaegeuk Kim
43691942321SJaegeuk Kim get_inline_info(inode, ri);
4373d1e3807SJaegeuk Kim
4387a2af766SChao Yu fi->i_extra_isize = f2fs_has_extra_attr(inode) ?
4397a2af766SChao Yu le16_to_cpu(ri->i_extra_isize) : 0;
4407a2af766SChao Yu
4417beb01f7SChao Yu if (f2fs_sb_has_flexible_inline_xattr(sbi)) {
4426afc662eSChao Yu fi->i_inline_xattr_size = le16_to_cpu(ri->i_inline_xattr_size);
4436afc662eSChao Yu } else if (f2fs_has_inline_xattr(inode) ||
4446afc662eSChao Yu f2fs_has_inline_dentry(inode)) {
4456afc662eSChao Yu fi->i_inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
4466afc662eSChao Yu } else {
4476afc662eSChao Yu
4486afc662eSChao Yu /*
4496afc662eSChao Yu * Previous inline data or directory always reserved 200 bytes
4506afc662eSChao Yu * in inode layout, even if inline_xattr is disabled. In order
4516afc662eSChao Yu * to keep inline_dentry's structure for backward compatibility,
4526afc662eSChao Yu * we get the space back only from inline_data.
4536afc662eSChao Yu */
4546afc662eSChao Yu fi->i_inline_xattr_size = 0;
4556afc662eSChao Yu }
4566afc662eSChao Yu
457958ccbbfSChao Yu if (!sanity_check_inode(inode, node_page)) {
458958ccbbfSChao Yu f2fs_put_page(node_page, 1);
459c9887949SChao Yu set_sbi_flag(sbi, SBI_NEED_FSCK);
460958ccbbfSChao Yu f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
461958ccbbfSChao Yu return -EFSCORRUPTED;
462958ccbbfSChao Yu }
463958ccbbfSChao Yu
464b3d208f9SJaegeuk Kim /* check data exist */
465b3d208f9SJaegeuk Kim if (f2fs_has_inline_data(inode) && !f2fs_exist_data(inode))
4669e5ba77fSChao Yu __recover_inline_status(inode, node_page);
467b3d208f9SJaegeuk Kim
468ef2a0071SChao Yu /* try to recover cold bit for non-dir inode */
469ef2a0071SChao Yu if (!S_ISDIR(inode->i_mode) && !is_cold_node(node_page)) {
470db5ae363SWuyun Zhao f2fs_wait_on_page_writeback(node_page, NODE, true, true);
471ef2a0071SChao Yu set_cold_node(node_page, false);
472ef2a0071SChao Yu set_page_dirty(node_page);
473ef2a0071SChao Yu }
474ef2a0071SChao Yu
4753d1e3807SJaegeuk Kim /* get rdev by using inline_info */
476dcd6b38bSChao Yu __get_inode_rdev(inode, node_page);
4773d1e3807SJaegeuk Kim
4784d57b86dSChao Yu if (!f2fs_need_inode_block_update(sbi, inode->i_ino))
47926de9b11SJaegeuk Kim fi->last_disk_size = inode->i_size;
48026de9b11SJaegeuk Kim
48159c84408SChao Yu if (fi->i_flags & F2FS_PROJINHERIT_FL)
4825c57132eSChao Yu set_inode_flag(inode, FI_PROJ_INHERIT);
4835c57132eSChao Yu
4847beb01f7SChao Yu if (f2fs_has_extra_attr(inode) && f2fs_sb_has_project_quota(sbi) &&
4855c57132eSChao Yu F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_projid))
4865c57132eSChao Yu i_projid = (projid_t)le32_to_cpu(ri->i_projid);
4875c57132eSChao Yu else
4885c57132eSChao Yu i_projid = F2FS_DEF_PROJID;
4895c57132eSChao Yu fi->i_projid = make_kprojid(&init_user_ns, i_projid);
4905c57132eSChao Yu
4917beb01f7SChao Yu if (f2fs_has_extra_attr(inode) && f2fs_sb_has_inode_crtime(sbi) &&
4921c1d35dfSChao Yu F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_crtime)) {
4931c1d35dfSChao Yu fi->i_crtime.tv_sec = le64_to_cpu(ri->i_crtime);
4941c1d35dfSChao Yu fi->i_crtime.tv_nsec = le32_to_cpu(ri->i_crtime_nsec);
4951c1d35dfSChao Yu }
4961c1d35dfSChao Yu
4974c8ff709SChao Yu if (f2fs_has_extra_attr(inode) && f2fs_sb_has_compression(sbi) &&
4984c8ff709SChao Yu (fi->i_flags & F2FS_COMPR_FL)) {
4994c8ff709SChao Yu if (F2FS_FITS_IN_INODE(ri, fi->i_extra_isize,
50064ee9163SChao Yu i_compress_flag)) {
501b90e5086SChao Yu unsigned short compress_flag;
502b90e5086SChao Yu
503c2759ebaSDaeho Jeong atomic_set(&fi->i_compr_blocks,
504c2759ebaSDaeho Jeong le64_to_cpu(ri->i_compr_blocks));
5054c8ff709SChao Yu fi->i_compress_algorithm = ri->i_compress_algorithm;
5064c8ff709SChao Yu fi->i_log_cluster_size = ri->i_log_cluster_size;
507b90e5086SChao Yu compress_flag = le16_to_cpu(ri->i_compress_flag);
508b90e5086SChao Yu fi->i_compress_level = compress_flag >>
509b90e5086SChao Yu COMPRESS_LEVEL_OFFSET;
510b90e5086SChao Yu fi->i_compress_flag = compress_flag &
511447286ebSYangtao Li GENMASK(COMPRESS_LEVEL_OFFSET - 1, 0);
512447286ebSYangtao Li fi->i_cluster_size = BIT(fi->i_log_cluster_size);
5134c8ff709SChao Yu set_inode_flag(inode, FI_COMPRESSED_FILE);
5144c8ff709SChao Yu }
5154c8ff709SChao Yu }
5164c8ff709SChao Yu
517049ea86cSZhang Qilong init_idisk_time(inode);
51872840cccSJaegeuk Kim
519263df781SChao Yu if (!sanity_check_extent_cache(inode, node_page)) {
520269d1194SChao Yu f2fs_put_page(node_page, 1);
521269d1194SChao Yu f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
522269d1194SChao Yu return -EFSCORRUPTED;
523269d1194SChao Yu }
524269d1194SChao Yu
525263df781SChao Yu /* Need all the flag bits */
526263df781SChao Yu f2fs_init_read_extent_tree(inode, node_page);
527263df781SChao Yu f2fs_init_age_extent_tree(inode);
528263df781SChao Yu
52919f99ceeSJaegeuk Kim f2fs_put_page(node_page, 1);
5309d1015ddSJaegeuk Kim
531d5e8f6c9SChao Yu stat_inc_inline_xattr(inode);
5329d1015ddSJaegeuk Kim stat_inc_inline_inode(inode);
5339d1015ddSJaegeuk Kim stat_inc_inline_dir(inode);
5344c8ff709SChao Yu stat_inc_compr_inode(inode);
535c2759ebaSDaeho Jeong stat_add_compr_blocks(inode, atomic_read(&fi->i_compr_blocks));
5369d1015ddSJaegeuk Kim
5379e5ba77fSChao Yu return 0;
53819f99ceeSJaegeuk Kim }
53919f99ceeSJaegeuk Kim
is_meta_ino(struct f2fs_sb_info * sbi,unsigned int ino)540fcc2d8ccSChao Yu static bool is_meta_ino(struct f2fs_sb_info *sbi, unsigned int ino)
541fcc2d8ccSChao Yu {
542fcc2d8ccSChao Yu return ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi) ||
543fcc2d8ccSChao Yu ino == F2FS_COMPRESS_INO(sbi);
544fcc2d8ccSChao Yu }
545fcc2d8ccSChao Yu
f2fs_iget(struct super_block * sb,unsigned long ino)54619f99ceeSJaegeuk Kim struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
54719f99ceeSJaegeuk Kim {
54819f99ceeSJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_SB(sb);
54919f99ceeSJaegeuk Kim struct inode *inode;
550a2a4a7e4SNamjae Jeon int ret = 0;
55119f99ceeSJaegeuk Kim
55219f99ceeSJaegeuk Kim inode = iget_locked(sb, ino);
55319f99ceeSJaegeuk Kim if (!inode)
55419f99ceeSJaegeuk Kim return ERR_PTR(-ENOMEM);
555a2a4a7e4SNamjae Jeon
556a2a4a7e4SNamjae Jeon if (!(inode->i_state & I_NEW)) {
557fcc2d8ccSChao Yu if (is_meta_ino(sbi, ino)) {
558fcc2d8ccSChao Yu f2fs_err(sbi, "inaccessible inode: %lu, run fsck to repair", ino);
559fcc2d8ccSChao Yu set_sbi_flag(sbi, SBI_NEED_FSCK);
560fcc2d8ccSChao Yu ret = -EFSCORRUPTED;
561fcc2d8ccSChao Yu trace_f2fs_iget_exit(inode, ret);
562fcc2d8ccSChao Yu iput(inode);
56395fa90c9SChao Yu f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
564fcc2d8ccSChao Yu return ERR_PTR(ret);
565fcc2d8ccSChao Yu }
566fcc2d8ccSChao Yu
567a2a4a7e4SNamjae Jeon trace_f2fs_iget(inode);
56819f99ceeSJaegeuk Kim return inode;
569a2a4a7e4SNamjae Jeon }
57019f99ceeSJaegeuk Kim
571fcc2d8ccSChao Yu if (is_meta_ino(sbi, ino))
5726ce19affSChao Yu goto make_now;
5736ce19affSChao Yu
57419f99ceeSJaegeuk Kim ret = do_read_inode(inode);
57519f99ceeSJaegeuk Kim if (ret)
57619f99ceeSJaegeuk Kim goto bad_inode;
57719f99ceeSJaegeuk Kim make_now:
57819f99ceeSJaegeuk Kim if (ino == F2FS_NODE_INO(sbi)) {
57919f99ceeSJaegeuk Kim inode->i_mapping->a_ops = &f2fs_node_aops;
58081114baaSChao Yu mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
58119f99ceeSJaegeuk Kim } else if (ino == F2FS_META_INO(sbi)) {
58219f99ceeSJaegeuk Kim inode->i_mapping->a_ops = &f2fs_meta_aops;
58381114baaSChao Yu mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
5846ce19affSChao Yu } else if (ino == F2FS_COMPRESS_INO(sbi)) {
5856ce19affSChao Yu #ifdef CONFIG_F2FS_FS_COMPRESSION
5866ce19affSChao Yu inode->i_mapping->a_ops = &f2fs_compress_aops;
587d1917865SFengnan Chang /*
588d1917865SFengnan Chang * generic_error_remove_page only truncates pages of regular
589d1917865SFengnan Chang * inode
590d1917865SFengnan Chang */
591d1917865SFengnan Chang inode->i_mode |= S_IFREG;
5926ce19affSChao Yu #endif
5936ce19affSChao Yu mapping_set_gfp_mask(inode->i_mapping,
5946ce19affSChao Yu GFP_NOFS | __GFP_HIGHMEM | __GFP_MOVABLE);
59519f99ceeSJaegeuk Kim } else if (S_ISREG(inode->i_mode)) {
59619f99ceeSJaegeuk Kim inode->i_op = &f2fs_file_inode_operations;
59719f99ceeSJaegeuk Kim inode->i_fop = &f2fs_file_operations;
59819f99ceeSJaegeuk Kim inode->i_mapping->a_ops = &f2fs_dblock_aops;
59919f99ceeSJaegeuk Kim } else if (S_ISDIR(inode->i_mode)) {
60019f99ceeSJaegeuk Kim inode->i_op = &f2fs_dir_inode_operations;
60119f99ceeSJaegeuk Kim inode->i_fop = &f2fs_dir_operations;
60219f99ceeSJaegeuk Kim inode->i_mapping->a_ops = &f2fs_dblock_aops;
60392d602bcSJaegeuk Kim mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
60419f99ceeSJaegeuk Kim } else if (S_ISLNK(inode->i_mode)) {
60562230e0dSChandan Rajendra if (file_is_encrypt(inode))
606cbaf042aSJaegeuk Kim inode->i_op = &f2fs_encrypted_symlink_inode_operations;
607cbaf042aSJaegeuk Kim else
60819f99ceeSJaegeuk Kim inode->i_op = &f2fs_symlink_inode_operations;
60921fc61c7SAl Viro inode_nohighmem(inode);
61019f99ceeSJaegeuk Kim inode->i_mapping->a_ops = &f2fs_dblock_aops;
61119f99ceeSJaegeuk Kim } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
61219f99ceeSJaegeuk Kim S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
61319f99ceeSJaegeuk Kim inode->i_op = &f2fs_special_inode_operations;
61419f99ceeSJaegeuk Kim init_special_inode(inode, inode->i_mode, inode->i_rdev);
61519f99ceeSJaegeuk Kim } else {
61619f99ceeSJaegeuk Kim ret = -EIO;
61719f99ceeSJaegeuk Kim goto bad_inode;
61819f99ceeSJaegeuk Kim }
61993607124SJaegeuk Kim f2fs_set_inode_flags(inode);
620d4dd19ecSJaegeuk Kim
62119f99ceeSJaegeuk Kim unlock_new_inode(inode);
622a2a4a7e4SNamjae Jeon trace_f2fs_iget(inode);
62319f99ceeSJaegeuk Kim return inode;
62419f99ceeSJaegeuk Kim
62519f99ceeSJaegeuk Kim bad_inode:
626546d22f0SChao Yu f2fs_inode_synced(inode);
62719f99ceeSJaegeuk Kim iget_failed(inode);
628a2a4a7e4SNamjae Jeon trace_f2fs_iget_exit(inode, ret);
62919f99ceeSJaegeuk Kim return ERR_PTR(ret);
63019f99ceeSJaegeuk Kim }
63119f99ceeSJaegeuk Kim
f2fs_iget_retry(struct super_block * sb,unsigned long ino)632e8ea9b3dSJaegeuk Kim struct inode *f2fs_iget_retry(struct super_block *sb, unsigned long ino)
633e8ea9b3dSJaegeuk Kim {
634e8ea9b3dSJaegeuk Kim struct inode *inode;
635e8ea9b3dSJaegeuk Kim retry:
636e8ea9b3dSJaegeuk Kim inode = f2fs_iget(sb, ino);
637e8ea9b3dSJaegeuk Kim if (IS_ERR(inode)) {
638e8ea9b3dSJaegeuk Kim if (PTR_ERR(inode) == -ENOMEM) {
6394034247aSNeilBrown memalloc_retry_wait(GFP_NOFS);
640e8ea9b3dSJaegeuk Kim goto retry;
641e8ea9b3dSJaegeuk Kim }
642e8ea9b3dSJaegeuk Kim }
643e8ea9b3dSJaegeuk Kim return inode;
644e8ea9b3dSJaegeuk Kim }
645e8ea9b3dSJaegeuk Kim
f2fs_update_inode(struct inode * inode,struct page * node_page)6464d57b86dSChao Yu void f2fs_update_inode(struct inode *inode, struct page *node_page)
64719f99ceeSJaegeuk Kim {
64819f99ceeSJaegeuk Kim struct f2fs_inode *ri;
649e7547dacSJaegeuk Kim struct extent_tree *et = F2FS_I(inode)->extent_tree[EX_READ];
65019f99ceeSJaegeuk Kim
651bae0ee7aSChao Yu f2fs_wait_on_page_writeback(node_page, NODE, true, true);
652211a6fa0SYunlei He set_page_dirty(node_page);
653211a6fa0SYunlei He
654211a6fa0SYunlei He f2fs_inode_synced(inode);
65519f99ceeSJaegeuk Kim
65658bfaf44SJaegeuk Kim ri = F2FS_INODE(node_page);
65719f99ceeSJaegeuk Kim
65819f99ceeSJaegeuk Kim ri->i_mode = cpu_to_le16(inode->i_mode);
65919f99ceeSJaegeuk Kim ri->i_advise = F2FS_I(inode)->i_advise;
66019f99ceeSJaegeuk Kim ri->i_uid = cpu_to_le32(i_uid_read(inode));
66119f99ceeSJaegeuk Kim ri->i_gid = cpu_to_le32(i_gid_read(inode));
66219f99ceeSJaegeuk Kim ri->i_links = cpu_to_le32(inode->i_nlink);
663000519f2SChao Yu ri->i_blocks = cpu_to_le64(SECTOR_TO_BLOCK(inode->i_blocks) + 1);
6640c872e2dSChao Yu
6654d8d45dfSDaeho Jeong if (!f2fs_is_atomic_file(inode) ||
6664d8d45dfSDaeho Jeong is_inode_flag_set(inode, FI_ATOMIC_COMMITTED))
6674d8d45dfSDaeho Jeong ri->i_size = cpu_to_le64(i_size_read(inode));
6684d8d45dfSDaeho Jeong
669b691d98fSChao Yu if (et) {
670b691d98fSChao Yu read_lock(&et->lock);
67112607c1bSJaegeuk Kim set_raw_read_extent(&et->largest, &ri->i_ext);
672b691d98fSChao Yu read_unlock(&et->lock);
673b691d98fSChao Yu } else {
6743e72f721SJaegeuk Kim memset(&ri->i_ext, 0, sizeof(ri->i_ext));
675b691d98fSChao Yu }
67691942321SJaegeuk Kim set_raw_inline(inode, ri);
67719f99ceeSJaegeuk Kim
67819f99ceeSJaegeuk Kim ri->i_atime = cpu_to_le64(inode->i_atime.tv_sec);
679c62ebd35SJeff Layton ri->i_ctime = cpu_to_le64(inode_get_ctime(inode).tv_sec);
68019f99ceeSJaegeuk Kim ri->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
68119f99ceeSJaegeuk Kim ri->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
682c62ebd35SJeff Layton ri->i_ctime_nsec = cpu_to_le32(inode_get_ctime(inode).tv_nsec);
68319f99ceeSJaegeuk Kim ri->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
6841c41e680SChao Yu if (S_ISDIR(inode->i_mode))
6851c41e680SChao Yu ri->i_current_depth =
6861c41e680SChao Yu cpu_to_le32(F2FS_I(inode)->i_current_depth);
6871c41e680SChao Yu else if (S_ISREG(inode->i_mode))
6882ef79ecbSChao Yu ri->i_gc_failures =
6892ef79ecbSChao Yu cpu_to_le16(F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN]);
69019f99ceeSJaegeuk Kim ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
69119f99ceeSJaegeuk Kim ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
6926666e6aaSJaegeuk Kim ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
69319f99ceeSJaegeuk Kim ri->i_generation = cpu_to_le32(inode->i_generation);
69438431545SJaegeuk Kim ri->i_dir_level = F2FS_I(inode)->i_dir_level;
6957d79e75fSChangman Lee
6965c57132eSChao Yu if (f2fs_has_extra_attr(inode)) {
6977a2af766SChao Yu ri->i_extra_isize = cpu_to_le16(F2FS_I(inode)->i_extra_isize);
6987a2af766SChao Yu
6997beb01f7SChao Yu if (f2fs_sb_has_flexible_inline_xattr(F2FS_I_SB(inode)))
7006afc662eSChao Yu ri->i_inline_xattr_size =
7016afc662eSChao Yu cpu_to_le16(F2FS_I(inode)->i_inline_xattr_size);
7026afc662eSChao Yu
7037beb01f7SChao Yu if (f2fs_sb_has_project_quota(F2FS_I_SB(inode)) &&
7045c57132eSChao Yu F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize,
7055c57132eSChao Yu i_projid)) {
7065c57132eSChao Yu projid_t i_projid;
7075c57132eSChao Yu
7085c57132eSChao Yu i_projid = from_kprojid(&init_user_ns,
7095c57132eSChao Yu F2FS_I(inode)->i_projid);
7105c57132eSChao Yu ri->i_projid = cpu_to_le32(i_projid);
7115c57132eSChao Yu }
7121c1d35dfSChao Yu
7137beb01f7SChao Yu if (f2fs_sb_has_inode_crtime(F2FS_I_SB(inode)) &&
7141c1d35dfSChao Yu F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize,
7151c1d35dfSChao Yu i_crtime)) {
7161c1d35dfSChao Yu ri->i_crtime =
7171c1d35dfSChao Yu cpu_to_le64(F2FS_I(inode)->i_crtime.tv_sec);
7181c1d35dfSChao Yu ri->i_crtime_nsec =
7191c1d35dfSChao Yu cpu_to_le32(F2FS_I(inode)->i_crtime.tv_nsec);
7201c1d35dfSChao Yu }
7214c8ff709SChao Yu
7224c8ff709SChao Yu if (f2fs_sb_has_compression(F2FS_I_SB(inode)) &&
7234c8ff709SChao Yu F2FS_FITS_IN_INODE(ri, F2FS_I(inode)->i_extra_isize,
72464ee9163SChao Yu i_compress_flag)) {
725b90e5086SChao Yu unsigned short compress_flag;
726b90e5086SChao Yu
7274c8ff709SChao Yu ri->i_compr_blocks =
728c2759ebaSDaeho Jeong cpu_to_le64(atomic_read(
729c2759ebaSDaeho Jeong &F2FS_I(inode)->i_compr_blocks));
7304c8ff709SChao Yu ri->i_compress_algorithm =
7314c8ff709SChao Yu F2FS_I(inode)->i_compress_algorithm;
732b90e5086SChao Yu compress_flag = F2FS_I(inode)->i_compress_flag |
733b90e5086SChao Yu F2FS_I(inode)->i_compress_level <<
734b90e5086SChao Yu COMPRESS_LEVEL_OFFSET;
735b90e5086SChao Yu ri->i_compress_flag = cpu_to_le16(compress_flag);
7364c8ff709SChao Yu ri->i_log_cluster_size =
7374c8ff709SChao Yu F2FS_I(inode)->i_log_cluster_size;
7384c8ff709SChao Yu }
7395c57132eSChao Yu }
7405c57132eSChao Yu
741dcd6b38bSChao Yu __set_inode_rdev(inode, node_page);
74212719ae1SJaegeuk Kim
7432049d4fcSJaegeuk Kim /* deleted inode */
7442049d4fcSJaegeuk Kim if (inode->i_nlink == 0)
745b763f3beSChao Yu clear_page_private_inline(node_page);
7462049d4fcSJaegeuk Kim
747049ea86cSZhang Qilong init_idisk_time(inode);
74854c55c4eSWeichao Guo #ifdef CONFIG_F2FS_CHECK_FS
74954c55c4eSWeichao Guo f2fs_inode_chksum_set(F2FS_I_SB(inode), node_page);
75054c55c4eSWeichao Guo #endif
75119f99ceeSJaegeuk Kim }
75219f99ceeSJaegeuk Kim
f2fs_update_inode_page(struct inode * inode)7534d57b86dSChao Yu void f2fs_update_inode_page(struct inode *inode)
75419f99ceeSJaegeuk Kim {
7554081363fSJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
75619f99ceeSJaegeuk Kim struct page *node_page;
7573aa51c61SJaegeuk Kim int count = 0;
758744602cfSJaegeuk Kim retry:
7594d57b86dSChao Yu node_page = f2fs_get_node_page(sbi, inode->i_ino);
760744602cfSJaegeuk Kim if (IS_ERR(node_page)) {
761744602cfSJaegeuk Kim int err = PTR_ERR(node_page);
7625f029c04SYi Zhuang
7633aa51c61SJaegeuk Kim /* The node block was truncated. */
7643aa51c61SJaegeuk Kim if (err == -ENOENT)
7653aa51c61SJaegeuk Kim return;
7663aa51c61SJaegeuk Kim
7673aa51c61SJaegeuk Kim if (err == -ENOMEM || ++count <= DEFAULT_RETRY_IO_COUNT)
768744602cfSJaegeuk Kim goto retry;
7693aa51c61SJaegeuk Kim f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_UPDATE_INODE);
770211a6fa0SYunlei He return;
771744602cfSJaegeuk Kim }
7724d57b86dSChao Yu f2fs_update_inode(inode, node_page);
77339936837SJaegeuk Kim f2fs_put_page(node_page, 1);
77439936837SJaegeuk Kim }
77539936837SJaegeuk Kim
f2fs_write_inode(struct inode * inode,struct writeback_control * wbc)77639936837SJaegeuk Kim int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
77739936837SJaegeuk Kim {
7784081363fSJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
77919f99ceeSJaegeuk Kim
78019f99ceeSJaegeuk Kim if (inode->i_ino == F2FS_NODE_INO(sbi) ||
78119f99ceeSJaegeuk Kim inode->i_ino == F2FS_META_INO(sbi))
78219f99ceeSJaegeuk Kim return 0;
78319f99ceeSJaegeuk Kim
784fe1897eaSChao Yu /*
785fe1897eaSChao Yu * atime could be updated without dirtying f2fs inode in lazytime mode
786fe1897eaSChao Yu */
787fe1897eaSChao Yu if (f2fs_is_time_consistent(inode) &&
788fe1897eaSChao Yu !is_inode_flag_set(inode, FI_DIRTY_INODE))
789b3783873SJaegeuk Kim return 0;
790b3783873SJaegeuk Kim
791*9669b28fSQi Han if (!f2fs_is_checkpoint_ready(sbi)) {
792*9669b28fSQi Han f2fs_mark_inode_dirty_sync(inode, true);
7934354994fSDaniel Rosenberg return -ENOSPC;
794*9669b28fSQi Han }
7954354994fSDaniel Rosenberg
79639936837SJaegeuk Kim /*
797c5cd29d2SJaegeuk Kim * We need to balance fs here to prevent from producing dirty node pages
7982c718feeSRuiqi Gong * during the urgent cleaning time when running out of free sections.
79939936837SJaegeuk Kim */
8004d57b86dSChao Yu f2fs_update_inode_page(inode);
801a7881893SJaegeuk Kim if (wbc && wbc->nr_to_write)
8022c4db1a6SJaegeuk Kim f2fs_balance_fs(sbi, true);
803744602cfSJaegeuk Kim return 0;
80419f99ceeSJaegeuk Kim }
80519f99ceeSJaegeuk Kim
8060a8165d7SJaegeuk Kim /*
80719f99ceeSJaegeuk Kim * Called at the last iput() if i_nlink is zero
80819f99ceeSJaegeuk Kim */
f2fs_evict_inode(struct inode * inode)80919f99ceeSJaegeuk Kim void f2fs_evict_inode(struct inode *inode)
81019f99ceeSJaegeuk Kim {
8114081363fSJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
812a46bebd5SDaeho Jeong struct f2fs_inode_info *fi = F2FS_I(inode);
813a46bebd5SDaeho Jeong nid_t xnid = fi->i_xattr_nid;
81413ec7297SChao Yu int err = 0;
81519f99ceeSJaegeuk Kim
8163db1de0eSDaeho Jeong f2fs_abort_atomic_write(inode, true);
81788b88a66SJaegeuk Kim
818b82d4300SSunmin Jeong if (fi->cow_inode && f2fs_is_cow_file(fi->cow_inode)) {
819a46bebd5SDaeho Jeong clear_inode_flag(fi->cow_inode, FI_COW_FILE);
820b82d4300SSunmin Jeong F2FS_I(fi->cow_inode)->atomic_inode = NULL;
821a46bebd5SDaeho Jeong iput(fi->cow_inode);
822a46bebd5SDaeho Jeong fi->cow_inode = NULL;
823a46bebd5SDaeho Jeong }
824a46bebd5SDaeho Jeong
825a2a4a7e4SNamjae Jeon trace_f2fs_evict_inode(inode);
82691b0abe3SJohannes Weiner truncate_inode_pages_final(&inode->i_data);
82719f99ceeSJaegeuk Kim
8282b642898SFengnan Chang if ((inode->i_nlink || is_bad_inode(inode)) &&
8292b642898SFengnan Chang test_opt(sbi, COMPRESS_CACHE) && f2fs_compressed_file(inode))
8306ce19affSChao Yu f2fs_invalidate_compress_pages(sbi, inode->i_ino);
8316ce19affSChao Yu
83219f99ceeSJaegeuk Kim if (inode->i_ino == F2FS_NODE_INO(sbi) ||
8336ce19affSChao Yu inode->i_ino == F2FS_META_INO(sbi) ||
8346ce19affSChao Yu inode->i_ino == F2FS_COMPRESS_INO(sbi))
835dbf20cb2SChao Yu goto out_clear;
83619f99ceeSJaegeuk Kim
837a7ffdbe2SJaegeuk Kim f2fs_bug_on(sbi, get_dirty_pages(inode));
8384d57b86dSChao Yu f2fs_remove_dirty_inode(inode);
83919f99ceeSJaegeuk Kim
8403e72f721SJaegeuk Kim f2fs_destroy_extent_tree(inode);
8413e72f721SJaegeuk Kim
84219f99ceeSJaegeuk Kim if (inode->i_nlink || is_bad_inode(inode))
84319f99ceeSJaegeuk Kim goto no_delete;
84419f99ceeSJaegeuk Kim
84510a26878SChao Yu err = f2fs_dquot_initialize(inode);
846af033b2aSChao Yu if (err) {
847af033b2aSChao Yu err = 0;
848af033b2aSChao Yu set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
849af033b2aSChao Yu }
8500abd675eSChao Yu
8514d57b86dSChao Yu f2fs_remove_ino_entry(sbi, inode->i_ino, APPEND_INO);
8524d57b86dSChao Yu f2fs_remove_ino_entry(sbi, inode->i_ino, UPDATE_INO);
8534d57b86dSChao Yu f2fs_remove_ino_entry(sbi, inode->i_ino, FLUSH_INO);
85460dcedc9SChao Yu
855ba900534SJaegeuk Kim if (!is_sbi_flag_set(sbi, SBI_IS_FREEZING))
856d6212a5fSChangman Lee sb_start_intwrite(inode->i_sb);
85791942321SJaegeuk Kim set_inode_flag(inode, FI_NO_ALLOC);
85819f99ceeSJaegeuk Kim i_size_write(inode, 0);
8594c0c2949SJaegeuk Kim retry:
86019f99ceeSJaegeuk Kim if (F2FS_HAS_BLOCKS(inode))
8619a449e9cSJaegeuk Kim err = f2fs_truncate(inode);
86219f99ceeSJaegeuk Kim
863c40e15a9SYangtao Li if (time_to_inject(sbi, FAULT_EVICT_INODE))
8648c1b3c0fSJaegeuk Kim err = -EIO;
8657fa750a1SArnd Bergmann
86613ec7297SChao Yu if (!err) {
867e479556bSGu Zheng f2fs_lock_op(sbi);
8684d57b86dSChao Yu err = f2fs_remove_inode_page(inode);
869e479556bSGu Zheng f2fs_unlock_op(sbi);
870f2db7105SChao Yu if (err == -ENOENT) {
871a11b9f65SChao Yu err = 0;
872f2db7105SChao Yu
873f2db7105SChao Yu /*
874f2db7105SChao Yu * in fuzzed image, another node may has the same
875f2db7105SChao Yu * block address as inode's, if it was truncated
876f2db7105SChao Yu * previously, truncation of inode node will fail.
877f2db7105SChao Yu */
878f2db7105SChao Yu if (is_inode_flag_set(inode, FI_DIRTY_INODE)) {
879f2db7105SChao Yu f2fs_warn(F2FS_I_SB(inode),
880f2db7105SChao Yu "f2fs_evict_inode: inconsistent node id, ino:%lu",
881f2db7105SChao Yu inode->i_ino);
882f2db7105SChao Yu f2fs_inode_synced(inode);
883f2db7105SChao Yu set_sbi_flag(sbi, SBI_NEED_FSCK);
884f2db7105SChao Yu }
885f2db7105SChao Yu }
88613ec7297SChao Yu }
88739936837SJaegeuk Kim
8884c0c2949SJaegeuk Kim /* give more chances, if ENOMEM case */
8894c0c2949SJaegeuk Kim if (err == -ENOMEM) {
8904c0c2949SJaegeuk Kim err = 0;
8914c0c2949SJaegeuk Kim goto retry;
8924c0c2949SJaegeuk Kim }
8934c0c2949SJaegeuk Kim
894af033b2aSChao Yu if (err) {
8954d57b86dSChao Yu f2fs_update_inode_page(inode);
8960f1898f9SChao Yu if (dquot_initialize_needed(inode))
897af033b2aSChao Yu set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
898af033b2aSChao Yu }
899ba900534SJaegeuk Kim if (!is_sbi_flag_set(sbi, SBI_IS_FREEZING))
900d6212a5fSChangman Lee sb_end_intwrite(inode->i_sb);
90119f99ceeSJaegeuk Kim no_delete:
9020abd675eSChao Yu dquot_drop(inode);
9030abd675eSChao Yu
904d5e8f6c9SChao Yu stat_dec_inline_xattr(inode);
9053289c061SJaegeuk Kim stat_dec_inline_dir(inode);
906e7a2bf22SJaegeuk Kim stat_dec_inline_inode(inode);
9074c8ff709SChao Yu stat_dec_compr_inode(inode);
908c2759ebaSDaeho Jeong stat_sub_compr_blocks(inode,
909a46bebd5SDaeho Jeong atomic_read(&fi->i_compr_blocks));
9100bdee482SChao Yu
91133ac18a1SChao Yu if (likely(!f2fs_cp_error(sbi) &&
9124354994fSDaniel Rosenberg !is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
913ca7d802aSChao Yu f2fs_bug_on(sbi, is_inode_flag_set(inode, FI_DIRTY_INODE));
914943973cdSJaegeuk Kim else
915943973cdSJaegeuk Kim f2fs_inode_synced(inode);
916ca7d802aSChao Yu
9177a88ddb5SChao Yu /* for the case f2fs_new_inode() was failed, .i_ino is zero, skip it */
9184f295443SJaegeuk Kim if (inode->i_ino)
9194f295443SJaegeuk Kim invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino,
9204f295443SJaegeuk Kim inode->i_ino);
921002a41caSChao Yu if (xnid)
922002a41caSChao Yu invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid);
92360dcedc9SChao Yu if (inode->i_nlink) {
92491942321SJaegeuk Kim if (is_inode_flag_set(inode, FI_APPEND_WRITE))
9254d57b86dSChao Yu f2fs_add_ino_entry(sbi, inode->i_ino, APPEND_INO);
92691942321SJaegeuk Kim if (is_inode_flag_set(inode, FI_UPDATE_WRITE))
9274d57b86dSChao Yu f2fs_add_ino_entry(sbi, inode->i_ino, UPDATE_INO);
92860dcedc9SChao Yu }
92991942321SJaegeuk Kim if (is_inode_flag_set(inode, FI_FREE_NID)) {
9304d57b86dSChao Yu f2fs_alloc_nid_failed(sbi, inode->i_ino);
93191942321SJaegeuk Kim clear_inode_flag(inode, FI_FREE_NID);
932d8c4256cSJaegeuk Kim } else {
933a4f843bdSJaegeuk Kim /*
934a4f843bdSJaegeuk Kim * If xattr nid is corrupted, we can reach out error condition,
9354d57b86dSChao Yu * err & !f2fs_exist_written_data(sbi, inode->i_ino, ORPHAN_INO)).
9364d57b86dSChao Yu * In that case, f2fs_check_nid_range() is enough to give a clue.
937a4f843bdSJaegeuk Kim */
938d8c4256cSJaegeuk Kim }
939dbf20cb2SChao Yu out_clear:
9403d204e24SEric Biggers fscrypt_put_encryption_info(inode);
94195ae251fSEric Biggers fsverity_cleanup_inode(inode);
942dbf20cb2SChao Yu clear_inode(inode);
94319f99ceeSJaegeuk Kim }
94444c16156SJaegeuk Kim
94544c16156SJaegeuk Kim /* caller should call f2fs_lock_op() */
f2fs_handle_failed_inode(struct inode * inode)9464d57b86dSChao Yu void f2fs_handle_failed_inode(struct inode *inode)
94744c16156SJaegeuk Kim {
94844c16156SJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
949221149c0SJaegeuk Kim struct node_info ni;
9507735730dSChao Yu int err;
95144c16156SJaegeuk Kim
952a11b9f65SChao Yu /*
953a11b9f65SChao Yu * clear nlink of inode in order to release resource of inode
954a11b9f65SChao Yu * immediately.
955a11b9f65SChao Yu */
956a11b9f65SChao Yu clear_nlink(inode);
957a11b9f65SChao Yu
958a11b9f65SChao Yu /*
959a11b9f65SChao Yu * we must call this to avoid inode being remained as dirty, resulting
960a11b9f65SChao Yu * in a panic when flushing dirty inodes in gdirty_list.
961a11b9f65SChao Yu */
9624d57b86dSChao Yu f2fs_update_inode_page(inode);
9639bb02c36SJaegeuk Kim f2fs_inode_synced(inode);
964a11b9f65SChao Yu
965221149c0SJaegeuk Kim /* don't make bad inode, since it becomes a regular file. */
96644c16156SJaegeuk Kim unlock_new_inode(inode);
96744c16156SJaegeuk Kim
96813ec7297SChao Yu /*
96913ec7297SChao Yu * Note: we should add inode to orphan list before f2fs_unlock_op()
97013ec7297SChao Yu * so we can prevent losing this orphan when encoutering checkpoint
97113ec7297SChao Yu * and following suddenly power-off.
97213ec7297SChao Yu */
973a9419b63SJaegeuk Kim err = f2fs_get_node_info(sbi, inode->i_ino, &ni, false);
9747735730dSChao Yu if (err) {
9757735730dSChao Yu set_sbi_flag(sbi, SBI_NEED_FSCK);
9762fef99b8SJaegeuk Kim set_inode_flag(inode, FI_FREE_NID);
977dcbb4c10SJoe Perches f2fs_warn(sbi, "May loss orphan inode, run fsck to fix.");
9787735730dSChao Yu goto out;
9797735730dSChao Yu }
980221149c0SJaegeuk Kim
981221149c0SJaegeuk Kim if (ni.blk_addr != NULL_ADDR) {
9827735730dSChao Yu err = f2fs_acquire_orphan_inode(sbi);
983221149c0SJaegeuk Kim if (err) {
984221149c0SJaegeuk Kim set_sbi_flag(sbi, SBI_NEED_FSCK);
985dcbb4c10SJoe Perches f2fs_warn(sbi, "Too many orphan inodes, run fsck to fix.");
986221149c0SJaegeuk Kim } else {
9874d57b86dSChao Yu f2fs_add_orphan_inode(inode);
98813ec7297SChao Yu }
9894d57b86dSChao Yu f2fs_alloc_nid_done(sbi, inode->i_ino);
990221149c0SJaegeuk Kim } else {
99191942321SJaegeuk Kim set_inode_flag(inode, FI_FREE_NID);
992221149c0SJaegeuk Kim }
993221149c0SJaegeuk Kim
9947735730dSChao Yu out:
99544c16156SJaegeuk Kim f2fs_unlock_op(sbi);
99644c16156SJaegeuk Kim
99744c16156SJaegeuk Kim /* iput will drop the inode object */
99844c16156SJaegeuk Kim iput(inode);
99944c16156SJaegeuk Kim }
1000