162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/f2fs/inline.c 462306a36Sopenharmony_ci * Copyright (c) 2013, Intel Corporation 562306a36Sopenharmony_ci * Authors: Huajun Li <huajun.li@intel.com> 662306a36Sopenharmony_ci * Haicheng Li <haicheng.li@intel.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/fs.h> 1062306a36Sopenharmony_ci#include <linux/f2fs_fs.h> 1162306a36Sopenharmony_ci#include <linux/fiemap.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include "f2fs.h" 1462306a36Sopenharmony_ci#include "node.h" 1562306a36Sopenharmony_ci#include <trace/events/f2fs.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic bool support_inline_data(struct inode *inode) 1862306a36Sopenharmony_ci{ 1962306a36Sopenharmony_ci if (f2fs_is_atomic_file(inode)) 2062306a36Sopenharmony_ci return false; 2162306a36Sopenharmony_ci if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) 2262306a36Sopenharmony_ci return false; 2362306a36Sopenharmony_ci if (i_size_read(inode) > MAX_INLINE_DATA(inode)) 2462306a36Sopenharmony_ci return false; 2562306a36Sopenharmony_ci return true; 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cibool f2fs_may_inline_data(struct inode *inode) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci if (!support_inline_data(inode)) 3162306a36Sopenharmony_ci return false; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci return !f2fs_post_read_required(inode); 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cibool f2fs_sanity_check_inline_data(struct inode *inode) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci if (!f2fs_has_inline_data(inode)) 3962306a36Sopenharmony_ci return false; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci if (!support_inline_data(inode)) 4262306a36Sopenharmony_ci return true; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* 4562306a36Sopenharmony_ci * used by sanity_check_inode(), when disk layout fields has not 4662306a36Sopenharmony_ci * been synchronized to inmem fields. 4762306a36Sopenharmony_ci */ 4862306a36Sopenharmony_ci return (S_ISREG(inode->i_mode) && 4962306a36Sopenharmony_ci (file_is_encrypt(inode) || file_is_verity(inode) || 5062306a36Sopenharmony_ci (F2FS_I(inode)->i_flags & F2FS_COMPR_FL))); 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cibool f2fs_may_inline_dentry(struct inode *inode) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci if (!test_opt(F2FS_I_SB(inode), INLINE_DENTRY)) 5662306a36Sopenharmony_ci return false; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci if (!S_ISDIR(inode->i_mode)) 5962306a36Sopenharmony_ci return false; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return true; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_civoid f2fs_do_read_inline_data(struct page *page, struct page *ipage) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci if (PageUptodate(page)) 6962306a36Sopenharmony_ci return; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci f2fs_bug_on(F2FS_P_SB(page), page->index); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci zero_user_segment(page, MAX_INLINE_DATA(inode), PAGE_SIZE); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci /* Copy the whole inline data block */ 7662306a36Sopenharmony_ci memcpy_to_page(page, 0, inline_data_addr(inode, ipage), 7762306a36Sopenharmony_ci MAX_INLINE_DATA(inode)); 7862306a36Sopenharmony_ci if (!PageUptodate(page)) 7962306a36Sopenharmony_ci SetPageUptodate(page); 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_civoid f2fs_truncate_inline_inode(struct inode *inode, 8362306a36Sopenharmony_ci struct page *ipage, u64 from) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci void *addr; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (from >= MAX_INLINE_DATA(inode)) 8862306a36Sopenharmony_ci return; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci addr = inline_data_addr(inode, ipage); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci f2fs_wait_on_page_writeback(ipage, NODE, true, true); 9362306a36Sopenharmony_ci memset(addr + from, 0, MAX_INLINE_DATA(inode) - from); 9462306a36Sopenharmony_ci set_page_dirty(ipage); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci if (from == 0) 9762306a36Sopenharmony_ci clear_inode_flag(inode, FI_DATA_EXIST); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ciint f2fs_read_inline_data(struct inode *inode, struct page *page) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci struct page *ipage; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino); 10562306a36Sopenharmony_ci if (IS_ERR(ipage)) { 10662306a36Sopenharmony_ci unlock_page(page); 10762306a36Sopenharmony_ci return PTR_ERR(ipage); 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci if (!f2fs_has_inline_data(inode)) { 11162306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 11262306a36Sopenharmony_ci return -EAGAIN; 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci if (page->index) 11662306a36Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 11762306a36Sopenharmony_ci else 11862306a36Sopenharmony_ci f2fs_do_read_inline_data(page, ipage); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci if (!PageUptodate(page)) 12162306a36Sopenharmony_ci SetPageUptodate(page); 12262306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 12362306a36Sopenharmony_ci unlock_page(page); 12462306a36Sopenharmony_ci return 0; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ciint f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci struct f2fs_io_info fio = { 13062306a36Sopenharmony_ci .sbi = F2FS_I_SB(dn->inode), 13162306a36Sopenharmony_ci .ino = dn->inode->i_ino, 13262306a36Sopenharmony_ci .type = DATA, 13362306a36Sopenharmony_ci .op = REQ_OP_WRITE, 13462306a36Sopenharmony_ci .op_flags = REQ_SYNC | REQ_PRIO, 13562306a36Sopenharmony_ci .page = page, 13662306a36Sopenharmony_ci .encrypted_page = NULL, 13762306a36Sopenharmony_ci .io_type = FS_DATA_IO, 13862306a36Sopenharmony_ci }; 13962306a36Sopenharmony_ci struct node_info ni; 14062306a36Sopenharmony_ci int dirty, err; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci if (!f2fs_exist_data(dn->inode)) 14362306a36Sopenharmony_ci goto clear_out; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci err = f2fs_reserve_block(dn, 0); 14662306a36Sopenharmony_ci if (err) 14762306a36Sopenharmony_ci return err; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci err = f2fs_get_node_info(fio.sbi, dn->nid, &ni, false); 15062306a36Sopenharmony_ci if (err) { 15162306a36Sopenharmony_ci f2fs_truncate_data_blocks_range(dn, 1); 15262306a36Sopenharmony_ci f2fs_put_dnode(dn); 15362306a36Sopenharmony_ci return err; 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci fio.version = ni.version; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci if (unlikely(dn->data_blkaddr != NEW_ADDR)) { 15962306a36Sopenharmony_ci f2fs_put_dnode(dn); 16062306a36Sopenharmony_ci set_sbi_flag(fio.sbi, SBI_NEED_FSCK); 16162306a36Sopenharmony_ci f2fs_warn(fio.sbi, "%s: corrupted inline inode ino=%lx, i_addr[0]:0x%x, run fsck to fix.", 16262306a36Sopenharmony_ci __func__, dn->inode->i_ino, dn->data_blkaddr); 16362306a36Sopenharmony_ci f2fs_handle_error(fio.sbi, ERROR_INVALID_BLKADDR); 16462306a36Sopenharmony_ci return -EFSCORRUPTED; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci f2fs_bug_on(F2FS_P_SB(page), PageWriteback(page)); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci f2fs_do_read_inline_data(page, dn->inode_page); 17062306a36Sopenharmony_ci set_page_dirty(page); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci /* clear dirty state */ 17362306a36Sopenharmony_ci dirty = clear_page_dirty_for_io(page); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* write data page to try to make data consistent */ 17662306a36Sopenharmony_ci set_page_writeback(page); 17762306a36Sopenharmony_ci fio.old_blkaddr = dn->data_blkaddr; 17862306a36Sopenharmony_ci set_inode_flag(dn->inode, FI_HOT_DATA); 17962306a36Sopenharmony_ci f2fs_outplace_write_data(dn, &fio); 18062306a36Sopenharmony_ci f2fs_wait_on_page_writeback(page, DATA, true, true); 18162306a36Sopenharmony_ci if (dirty) { 18262306a36Sopenharmony_ci inode_dec_dirty_pages(dn->inode); 18362306a36Sopenharmony_ci f2fs_remove_dirty_inode(dn->inode); 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci /* this converted inline_data should be recovered. */ 18762306a36Sopenharmony_ci set_inode_flag(dn->inode, FI_APPEND_WRITE); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci /* clear inline data and flag after data writeback */ 19062306a36Sopenharmony_ci f2fs_truncate_inline_inode(dn->inode, dn->inode_page, 0); 19162306a36Sopenharmony_ci clear_page_private_inline(dn->inode_page); 19262306a36Sopenharmony_ciclear_out: 19362306a36Sopenharmony_ci stat_dec_inline_inode(dn->inode); 19462306a36Sopenharmony_ci clear_inode_flag(dn->inode, FI_INLINE_DATA); 19562306a36Sopenharmony_ci f2fs_put_dnode(dn); 19662306a36Sopenharmony_ci return 0; 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ciint f2fs_convert_inline_inode(struct inode *inode) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 20262306a36Sopenharmony_ci struct dnode_of_data dn; 20362306a36Sopenharmony_ci struct page *ipage, *page; 20462306a36Sopenharmony_ci int err = 0; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci if (!f2fs_has_inline_data(inode) || 20762306a36Sopenharmony_ci f2fs_hw_is_readonly(sbi) || f2fs_readonly(sbi->sb)) 20862306a36Sopenharmony_ci return 0; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci err = f2fs_dquot_initialize(inode); 21162306a36Sopenharmony_ci if (err) 21262306a36Sopenharmony_ci return err; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci page = f2fs_grab_cache_page(inode->i_mapping, 0, false); 21562306a36Sopenharmony_ci if (!page) 21662306a36Sopenharmony_ci return -ENOMEM; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci f2fs_lock_op(sbi); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci ipage = f2fs_get_node_page(sbi, inode->i_ino); 22162306a36Sopenharmony_ci if (IS_ERR(ipage)) { 22262306a36Sopenharmony_ci err = PTR_ERR(ipage); 22362306a36Sopenharmony_ci goto out; 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci set_new_dnode(&dn, inode, ipage, ipage, 0); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci if (f2fs_has_inline_data(inode)) 22962306a36Sopenharmony_ci err = f2fs_convert_inline_page(&dn, page); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci f2fs_put_dnode(&dn); 23262306a36Sopenharmony_ciout: 23362306a36Sopenharmony_ci f2fs_unlock_op(sbi); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci f2fs_put_page(page, 1); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci if (!err) 23862306a36Sopenharmony_ci f2fs_balance_fs(sbi, dn.node_changed); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci return err; 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ciint f2fs_write_inline_data(struct inode *inode, struct page *page) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci struct dnode_of_data dn; 24662306a36Sopenharmony_ci int err; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, 0); 24962306a36Sopenharmony_ci err = f2fs_get_dnode_of_data(&dn, 0, LOOKUP_NODE); 25062306a36Sopenharmony_ci if (err) 25162306a36Sopenharmony_ci return err; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci if (!f2fs_has_inline_data(inode)) { 25462306a36Sopenharmony_ci f2fs_put_dnode(&dn); 25562306a36Sopenharmony_ci return -EAGAIN; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci f2fs_bug_on(F2FS_I_SB(inode), page->index); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci f2fs_wait_on_page_writeback(dn.inode_page, NODE, true, true); 26162306a36Sopenharmony_ci memcpy_from_page(inline_data_addr(inode, dn.inode_page), 26262306a36Sopenharmony_ci page, 0, MAX_INLINE_DATA(inode)); 26362306a36Sopenharmony_ci set_page_dirty(dn.inode_page); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci f2fs_clear_page_cache_dirty_tag(page); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci set_inode_flag(inode, FI_APPEND_WRITE); 26862306a36Sopenharmony_ci set_inode_flag(inode, FI_DATA_EXIST); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci clear_page_private_inline(dn.inode_page); 27162306a36Sopenharmony_ci f2fs_put_dnode(&dn); 27262306a36Sopenharmony_ci return 0; 27362306a36Sopenharmony_ci} 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ciint f2fs_recover_inline_data(struct inode *inode, struct page *npage) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 27862306a36Sopenharmony_ci struct f2fs_inode *ri = NULL; 27962306a36Sopenharmony_ci void *src_addr, *dst_addr; 28062306a36Sopenharmony_ci struct page *ipage; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci /* 28362306a36Sopenharmony_ci * The inline_data recovery policy is as follows. 28462306a36Sopenharmony_ci * [prev.] [next] of inline_data flag 28562306a36Sopenharmony_ci * o o -> recover inline_data 28662306a36Sopenharmony_ci * o x -> remove inline_data, and then recover data blocks 28762306a36Sopenharmony_ci * x o -> remove data blocks, and then recover inline_data 28862306a36Sopenharmony_ci * x x -> recover data blocks 28962306a36Sopenharmony_ci */ 29062306a36Sopenharmony_ci if (IS_INODE(npage)) 29162306a36Sopenharmony_ci ri = F2FS_INODE(npage); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci if (f2fs_has_inline_data(inode) && 29462306a36Sopenharmony_ci ri && (ri->i_inline & F2FS_INLINE_DATA)) { 29562306a36Sopenharmony_ciprocess_inline: 29662306a36Sopenharmony_ci ipage = f2fs_get_node_page(sbi, inode->i_ino); 29762306a36Sopenharmony_ci if (IS_ERR(ipage)) 29862306a36Sopenharmony_ci return PTR_ERR(ipage); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci f2fs_wait_on_page_writeback(ipage, NODE, true, true); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci src_addr = inline_data_addr(inode, npage); 30362306a36Sopenharmony_ci dst_addr = inline_data_addr(inode, ipage); 30462306a36Sopenharmony_ci memcpy(dst_addr, src_addr, MAX_INLINE_DATA(inode)); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci set_inode_flag(inode, FI_INLINE_DATA); 30762306a36Sopenharmony_ci set_inode_flag(inode, FI_DATA_EXIST); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci set_page_dirty(ipage); 31062306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 31162306a36Sopenharmony_ci return 1; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci if (f2fs_has_inline_data(inode)) { 31562306a36Sopenharmony_ci ipage = f2fs_get_node_page(sbi, inode->i_ino); 31662306a36Sopenharmony_ci if (IS_ERR(ipage)) 31762306a36Sopenharmony_ci return PTR_ERR(ipage); 31862306a36Sopenharmony_ci f2fs_truncate_inline_inode(inode, ipage, 0); 31962306a36Sopenharmony_ci stat_dec_inline_inode(inode); 32062306a36Sopenharmony_ci clear_inode_flag(inode, FI_INLINE_DATA); 32162306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 32262306a36Sopenharmony_ci } else if (ri && (ri->i_inline & F2FS_INLINE_DATA)) { 32362306a36Sopenharmony_ci int ret; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci ret = f2fs_truncate_blocks(inode, 0, false); 32662306a36Sopenharmony_ci if (ret) 32762306a36Sopenharmony_ci return ret; 32862306a36Sopenharmony_ci stat_inc_inline_inode(inode); 32962306a36Sopenharmony_ci goto process_inline; 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci return 0; 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistruct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir, 33562306a36Sopenharmony_ci const struct f2fs_filename *fname, 33662306a36Sopenharmony_ci struct page **res_page) 33762306a36Sopenharmony_ci{ 33862306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); 33962306a36Sopenharmony_ci struct f2fs_dir_entry *de; 34062306a36Sopenharmony_ci struct f2fs_dentry_ptr d; 34162306a36Sopenharmony_ci struct page *ipage; 34262306a36Sopenharmony_ci void *inline_dentry; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci ipage = f2fs_get_node_page(sbi, dir->i_ino); 34562306a36Sopenharmony_ci if (IS_ERR(ipage)) { 34662306a36Sopenharmony_ci *res_page = ipage; 34762306a36Sopenharmony_ci return NULL; 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci inline_dentry = inline_data_addr(dir, ipage); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci make_dentry_ptr_inline(dir, &d, inline_dentry); 35362306a36Sopenharmony_ci de = f2fs_find_target_dentry(&d, fname, NULL); 35462306a36Sopenharmony_ci unlock_page(ipage); 35562306a36Sopenharmony_ci if (IS_ERR(de)) { 35662306a36Sopenharmony_ci *res_page = ERR_CAST(de); 35762306a36Sopenharmony_ci de = NULL; 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci if (de) 36062306a36Sopenharmony_ci *res_page = ipage; 36162306a36Sopenharmony_ci else 36262306a36Sopenharmony_ci f2fs_put_page(ipage, 0); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci return de; 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ciint f2fs_make_empty_inline_dir(struct inode *inode, struct inode *parent, 36862306a36Sopenharmony_ci struct page *ipage) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci struct f2fs_dentry_ptr d; 37162306a36Sopenharmony_ci void *inline_dentry; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci inline_dentry = inline_data_addr(inode, ipage); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci make_dentry_ptr_inline(inode, &d, inline_dentry); 37662306a36Sopenharmony_ci f2fs_do_make_empty_dir(inode, parent, &d); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci set_page_dirty(ipage); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* update i_size to MAX_INLINE_DATA */ 38162306a36Sopenharmony_ci if (i_size_read(inode) < MAX_INLINE_DATA(inode)) 38262306a36Sopenharmony_ci f2fs_i_size_write(inode, MAX_INLINE_DATA(inode)); 38362306a36Sopenharmony_ci return 0; 38462306a36Sopenharmony_ci} 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci/* 38762306a36Sopenharmony_ci * NOTE: ipage is grabbed by caller, but if any error occurs, we should 38862306a36Sopenharmony_ci * release ipage in this function. 38962306a36Sopenharmony_ci */ 39062306a36Sopenharmony_cistatic int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage, 39162306a36Sopenharmony_ci void *inline_dentry) 39262306a36Sopenharmony_ci{ 39362306a36Sopenharmony_ci struct page *page; 39462306a36Sopenharmony_ci struct dnode_of_data dn; 39562306a36Sopenharmony_ci struct f2fs_dentry_block *dentry_blk; 39662306a36Sopenharmony_ci struct f2fs_dentry_ptr src, dst; 39762306a36Sopenharmony_ci int err; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci page = f2fs_grab_cache_page(dir->i_mapping, 0, true); 40062306a36Sopenharmony_ci if (!page) { 40162306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 40262306a36Sopenharmony_ci return -ENOMEM; 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci set_new_dnode(&dn, dir, ipage, NULL, 0); 40662306a36Sopenharmony_ci err = f2fs_reserve_block(&dn, 0); 40762306a36Sopenharmony_ci if (err) 40862306a36Sopenharmony_ci goto out; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci if (unlikely(dn.data_blkaddr != NEW_ADDR)) { 41162306a36Sopenharmony_ci f2fs_put_dnode(&dn); 41262306a36Sopenharmony_ci set_sbi_flag(F2FS_P_SB(page), SBI_NEED_FSCK); 41362306a36Sopenharmony_ci f2fs_warn(F2FS_P_SB(page), "%s: corrupted inline inode ino=%lx, i_addr[0]:0x%x, run fsck to fix.", 41462306a36Sopenharmony_ci __func__, dir->i_ino, dn.data_blkaddr); 41562306a36Sopenharmony_ci f2fs_handle_error(F2FS_P_SB(page), ERROR_INVALID_BLKADDR); 41662306a36Sopenharmony_ci err = -EFSCORRUPTED; 41762306a36Sopenharmony_ci goto out; 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci f2fs_wait_on_page_writeback(page, DATA, true, true); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci dentry_blk = page_address(page); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci /* 42562306a36Sopenharmony_ci * Start by zeroing the full block, to ensure that all unused space is 42662306a36Sopenharmony_ci * zeroed and no uninitialized memory is leaked to disk. 42762306a36Sopenharmony_ci */ 42862306a36Sopenharmony_ci memset(dentry_blk, 0, F2FS_BLKSIZE); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci make_dentry_ptr_inline(dir, &src, inline_dentry); 43162306a36Sopenharmony_ci make_dentry_ptr_block(dir, &dst, dentry_blk); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci /* copy data from inline dentry block to new dentry block */ 43462306a36Sopenharmony_ci memcpy(dst.bitmap, src.bitmap, src.nr_bitmap); 43562306a36Sopenharmony_ci memcpy(dst.dentry, src.dentry, SIZE_OF_DIR_ENTRY * src.max); 43662306a36Sopenharmony_ci memcpy(dst.filename, src.filename, src.max * F2FS_SLOT_LEN); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci if (!PageUptodate(page)) 43962306a36Sopenharmony_ci SetPageUptodate(page); 44062306a36Sopenharmony_ci set_page_dirty(page); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci /* clear inline dir and flag after data writeback */ 44362306a36Sopenharmony_ci f2fs_truncate_inline_inode(dir, ipage, 0); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci stat_dec_inline_dir(dir); 44662306a36Sopenharmony_ci clear_inode_flag(dir, FI_INLINE_DENTRY); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci /* 44962306a36Sopenharmony_ci * should retrieve reserved space which was used to keep 45062306a36Sopenharmony_ci * inline_dentry's structure for backward compatibility. 45162306a36Sopenharmony_ci */ 45262306a36Sopenharmony_ci if (!f2fs_sb_has_flexible_inline_xattr(F2FS_I_SB(dir)) && 45362306a36Sopenharmony_ci !f2fs_has_inline_xattr(dir)) 45462306a36Sopenharmony_ci F2FS_I(dir)->i_inline_xattr_size = 0; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci f2fs_i_depth_write(dir, 1); 45762306a36Sopenharmony_ci if (i_size_read(dir) < PAGE_SIZE) 45862306a36Sopenharmony_ci f2fs_i_size_write(dir, PAGE_SIZE); 45962306a36Sopenharmony_ciout: 46062306a36Sopenharmony_ci f2fs_put_page(page, 1); 46162306a36Sopenharmony_ci return err; 46262306a36Sopenharmony_ci} 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_cistatic int f2fs_add_inline_entries(struct inode *dir, void *inline_dentry) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci struct f2fs_dentry_ptr d; 46762306a36Sopenharmony_ci unsigned long bit_pos = 0; 46862306a36Sopenharmony_ci int err = 0; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci make_dentry_ptr_inline(dir, &d, inline_dentry); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci while (bit_pos < d.max) { 47362306a36Sopenharmony_ci struct f2fs_dir_entry *de; 47462306a36Sopenharmony_ci struct f2fs_filename fname; 47562306a36Sopenharmony_ci nid_t ino; 47662306a36Sopenharmony_ci umode_t fake_mode; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci if (!test_bit_le(bit_pos, d.bitmap)) { 47962306a36Sopenharmony_ci bit_pos++; 48062306a36Sopenharmony_ci continue; 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci de = &d.dentry[bit_pos]; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci if (unlikely(!de->name_len)) { 48662306a36Sopenharmony_ci bit_pos++; 48762306a36Sopenharmony_ci continue; 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci /* 49162306a36Sopenharmony_ci * We only need the disk_name and hash to move the dentry. 49262306a36Sopenharmony_ci * We don't need the original or casefolded filenames. 49362306a36Sopenharmony_ci */ 49462306a36Sopenharmony_ci memset(&fname, 0, sizeof(fname)); 49562306a36Sopenharmony_ci fname.disk_name.name = d.filename[bit_pos]; 49662306a36Sopenharmony_ci fname.disk_name.len = le16_to_cpu(de->name_len); 49762306a36Sopenharmony_ci fname.hash = de->hash_code; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci ino = le32_to_cpu(de->ino); 50062306a36Sopenharmony_ci fake_mode = fs_ftype_to_dtype(de->file_type) << S_DT_SHIFT; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci err = f2fs_add_regular_entry(dir, &fname, NULL, ino, fake_mode); 50362306a36Sopenharmony_ci if (err) 50462306a36Sopenharmony_ci goto punch_dentry_pages; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci return 0; 50962306a36Sopenharmony_cipunch_dentry_pages: 51062306a36Sopenharmony_ci truncate_inode_pages(&dir->i_data, 0); 51162306a36Sopenharmony_ci f2fs_truncate_blocks(dir, 0, false); 51262306a36Sopenharmony_ci f2fs_remove_dirty_inode(dir); 51362306a36Sopenharmony_ci return err; 51462306a36Sopenharmony_ci} 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cistatic int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage, 51762306a36Sopenharmony_ci void *inline_dentry) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci void *backup_dentry; 52062306a36Sopenharmony_ci int err; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci backup_dentry = f2fs_kmalloc(F2FS_I_SB(dir), 52362306a36Sopenharmony_ci MAX_INLINE_DATA(dir), GFP_F2FS_ZERO); 52462306a36Sopenharmony_ci if (!backup_dentry) { 52562306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 52662306a36Sopenharmony_ci return -ENOMEM; 52762306a36Sopenharmony_ci } 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci memcpy(backup_dentry, inline_dentry, MAX_INLINE_DATA(dir)); 53062306a36Sopenharmony_ci f2fs_truncate_inline_inode(dir, ipage, 0); 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci unlock_page(ipage); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci err = f2fs_add_inline_entries(dir, backup_dentry); 53562306a36Sopenharmony_ci if (err) 53662306a36Sopenharmony_ci goto recover; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci lock_page(ipage); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci stat_dec_inline_dir(dir); 54162306a36Sopenharmony_ci clear_inode_flag(dir, FI_INLINE_DENTRY); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci /* 54462306a36Sopenharmony_ci * should retrieve reserved space which was used to keep 54562306a36Sopenharmony_ci * inline_dentry's structure for backward compatibility. 54662306a36Sopenharmony_ci */ 54762306a36Sopenharmony_ci if (!f2fs_sb_has_flexible_inline_xattr(F2FS_I_SB(dir)) && 54862306a36Sopenharmony_ci !f2fs_has_inline_xattr(dir)) 54962306a36Sopenharmony_ci F2FS_I(dir)->i_inline_xattr_size = 0; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci kfree(backup_dentry); 55262306a36Sopenharmony_ci return 0; 55362306a36Sopenharmony_cirecover: 55462306a36Sopenharmony_ci lock_page(ipage); 55562306a36Sopenharmony_ci f2fs_wait_on_page_writeback(ipage, NODE, true, true); 55662306a36Sopenharmony_ci memcpy(inline_dentry, backup_dentry, MAX_INLINE_DATA(dir)); 55762306a36Sopenharmony_ci f2fs_i_depth_write(dir, 0); 55862306a36Sopenharmony_ci f2fs_i_size_write(dir, MAX_INLINE_DATA(dir)); 55962306a36Sopenharmony_ci set_page_dirty(ipage); 56062306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci kfree(backup_dentry); 56362306a36Sopenharmony_ci return err; 56462306a36Sopenharmony_ci} 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_cistatic int do_convert_inline_dir(struct inode *dir, struct page *ipage, 56762306a36Sopenharmony_ci void *inline_dentry) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci if (!F2FS_I(dir)->i_dir_level) 57062306a36Sopenharmony_ci return f2fs_move_inline_dirents(dir, ipage, inline_dentry); 57162306a36Sopenharmony_ci else 57262306a36Sopenharmony_ci return f2fs_move_rehashed_dirents(dir, ipage, inline_dentry); 57362306a36Sopenharmony_ci} 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ciint f2fs_try_convert_inline_dir(struct inode *dir, struct dentry *dentry) 57662306a36Sopenharmony_ci{ 57762306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dir); 57862306a36Sopenharmony_ci struct page *ipage; 57962306a36Sopenharmony_ci struct f2fs_filename fname; 58062306a36Sopenharmony_ci void *inline_dentry = NULL; 58162306a36Sopenharmony_ci int err = 0; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci if (!f2fs_has_inline_dentry(dir)) 58462306a36Sopenharmony_ci return 0; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci f2fs_lock_op(sbi); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci err = f2fs_setup_filename(dir, &dentry->d_name, 0, &fname); 58962306a36Sopenharmony_ci if (err) 59062306a36Sopenharmony_ci goto out; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci ipage = f2fs_get_node_page(sbi, dir->i_ino); 59362306a36Sopenharmony_ci if (IS_ERR(ipage)) { 59462306a36Sopenharmony_ci err = PTR_ERR(ipage); 59562306a36Sopenharmony_ci goto out_fname; 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci if (f2fs_has_enough_room(dir, ipage, &fname)) { 59962306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 60062306a36Sopenharmony_ci goto out_fname; 60162306a36Sopenharmony_ci } 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci inline_dentry = inline_data_addr(dir, ipage); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci err = do_convert_inline_dir(dir, ipage, inline_dentry); 60662306a36Sopenharmony_ci if (!err) 60762306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 60862306a36Sopenharmony_ciout_fname: 60962306a36Sopenharmony_ci f2fs_free_filename(&fname); 61062306a36Sopenharmony_ciout: 61162306a36Sopenharmony_ci f2fs_unlock_op(sbi); 61262306a36Sopenharmony_ci return err; 61362306a36Sopenharmony_ci} 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ciint f2fs_add_inline_entry(struct inode *dir, const struct f2fs_filename *fname, 61662306a36Sopenharmony_ci struct inode *inode, nid_t ino, umode_t mode) 61762306a36Sopenharmony_ci{ 61862306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dir); 61962306a36Sopenharmony_ci struct page *ipage; 62062306a36Sopenharmony_ci unsigned int bit_pos; 62162306a36Sopenharmony_ci void *inline_dentry = NULL; 62262306a36Sopenharmony_ci struct f2fs_dentry_ptr d; 62362306a36Sopenharmony_ci int slots = GET_DENTRY_SLOTS(fname->disk_name.len); 62462306a36Sopenharmony_ci struct page *page = NULL; 62562306a36Sopenharmony_ci int err = 0; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci ipage = f2fs_get_node_page(sbi, dir->i_ino); 62862306a36Sopenharmony_ci if (IS_ERR(ipage)) 62962306a36Sopenharmony_ci return PTR_ERR(ipage); 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci inline_dentry = inline_data_addr(dir, ipage); 63262306a36Sopenharmony_ci make_dentry_ptr_inline(dir, &d, inline_dentry); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci bit_pos = f2fs_room_for_filename(d.bitmap, slots, d.max); 63562306a36Sopenharmony_ci if (bit_pos >= d.max) { 63662306a36Sopenharmony_ci err = do_convert_inline_dir(dir, ipage, inline_dentry); 63762306a36Sopenharmony_ci if (err) 63862306a36Sopenharmony_ci return err; 63962306a36Sopenharmony_ci err = -EAGAIN; 64062306a36Sopenharmony_ci goto out; 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci if (inode) { 64462306a36Sopenharmony_ci f2fs_down_write_nested(&F2FS_I(inode)->i_sem, 64562306a36Sopenharmony_ci SINGLE_DEPTH_NESTING); 64662306a36Sopenharmony_ci page = f2fs_init_inode_metadata(inode, dir, fname, ipage); 64762306a36Sopenharmony_ci if (IS_ERR(page)) { 64862306a36Sopenharmony_ci err = PTR_ERR(page); 64962306a36Sopenharmony_ci goto fail; 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci f2fs_wait_on_page_writeback(ipage, NODE, true, true); 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci f2fs_update_dentry(ino, mode, &d, &fname->disk_name, fname->hash, 65662306a36Sopenharmony_ci bit_pos); 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci set_page_dirty(ipage); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci /* we don't need to mark_inode_dirty now */ 66162306a36Sopenharmony_ci if (inode) { 66262306a36Sopenharmony_ci f2fs_i_pino_write(inode, dir->i_ino); 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci /* synchronize inode page's data from inode cache */ 66562306a36Sopenharmony_ci if (is_inode_flag_set(inode, FI_NEW_INODE)) 66662306a36Sopenharmony_ci f2fs_update_inode(inode, page); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci f2fs_put_page(page, 1); 66962306a36Sopenharmony_ci } 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci f2fs_update_parent_metadata(dir, inode, 0); 67262306a36Sopenharmony_cifail: 67362306a36Sopenharmony_ci if (inode) 67462306a36Sopenharmony_ci f2fs_up_write(&F2FS_I(inode)->i_sem); 67562306a36Sopenharmony_ciout: 67662306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 67762306a36Sopenharmony_ci return err; 67862306a36Sopenharmony_ci} 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_civoid f2fs_delete_inline_entry(struct f2fs_dir_entry *dentry, struct page *page, 68162306a36Sopenharmony_ci struct inode *dir, struct inode *inode) 68262306a36Sopenharmony_ci{ 68362306a36Sopenharmony_ci struct f2fs_dentry_ptr d; 68462306a36Sopenharmony_ci void *inline_dentry; 68562306a36Sopenharmony_ci int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len)); 68662306a36Sopenharmony_ci unsigned int bit_pos; 68762306a36Sopenharmony_ci int i; 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci lock_page(page); 69062306a36Sopenharmony_ci f2fs_wait_on_page_writeback(page, NODE, true, true); 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci inline_dentry = inline_data_addr(dir, page); 69362306a36Sopenharmony_ci make_dentry_ptr_inline(dir, &d, inline_dentry); 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci bit_pos = dentry - d.dentry; 69662306a36Sopenharmony_ci for (i = 0; i < slots; i++) 69762306a36Sopenharmony_ci __clear_bit_le(bit_pos + i, d.bitmap); 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci set_page_dirty(page); 70062306a36Sopenharmony_ci f2fs_put_page(page, 1); 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci dir->i_mtime = inode_set_ctime_current(dir); 70362306a36Sopenharmony_ci f2fs_mark_inode_dirty_sync(dir, false); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci if (inode) 70662306a36Sopenharmony_ci f2fs_drop_nlink(dir, inode); 70762306a36Sopenharmony_ci} 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_cibool f2fs_empty_inline_dir(struct inode *dir) 71062306a36Sopenharmony_ci{ 71162306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dir); 71262306a36Sopenharmony_ci struct page *ipage; 71362306a36Sopenharmony_ci unsigned int bit_pos = 2; 71462306a36Sopenharmony_ci void *inline_dentry; 71562306a36Sopenharmony_ci struct f2fs_dentry_ptr d; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci ipage = f2fs_get_node_page(sbi, dir->i_ino); 71862306a36Sopenharmony_ci if (IS_ERR(ipage)) 71962306a36Sopenharmony_ci return false; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci inline_dentry = inline_data_addr(dir, ipage); 72262306a36Sopenharmony_ci make_dentry_ptr_inline(dir, &d, inline_dentry); 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci bit_pos = find_next_bit_le(d.bitmap, d.max, bit_pos); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci if (bit_pos < d.max) 72962306a36Sopenharmony_ci return false; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci return true; 73262306a36Sopenharmony_ci} 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ciint f2fs_read_inline_dir(struct file *file, struct dir_context *ctx, 73562306a36Sopenharmony_ci struct fscrypt_str *fstr) 73662306a36Sopenharmony_ci{ 73762306a36Sopenharmony_ci struct inode *inode = file_inode(file); 73862306a36Sopenharmony_ci struct page *ipage = NULL; 73962306a36Sopenharmony_ci struct f2fs_dentry_ptr d; 74062306a36Sopenharmony_ci void *inline_dentry = NULL; 74162306a36Sopenharmony_ci int err; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci make_dentry_ptr_inline(inode, &d, inline_dentry); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci if (ctx->pos == d.max) 74662306a36Sopenharmony_ci return 0; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino); 74962306a36Sopenharmony_ci if (IS_ERR(ipage)) 75062306a36Sopenharmony_ci return PTR_ERR(ipage); 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci /* 75362306a36Sopenharmony_ci * f2fs_readdir was protected by inode.i_rwsem, it is safe to access 75462306a36Sopenharmony_ci * ipage without page's lock held. 75562306a36Sopenharmony_ci */ 75662306a36Sopenharmony_ci unlock_page(ipage); 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci inline_dentry = inline_data_addr(inode, ipage); 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci make_dentry_ptr_inline(inode, &d, inline_dentry); 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci err = f2fs_fill_dentries(ctx, &d, 0, fstr); 76362306a36Sopenharmony_ci if (!err) 76462306a36Sopenharmony_ci ctx->pos = d.max; 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci f2fs_put_page(ipage, 0); 76762306a36Sopenharmony_ci return err < 0 ? err : 0; 76862306a36Sopenharmony_ci} 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ciint f2fs_inline_data_fiemap(struct inode *inode, 77162306a36Sopenharmony_ci struct fiemap_extent_info *fieinfo, __u64 start, __u64 len) 77262306a36Sopenharmony_ci{ 77362306a36Sopenharmony_ci __u64 byteaddr, ilen; 77462306a36Sopenharmony_ci __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED | 77562306a36Sopenharmony_ci FIEMAP_EXTENT_LAST; 77662306a36Sopenharmony_ci struct node_info ni; 77762306a36Sopenharmony_ci struct page *ipage; 77862306a36Sopenharmony_ci int err = 0; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino); 78162306a36Sopenharmony_ci if (IS_ERR(ipage)) 78262306a36Sopenharmony_ci return PTR_ERR(ipage); 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci if ((S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) && 78562306a36Sopenharmony_ci !f2fs_has_inline_data(inode)) { 78662306a36Sopenharmony_ci err = -EAGAIN; 78762306a36Sopenharmony_ci goto out; 78862306a36Sopenharmony_ci } 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode) && !f2fs_has_inline_dentry(inode)) { 79162306a36Sopenharmony_ci err = -EAGAIN; 79262306a36Sopenharmony_ci goto out; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci ilen = min_t(size_t, MAX_INLINE_DATA(inode), i_size_read(inode)); 79662306a36Sopenharmony_ci if (start >= ilen) 79762306a36Sopenharmony_ci goto out; 79862306a36Sopenharmony_ci if (start + len < ilen) 79962306a36Sopenharmony_ci ilen = start + len; 80062306a36Sopenharmony_ci ilen -= start; 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci err = f2fs_get_node_info(F2FS_I_SB(inode), inode->i_ino, &ni, false); 80362306a36Sopenharmony_ci if (err) 80462306a36Sopenharmony_ci goto out; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci byteaddr = (__u64)ni.blk_addr << inode->i_sb->s_blocksize_bits; 80762306a36Sopenharmony_ci byteaddr += (char *)inline_data_addr(inode, ipage) - 80862306a36Sopenharmony_ci (char *)F2FS_INODE(ipage); 80962306a36Sopenharmony_ci err = fiemap_fill_next_extent(fieinfo, start, byteaddr, ilen, flags); 81062306a36Sopenharmony_ci trace_f2fs_fiemap(inode, start, byteaddr, ilen, flags, err); 81162306a36Sopenharmony_ciout: 81262306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 81362306a36Sopenharmony_ci return err; 81462306a36Sopenharmony_ci} 815