18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * fs/f2fs/inline.c
48c2ecf20Sopenharmony_ci * Copyright (c) 2013, Intel Corporation
58c2ecf20Sopenharmony_ci * Authors: Huajun Li <huajun.li@intel.com>
68c2ecf20Sopenharmony_ci *          Haicheng Li <haicheng.li@intel.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/fs.h>
108c2ecf20Sopenharmony_ci#include <linux/f2fs_fs.h>
118c2ecf20Sopenharmony_ci#include <linux/fiemap.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "f2fs.h"
148c2ecf20Sopenharmony_ci#include "node.h"
158c2ecf20Sopenharmony_ci#include <trace/events/f2fs.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cistatic bool support_inline_data(struct inode *inode)
188c2ecf20Sopenharmony_ci{
198c2ecf20Sopenharmony_ci	if (f2fs_is_atomic_file(inode))
208c2ecf20Sopenharmony_ci		return false;
218c2ecf20Sopenharmony_ci	if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode))
228c2ecf20Sopenharmony_ci		return false;
238c2ecf20Sopenharmony_ci	if (i_size_read(inode) > MAX_INLINE_DATA(inode))
248c2ecf20Sopenharmony_ci		return false;
258c2ecf20Sopenharmony_ci	return true;
268c2ecf20Sopenharmony_ci}
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cibool f2fs_may_inline_data(struct inode *inode)
298c2ecf20Sopenharmony_ci{
308c2ecf20Sopenharmony_ci	if (!support_inline_data(inode))
318c2ecf20Sopenharmony_ci		return false;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	return !f2fs_post_read_required(inode);
348c2ecf20Sopenharmony_ci}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cibool f2fs_sanity_check_inline_data(struct inode *inode)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	if (!f2fs_has_inline_data(inode))
398c2ecf20Sopenharmony_ci		return false;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	if (!support_inline_data(inode))
428c2ecf20Sopenharmony_ci		return true;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	/*
458c2ecf20Sopenharmony_ci	 * used by sanity_check_inode(), when disk layout fields has not
468c2ecf20Sopenharmony_ci	 * been synchronized to inmem fields.
478c2ecf20Sopenharmony_ci	 */
488c2ecf20Sopenharmony_ci	return (S_ISREG(inode->i_mode) &&
498c2ecf20Sopenharmony_ci		(file_is_encrypt(inode) || file_is_verity(inode) ||
508c2ecf20Sopenharmony_ci		(F2FS_I(inode)->i_flags & F2FS_COMPR_FL)));
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cibool f2fs_may_inline_dentry(struct inode *inode)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	if (!test_opt(F2FS_I_SB(inode), INLINE_DENTRY))
568c2ecf20Sopenharmony_ci		return false;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	if (!S_ISDIR(inode->i_mode))
598c2ecf20Sopenharmony_ci		return false;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	return true;
628c2ecf20Sopenharmony_ci}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_civoid f2fs_do_read_inline_data(struct page *page, struct page *ipage)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	struct inode *inode = page->mapping->host;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	if (PageUptodate(page))
698c2ecf20Sopenharmony_ci		return;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	f2fs_bug_on(F2FS_P_SB(page), page->index);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	zero_user_segment(page, MAX_INLINE_DATA(inode), PAGE_SIZE);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	/* Copy the whole inline data block */
768c2ecf20Sopenharmony_ci	memcpy_to_page(page, 0, inline_data_addr(inode, ipage),
778c2ecf20Sopenharmony_ci		       MAX_INLINE_DATA(inode));
788c2ecf20Sopenharmony_ci	if (!PageUptodate(page))
798c2ecf20Sopenharmony_ci		SetPageUptodate(page);
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_civoid f2fs_truncate_inline_inode(struct inode *inode,
838c2ecf20Sopenharmony_ci					struct page *ipage, u64 from)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	void *addr;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	if (from >= MAX_INLINE_DATA(inode))
888c2ecf20Sopenharmony_ci		return;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	addr = inline_data_addr(inode, ipage);
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(ipage, NODE, true, true);
938c2ecf20Sopenharmony_ci	memset(addr + from, 0, MAX_INLINE_DATA(inode) - from);
948c2ecf20Sopenharmony_ci	set_page_dirty(ipage);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	if (from == 0)
978c2ecf20Sopenharmony_ci		clear_inode_flag(inode, FI_DATA_EXIST);
988c2ecf20Sopenharmony_ci}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ciint f2fs_read_inline_data(struct inode *inode, struct page *page)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	struct page *ipage;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino);
1058c2ecf20Sopenharmony_ci	if (IS_ERR(ipage)) {
1068c2ecf20Sopenharmony_ci		unlock_page(page);
1078c2ecf20Sopenharmony_ci		return PTR_ERR(ipage);
1088c2ecf20Sopenharmony_ci	}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	if (!f2fs_has_inline_data(inode)) {
1118c2ecf20Sopenharmony_ci		f2fs_put_page(ipage, 1);
1128c2ecf20Sopenharmony_ci		return -EAGAIN;
1138c2ecf20Sopenharmony_ci	}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	if (page->index)
1168c2ecf20Sopenharmony_ci		zero_user_segment(page, 0, PAGE_SIZE);
1178c2ecf20Sopenharmony_ci	else
1188c2ecf20Sopenharmony_ci		f2fs_do_read_inline_data(page, ipage);
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	if (!PageUptodate(page))
1218c2ecf20Sopenharmony_ci		SetPageUptodate(page);
1228c2ecf20Sopenharmony_ci	f2fs_put_page(ipage, 1);
1238c2ecf20Sopenharmony_ci	unlock_page(page);
1248c2ecf20Sopenharmony_ci	return 0;
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ciint f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	struct f2fs_io_info fio = {
1308c2ecf20Sopenharmony_ci		.sbi = F2FS_I_SB(dn->inode),
1318c2ecf20Sopenharmony_ci		.ino = dn->inode->i_ino,
1328c2ecf20Sopenharmony_ci		.type = DATA,
1338c2ecf20Sopenharmony_ci		.op = REQ_OP_WRITE,
1348c2ecf20Sopenharmony_ci		.op_flags = REQ_SYNC | REQ_PRIO,
1358c2ecf20Sopenharmony_ci		.page = page,
1368c2ecf20Sopenharmony_ci		.encrypted_page = NULL,
1378c2ecf20Sopenharmony_ci		.io_type = FS_DATA_IO,
1388c2ecf20Sopenharmony_ci	};
1398c2ecf20Sopenharmony_ci	struct node_info ni;
1408c2ecf20Sopenharmony_ci	int dirty, err;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	if (!f2fs_exist_data(dn->inode))
1438c2ecf20Sopenharmony_ci		goto clear_out;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	err = f2fs_reserve_block(dn, 0);
1468c2ecf20Sopenharmony_ci	if (err)
1478c2ecf20Sopenharmony_ci		return err;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	err = f2fs_get_node_info(fio.sbi, dn->nid, &ni);
1508c2ecf20Sopenharmony_ci	if (err) {
1518c2ecf20Sopenharmony_ci		f2fs_truncate_data_blocks_range(dn, 1);
1528c2ecf20Sopenharmony_ci		f2fs_put_dnode(dn);
1538c2ecf20Sopenharmony_ci		return err;
1548c2ecf20Sopenharmony_ci	}
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	fio.version = ni.version;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	if (unlikely(dn->data_blkaddr != NEW_ADDR)) {
1598c2ecf20Sopenharmony_ci		f2fs_put_dnode(dn);
1608c2ecf20Sopenharmony_ci		set_sbi_flag(fio.sbi, SBI_NEED_FSCK);
1618c2ecf20Sopenharmony_ci		f2fs_warn(fio.sbi, "%s: corrupted inline inode ino=%lx, i_addr[0]:0x%x, run fsck to fix.",
1628c2ecf20Sopenharmony_ci			  __func__, dn->inode->i_ino, dn->data_blkaddr);
1638c2ecf20Sopenharmony_ci		return -EFSCORRUPTED;
1648c2ecf20Sopenharmony_ci	}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	f2fs_bug_on(F2FS_P_SB(page), PageWriteback(page));
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	f2fs_do_read_inline_data(page, dn->inode_page);
1698c2ecf20Sopenharmony_ci	set_page_dirty(page);
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	/* clear dirty state */
1728c2ecf20Sopenharmony_ci	dirty = clear_page_dirty_for_io(page);
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	/* write data page to try to make data consistent */
1758c2ecf20Sopenharmony_ci	set_page_writeback(page);
1768c2ecf20Sopenharmony_ci	ClearPageError(page);
1778c2ecf20Sopenharmony_ci	fio.old_blkaddr = dn->data_blkaddr;
1788c2ecf20Sopenharmony_ci	set_inode_flag(dn->inode, FI_HOT_DATA);
1798c2ecf20Sopenharmony_ci	f2fs_outplace_write_data(dn, &fio);
1808c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(page, DATA, true, true);
1818c2ecf20Sopenharmony_ci	if (dirty) {
1828c2ecf20Sopenharmony_ci		inode_dec_dirty_pages(dn->inode);
1838c2ecf20Sopenharmony_ci		f2fs_remove_dirty_inode(dn->inode);
1848c2ecf20Sopenharmony_ci	}
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	/* this converted inline_data should be recovered. */
1878c2ecf20Sopenharmony_ci	set_inode_flag(dn->inode, FI_APPEND_WRITE);
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	/* clear inline data and flag after data writeback */
1908c2ecf20Sopenharmony_ci	f2fs_truncate_inline_inode(dn->inode, dn->inode_page, 0);
1918c2ecf20Sopenharmony_ci	clear_inline_node(dn->inode_page);
1928c2ecf20Sopenharmony_ciclear_out:
1938c2ecf20Sopenharmony_ci	stat_dec_inline_inode(dn->inode);
1948c2ecf20Sopenharmony_ci	clear_inode_flag(dn->inode, FI_INLINE_DATA);
1958c2ecf20Sopenharmony_ci	f2fs_put_dnode(dn);
1968c2ecf20Sopenharmony_ci	return 0;
1978c2ecf20Sopenharmony_ci}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ciint f2fs_convert_inline_inode(struct inode *inode)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
2028c2ecf20Sopenharmony_ci	struct dnode_of_data dn;
2038c2ecf20Sopenharmony_ci	struct page *ipage, *page;
2048c2ecf20Sopenharmony_ci	int err = 0;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	if (!f2fs_has_inline_data(inode))
2078c2ecf20Sopenharmony_ci		return 0;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	err = dquot_initialize(inode);
2108c2ecf20Sopenharmony_ci	if (err)
2118c2ecf20Sopenharmony_ci		return err;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	page = f2fs_grab_cache_page(inode->i_mapping, 0, false);
2148c2ecf20Sopenharmony_ci	if (!page)
2158c2ecf20Sopenharmony_ci		return -ENOMEM;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	f2fs_lock_op(sbi);
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	ipage = f2fs_get_node_page(sbi, inode->i_ino);
2208c2ecf20Sopenharmony_ci	if (IS_ERR(ipage)) {
2218c2ecf20Sopenharmony_ci		err = PTR_ERR(ipage);
2228c2ecf20Sopenharmony_ci		goto out;
2238c2ecf20Sopenharmony_ci	}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	set_new_dnode(&dn, inode, ipage, ipage, 0);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	if (f2fs_has_inline_data(inode))
2288c2ecf20Sopenharmony_ci		err = f2fs_convert_inline_page(&dn, page);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	f2fs_put_dnode(&dn);
2318c2ecf20Sopenharmony_ciout:
2328c2ecf20Sopenharmony_ci	f2fs_unlock_op(sbi);
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	f2fs_put_page(page, 1);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	if (!err)
2378c2ecf20Sopenharmony_ci		f2fs_balance_fs(sbi, dn.node_changed);
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	return err;
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ciint f2fs_write_inline_data(struct inode *inode, struct page *page)
2438c2ecf20Sopenharmony_ci{
2448c2ecf20Sopenharmony_ci	struct dnode_of_data dn;
2458c2ecf20Sopenharmony_ci	int err;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	set_new_dnode(&dn, inode, NULL, NULL, 0);
2488c2ecf20Sopenharmony_ci	err = f2fs_get_dnode_of_data(&dn, 0, LOOKUP_NODE);
2498c2ecf20Sopenharmony_ci	if (err)
2508c2ecf20Sopenharmony_ci		return err;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	if (!f2fs_has_inline_data(inode)) {
2538c2ecf20Sopenharmony_ci		f2fs_put_dnode(&dn);
2548c2ecf20Sopenharmony_ci		return -EAGAIN;
2558c2ecf20Sopenharmony_ci	}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	f2fs_bug_on(F2FS_I_SB(inode), page->index);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(dn.inode_page, NODE, true, true);
2608c2ecf20Sopenharmony_ci	memcpy_from_page(inline_data_addr(inode, dn.inode_page),
2618c2ecf20Sopenharmony_ci			 page, 0, MAX_INLINE_DATA(inode));
2628c2ecf20Sopenharmony_ci	set_page_dirty(dn.inode_page);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	f2fs_clear_page_cache_dirty_tag(page);
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	set_inode_flag(inode, FI_APPEND_WRITE);
2678c2ecf20Sopenharmony_ci	set_inode_flag(inode, FI_DATA_EXIST);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	clear_inline_node(dn.inode_page);
2708c2ecf20Sopenharmony_ci	f2fs_put_dnode(&dn);
2718c2ecf20Sopenharmony_ci	return 0;
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ciint f2fs_recover_inline_data(struct inode *inode, struct page *npage)
2758c2ecf20Sopenharmony_ci{
2768c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
2778c2ecf20Sopenharmony_ci	struct f2fs_inode *ri = NULL;
2788c2ecf20Sopenharmony_ci	void *src_addr, *dst_addr;
2798c2ecf20Sopenharmony_ci	struct page *ipage;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	/*
2828c2ecf20Sopenharmony_ci	 * The inline_data recovery policy is as follows.
2838c2ecf20Sopenharmony_ci	 * [prev.] [next] of inline_data flag
2848c2ecf20Sopenharmony_ci	 *    o       o  -> recover inline_data
2858c2ecf20Sopenharmony_ci	 *    o       x  -> remove inline_data, and then recover data blocks
2868c2ecf20Sopenharmony_ci	 *    x       o  -> remove inline_data, and then recover inline_data
2878c2ecf20Sopenharmony_ci	 *    x       x  -> recover data blocks
2888c2ecf20Sopenharmony_ci	 */
2898c2ecf20Sopenharmony_ci	if (IS_INODE(npage))
2908c2ecf20Sopenharmony_ci		ri = F2FS_INODE(npage);
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	if (f2fs_has_inline_data(inode) &&
2938c2ecf20Sopenharmony_ci			ri && (ri->i_inline & F2FS_INLINE_DATA)) {
2948c2ecf20Sopenharmony_ciprocess_inline:
2958c2ecf20Sopenharmony_ci		ipage = f2fs_get_node_page(sbi, inode->i_ino);
2968c2ecf20Sopenharmony_ci		if (IS_ERR(ipage))
2978c2ecf20Sopenharmony_ci			return PTR_ERR(ipage);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci		f2fs_wait_on_page_writeback(ipage, NODE, true, true);
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci		src_addr = inline_data_addr(inode, npage);
3028c2ecf20Sopenharmony_ci		dst_addr = inline_data_addr(inode, ipage);
3038c2ecf20Sopenharmony_ci		memcpy(dst_addr, src_addr, MAX_INLINE_DATA(inode));
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci		set_inode_flag(inode, FI_INLINE_DATA);
3068c2ecf20Sopenharmony_ci		set_inode_flag(inode, FI_DATA_EXIST);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci		set_page_dirty(ipage);
3098c2ecf20Sopenharmony_ci		f2fs_put_page(ipage, 1);
3108c2ecf20Sopenharmony_ci		return 1;
3118c2ecf20Sopenharmony_ci	}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	if (f2fs_has_inline_data(inode)) {
3148c2ecf20Sopenharmony_ci		ipage = f2fs_get_node_page(sbi, inode->i_ino);
3158c2ecf20Sopenharmony_ci		if (IS_ERR(ipage))
3168c2ecf20Sopenharmony_ci			return PTR_ERR(ipage);
3178c2ecf20Sopenharmony_ci		f2fs_truncate_inline_inode(inode, ipage, 0);
3188c2ecf20Sopenharmony_ci		clear_inode_flag(inode, FI_INLINE_DATA);
3198c2ecf20Sopenharmony_ci		f2fs_put_page(ipage, 1);
3208c2ecf20Sopenharmony_ci	} else if (ri && (ri->i_inline & F2FS_INLINE_DATA)) {
3218c2ecf20Sopenharmony_ci		int ret;
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci		ret = f2fs_truncate_blocks(inode, 0, false);
3248c2ecf20Sopenharmony_ci		if (ret)
3258c2ecf20Sopenharmony_ci			return ret;
3268c2ecf20Sopenharmony_ci		goto process_inline;
3278c2ecf20Sopenharmony_ci	}
3288c2ecf20Sopenharmony_ci	return 0;
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_cistruct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir,
3328c2ecf20Sopenharmony_ci					const struct f2fs_filename *fname,
3338c2ecf20Sopenharmony_ci					struct page **res_page)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
3368c2ecf20Sopenharmony_ci	struct f2fs_dir_entry *de;
3378c2ecf20Sopenharmony_ci	struct f2fs_dentry_ptr d;
3388c2ecf20Sopenharmony_ci	struct page *ipage;
3398c2ecf20Sopenharmony_ci	void *inline_dentry;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	ipage = f2fs_get_node_page(sbi, dir->i_ino);
3428c2ecf20Sopenharmony_ci	if (IS_ERR(ipage)) {
3438c2ecf20Sopenharmony_ci		*res_page = ipage;
3448c2ecf20Sopenharmony_ci		return NULL;
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	inline_dentry = inline_data_addr(dir, ipage);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	make_dentry_ptr_inline(dir, &d, inline_dentry);
3508c2ecf20Sopenharmony_ci	de = f2fs_find_target_dentry(&d, fname, NULL);
3518c2ecf20Sopenharmony_ci	unlock_page(ipage);
3528c2ecf20Sopenharmony_ci	if (de)
3538c2ecf20Sopenharmony_ci		*res_page = ipage;
3548c2ecf20Sopenharmony_ci	else
3558c2ecf20Sopenharmony_ci		f2fs_put_page(ipage, 0);
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	return de;
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ciint f2fs_make_empty_inline_dir(struct inode *inode, struct inode *parent,
3618c2ecf20Sopenharmony_ci							struct page *ipage)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	struct f2fs_dentry_ptr d;
3648c2ecf20Sopenharmony_ci	void *inline_dentry;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	inline_dentry = inline_data_addr(inode, ipage);
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	make_dentry_ptr_inline(inode, &d, inline_dentry);
3698c2ecf20Sopenharmony_ci	f2fs_do_make_empty_dir(inode, parent, &d);
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	set_page_dirty(ipage);
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	/* update i_size to MAX_INLINE_DATA */
3748c2ecf20Sopenharmony_ci	if (i_size_read(inode) < MAX_INLINE_DATA(inode))
3758c2ecf20Sopenharmony_ci		f2fs_i_size_write(inode, MAX_INLINE_DATA(inode));
3768c2ecf20Sopenharmony_ci	return 0;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci/*
3808c2ecf20Sopenharmony_ci * NOTE: ipage is grabbed by caller, but if any error occurs, we should
3818c2ecf20Sopenharmony_ci * release ipage in this function.
3828c2ecf20Sopenharmony_ci */
3838c2ecf20Sopenharmony_cistatic int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,
3848c2ecf20Sopenharmony_ci							void *inline_dentry)
3858c2ecf20Sopenharmony_ci{
3868c2ecf20Sopenharmony_ci	struct page *page;
3878c2ecf20Sopenharmony_ci	struct dnode_of_data dn;
3888c2ecf20Sopenharmony_ci	struct f2fs_dentry_block *dentry_blk;
3898c2ecf20Sopenharmony_ci	struct f2fs_dentry_ptr src, dst;
3908c2ecf20Sopenharmony_ci	int err;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	page = f2fs_grab_cache_page(dir->i_mapping, 0, true);
3938c2ecf20Sopenharmony_ci	if (!page) {
3948c2ecf20Sopenharmony_ci		f2fs_put_page(ipage, 1);
3958c2ecf20Sopenharmony_ci		return -ENOMEM;
3968c2ecf20Sopenharmony_ci	}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	set_new_dnode(&dn, dir, ipage, NULL, 0);
3998c2ecf20Sopenharmony_ci	err = f2fs_reserve_block(&dn, 0);
4008c2ecf20Sopenharmony_ci	if (err)
4018c2ecf20Sopenharmony_ci		goto out;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	if (unlikely(dn.data_blkaddr != NEW_ADDR)) {
4048c2ecf20Sopenharmony_ci		f2fs_put_dnode(&dn);
4058c2ecf20Sopenharmony_ci		set_sbi_flag(F2FS_P_SB(page), SBI_NEED_FSCK);
4068c2ecf20Sopenharmony_ci		f2fs_warn(F2FS_P_SB(page), "%s: corrupted inline inode ino=%lx, i_addr[0]:0x%x, run fsck to fix.",
4078c2ecf20Sopenharmony_ci			  __func__, dir->i_ino, dn.data_blkaddr);
4088c2ecf20Sopenharmony_ci		err = -EFSCORRUPTED;
4098c2ecf20Sopenharmony_ci		goto out;
4108c2ecf20Sopenharmony_ci	}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(page, DATA, true, true);
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	dentry_blk = page_address(page);
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	/*
4178c2ecf20Sopenharmony_ci	 * Start by zeroing the full block, to ensure that all unused space is
4188c2ecf20Sopenharmony_ci	 * zeroed and no uninitialized memory is leaked to disk.
4198c2ecf20Sopenharmony_ci	 */
4208c2ecf20Sopenharmony_ci	memset(dentry_blk, 0, F2FS_BLKSIZE);
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	make_dentry_ptr_inline(dir, &src, inline_dentry);
4238c2ecf20Sopenharmony_ci	make_dentry_ptr_block(dir, &dst, dentry_blk);
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	/* copy data from inline dentry block to new dentry block */
4268c2ecf20Sopenharmony_ci	memcpy(dst.bitmap, src.bitmap, src.nr_bitmap);
4278c2ecf20Sopenharmony_ci	memcpy(dst.dentry, src.dentry, SIZE_OF_DIR_ENTRY * src.max);
4288c2ecf20Sopenharmony_ci	memcpy(dst.filename, src.filename, src.max * F2FS_SLOT_LEN);
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	if (!PageUptodate(page))
4318c2ecf20Sopenharmony_ci		SetPageUptodate(page);
4328c2ecf20Sopenharmony_ci	set_page_dirty(page);
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	/* clear inline dir and flag after data writeback */
4358c2ecf20Sopenharmony_ci	f2fs_truncate_inline_inode(dir, ipage, 0);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	stat_dec_inline_dir(dir);
4388c2ecf20Sopenharmony_ci	clear_inode_flag(dir, FI_INLINE_DENTRY);
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	/*
4418c2ecf20Sopenharmony_ci	 * should retrieve reserved space which was used to keep
4428c2ecf20Sopenharmony_ci	 * inline_dentry's structure for backward compatibility.
4438c2ecf20Sopenharmony_ci	 */
4448c2ecf20Sopenharmony_ci	if (!f2fs_sb_has_flexible_inline_xattr(F2FS_I_SB(dir)) &&
4458c2ecf20Sopenharmony_ci			!f2fs_has_inline_xattr(dir))
4468c2ecf20Sopenharmony_ci		F2FS_I(dir)->i_inline_xattr_size = 0;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	f2fs_i_depth_write(dir, 1);
4498c2ecf20Sopenharmony_ci	if (i_size_read(dir) < PAGE_SIZE)
4508c2ecf20Sopenharmony_ci		f2fs_i_size_write(dir, PAGE_SIZE);
4518c2ecf20Sopenharmony_ciout:
4528c2ecf20Sopenharmony_ci	f2fs_put_page(page, 1);
4538c2ecf20Sopenharmony_ci	return err;
4548c2ecf20Sopenharmony_ci}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_cistatic int f2fs_add_inline_entries(struct inode *dir, void *inline_dentry)
4578c2ecf20Sopenharmony_ci{
4588c2ecf20Sopenharmony_ci	struct f2fs_dentry_ptr d;
4598c2ecf20Sopenharmony_ci	unsigned long bit_pos = 0;
4608c2ecf20Sopenharmony_ci	int err = 0;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	make_dentry_ptr_inline(dir, &d, inline_dentry);
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	while (bit_pos < d.max) {
4658c2ecf20Sopenharmony_ci		struct f2fs_dir_entry *de;
4668c2ecf20Sopenharmony_ci		struct f2fs_filename fname;
4678c2ecf20Sopenharmony_ci		nid_t ino;
4688c2ecf20Sopenharmony_ci		umode_t fake_mode;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci		if (!test_bit_le(bit_pos, d.bitmap)) {
4718c2ecf20Sopenharmony_ci			bit_pos++;
4728c2ecf20Sopenharmony_ci			continue;
4738c2ecf20Sopenharmony_ci		}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci		de = &d.dentry[bit_pos];
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci		if (unlikely(!de->name_len)) {
4788c2ecf20Sopenharmony_ci			bit_pos++;
4798c2ecf20Sopenharmony_ci			continue;
4808c2ecf20Sopenharmony_ci		}
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci		/*
4838c2ecf20Sopenharmony_ci		 * We only need the disk_name and hash to move the dentry.
4848c2ecf20Sopenharmony_ci		 * We don't need the original or casefolded filenames.
4858c2ecf20Sopenharmony_ci		 */
4868c2ecf20Sopenharmony_ci		memset(&fname, 0, sizeof(fname));
4878c2ecf20Sopenharmony_ci		fname.disk_name.name = d.filename[bit_pos];
4888c2ecf20Sopenharmony_ci		fname.disk_name.len = le16_to_cpu(de->name_len);
4898c2ecf20Sopenharmony_ci		fname.hash = de->hash_code;
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci		ino = le32_to_cpu(de->ino);
4928c2ecf20Sopenharmony_ci		fake_mode = f2fs_get_de_type(de) << S_SHIFT;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci		err = f2fs_add_regular_entry(dir, &fname, NULL, ino, fake_mode);
4958c2ecf20Sopenharmony_ci		if (err)
4968c2ecf20Sopenharmony_ci			goto punch_dentry_pages;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci		bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
4998c2ecf20Sopenharmony_ci	}
5008c2ecf20Sopenharmony_ci	return 0;
5018c2ecf20Sopenharmony_cipunch_dentry_pages:
5028c2ecf20Sopenharmony_ci	truncate_inode_pages(&dir->i_data, 0);
5038c2ecf20Sopenharmony_ci	f2fs_truncate_blocks(dir, 0, false);
5048c2ecf20Sopenharmony_ci	f2fs_remove_dirty_inode(dir);
5058c2ecf20Sopenharmony_ci	return err;
5068c2ecf20Sopenharmony_ci}
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_cistatic int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage,
5098c2ecf20Sopenharmony_ci							void *inline_dentry)
5108c2ecf20Sopenharmony_ci{
5118c2ecf20Sopenharmony_ci	void *backup_dentry;
5128c2ecf20Sopenharmony_ci	int err;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	backup_dentry = f2fs_kmalloc(F2FS_I_SB(dir),
5158c2ecf20Sopenharmony_ci				MAX_INLINE_DATA(dir), GFP_F2FS_ZERO);
5168c2ecf20Sopenharmony_ci	if (!backup_dentry) {
5178c2ecf20Sopenharmony_ci		f2fs_put_page(ipage, 1);
5188c2ecf20Sopenharmony_ci		return -ENOMEM;
5198c2ecf20Sopenharmony_ci	}
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	memcpy(backup_dentry, inline_dentry, MAX_INLINE_DATA(dir));
5228c2ecf20Sopenharmony_ci	f2fs_truncate_inline_inode(dir, ipage, 0);
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	unlock_page(ipage);
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	err = f2fs_add_inline_entries(dir, backup_dentry);
5278c2ecf20Sopenharmony_ci	if (err)
5288c2ecf20Sopenharmony_ci		goto recover;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	lock_page(ipage);
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	stat_dec_inline_dir(dir);
5338c2ecf20Sopenharmony_ci	clear_inode_flag(dir, FI_INLINE_DENTRY);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	/*
5368c2ecf20Sopenharmony_ci	 * should retrieve reserved space which was used to keep
5378c2ecf20Sopenharmony_ci	 * inline_dentry's structure for backward compatibility.
5388c2ecf20Sopenharmony_ci	 */
5398c2ecf20Sopenharmony_ci	if (!f2fs_sb_has_flexible_inline_xattr(F2FS_I_SB(dir)) &&
5408c2ecf20Sopenharmony_ci			!f2fs_has_inline_xattr(dir))
5418c2ecf20Sopenharmony_ci		F2FS_I(dir)->i_inline_xattr_size = 0;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	kfree(backup_dentry);
5448c2ecf20Sopenharmony_ci	return 0;
5458c2ecf20Sopenharmony_cirecover:
5468c2ecf20Sopenharmony_ci	lock_page(ipage);
5478c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(ipage, NODE, true, true);
5488c2ecf20Sopenharmony_ci	memcpy(inline_dentry, backup_dentry, MAX_INLINE_DATA(dir));
5498c2ecf20Sopenharmony_ci	f2fs_i_depth_write(dir, 0);
5508c2ecf20Sopenharmony_ci	f2fs_i_size_write(dir, MAX_INLINE_DATA(dir));
5518c2ecf20Sopenharmony_ci	set_page_dirty(ipage);
5528c2ecf20Sopenharmony_ci	f2fs_put_page(ipage, 1);
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	kfree(backup_dentry);
5558c2ecf20Sopenharmony_ci	return err;
5568c2ecf20Sopenharmony_ci}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_cistatic int do_convert_inline_dir(struct inode *dir, struct page *ipage,
5598c2ecf20Sopenharmony_ci							void *inline_dentry)
5608c2ecf20Sopenharmony_ci{
5618c2ecf20Sopenharmony_ci	if (!F2FS_I(dir)->i_dir_level)
5628c2ecf20Sopenharmony_ci		return f2fs_move_inline_dirents(dir, ipage, inline_dentry);
5638c2ecf20Sopenharmony_ci	else
5648c2ecf20Sopenharmony_ci		return f2fs_move_rehashed_dirents(dir, ipage, inline_dentry);
5658c2ecf20Sopenharmony_ci}
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ciint f2fs_try_convert_inline_dir(struct inode *dir, struct dentry *dentry)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
5708c2ecf20Sopenharmony_ci	struct page *ipage;
5718c2ecf20Sopenharmony_ci	struct f2fs_filename fname;
5728c2ecf20Sopenharmony_ci	void *inline_dentry = NULL;
5738c2ecf20Sopenharmony_ci	int err = 0;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	if (!f2fs_has_inline_dentry(dir))
5768c2ecf20Sopenharmony_ci		return 0;
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	f2fs_lock_op(sbi);
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	err = f2fs_setup_filename(dir, &dentry->d_name, 0, &fname);
5818c2ecf20Sopenharmony_ci	if (err)
5828c2ecf20Sopenharmony_ci		goto out;
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	ipage = f2fs_get_node_page(sbi, dir->i_ino);
5858c2ecf20Sopenharmony_ci	if (IS_ERR(ipage)) {
5868c2ecf20Sopenharmony_ci		err = PTR_ERR(ipage);
5878c2ecf20Sopenharmony_ci		goto out_fname;
5888c2ecf20Sopenharmony_ci	}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	if (f2fs_has_enough_room(dir, ipage, &fname)) {
5918c2ecf20Sopenharmony_ci		f2fs_put_page(ipage, 1);
5928c2ecf20Sopenharmony_ci		goto out_fname;
5938c2ecf20Sopenharmony_ci	}
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	inline_dentry = inline_data_addr(dir, ipage);
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	err = do_convert_inline_dir(dir, ipage, inline_dentry);
5988c2ecf20Sopenharmony_ci	if (!err)
5998c2ecf20Sopenharmony_ci		f2fs_put_page(ipage, 1);
6008c2ecf20Sopenharmony_ciout_fname:
6018c2ecf20Sopenharmony_ci	f2fs_free_filename(&fname);
6028c2ecf20Sopenharmony_ciout:
6038c2ecf20Sopenharmony_ci	f2fs_unlock_op(sbi);
6048c2ecf20Sopenharmony_ci	return err;
6058c2ecf20Sopenharmony_ci}
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ciint f2fs_add_inline_entry(struct inode *dir, const struct f2fs_filename *fname,
6088c2ecf20Sopenharmony_ci			  struct inode *inode, nid_t ino, umode_t mode)
6098c2ecf20Sopenharmony_ci{
6108c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
6118c2ecf20Sopenharmony_ci	struct page *ipage;
6128c2ecf20Sopenharmony_ci	unsigned int bit_pos;
6138c2ecf20Sopenharmony_ci	void *inline_dentry = NULL;
6148c2ecf20Sopenharmony_ci	struct f2fs_dentry_ptr d;
6158c2ecf20Sopenharmony_ci	int slots = GET_DENTRY_SLOTS(fname->disk_name.len);
6168c2ecf20Sopenharmony_ci	struct page *page = NULL;
6178c2ecf20Sopenharmony_ci	int err = 0;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	ipage = f2fs_get_node_page(sbi, dir->i_ino);
6208c2ecf20Sopenharmony_ci	if (IS_ERR(ipage))
6218c2ecf20Sopenharmony_ci		return PTR_ERR(ipage);
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	inline_dentry = inline_data_addr(dir, ipage);
6248c2ecf20Sopenharmony_ci	make_dentry_ptr_inline(dir, &d, inline_dentry);
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	bit_pos = f2fs_room_for_filename(d.bitmap, slots, d.max);
6278c2ecf20Sopenharmony_ci	if (bit_pos >= d.max) {
6288c2ecf20Sopenharmony_ci		err = do_convert_inline_dir(dir, ipage, inline_dentry);
6298c2ecf20Sopenharmony_ci		if (err)
6308c2ecf20Sopenharmony_ci			return err;
6318c2ecf20Sopenharmony_ci		err = -EAGAIN;
6328c2ecf20Sopenharmony_ci		goto out;
6338c2ecf20Sopenharmony_ci	}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	if (inode) {
6368c2ecf20Sopenharmony_ci		down_write(&F2FS_I(inode)->i_sem);
6378c2ecf20Sopenharmony_ci		page = f2fs_init_inode_metadata(inode, dir, fname, ipage);
6388c2ecf20Sopenharmony_ci		if (IS_ERR(page)) {
6398c2ecf20Sopenharmony_ci			err = PTR_ERR(page);
6408c2ecf20Sopenharmony_ci			goto fail;
6418c2ecf20Sopenharmony_ci		}
6428c2ecf20Sopenharmony_ci	}
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(ipage, NODE, true, true);
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	f2fs_update_dentry(ino, mode, &d, &fname->disk_name, fname->hash,
6478c2ecf20Sopenharmony_ci			   bit_pos);
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	set_page_dirty(ipage);
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	/* we don't need to mark_inode_dirty now */
6528c2ecf20Sopenharmony_ci	if (inode) {
6538c2ecf20Sopenharmony_ci		f2fs_i_pino_write(inode, dir->i_ino);
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci		/* synchronize inode page's data from inode cache */
6568c2ecf20Sopenharmony_ci		if (is_inode_flag_set(inode, FI_NEW_INODE))
6578c2ecf20Sopenharmony_ci			f2fs_update_inode(inode, page);
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci		f2fs_put_page(page, 1);
6608c2ecf20Sopenharmony_ci	}
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	f2fs_update_parent_metadata(dir, inode, 0);
6638c2ecf20Sopenharmony_cifail:
6648c2ecf20Sopenharmony_ci	if (inode)
6658c2ecf20Sopenharmony_ci		up_write(&F2FS_I(inode)->i_sem);
6668c2ecf20Sopenharmony_ciout:
6678c2ecf20Sopenharmony_ci	f2fs_put_page(ipage, 1);
6688c2ecf20Sopenharmony_ci	return err;
6698c2ecf20Sopenharmony_ci}
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_civoid f2fs_delete_inline_entry(struct f2fs_dir_entry *dentry, struct page *page,
6728c2ecf20Sopenharmony_ci					struct inode *dir, struct inode *inode)
6738c2ecf20Sopenharmony_ci{
6748c2ecf20Sopenharmony_ci	struct f2fs_dentry_ptr d;
6758c2ecf20Sopenharmony_ci	void *inline_dentry;
6768c2ecf20Sopenharmony_ci	int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len));
6778c2ecf20Sopenharmony_ci	unsigned int bit_pos;
6788c2ecf20Sopenharmony_ci	int i;
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	lock_page(page);
6818c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(page, NODE, true, true);
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	inline_dentry = inline_data_addr(dir, page);
6848c2ecf20Sopenharmony_ci	make_dentry_ptr_inline(dir, &d, inline_dentry);
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	bit_pos = dentry - d.dentry;
6878c2ecf20Sopenharmony_ci	for (i = 0; i < slots; i++)
6888c2ecf20Sopenharmony_ci		__clear_bit_le(bit_pos + i, d.bitmap);
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	set_page_dirty(page);
6918c2ecf20Sopenharmony_ci	f2fs_put_page(page, 1);
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	dir->i_ctime = dir->i_mtime = current_time(dir);
6948c2ecf20Sopenharmony_ci	f2fs_mark_inode_dirty_sync(dir, false);
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	if (inode)
6978c2ecf20Sopenharmony_ci		f2fs_drop_nlink(dir, inode);
6988c2ecf20Sopenharmony_ci}
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_cibool f2fs_empty_inline_dir(struct inode *dir)
7018c2ecf20Sopenharmony_ci{
7028c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
7038c2ecf20Sopenharmony_ci	struct page *ipage;
7048c2ecf20Sopenharmony_ci	unsigned int bit_pos = 2;
7058c2ecf20Sopenharmony_ci	void *inline_dentry;
7068c2ecf20Sopenharmony_ci	struct f2fs_dentry_ptr d;
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	ipage = f2fs_get_node_page(sbi, dir->i_ino);
7098c2ecf20Sopenharmony_ci	if (IS_ERR(ipage))
7108c2ecf20Sopenharmony_ci		return false;
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci	inline_dentry = inline_data_addr(dir, ipage);
7138c2ecf20Sopenharmony_ci	make_dentry_ptr_inline(dir, &d, inline_dentry);
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	bit_pos = find_next_bit_le(d.bitmap, d.max, bit_pos);
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	f2fs_put_page(ipage, 1);
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	if (bit_pos < d.max)
7208c2ecf20Sopenharmony_ci		return false;
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	return true;
7238c2ecf20Sopenharmony_ci}
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ciint f2fs_read_inline_dir(struct file *file, struct dir_context *ctx,
7268c2ecf20Sopenharmony_ci				struct fscrypt_str *fstr)
7278c2ecf20Sopenharmony_ci{
7288c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
7298c2ecf20Sopenharmony_ci	struct page *ipage = NULL;
7308c2ecf20Sopenharmony_ci	struct f2fs_dentry_ptr d;
7318c2ecf20Sopenharmony_ci	void *inline_dentry = NULL;
7328c2ecf20Sopenharmony_ci	int err;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	make_dentry_ptr_inline(inode, &d, inline_dentry);
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	if (ctx->pos == d.max)
7378c2ecf20Sopenharmony_ci		return 0;
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino);
7408c2ecf20Sopenharmony_ci	if (IS_ERR(ipage))
7418c2ecf20Sopenharmony_ci		return PTR_ERR(ipage);
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	/*
7448c2ecf20Sopenharmony_ci	 * f2fs_readdir was protected by inode.i_rwsem, it is safe to access
7458c2ecf20Sopenharmony_ci	 * ipage without page's lock held.
7468c2ecf20Sopenharmony_ci	 */
7478c2ecf20Sopenharmony_ci	unlock_page(ipage);
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	inline_dentry = inline_data_addr(inode, ipage);
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	make_dentry_ptr_inline(inode, &d, inline_dentry);
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	err = f2fs_fill_dentries(ctx, &d, 0, fstr);
7548c2ecf20Sopenharmony_ci	if (!err)
7558c2ecf20Sopenharmony_ci		ctx->pos = d.max;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	f2fs_put_page(ipage, 0);
7588c2ecf20Sopenharmony_ci	return err < 0 ? err : 0;
7598c2ecf20Sopenharmony_ci}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ciint f2fs_inline_data_fiemap(struct inode *inode,
7628c2ecf20Sopenharmony_ci		struct fiemap_extent_info *fieinfo, __u64 start, __u64 len)
7638c2ecf20Sopenharmony_ci{
7648c2ecf20Sopenharmony_ci	__u64 byteaddr, ilen;
7658c2ecf20Sopenharmony_ci	__u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED |
7668c2ecf20Sopenharmony_ci		FIEMAP_EXTENT_LAST;
7678c2ecf20Sopenharmony_ci	struct node_info ni;
7688c2ecf20Sopenharmony_ci	struct page *ipage;
7698c2ecf20Sopenharmony_ci	int err = 0;
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino);
7728c2ecf20Sopenharmony_ci	if (IS_ERR(ipage))
7738c2ecf20Sopenharmony_ci		return PTR_ERR(ipage);
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	if ((S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
7768c2ecf20Sopenharmony_ci				!f2fs_has_inline_data(inode)) {
7778c2ecf20Sopenharmony_ci		err = -EAGAIN;
7788c2ecf20Sopenharmony_ci		goto out;
7798c2ecf20Sopenharmony_ci	}
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	if (S_ISDIR(inode->i_mode) && !f2fs_has_inline_dentry(inode)) {
7828c2ecf20Sopenharmony_ci		err = -EAGAIN;
7838c2ecf20Sopenharmony_ci		goto out;
7848c2ecf20Sopenharmony_ci	}
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	ilen = min_t(size_t, MAX_INLINE_DATA(inode), i_size_read(inode));
7878c2ecf20Sopenharmony_ci	if (start >= ilen)
7888c2ecf20Sopenharmony_ci		goto out;
7898c2ecf20Sopenharmony_ci	if (start + len < ilen)
7908c2ecf20Sopenharmony_ci		ilen = start + len;
7918c2ecf20Sopenharmony_ci	ilen -= start;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	err = f2fs_get_node_info(F2FS_I_SB(inode), inode->i_ino, &ni);
7948c2ecf20Sopenharmony_ci	if (err)
7958c2ecf20Sopenharmony_ci		goto out;
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	byteaddr = (__u64)ni.blk_addr << inode->i_sb->s_blocksize_bits;
7988c2ecf20Sopenharmony_ci	byteaddr += (char *)inline_data_addr(inode, ipage) -
7998c2ecf20Sopenharmony_ci					(char *)F2FS_INODE(ipage);
8008c2ecf20Sopenharmony_ci	err = fiemap_fill_next_extent(fieinfo, start, byteaddr, ilen, flags);
8018c2ecf20Sopenharmony_ci	trace_f2fs_fiemap(inode, start, byteaddr, ilen, flags, err);
8028c2ecf20Sopenharmony_ciout:
8038c2ecf20Sopenharmony_ci	f2fs_put_page(ipage, 1);
8048c2ecf20Sopenharmony_ci	return err;
8058c2ecf20Sopenharmony_ci}
806