147e4937aSGao Xiang // SPDX-License-Identifier: GPL-2.0-only 247e4937aSGao Xiang /* 347e4937aSGao Xiang * Copyright (C) 2017-2018 HUAWEI, Inc. 447e4937aSGao Xiang * http://www.huawei.com/ 547e4937aSGao Xiang * Created by Gao Xiang <gaoxiang25@huawei.com> 647e4937aSGao Xiang */ 747e4937aSGao Xiang #include "xattr.h" 847e4937aSGao Xiang 947e4937aSGao Xiang #include <trace/events/erofs.h> 1047e4937aSGao Xiang 1147e4937aSGao Xiang /* no locking */ 1247e4937aSGao Xiang static int read_inode(struct inode *inode, void *data) 1347e4937aSGao Xiang { 1447e4937aSGao Xiang struct erofs_vnode *vi = EROFS_V(inode); 1547e4937aSGao Xiang struct erofs_inode_v1 *v1 = data; 1647e4937aSGao Xiang const unsigned int advise = le16_to_cpu(v1->i_advise); 1747e4937aSGao Xiang erofs_blk_t nblks = 0; 1847e4937aSGao Xiang 1947e4937aSGao Xiang vi->datamode = __inode_data_mapping(advise); 2047e4937aSGao Xiang 2147e4937aSGao Xiang if (unlikely(vi->datamode >= EROFS_INODE_LAYOUT_MAX)) { 2247e4937aSGao Xiang errln("unsupported data mapping %u of nid %llu", 2347e4937aSGao Xiang vi->datamode, vi->nid); 2447e4937aSGao Xiang DBG_BUGON(1); 2547e4937aSGao Xiang return -EOPNOTSUPP; 2647e4937aSGao Xiang } 2747e4937aSGao Xiang 2847e4937aSGao Xiang if (__inode_version(advise) == EROFS_INODE_LAYOUT_V2) { 2947e4937aSGao Xiang struct erofs_inode_v2 *v2 = data; 3047e4937aSGao Xiang 3147e4937aSGao Xiang vi->inode_isize = sizeof(struct erofs_inode_v2); 3247e4937aSGao Xiang vi->xattr_isize = ondisk_xattr_ibody_size(v2->i_xattr_icount); 3347e4937aSGao Xiang 3447e4937aSGao Xiang inode->i_mode = le16_to_cpu(v2->i_mode); 3547e4937aSGao Xiang if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || 3647e4937aSGao Xiang S_ISLNK(inode->i_mode)) 3747e4937aSGao Xiang vi->raw_blkaddr = le32_to_cpu(v2->i_u.raw_blkaddr); 3847e4937aSGao Xiang else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) 3947e4937aSGao Xiang inode->i_rdev = 4047e4937aSGao Xiang new_decode_dev(le32_to_cpu(v2->i_u.rdev)); 4147e4937aSGao Xiang else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) 4247e4937aSGao Xiang inode->i_rdev = 0; 4347e4937aSGao Xiang else 4447e4937aSGao Xiang goto bogusimode; 4547e4937aSGao Xiang 4647e4937aSGao Xiang i_uid_write(inode, le32_to_cpu(v2->i_uid)); 4747e4937aSGao Xiang i_gid_write(inode, le32_to_cpu(v2->i_gid)); 4847e4937aSGao Xiang set_nlink(inode, le32_to_cpu(v2->i_nlink)); 4947e4937aSGao Xiang 5047e4937aSGao Xiang /* ns timestamp */ 5147e4937aSGao Xiang inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = 5247e4937aSGao Xiang le64_to_cpu(v2->i_ctime); 5347e4937aSGao Xiang inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 5447e4937aSGao Xiang le32_to_cpu(v2->i_ctime_nsec); 5547e4937aSGao Xiang 5647e4937aSGao Xiang inode->i_size = le64_to_cpu(v2->i_size); 5747e4937aSGao Xiang 5847e4937aSGao Xiang /* total blocks for compressed files */ 5947e4937aSGao Xiang if (is_inode_layout_compression(inode)) 6047e4937aSGao Xiang nblks = le32_to_cpu(v2->i_u.compressed_blocks); 6147e4937aSGao Xiang } else if (__inode_version(advise) == EROFS_INODE_LAYOUT_V1) { 6247e4937aSGao Xiang struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); 6347e4937aSGao Xiang 6447e4937aSGao Xiang vi->inode_isize = sizeof(struct erofs_inode_v1); 6547e4937aSGao Xiang vi->xattr_isize = ondisk_xattr_ibody_size(v1->i_xattr_icount); 6647e4937aSGao Xiang 6747e4937aSGao Xiang inode->i_mode = le16_to_cpu(v1->i_mode); 6847e4937aSGao Xiang if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || 6947e4937aSGao Xiang S_ISLNK(inode->i_mode)) 7047e4937aSGao Xiang vi->raw_blkaddr = le32_to_cpu(v1->i_u.raw_blkaddr); 7147e4937aSGao Xiang else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) 7247e4937aSGao Xiang inode->i_rdev = 7347e4937aSGao Xiang new_decode_dev(le32_to_cpu(v1->i_u.rdev)); 7447e4937aSGao Xiang else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) 7547e4937aSGao Xiang inode->i_rdev = 0; 7647e4937aSGao Xiang else 7747e4937aSGao Xiang goto bogusimode; 7847e4937aSGao Xiang 7947e4937aSGao Xiang i_uid_write(inode, le16_to_cpu(v1->i_uid)); 8047e4937aSGao Xiang i_gid_write(inode, le16_to_cpu(v1->i_gid)); 8147e4937aSGao Xiang set_nlink(inode, le16_to_cpu(v1->i_nlink)); 8247e4937aSGao Xiang 8347e4937aSGao Xiang /* use build time to derive all file time */ 8447e4937aSGao Xiang inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = 8547e4937aSGao Xiang sbi->build_time; 8647e4937aSGao Xiang inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 8747e4937aSGao Xiang sbi->build_time_nsec; 8847e4937aSGao Xiang 8947e4937aSGao Xiang inode->i_size = le32_to_cpu(v1->i_size); 9047e4937aSGao Xiang if (is_inode_layout_compression(inode)) 9147e4937aSGao Xiang nblks = le32_to_cpu(v1->i_u.compressed_blocks); 9247e4937aSGao Xiang } else { 9347e4937aSGao Xiang errln("unsupported on-disk inode version %u of nid %llu", 9447e4937aSGao Xiang __inode_version(advise), vi->nid); 9547e4937aSGao Xiang DBG_BUGON(1); 9647e4937aSGao Xiang return -EOPNOTSUPP; 9747e4937aSGao Xiang } 9847e4937aSGao Xiang 9947e4937aSGao Xiang if (!nblks) 10047e4937aSGao Xiang /* measure inode.i_blocks as generic filesystems */ 10147e4937aSGao Xiang inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9; 10247e4937aSGao Xiang else 10347e4937aSGao Xiang inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK; 10447e4937aSGao Xiang return 0; 10547e4937aSGao Xiang 10647e4937aSGao Xiang bogusimode: 10747e4937aSGao Xiang errln("bogus i_mode (%o) @ nid %llu", inode->i_mode, vi->nid); 10847e4937aSGao Xiang DBG_BUGON(1); 10947e4937aSGao Xiang return -EFSCORRUPTED; 11047e4937aSGao Xiang } 11147e4937aSGao Xiang 11247e4937aSGao Xiang /* 11347e4937aSGao Xiang * try_lock can be required since locking order is: 11447e4937aSGao Xiang * file data(fs_inode) 11547e4937aSGao Xiang * meta(bd_inode) 11647e4937aSGao Xiang * but the majority of the callers is "iget", 11747e4937aSGao Xiang * in that case we are pretty sure no deadlock since 11847e4937aSGao Xiang * no data operations exist. However I tend to 11947e4937aSGao Xiang * try_lock since it takes no much overhead and 12047e4937aSGao Xiang * will success immediately. 12147e4937aSGao Xiang */ 12247e4937aSGao Xiang static int fill_inline_data(struct inode *inode, void *data, 12347e4937aSGao Xiang unsigned int m_pofs) 12447e4937aSGao Xiang { 12547e4937aSGao Xiang struct erofs_vnode *vi = EROFS_V(inode); 12647e4937aSGao Xiang struct erofs_sb_info *sbi = EROFS_I_SB(inode); 12747e4937aSGao Xiang 12847e4937aSGao Xiang /* should be inode inline C */ 12947e4937aSGao Xiang if (!is_inode_flat_inline(inode)) 13047e4937aSGao Xiang return 0; 13147e4937aSGao Xiang 13247e4937aSGao Xiang /* fast symlink (following ext4) */ 13347e4937aSGao Xiang if (S_ISLNK(inode->i_mode) && inode->i_size < PAGE_SIZE) { 13447e4937aSGao Xiang char *lnk = erofs_kmalloc(sbi, inode->i_size + 1, GFP_KERNEL); 13547e4937aSGao Xiang 13647e4937aSGao Xiang if (unlikely(!lnk)) 13747e4937aSGao Xiang return -ENOMEM; 13847e4937aSGao Xiang 13947e4937aSGao Xiang m_pofs += vi->inode_isize + vi->xattr_isize; 14047e4937aSGao Xiang 14147e4937aSGao Xiang /* inline symlink data shouldn't across page boundary as well */ 14247e4937aSGao Xiang if (unlikely(m_pofs + inode->i_size > PAGE_SIZE)) { 14347e4937aSGao Xiang kfree(lnk); 14447e4937aSGao Xiang errln("inline data cross block boundary @ nid %llu", 14547e4937aSGao Xiang vi->nid); 14647e4937aSGao Xiang DBG_BUGON(1); 14747e4937aSGao Xiang return -EFSCORRUPTED; 14847e4937aSGao Xiang } 14947e4937aSGao Xiang 15047e4937aSGao Xiang /* get in-page inline data */ 15147e4937aSGao Xiang memcpy(lnk, data + m_pofs, inode->i_size); 15247e4937aSGao Xiang lnk[inode->i_size] = '\0'; 15347e4937aSGao Xiang 15447e4937aSGao Xiang inode->i_link = lnk; 15547e4937aSGao Xiang set_inode_fast_symlink(inode); 15647e4937aSGao Xiang } 15747e4937aSGao Xiang return 0; 15847e4937aSGao Xiang } 15947e4937aSGao Xiang 16047e4937aSGao Xiang static int fill_inode(struct inode *inode, int isdir) 16147e4937aSGao Xiang { 16247e4937aSGao Xiang struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); 16347e4937aSGao Xiang struct erofs_vnode *vi = EROFS_V(inode); 16447e4937aSGao Xiang struct page *page; 16547e4937aSGao Xiang void *data; 16647e4937aSGao Xiang int err; 16747e4937aSGao Xiang erofs_blk_t blkaddr; 16847e4937aSGao Xiang unsigned int ofs; 16947e4937aSGao Xiang erofs_off_t inode_loc; 17047e4937aSGao Xiang 17147e4937aSGao Xiang trace_erofs_fill_inode(inode, isdir); 17247e4937aSGao Xiang inode_loc = iloc(sbi, vi->nid); 17347e4937aSGao Xiang blkaddr = erofs_blknr(inode_loc); 17447e4937aSGao Xiang ofs = erofs_blkoff(inode_loc); 17547e4937aSGao Xiang 17647e4937aSGao Xiang debugln("%s, reading inode nid %llu at %u of blkaddr %u", 17747e4937aSGao Xiang __func__, vi->nid, ofs, blkaddr); 17847e4937aSGao Xiang 17947e4937aSGao Xiang page = erofs_get_meta_page(inode->i_sb, blkaddr, isdir); 18047e4937aSGao Xiang 18147e4937aSGao Xiang if (IS_ERR(page)) { 18247e4937aSGao Xiang errln("failed to get inode (nid: %llu) page, err %ld", 18347e4937aSGao Xiang vi->nid, PTR_ERR(page)); 18447e4937aSGao Xiang return PTR_ERR(page); 18547e4937aSGao Xiang } 18647e4937aSGao Xiang 18747e4937aSGao Xiang DBG_BUGON(!PageUptodate(page)); 18847e4937aSGao Xiang data = page_address(page); 18947e4937aSGao Xiang 19047e4937aSGao Xiang err = read_inode(inode, data + ofs); 19147e4937aSGao Xiang if (!err) { 19247e4937aSGao Xiang /* setup the new inode */ 19347e4937aSGao Xiang if (S_ISREG(inode->i_mode)) { 19447e4937aSGao Xiang inode->i_op = &erofs_generic_iops; 19547e4937aSGao Xiang inode->i_fop = &generic_ro_fops; 19647e4937aSGao Xiang } else if (S_ISDIR(inode->i_mode)) { 19747e4937aSGao Xiang inode->i_op = &erofs_dir_iops; 19847e4937aSGao Xiang inode->i_fop = &erofs_dir_fops; 19947e4937aSGao Xiang } else if (S_ISLNK(inode->i_mode)) { 20047e4937aSGao Xiang /* by default, page_get_link is used for symlink */ 20147e4937aSGao Xiang inode->i_op = &erofs_symlink_iops; 20247e4937aSGao Xiang inode_nohighmem(inode); 20347e4937aSGao Xiang } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || 20447e4937aSGao Xiang S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { 20547e4937aSGao Xiang inode->i_op = &erofs_generic_iops; 20647e4937aSGao Xiang init_special_inode(inode, inode->i_mode, inode->i_rdev); 20747e4937aSGao Xiang goto out_unlock; 20847e4937aSGao Xiang } else { 20947e4937aSGao Xiang err = -EFSCORRUPTED; 21047e4937aSGao Xiang goto out_unlock; 21147e4937aSGao Xiang } 21247e4937aSGao Xiang 21347e4937aSGao Xiang if (is_inode_layout_compression(inode)) { 21447e4937aSGao Xiang err = z_erofs_fill_inode(inode); 21547e4937aSGao Xiang goto out_unlock; 21647e4937aSGao Xiang } 21747e4937aSGao Xiang 21847e4937aSGao Xiang inode->i_mapping->a_ops = &erofs_raw_access_aops; 21947e4937aSGao Xiang 22047e4937aSGao Xiang /* fill last page if inline data is available */ 22147e4937aSGao Xiang err = fill_inline_data(inode, data, ofs); 22247e4937aSGao Xiang } 22347e4937aSGao Xiang 22447e4937aSGao Xiang out_unlock: 22547e4937aSGao Xiang unlock_page(page); 22647e4937aSGao Xiang put_page(page); 22747e4937aSGao Xiang return err; 22847e4937aSGao Xiang } 22947e4937aSGao Xiang 23047e4937aSGao Xiang /* 23147e4937aSGao Xiang * erofs nid is 64bits, but i_ino is 'unsigned long', therefore 23247e4937aSGao Xiang * we should do more for 32-bit platform to find the right inode. 23347e4937aSGao Xiang */ 23447e4937aSGao Xiang #if BITS_PER_LONG == 32 23547e4937aSGao Xiang static int erofs_ilookup_test_actor(struct inode *inode, void *opaque) 23647e4937aSGao Xiang { 23747e4937aSGao Xiang const erofs_nid_t nid = *(erofs_nid_t *)opaque; 23847e4937aSGao Xiang 23947e4937aSGao Xiang return EROFS_V(inode)->nid == nid; 24047e4937aSGao Xiang } 24147e4937aSGao Xiang 24247e4937aSGao Xiang static int erofs_iget_set_actor(struct inode *inode, void *opaque) 24347e4937aSGao Xiang { 24447e4937aSGao Xiang const erofs_nid_t nid = *(erofs_nid_t *)opaque; 24547e4937aSGao Xiang 24647e4937aSGao Xiang inode->i_ino = erofs_inode_hash(nid); 24747e4937aSGao Xiang return 0; 24847e4937aSGao Xiang } 24947e4937aSGao Xiang #endif 25047e4937aSGao Xiang 25147e4937aSGao Xiang static inline struct inode *erofs_iget_locked(struct super_block *sb, 25247e4937aSGao Xiang erofs_nid_t nid) 25347e4937aSGao Xiang { 25447e4937aSGao Xiang const unsigned long hashval = erofs_inode_hash(nid); 25547e4937aSGao Xiang 25647e4937aSGao Xiang #if BITS_PER_LONG >= 64 25747e4937aSGao Xiang /* it is safe to use iget_locked for >= 64-bit platform */ 25847e4937aSGao Xiang return iget_locked(sb, hashval); 25947e4937aSGao Xiang #else 26047e4937aSGao Xiang return iget5_locked(sb, hashval, erofs_ilookup_test_actor, 26147e4937aSGao Xiang erofs_iget_set_actor, &nid); 26247e4937aSGao Xiang #endif 26347e4937aSGao Xiang } 26447e4937aSGao Xiang 26547e4937aSGao Xiang struct inode *erofs_iget(struct super_block *sb, 26647e4937aSGao Xiang erofs_nid_t nid, 26747e4937aSGao Xiang bool isdir) 26847e4937aSGao Xiang { 26947e4937aSGao Xiang struct inode *inode = erofs_iget_locked(sb, nid); 27047e4937aSGao Xiang 27147e4937aSGao Xiang if (unlikely(!inode)) 27247e4937aSGao Xiang return ERR_PTR(-ENOMEM); 27347e4937aSGao Xiang 27447e4937aSGao Xiang if (inode->i_state & I_NEW) { 27547e4937aSGao Xiang int err; 27647e4937aSGao Xiang struct erofs_vnode *vi = EROFS_V(inode); 27747e4937aSGao Xiang 27847e4937aSGao Xiang vi->nid = nid; 27947e4937aSGao Xiang 28047e4937aSGao Xiang err = fill_inode(inode, isdir); 28147e4937aSGao Xiang if (likely(!err)) 28247e4937aSGao Xiang unlock_new_inode(inode); 28347e4937aSGao Xiang else { 28447e4937aSGao Xiang iget_failed(inode); 28547e4937aSGao Xiang inode = ERR_PTR(err); 28647e4937aSGao Xiang } 28747e4937aSGao Xiang } 28847e4937aSGao Xiang return inode; 28947e4937aSGao Xiang } 29047e4937aSGao Xiang 29147e4937aSGao Xiang int erofs_getattr(const struct path *path, struct kstat *stat, 29247e4937aSGao Xiang u32 request_mask, unsigned int query_flags) 29347e4937aSGao Xiang { 29447e4937aSGao Xiang struct inode *const inode = d_inode(path->dentry); 29547e4937aSGao Xiang 29647e4937aSGao Xiang if (is_inode_layout_compression(inode)) 29747e4937aSGao Xiang stat->attributes |= STATX_ATTR_COMPRESSED; 29847e4937aSGao Xiang 29947e4937aSGao Xiang stat->attributes |= STATX_ATTR_IMMUTABLE; 30047e4937aSGao Xiang stat->attributes_mask |= (STATX_ATTR_COMPRESSED | 30147e4937aSGao Xiang STATX_ATTR_IMMUTABLE); 30247e4937aSGao Xiang 30347e4937aSGao Xiang generic_fillattr(inode, stat); 30447e4937aSGao Xiang return 0; 30547e4937aSGao Xiang } 30647e4937aSGao Xiang 30747e4937aSGao Xiang const struct inode_operations erofs_generic_iops = { 30847e4937aSGao Xiang .getattr = erofs_getattr, 30947e4937aSGao Xiang #ifdef CONFIG_EROFS_FS_XATTR 31047e4937aSGao Xiang .listxattr = erofs_listxattr, 31147e4937aSGao Xiang #endif 31247e4937aSGao Xiang .get_acl = erofs_get_acl, 31347e4937aSGao Xiang }; 31447e4937aSGao Xiang 31547e4937aSGao Xiang const struct inode_operations erofs_symlink_iops = { 31647e4937aSGao Xiang .get_link = page_get_link, 31747e4937aSGao Xiang .getattr = erofs_getattr, 31847e4937aSGao Xiang #ifdef CONFIG_EROFS_FS_XATTR 31947e4937aSGao Xiang .listxattr = erofs_listxattr, 32047e4937aSGao Xiang #endif 32147e4937aSGao Xiang .get_acl = erofs_get_acl, 32247e4937aSGao Xiang }; 32347e4937aSGao Xiang 32447e4937aSGao Xiang const struct inode_operations erofs_fast_symlink_iops = { 32547e4937aSGao Xiang .get_link = simple_get_link, 32647e4937aSGao Xiang .getattr = erofs_getattr, 32747e4937aSGao Xiang #ifdef CONFIG_EROFS_FS_XATTR 32847e4937aSGao Xiang .listxattr = erofs_listxattr, 32947e4937aSGao Xiang #endif 33047e4937aSGao Xiang .get_acl = erofs_get_acl, 33147e4937aSGao Xiang }; 33247e4937aSGao Xiang 333