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#ifndef __EROFS_INTERNAL_H 88c2ecf20Sopenharmony_ci#define __EROFS_INTERNAL_H 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/fs.h> 118c2ecf20Sopenharmony_ci#include <linux/dcache.h> 128c2ecf20Sopenharmony_ci#include <linux/mm.h> 138c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 148c2ecf20Sopenharmony_ci#include <linux/bio.h> 158c2ecf20Sopenharmony_ci#include <linux/buffer_head.h> 168c2ecf20Sopenharmony_ci#include <linux/magic.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 198c2ecf20Sopenharmony_ci#include "erofs_fs.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* redefine pr_fmt "erofs: " */ 228c2ecf20Sopenharmony_ci#undef pr_fmt 238c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "erofs: " fmt 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci__printf(3, 4) void _erofs_err(struct super_block *sb, 268c2ecf20Sopenharmony_ci const char *function, const char *fmt, ...); 278c2ecf20Sopenharmony_ci#define erofs_err(sb, fmt, ...) \ 288c2ecf20Sopenharmony_ci _erofs_err(sb, __func__, fmt "\n", ##__VA_ARGS__) 298c2ecf20Sopenharmony_ci__printf(3, 4) void _erofs_info(struct super_block *sb, 308c2ecf20Sopenharmony_ci const char *function, const char *fmt, ...); 318c2ecf20Sopenharmony_ci#define erofs_info(sb, fmt, ...) \ 328c2ecf20Sopenharmony_ci _erofs_info(sb, __func__, fmt "\n", ##__VA_ARGS__) 338c2ecf20Sopenharmony_ci#ifdef CONFIG_EROFS_FS_DEBUG 348c2ecf20Sopenharmony_ci#define erofs_dbg(x, ...) pr_debug(x "\n", ##__VA_ARGS__) 358c2ecf20Sopenharmony_ci#define DBG_BUGON BUG_ON 368c2ecf20Sopenharmony_ci#else 378c2ecf20Sopenharmony_ci#define erofs_dbg(x, ...) ((void)0) 388c2ecf20Sopenharmony_ci#define DBG_BUGON(x) ((void)(x)) 398c2ecf20Sopenharmony_ci#endif /* !CONFIG_EROFS_FS_DEBUG */ 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* EROFS_SUPER_MAGIC_V1 to represent the whole file system */ 428c2ecf20Sopenharmony_ci#define EROFS_SUPER_MAGIC EROFS_SUPER_MAGIC_V1 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_citypedef u64 erofs_nid_t; 458c2ecf20Sopenharmony_citypedef u64 erofs_off_t; 468c2ecf20Sopenharmony_ci/* data type for filesystem-wide blocks number */ 478c2ecf20Sopenharmony_citypedef u32 erofs_blk_t; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistruct erofs_fs_context { 508c2ecf20Sopenharmony_ci#ifdef CONFIG_EROFS_FS_ZIP 518c2ecf20Sopenharmony_ci /* current strategy of how to use managed cache */ 528c2ecf20Sopenharmony_ci unsigned char cache_strategy; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* threshold for decompression synchronously */ 558c2ecf20Sopenharmony_ci unsigned int max_sync_decompress_pages; 568c2ecf20Sopenharmony_ci#endif 578c2ecf20Sopenharmony_ci unsigned int mount_opt; 588c2ecf20Sopenharmony_ci}; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistruct erofs_sb_info { 618c2ecf20Sopenharmony_ci#ifdef CONFIG_EROFS_FS_ZIP 628c2ecf20Sopenharmony_ci /* list for all registered superblocks, mainly for shrinker */ 638c2ecf20Sopenharmony_ci struct list_head list; 648c2ecf20Sopenharmony_ci struct mutex umount_mutex; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* managed XArray arranged in physical block number */ 678c2ecf20Sopenharmony_ci struct xarray managed_pslots; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci unsigned int shrinker_run_no; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci /* pseudo inode to manage cached pages */ 728c2ecf20Sopenharmony_ci struct inode *managed_cache; 738c2ecf20Sopenharmony_ci#endif /* CONFIG_EROFS_FS_ZIP */ 748c2ecf20Sopenharmony_ci u32 blocks; 758c2ecf20Sopenharmony_ci u32 meta_blkaddr; 768c2ecf20Sopenharmony_ci#ifdef CONFIG_EROFS_FS_XATTR 778c2ecf20Sopenharmony_ci u32 xattr_blkaddr; 788c2ecf20Sopenharmony_ci#endif 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci /* inode slot unit size in bit shift */ 818c2ecf20Sopenharmony_ci unsigned char islotbits; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci u32 build_time_nsec; 848c2ecf20Sopenharmony_ci u64 build_time; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci /* what we really care is nid, rather than ino.. */ 878c2ecf20Sopenharmony_ci erofs_nid_t root_nid; 888c2ecf20Sopenharmony_ci /* used for statfs, f_files - f_favail */ 898c2ecf20Sopenharmony_ci u64 inos; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci u8 uuid[16]; /* 128-bit uuid for volume */ 928c2ecf20Sopenharmony_ci u8 volume_name[16]; /* volume name */ 938c2ecf20Sopenharmony_ci u32 feature_compat; 948c2ecf20Sopenharmony_ci u32 feature_incompat; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci struct erofs_fs_context ctx; /* options */ 978c2ecf20Sopenharmony_ci}; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci#define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info) 1008c2ecf20Sopenharmony_ci#define EROFS_I_SB(inode) ((struct erofs_sb_info *)(inode)->i_sb->s_fs_info) 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci/* Mount flags set via mount options or defaults */ 1038c2ecf20Sopenharmony_ci#define EROFS_MOUNT_XATTR_USER 0x00000010 1048c2ecf20Sopenharmony_ci#define EROFS_MOUNT_POSIX_ACL 0x00000020 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci#define clear_opt(ctx, option) ((ctx)->mount_opt &= ~EROFS_MOUNT_##option) 1078c2ecf20Sopenharmony_ci#define set_opt(ctx, option) ((ctx)->mount_opt |= EROFS_MOUNT_##option) 1088c2ecf20Sopenharmony_ci#define test_opt(ctx, option) ((ctx)->mount_opt & EROFS_MOUNT_##option) 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cienum { 1118c2ecf20Sopenharmony_ci EROFS_ZIP_CACHE_DISABLED, 1128c2ecf20Sopenharmony_ci EROFS_ZIP_CACHE_READAHEAD, 1138c2ecf20Sopenharmony_ci EROFS_ZIP_CACHE_READAROUND 1148c2ecf20Sopenharmony_ci}; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci#ifdef CONFIG_EROFS_FS_ZIP 1178c2ecf20Sopenharmony_ci#define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/* basic unit of the workstation of a super_block */ 1208c2ecf20Sopenharmony_cistruct erofs_workgroup { 1218c2ecf20Sopenharmony_ci /* the workgroup index in the workstation */ 1228c2ecf20Sopenharmony_ci pgoff_t index; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* overall workgroup reference count */ 1258c2ecf20Sopenharmony_ci atomic_t refcount; 1268c2ecf20Sopenharmony_ci}; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci#if defined(CONFIG_SMP) 1298c2ecf20Sopenharmony_cistatic inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp, 1308c2ecf20Sopenharmony_ci int val) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci preempt_disable(); 1338c2ecf20Sopenharmony_ci if (val != atomic_cmpxchg(&grp->refcount, val, EROFS_LOCKED_MAGIC)) { 1348c2ecf20Sopenharmony_ci preempt_enable(); 1358c2ecf20Sopenharmony_ci return false; 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci return true; 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp, 1418c2ecf20Sopenharmony_ci int orig_val) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci /* 1448c2ecf20Sopenharmony_ci * other observers should notice all modifications 1458c2ecf20Sopenharmony_ci * in the freezing period. 1468c2ecf20Sopenharmony_ci */ 1478c2ecf20Sopenharmony_ci smp_mb(); 1488c2ecf20Sopenharmony_ci atomic_set(&grp->refcount, orig_val); 1498c2ecf20Sopenharmony_ci preempt_enable(); 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci return atomic_cond_read_relaxed(&grp->refcount, 1558c2ecf20Sopenharmony_ci VAL != EROFS_LOCKED_MAGIC); 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci#else 1588c2ecf20Sopenharmony_cistatic inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp, 1598c2ecf20Sopenharmony_ci int val) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci preempt_disable(); 1628c2ecf20Sopenharmony_ci /* no need to spin on UP platforms, let's just disable preemption. */ 1638c2ecf20Sopenharmony_ci if (val != atomic_read(&grp->refcount)) { 1648c2ecf20Sopenharmony_ci preempt_enable(); 1658c2ecf20Sopenharmony_ci return false; 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci return true; 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp, 1718c2ecf20Sopenharmony_ci int orig_val) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci preempt_enable(); 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cistatic inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci int v = atomic_read(&grp->refcount); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* workgroup is never freezed on uniprocessor systems */ 1818c2ecf20Sopenharmony_ci DBG_BUGON(v == EROFS_LOCKED_MAGIC); 1828c2ecf20Sopenharmony_ci return v; 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci#endif /* !CONFIG_SMP */ 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci/* hard limit of pages per compressed cluster */ 1878c2ecf20Sopenharmony_ci#define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) 1888c2ecf20Sopenharmony_ci#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES 1898c2ecf20Sopenharmony_ci#else 1908c2ecf20Sopenharmony_ci#define EROFS_PCPUBUF_NR_PAGES 0 1918c2ecf20Sopenharmony_ci#endif /* !CONFIG_EROFS_FS_ZIP */ 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci/* we strictly follow PAGE_SIZE and no buffer head yet */ 1948c2ecf20Sopenharmony_ci#define LOG_BLOCK_SIZE PAGE_SHIFT 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci#undef LOG_SECTORS_PER_BLOCK 1978c2ecf20Sopenharmony_ci#define LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci#undef SECTORS_PER_BLOCK 2008c2ecf20Sopenharmony_ci#define SECTORS_PER_BLOCK (1 << SECTORS_PER_BLOCK) 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci#define EROFS_BLKSIZ (1 << LOG_BLOCK_SIZE) 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci#if (EROFS_BLKSIZ % 4096 || !EROFS_BLKSIZ) 2058c2ecf20Sopenharmony_ci#error erofs cannot be used in this platform 2068c2ecf20Sopenharmony_ci#endif 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci#define ROOT_NID(sb) ((sb)->root_nid) 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci#define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ) 2118c2ecf20Sopenharmony_ci#define erofs_blkoff(addr) ((addr) % EROFS_BLKSIZ) 2128c2ecf20Sopenharmony_ci#define blknr_to_addr(nr) ((erofs_off_t)(nr) * EROFS_BLKSIZ) 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic inline erofs_off_t iloc(struct erofs_sb_info *sbi, erofs_nid_t nid) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci return blknr_to_addr(sbi->meta_blkaddr) + (nid << sbi->islotbits); 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci/* atomic flag definitions */ 2208c2ecf20Sopenharmony_ci#define EROFS_I_EA_INITED_BIT 0 2218c2ecf20Sopenharmony_ci#define EROFS_I_Z_INITED_BIT 1 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci/* bitlock definitions (arranged in reverse order) */ 2248c2ecf20Sopenharmony_ci#define EROFS_I_BL_XATTR_BIT (BITS_PER_LONG - 1) 2258c2ecf20Sopenharmony_ci#define EROFS_I_BL_Z_BIT (BITS_PER_LONG - 2) 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistruct erofs_inode { 2288c2ecf20Sopenharmony_ci erofs_nid_t nid; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* atomic flags (including bitlocks) */ 2318c2ecf20Sopenharmony_ci unsigned long flags; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci unsigned char datalayout; 2348c2ecf20Sopenharmony_ci unsigned char inode_isize; 2358c2ecf20Sopenharmony_ci unsigned int xattr_isize; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci unsigned int xattr_shared_count; 2388c2ecf20Sopenharmony_ci unsigned int *xattr_shared_xattrs; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci union { 2418c2ecf20Sopenharmony_ci erofs_blk_t raw_blkaddr; 2428c2ecf20Sopenharmony_ci#ifdef CONFIG_EROFS_FS_ZIP 2438c2ecf20Sopenharmony_ci struct { 2448c2ecf20Sopenharmony_ci unsigned short z_advise; 2458c2ecf20Sopenharmony_ci unsigned char z_algorithmtype[2]; 2468c2ecf20Sopenharmony_ci unsigned char z_logical_clusterbits; 2478c2ecf20Sopenharmony_ci unsigned char z_physical_clusterbits[2]; 2488c2ecf20Sopenharmony_ci }; 2498c2ecf20Sopenharmony_ci#endif /* CONFIG_EROFS_FS_ZIP */ 2508c2ecf20Sopenharmony_ci }; 2518c2ecf20Sopenharmony_ci /* the corresponding vfs inode */ 2528c2ecf20Sopenharmony_ci struct inode vfs_inode; 2538c2ecf20Sopenharmony_ci}; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci#define EROFS_I(ptr) \ 2568c2ecf20Sopenharmony_ci container_of(ptr, struct erofs_inode, vfs_inode) 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic inline unsigned long erofs_inode_datablocks(struct inode *inode) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci /* since i_size cannot be changed */ 2618c2ecf20Sopenharmony_ci return DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ); 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit, 2658c2ecf20Sopenharmony_ci unsigned int bits) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci return (value >> bit) & ((1 << bits) - 1); 2698c2ecf20Sopenharmony_ci} 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_cistatic inline unsigned int erofs_inode_version(unsigned int value) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci return erofs_bitrange(value, EROFS_I_VERSION_BIT, 2758c2ecf20Sopenharmony_ci EROFS_I_VERSION_BITS); 2768c2ecf20Sopenharmony_ci} 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_cistatic inline unsigned int erofs_inode_datalayout(unsigned int value) 2798c2ecf20Sopenharmony_ci{ 2808c2ecf20Sopenharmony_ci return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT, 2818c2ecf20Sopenharmony_ci EROFS_I_DATALAYOUT_BITS); 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ciextern const struct super_operations erofs_sops; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ciextern const struct address_space_operations erofs_raw_access_aops; 2878c2ecf20Sopenharmony_ciextern const struct address_space_operations z_erofs_aops; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci/* 2908c2ecf20Sopenharmony_ci * Logical to physical block mapping, used by erofs_map_blocks() 2918c2ecf20Sopenharmony_ci * 2928c2ecf20Sopenharmony_ci * Different with other file systems, it is used for 2 access modes: 2938c2ecf20Sopenharmony_ci * 2948c2ecf20Sopenharmony_ci * 1) RAW access mode: 2958c2ecf20Sopenharmony_ci * 2968c2ecf20Sopenharmony_ci * Users pass a valid (m_lblk, m_lofs -- usually 0) pair, 2978c2ecf20Sopenharmony_ci * and get the valid m_pblk, m_pofs and the longest m_len(in bytes). 2988c2ecf20Sopenharmony_ci * 2998c2ecf20Sopenharmony_ci * Note that m_lblk in the RAW access mode refers to the number of 3008c2ecf20Sopenharmony_ci * the compressed ondisk block rather than the uncompressed 3018c2ecf20Sopenharmony_ci * in-memory block for the compressed file. 3028c2ecf20Sopenharmony_ci * 3038c2ecf20Sopenharmony_ci * m_pofs equals to m_lofs except for the inline data page. 3048c2ecf20Sopenharmony_ci * 3058c2ecf20Sopenharmony_ci * 2) Normal access mode: 3068c2ecf20Sopenharmony_ci * 3078c2ecf20Sopenharmony_ci * If the inode is not compressed, it has no difference with 3088c2ecf20Sopenharmony_ci * the RAW access mode. However, if the inode is compressed, 3098c2ecf20Sopenharmony_ci * users should pass a valid (m_lblk, m_lofs) pair, and get 3108c2ecf20Sopenharmony_ci * the needed m_pblk, m_pofs, m_len to get the compressed data 3118c2ecf20Sopenharmony_ci * and the updated m_lblk, m_lofs which indicates the start 3128c2ecf20Sopenharmony_ci * of the corresponding uncompressed data in the file. 3138c2ecf20Sopenharmony_ci */ 3148c2ecf20Sopenharmony_cienum { 3158c2ecf20Sopenharmony_ci BH_Zipped = BH_PrivateStart, 3168c2ecf20Sopenharmony_ci BH_FullMapped, 3178c2ecf20Sopenharmony_ci}; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci/* Has a disk mapping */ 3208c2ecf20Sopenharmony_ci#define EROFS_MAP_MAPPED (1 << BH_Mapped) 3218c2ecf20Sopenharmony_ci/* Located in metadata (could be copied from bd_inode) */ 3228c2ecf20Sopenharmony_ci#define EROFS_MAP_META (1 << BH_Meta) 3238c2ecf20Sopenharmony_ci/* The extent has been compressed */ 3248c2ecf20Sopenharmony_ci#define EROFS_MAP_ZIPPED (1 << BH_Zipped) 3258c2ecf20Sopenharmony_ci/* The length of extent is full */ 3268c2ecf20Sopenharmony_ci#define EROFS_MAP_FULL_MAPPED (1 << BH_FullMapped) 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_cistruct erofs_map_blocks { 3298c2ecf20Sopenharmony_ci erofs_off_t m_pa, m_la; 3308c2ecf20Sopenharmony_ci u64 m_plen, m_llen; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci unsigned int m_flags; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci struct page *mpage; 3358c2ecf20Sopenharmony_ci}; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci/* Flags used by erofs_map_blocks() */ 3388c2ecf20Sopenharmony_ci#define EROFS_GET_BLOCKS_RAW 0x0001 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci/* zmap.c */ 3418c2ecf20Sopenharmony_ci#ifdef CONFIG_EROFS_FS_ZIP 3428c2ecf20Sopenharmony_ciint z_erofs_fill_inode(struct inode *inode); 3438c2ecf20Sopenharmony_ciint z_erofs_map_blocks_iter(struct inode *inode, 3448c2ecf20Sopenharmony_ci struct erofs_map_blocks *map, 3458c2ecf20Sopenharmony_ci int flags); 3468c2ecf20Sopenharmony_ci#else 3478c2ecf20Sopenharmony_cistatic inline int z_erofs_fill_inode(struct inode *inode) { return -EOPNOTSUPP; } 3488c2ecf20Sopenharmony_cistatic inline int z_erofs_map_blocks_iter(struct inode *inode, 3498c2ecf20Sopenharmony_ci struct erofs_map_blocks *map, 3508c2ecf20Sopenharmony_ci int flags) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci#endif /* !CONFIG_EROFS_FS_ZIP */ 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci/* data.c */ 3578c2ecf20Sopenharmony_cistruct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ciint erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci/* inode.c */ 3628c2ecf20Sopenharmony_cistatic inline unsigned long erofs_inode_hash(erofs_nid_t nid) 3638c2ecf20Sopenharmony_ci{ 3648c2ecf20Sopenharmony_ci#if BITS_PER_LONG == 32 3658c2ecf20Sopenharmony_ci return (nid >> 32) ^ (nid & 0xffffffff); 3668c2ecf20Sopenharmony_ci#else 3678c2ecf20Sopenharmony_ci return nid; 3688c2ecf20Sopenharmony_ci#endif 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ciextern const struct inode_operations erofs_generic_iops; 3728c2ecf20Sopenharmony_ciextern const struct inode_operations erofs_symlink_iops; 3738c2ecf20Sopenharmony_ciextern const struct inode_operations erofs_fast_symlink_iops; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistruct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid, bool dir); 3768c2ecf20Sopenharmony_ciint erofs_getattr(const struct path *path, struct kstat *stat, 3778c2ecf20Sopenharmony_ci u32 request_mask, unsigned int query_flags); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci/* namei.c */ 3808c2ecf20Sopenharmony_ciextern const struct inode_operations erofs_dir_iops; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ciint erofs_namei(struct inode *dir, struct qstr *name, 3838c2ecf20Sopenharmony_ci erofs_nid_t *nid, unsigned int *d_type); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci/* dir.c */ 3868c2ecf20Sopenharmony_ciextern const struct file_operations erofs_dir_fops; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci/* utils.c / zdata.c */ 3898c2ecf20Sopenharmony_cistruct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci#if (EROFS_PCPUBUF_NR_PAGES > 0) 3928c2ecf20Sopenharmony_civoid *erofs_get_pcpubuf(unsigned int pagenr); 3938c2ecf20Sopenharmony_ci#define erofs_put_pcpubuf(buf) do { \ 3948c2ecf20Sopenharmony_ci (void)&(buf); \ 3958c2ecf20Sopenharmony_ci preempt_enable(); \ 3968c2ecf20Sopenharmony_ci} while (0) 3978c2ecf20Sopenharmony_ci#else 3988c2ecf20Sopenharmony_cistatic inline void *erofs_get_pcpubuf(unsigned int pagenr) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci return ERR_PTR(-EOPNOTSUPP); 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci#define erofs_put_pcpubuf(buf) do {} while (0) 4048c2ecf20Sopenharmony_ci#endif 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci#ifdef CONFIG_EROFS_FS_ZIP 4078c2ecf20Sopenharmony_ciint erofs_workgroup_put(struct erofs_workgroup *grp); 4088c2ecf20Sopenharmony_cistruct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, 4098c2ecf20Sopenharmony_ci pgoff_t index); 4108c2ecf20Sopenharmony_cistruct erofs_workgroup *erofs_insert_workgroup(struct super_block *sb, 4118c2ecf20Sopenharmony_ci struct erofs_workgroup *grp); 4128c2ecf20Sopenharmony_civoid erofs_workgroup_free_rcu(struct erofs_workgroup *grp); 4138c2ecf20Sopenharmony_civoid erofs_shrinker_register(struct super_block *sb); 4148c2ecf20Sopenharmony_civoid erofs_shrinker_unregister(struct super_block *sb); 4158c2ecf20Sopenharmony_ciint __init erofs_init_shrinker(void); 4168c2ecf20Sopenharmony_civoid erofs_exit_shrinker(void); 4178c2ecf20Sopenharmony_ciint __init z_erofs_init_zip_subsystem(void); 4188c2ecf20Sopenharmony_civoid z_erofs_exit_zip_subsystem(void); 4198c2ecf20Sopenharmony_ciint erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, 4208c2ecf20Sopenharmony_ci struct erofs_workgroup *egrp); 4218c2ecf20Sopenharmony_ciint erofs_try_to_free_cached_page(struct address_space *mapping, 4228c2ecf20Sopenharmony_ci struct page *page); 4238c2ecf20Sopenharmony_ci#else 4248c2ecf20Sopenharmony_cistatic inline void erofs_shrinker_register(struct super_block *sb) {} 4258c2ecf20Sopenharmony_cistatic inline void erofs_shrinker_unregister(struct super_block *sb) {} 4268c2ecf20Sopenharmony_cistatic inline int erofs_init_shrinker(void) { return 0; } 4278c2ecf20Sopenharmony_cistatic inline void erofs_exit_shrinker(void) {} 4288c2ecf20Sopenharmony_cistatic inline int z_erofs_init_zip_subsystem(void) { return 0; } 4298c2ecf20Sopenharmony_cistatic inline void z_erofs_exit_zip_subsystem(void) {} 4308c2ecf20Sopenharmony_ci#endif /* !CONFIG_EROFS_FS_ZIP */ 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci#endif /* __EROFS_INTERNAL_H */ 4358c2ecf20Sopenharmony_ci 436