18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2017-2018 HUAWEI, Inc. 48c2ecf20Sopenharmony_ci * https://www.huawei.com/ 58c2ecf20Sopenharmony_ci * Created by Gao Xiang <gaoxiang25@huawei.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#include "xattr.h" 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <trace/events/erofs.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* 128c2ecf20Sopenharmony_ci * if inode is successfully read, return its inode page (or sometimes 138c2ecf20Sopenharmony_ci * the inode payload page if it's an extended inode) in order to fill 148c2ecf20Sopenharmony_ci * inline data if possible. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_cistatic struct page *erofs_read_inode(struct inode *inode, 178c2ecf20Sopenharmony_ci unsigned int *ofs) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci struct super_block *sb = inode->i_sb; 208c2ecf20Sopenharmony_ci struct erofs_sb_info *sbi = EROFS_SB(sb); 218c2ecf20Sopenharmony_ci struct erofs_inode *vi = EROFS_I(inode); 228c2ecf20Sopenharmony_ci const erofs_off_t inode_loc = iloc(sbi, vi->nid); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci erofs_blk_t blkaddr, nblks = 0; 258c2ecf20Sopenharmony_ci struct page *page; 268c2ecf20Sopenharmony_ci struct erofs_inode_compact *dic; 278c2ecf20Sopenharmony_ci struct erofs_inode_extended *die, *copied = NULL; 288c2ecf20Sopenharmony_ci unsigned int ifmt; 298c2ecf20Sopenharmony_ci int err; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci blkaddr = erofs_blknr(inode_loc); 328c2ecf20Sopenharmony_ci *ofs = erofs_blkoff(inode_loc); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci erofs_dbg("%s, reading inode nid %llu at %u of blkaddr %u", 358c2ecf20Sopenharmony_ci __func__, vi->nid, *ofs, blkaddr); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci page = erofs_get_meta_page(sb, blkaddr); 388c2ecf20Sopenharmony_ci if (IS_ERR(page)) { 398c2ecf20Sopenharmony_ci erofs_err(sb, "failed to get inode (nid: %llu) page, err %ld", 408c2ecf20Sopenharmony_ci vi->nid, PTR_ERR(page)); 418c2ecf20Sopenharmony_ci return page; 428c2ecf20Sopenharmony_ci } 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci dic = page_address(page) + *ofs; 458c2ecf20Sopenharmony_ci ifmt = le16_to_cpu(dic->i_format); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (ifmt & ~EROFS_I_ALL) { 488c2ecf20Sopenharmony_ci erofs_err(inode->i_sb, "unsupported i_format %u of nid %llu", 498c2ecf20Sopenharmony_ci ifmt, vi->nid); 508c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 518c2ecf20Sopenharmony_ci goto err_out; 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci vi->datalayout = erofs_inode_datalayout(ifmt); 558c2ecf20Sopenharmony_ci if (vi->datalayout >= EROFS_INODE_DATALAYOUT_MAX) { 568c2ecf20Sopenharmony_ci erofs_err(inode->i_sb, "unsupported datalayout %u of nid %llu", 578c2ecf20Sopenharmony_ci vi->datalayout, vi->nid); 588c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 598c2ecf20Sopenharmony_ci goto err_out; 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci switch (erofs_inode_version(ifmt)) { 638c2ecf20Sopenharmony_ci case EROFS_INODE_LAYOUT_EXTENDED: 648c2ecf20Sopenharmony_ci vi->inode_isize = sizeof(struct erofs_inode_extended); 658c2ecf20Sopenharmony_ci /* check if the inode acrosses page boundary */ 668c2ecf20Sopenharmony_ci if (*ofs + vi->inode_isize <= PAGE_SIZE) { 678c2ecf20Sopenharmony_ci *ofs += vi->inode_isize; 688c2ecf20Sopenharmony_ci die = (struct erofs_inode_extended *)dic; 698c2ecf20Sopenharmony_ci } else { 708c2ecf20Sopenharmony_ci const unsigned int gotten = PAGE_SIZE - *ofs; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci copied = kmalloc(vi->inode_isize, GFP_NOFS); 738c2ecf20Sopenharmony_ci if (!copied) { 748c2ecf20Sopenharmony_ci err = -ENOMEM; 758c2ecf20Sopenharmony_ci goto err_out; 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci memcpy(copied, dic, gotten); 788c2ecf20Sopenharmony_ci unlock_page(page); 798c2ecf20Sopenharmony_ci put_page(page); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci page = erofs_get_meta_page(sb, blkaddr + 1); 828c2ecf20Sopenharmony_ci if (IS_ERR(page)) { 838c2ecf20Sopenharmony_ci erofs_err(sb, "failed to get inode payload page (nid: %llu), err %ld", 848c2ecf20Sopenharmony_ci vi->nid, PTR_ERR(page)); 858c2ecf20Sopenharmony_ci kfree(copied); 868c2ecf20Sopenharmony_ci return page; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci *ofs = vi->inode_isize - gotten; 898c2ecf20Sopenharmony_ci memcpy((u8 *)copied + gotten, page_address(page), *ofs); 908c2ecf20Sopenharmony_ci die = copied; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci vi->xattr_isize = erofs_xattr_ibody_size(die->i_xattr_icount); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci inode->i_mode = le16_to_cpu(die->i_mode); 958c2ecf20Sopenharmony_ci switch (inode->i_mode & S_IFMT) { 968c2ecf20Sopenharmony_ci case S_IFREG: 978c2ecf20Sopenharmony_ci case S_IFDIR: 988c2ecf20Sopenharmony_ci case S_IFLNK: 998c2ecf20Sopenharmony_ci vi->raw_blkaddr = le32_to_cpu(die->i_u.raw_blkaddr); 1008c2ecf20Sopenharmony_ci break; 1018c2ecf20Sopenharmony_ci case S_IFCHR: 1028c2ecf20Sopenharmony_ci case S_IFBLK: 1038c2ecf20Sopenharmony_ci inode->i_rdev = 1048c2ecf20Sopenharmony_ci new_decode_dev(le32_to_cpu(die->i_u.rdev)); 1058c2ecf20Sopenharmony_ci break; 1068c2ecf20Sopenharmony_ci case S_IFIFO: 1078c2ecf20Sopenharmony_ci case S_IFSOCK: 1088c2ecf20Sopenharmony_ci inode->i_rdev = 0; 1098c2ecf20Sopenharmony_ci break; 1108c2ecf20Sopenharmony_ci default: 1118c2ecf20Sopenharmony_ci goto bogusimode; 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci i_uid_write(inode, le32_to_cpu(die->i_uid)); 1148c2ecf20Sopenharmony_ci i_gid_write(inode, le32_to_cpu(die->i_gid)); 1158c2ecf20Sopenharmony_ci set_nlink(inode, le32_to_cpu(die->i_nlink)); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* extended inode has its own timestamp */ 1188c2ecf20Sopenharmony_ci inode->i_ctime.tv_sec = le64_to_cpu(die->i_ctime); 1198c2ecf20Sopenharmony_ci inode->i_ctime.tv_nsec = le32_to_cpu(die->i_ctime_nsec); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci inode->i_size = le64_to_cpu(die->i_size); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* total blocks for compressed files */ 1248c2ecf20Sopenharmony_ci if (erofs_inode_is_data_compressed(vi->datalayout)) 1258c2ecf20Sopenharmony_ci nblks = le32_to_cpu(die->i_u.compressed_blocks); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci kfree(copied); 1288c2ecf20Sopenharmony_ci break; 1298c2ecf20Sopenharmony_ci case EROFS_INODE_LAYOUT_COMPACT: 1308c2ecf20Sopenharmony_ci vi->inode_isize = sizeof(struct erofs_inode_compact); 1318c2ecf20Sopenharmony_ci *ofs += vi->inode_isize; 1328c2ecf20Sopenharmony_ci vi->xattr_isize = erofs_xattr_ibody_size(dic->i_xattr_icount); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci inode->i_mode = le16_to_cpu(dic->i_mode); 1358c2ecf20Sopenharmony_ci switch (inode->i_mode & S_IFMT) { 1368c2ecf20Sopenharmony_ci case S_IFREG: 1378c2ecf20Sopenharmony_ci case S_IFDIR: 1388c2ecf20Sopenharmony_ci case S_IFLNK: 1398c2ecf20Sopenharmony_ci vi->raw_blkaddr = le32_to_cpu(dic->i_u.raw_blkaddr); 1408c2ecf20Sopenharmony_ci break; 1418c2ecf20Sopenharmony_ci case S_IFCHR: 1428c2ecf20Sopenharmony_ci case S_IFBLK: 1438c2ecf20Sopenharmony_ci inode->i_rdev = 1448c2ecf20Sopenharmony_ci new_decode_dev(le32_to_cpu(dic->i_u.rdev)); 1458c2ecf20Sopenharmony_ci break; 1468c2ecf20Sopenharmony_ci case S_IFIFO: 1478c2ecf20Sopenharmony_ci case S_IFSOCK: 1488c2ecf20Sopenharmony_ci inode->i_rdev = 0; 1498c2ecf20Sopenharmony_ci break; 1508c2ecf20Sopenharmony_ci default: 1518c2ecf20Sopenharmony_ci goto bogusimode; 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci i_uid_write(inode, le16_to_cpu(dic->i_uid)); 1548c2ecf20Sopenharmony_ci i_gid_write(inode, le16_to_cpu(dic->i_gid)); 1558c2ecf20Sopenharmony_ci set_nlink(inode, le16_to_cpu(dic->i_nlink)); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* use build time for compact inodes */ 1588c2ecf20Sopenharmony_ci inode->i_ctime.tv_sec = sbi->build_time; 1598c2ecf20Sopenharmony_ci inode->i_ctime.tv_nsec = sbi->build_time_nsec; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci inode->i_size = le32_to_cpu(dic->i_size); 1628c2ecf20Sopenharmony_ci if (erofs_inode_is_data_compressed(vi->datalayout)) 1638c2ecf20Sopenharmony_ci nblks = le32_to_cpu(dic->i_u.compressed_blocks); 1648c2ecf20Sopenharmony_ci break; 1658c2ecf20Sopenharmony_ci default: 1668c2ecf20Sopenharmony_ci erofs_err(inode->i_sb, 1678c2ecf20Sopenharmony_ci "unsupported on-disk inode version %u of nid %llu", 1688c2ecf20Sopenharmony_ci erofs_inode_version(ifmt), vi->nid); 1698c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 1708c2ecf20Sopenharmony_ci goto err_out; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci inode->i_mtime.tv_sec = inode->i_ctime.tv_sec; 1748c2ecf20Sopenharmony_ci inode->i_atime.tv_sec = inode->i_ctime.tv_sec; 1758c2ecf20Sopenharmony_ci inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec; 1768c2ecf20Sopenharmony_ci inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci if (!nblks) 1798c2ecf20Sopenharmony_ci /* measure inode.i_blocks as generic filesystems */ 1808c2ecf20Sopenharmony_ci inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9; 1818c2ecf20Sopenharmony_ci else 1828c2ecf20Sopenharmony_ci inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK; 1838c2ecf20Sopenharmony_ci return page; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cibogusimode: 1868c2ecf20Sopenharmony_ci erofs_err(inode->i_sb, "bogus i_mode (%o) @ nid %llu", 1878c2ecf20Sopenharmony_ci inode->i_mode, vi->nid); 1888c2ecf20Sopenharmony_ci err = -EFSCORRUPTED; 1898c2ecf20Sopenharmony_cierr_out: 1908c2ecf20Sopenharmony_ci DBG_BUGON(1); 1918c2ecf20Sopenharmony_ci kfree(copied); 1928c2ecf20Sopenharmony_ci unlock_page(page); 1938c2ecf20Sopenharmony_ci put_page(page); 1948c2ecf20Sopenharmony_ci return ERR_PTR(err); 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int erofs_fill_symlink(struct inode *inode, void *data, 1988c2ecf20Sopenharmony_ci unsigned int m_pofs) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci struct erofs_inode *vi = EROFS_I(inode); 2018c2ecf20Sopenharmony_ci char *lnk; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci /* if it cannot be handled with fast symlink scheme */ 2048c2ecf20Sopenharmony_ci if (vi->datalayout != EROFS_INODE_FLAT_INLINE || 2058c2ecf20Sopenharmony_ci inode->i_size >= PAGE_SIZE) { 2068c2ecf20Sopenharmony_ci inode->i_op = &erofs_symlink_iops; 2078c2ecf20Sopenharmony_ci return 0; 2088c2ecf20Sopenharmony_ci } 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci lnk = kmalloc(inode->i_size + 1, GFP_KERNEL); 2118c2ecf20Sopenharmony_ci if (!lnk) 2128c2ecf20Sopenharmony_ci return -ENOMEM; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci m_pofs += vi->xattr_isize; 2158c2ecf20Sopenharmony_ci /* inline symlink data shouldn't cross page boundary as well */ 2168c2ecf20Sopenharmony_ci if (m_pofs + inode->i_size > PAGE_SIZE) { 2178c2ecf20Sopenharmony_ci kfree(lnk); 2188c2ecf20Sopenharmony_ci erofs_err(inode->i_sb, 2198c2ecf20Sopenharmony_ci "inline data cross block boundary @ nid %llu", 2208c2ecf20Sopenharmony_ci vi->nid); 2218c2ecf20Sopenharmony_ci DBG_BUGON(1); 2228c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci memcpy(lnk, data + m_pofs, inode->i_size); 2268c2ecf20Sopenharmony_ci lnk[inode->i_size] = '\0'; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci inode->i_link = lnk; 2298c2ecf20Sopenharmony_ci inode->i_op = &erofs_fast_symlink_iops; 2308c2ecf20Sopenharmony_ci return 0; 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cistatic int erofs_fill_inode(struct inode *inode, int isdir) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci struct erofs_inode *vi = EROFS_I(inode); 2368c2ecf20Sopenharmony_ci struct page *page; 2378c2ecf20Sopenharmony_ci unsigned int ofs; 2388c2ecf20Sopenharmony_ci int err = 0; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci trace_erofs_fill_inode(inode, isdir); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* read inode base data from disk */ 2438c2ecf20Sopenharmony_ci page = erofs_read_inode(inode, &ofs); 2448c2ecf20Sopenharmony_ci if (IS_ERR(page)) 2458c2ecf20Sopenharmony_ci return PTR_ERR(page); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci /* setup the new inode */ 2488c2ecf20Sopenharmony_ci switch (inode->i_mode & S_IFMT) { 2498c2ecf20Sopenharmony_ci case S_IFREG: 2508c2ecf20Sopenharmony_ci inode->i_op = &erofs_generic_iops; 2518c2ecf20Sopenharmony_ci inode->i_fop = &generic_ro_fops; 2528c2ecf20Sopenharmony_ci break; 2538c2ecf20Sopenharmony_ci case S_IFDIR: 2548c2ecf20Sopenharmony_ci inode->i_op = &erofs_dir_iops; 2558c2ecf20Sopenharmony_ci inode->i_fop = &erofs_dir_fops; 2568c2ecf20Sopenharmony_ci break; 2578c2ecf20Sopenharmony_ci case S_IFLNK: 2588c2ecf20Sopenharmony_ci err = erofs_fill_symlink(inode, page_address(page), ofs); 2598c2ecf20Sopenharmony_ci if (err) 2608c2ecf20Sopenharmony_ci goto out_unlock; 2618c2ecf20Sopenharmony_ci inode_nohighmem(inode); 2628c2ecf20Sopenharmony_ci break; 2638c2ecf20Sopenharmony_ci case S_IFCHR: 2648c2ecf20Sopenharmony_ci case S_IFBLK: 2658c2ecf20Sopenharmony_ci case S_IFIFO: 2668c2ecf20Sopenharmony_ci case S_IFSOCK: 2678c2ecf20Sopenharmony_ci inode->i_op = &erofs_generic_iops; 2688c2ecf20Sopenharmony_ci init_special_inode(inode, inode->i_mode, inode->i_rdev); 2698c2ecf20Sopenharmony_ci goto out_unlock; 2708c2ecf20Sopenharmony_ci default: 2718c2ecf20Sopenharmony_ci err = -EFSCORRUPTED; 2728c2ecf20Sopenharmony_ci goto out_unlock; 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci if (erofs_inode_is_data_compressed(vi->datalayout)) { 2768c2ecf20Sopenharmony_ci err = z_erofs_fill_inode(inode); 2778c2ecf20Sopenharmony_ci goto out_unlock; 2788c2ecf20Sopenharmony_ci } 2798c2ecf20Sopenharmony_ci inode->i_mapping->a_ops = &erofs_raw_access_aops; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ciout_unlock: 2828c2ecf20Sopenharmony_ci unlock_page(page); 2838c2ecf20Sopenharmony_ci put_page(page); 2848c2ecf20Sopenharmony_ci return err; 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci/* 2888c2ecf20Sopenharmony_ci * erofs nid is 64bits, but i_ino is 'unsigned long', therefore 2898c2ecf20Sopenharmony_ci * we should do more for 32-bit platform to find the right inode. 2908c2ecf20Sopenharmony_ci */ 2918c2ecf20Sopenharmony_cistatic int erofs_ilookup_test_actor(struct inode *inode, void *opaque) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci const erofs_nid_t nid = *(erofs_nid_t *)opaque; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci return EROFS_I(inode)->nid == nid; 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic int erofs_iget_set_actor(struct inode *inode, void *opaque) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci const erofs_nid_t nid = *(erofs_nid_t *)opaque; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci inode->i_ino = erofs_inode_hash(nid); 3038c2ecf20Sopenharmony_ci return 0; 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic inline struct inode *erofs_iget_locked(struct super_block *sb, 3078c2ecf20Sopenharmony_ci erofs_nid_t nid) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci const unsigned long hashval = erofs_inode_hash(nid); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci return iget5_locked(sb, hashval, erofs_ilookup_test_actor, 3128c2ecf20Sopenharmony_ci erofs_iget_set_actor, &nid); 3138c2ecf20Sopenharmony_ci} 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_cistruct inode *erofs_iget(struct super_block *sb, 3168c2ecf20Sopenharmony_ci erofs_nid_t nid, 3178c2ecf20Sopenharmony_ci bool isdir) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci struct inode *inode = erofs_iget_locked(sb, nid); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci if (!inode) 3228c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if (inode->i_state & I_NEW) { 3258c2ecf20Sopenharmony_ci int err; 3268c2ecf20Sopenharmony_ci struct erofs_inode *vi = EROFS_I(inode); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci vi->nid = nid; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci err = erofs_fill_inode(inode, isdir); 3318c2ecf20Sopenharmony_ci if (!err) 3328c2ecf20Sopenharmony_ci unlock_new_inode(inode); 3338c2ecf20Sopenharmony_ci else { 3348c2ecf20Sopenharmony_ci iget_failed(inode); 3358c2ecf20Sopenharmony_ci inode = ERR_PTR(err); 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci return inode; 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ciint erofs_getattr(const struct path *path, struct kstat *stat, 3428c2ecf20Sopenharmony_ci u32 request_mask, unsigned int query_flags) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci struct inode *const inode = d_inode(path->dentry); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci if (erofs_inode_is_data_compressed(EROFS_I(inode)->datalayout)) 3478c2ecf20Sopenharmony_ci stat->attributes |= STATX_ATTR_COMPRESSED; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci stat->attributes |= STATX_ATTR_IMMUTABLE; 3508c2ecf20Sopenharmony_ci stat->attributes_mask |= (STATX_ATTR_COMPRESSED | 3518c2ecf20Sopenharmony_ci STATX_ATTR_IMMUTABLE); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci generic_fillattr(inode, stat); 3548c2ecf20Sopenharmony_ci return 0; 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ciconst struct inode_operations erofs_generic_iops = { 3588c2ecf20Sopenharmony_ci .getattr = erofs_getattr, 3598c2ecf20Sopenharmony_ci .listxattr = erofs_listxattr, 3608c2ecf20Sopenharmony_ci .get_acl = erofs_get_acl, 3618c2ecf20Sopenharmony_ci}; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ciconst struct inode_operations erofs_symlink_iops = { 3648c2ecf20Sopenharmony_ci .get_link = page_get_link, 3658c2ecf20Sopenharmony_ci .getattr = erofs_getattr, 3668c2ecf20Sopenharmony_ci .listxattr = erofs_listxattr, 3678c2ecf20Sopenharmony_ci .get_acl = erofs_get_acl, 3688c2ecf20Sopenharmony_ci}; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ciconst struct inode_operations erofs_fast_symlink_iops = { 3718c2ecf20Sopenharmony_ci .get_link = simple_get_link, 3728c2ecf20Sopenharmony_ci .getattr = erofs_getattr, 3738c2ecf20Sopenharmony_ci .listxattr = erofs_listxattr, 3748c2ecf20Sopenharmony_ci .get_acl = erofs_get_acl, 3758c2ecf20Sopenharmony_ci}; 3768c2ecf20Sopenharmony_ci 377