/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2017-2018 HUAWEI, Inc. * https://www.huawei.com/ * Copyright (C) 2021, Alibaba Cloud */ #ifndef __EROFS_INTERNAL_H #define __EROFS_INTERNAL_H #include #include // MUST FIRST #include #include #include #include #include #include "erofs_fs.h" MALLOC_DECLARE(M_EROFS); struct cdev; struct g_consumer; struct erofs_device_info; /* EROFS_SUPER_MAGIC_V1 to represent the whole file system */ #define EROFS_SUPER_MAGIC EROFS_SUPER_MAGIC_V1 typedef uint64_t erofs_nid_t; typedef uint64_t erofs_off_t; typedef uint64_t erofs_blk_t; #define EROFS_FEATURE_FUNCS(name, compat, feature) \ static inline bool erofs_sb_has_##name(struct erofs_mount *em) \ { \ return ( \ (em->feature_##compat & EROFS_FEATURE_##feature) != 0); \ } #define EROFS_MOUNT_XATTR_USER 0x00000010 #define EROFS_MOUNT_POSIX_ACL 0x00000020 #define clear_opt(opt, option) ((opt)->mount_opt &= ~EROFS_MOUNT_##option) #define set_opt(opt, option) ((opt)->mount_opt |= EROFS_MOUNT_##option) #define test_opt(opt, option) ((opt)->mount_opt & EROFS_MOUNT_##option) struct erofs_mount_opts { unsigned int mount_opt; }; enum { EROFS_SYNC_DECOMPRESS_AUTO, EROFS_SYNC_DECOMPRESS_FORCE_ON, EROFS_SYNC_DECOMPRESS_FORCE_OFF }; enum { EROFS_ZIP_CACHE_DISABLED, EROFS_ZIP_CACHE_READAHEAD, EROFS_ZIP_CACHE_READAROUND }; struct erofs_sb_lz4_info { uint16_t max_distance_pages; uint16_t max_pclusterblks; }; struct erofs_buf { void *base; erofs_off_t off; }; #define __EROFS_BUF_INITIALIZER ((struct erofs_buf) { .base = NULL }) #define EROFS_MAP_MAPPED 0x0001 #define EROFS_MAP_META 0x0002 #define EROFS_MAP_PARTIAL_MAPPED 0x0004 #define EROFS_MAP_PARTIAL_REF 0x0008 #define EROFS_MAP_FRAGMENT 0x0010 #define EROFS_MAP_FULL(f) \ (!((f) & (EROFS_MAP_PARTIAL_MAPPED | EROFS_MAP_PARTIAL_REF))) struct erofs_map_blocks { struct erofs_buf buf; erofs_off_t m_pa, m_la; uint64_t m_plen, m_llen; unsigned short m_deviceid; char m_algorithmformat; unsigned int m_flags; }; #define EROFS_GET_BLOCKS_FIEMAP 0x0001 #define EROFS_GET_BLOCKS_READMORE 0x0002 #define EROFS_GET_BLOCKS_FINDTAIL 0x0004 enum { Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX, Z_EROFS_COMPRESSION_INTERLACED, Z_EROFS_COMPRESSION_RUNTIME_MAX }; struct erofs_map_dev { struct erofs_mount *m_em; struct erofs_device_info *m_dif; erofs_off_t m_pa; uint64_t m_plen; unsigned int m_deviceid; }; struct erofs_device_info { struct vnode *devvp; struct cdev *dev; struct g_consumer *cp; erofs_blk_t blocks; erofs_blk_t uniaddr; uint64_t mediasize; uint32_t sectorsize; }; struct erofs_xattr_prefix_item { uint8_t base_index; uint8_t infix_len; char *infix; }; struct erofs_zextent_cache { void *data; erofs_nid_t m_nid; erofs_off_t m_pa; erofs_off_t m_la; uint64_t m_plen; uint64_t m_llen; unsigned int m_deviceid; unsigned int m_flags; unsigned char m_algorithmformat; }; struct erofs_mount { struct mount *mnt; struct erofs_device_info dif0; uint32_t block_size; uint32_t sb_size; uint8_t block_bits; uint32_t meta_blkaddr; uint32_t xattr_blkaddr; uint32_t xattr_prefix_start; uint8_t xattr_prefix_count; uint64_t packed_nid; uint64_t metabox_nid; struct erofs_node *metabox_en; struct erofs_node *packed_inode; struct erofs_xattr_prefix_item *xattr_prefixes; uint64_t blocks; uint64_t inos; uint64_t root_nid; uint64_t epoch; uint32_t fixed_nsec; uint32_t generation_seed; uint32_t feature_compat; uint32_t feature_incompat; char volume_name[17]; struct erofs_mount_opts opt; struct erofs_sb_lz4_info lz4; uint16_t available_compr_algs; uint32_t lzma_dict_size; uint8_t deflate_windowbits; uint8_t zstd_windowlog; /* Device table */ uint16_t extra_devices; uint16_t device_id_mask; bool flatdev; erofs_blk_t total_blocks; erofs_blk_t flatdev_blocks; struct erofs_device_info *devs; struct mtx z_extent_cache_lock; struct erofs_zextent_cache z_extent_cache; bool z_extent_cache_initialized; }; struct erofs_node { struct vnode *vnode; uint64_t nid; uint64_t size; uint64_t data_blocks; /* Absolute device offset, or metabox-file offset when bit 63 is set. */ uint64_t inode_off; uint64_t startblk; uint32_t ino; uint32_t generation; uint32_t nlink; uid_t uid; gid_t gid; mode_t mode; __enum_uint8(vtype) vtype; dev_t rdev; uint64_t mtime; uint32_t mtime_nsec; uint8_t datalayout; uint8_t inode_isize; uint32_t xattr_isize; bool inline_data; bool compact_inode; bool dot_omitted; /* Compression fields */ uint16_t z_advise; uint8_t z_algorithmtype[2]; uint8_t z_lclusterbits; uint16_t z_idata_size; uint64_t z_fragmentoff; uint64_t z_tailextent_headlcn; uint64_t z_extents; bool z_initialized; /* Chunk-based fields */ uint16_t chunkformat; uint8_t chunkbits; /* Fragment fields */ bool fragment; }; struct erofs_fid { uint16_t len; uint16_t pad; uint32_t nid_hi; uint32_t nid_lo; uint32_t gen; }; _Static_assert(sizeof(struct erofs_fid) == 16, "EROFS file handle ABI must be 16 bytes"); _Static_assert(sizeof(struct erofs_fid) <= sizeof(struct fid), "struct erofs_fid must fit within struct fid"); #define VTOE(vp) ((struct erofs_node *)(vp)->v_data) #define MTOE(mp) ((struct erofs_mount *)(mp)->mnt_data) EROFS_FEATURE_FUNCS(lz4_0padding, incompat, INCOMPAT_LZ4_0PADDING) EROFS_FEATURE_FUNCS(compr_cfgs, incompat, INCOMPAT_COMPR_CFGS) EROFS_FEATURE_FUNCS(big_pcluster, incompat, INCOMPAT_BIG_PCLUSTER) EROFS_FEATURE_FUNCS(chunked_file, incompat, INCOMPAT_CHUNKED_FILE) EROFS_FEATURE_FUNCS(device_table, incompat, INCOMPAT_DEVICE_TABLE) EROFS_FEATURE_FUNCS(compr_head2, incompat, INCOMPAT_COMPR_HEAD2) EROFS_FEATURE_FUNCS(ztailpacking, incompat, INCOMPAT_ZTAILPACKING) EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS) EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE) EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES) EROFS_FEATURE_FUNCS(48bit, incompat, INCOMPAT_48BIT) EROFS_FEATURE_FUNCS(metabox, incompat, INCOMPAT_METABOX) EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM) EROFS_FEATURE_FUNCS(xattr_filter, compat, COMPAT_XATTR_FILTER) EROFS_FEATURE_FUNCS(shared_ea_in_metabox, compat, COMPAT_SHARED_EA_IN_METABOX) EROFS_FEATURE_FUNCS(plain_xattr_pfx, compat, COMPAT_PLAIN_XATTR_PFX) EROFS_FEATURE_FUNCS(ishare_xattrs, compat, COMPAT_ISHARE_XATTRS) EROFS_FEATURE_FUNCS(mtime, compat, COMPAT_MTIME) static inline bool erofs_is_fileio_mode(struct erofs_mount *em __unused) { return (false); } static inline unsigned int erofs_inode_version(unsigned int ifmt) { return ((ifmt >> EROFS_I_VERSION_BIT) & EROFS_I_VERSION_MASK); } static inline unsigned int erofs_inode_datalayout(unsigned int ifmt) { return ((ifmt >> EROFS_I_DATALAYOUT_BIT) & EROFS_I_DATALAYOUT_MASK); } static inline bool erofs_nid_in_metabox(erofs_nid_t nid) { return ((nid & EROFS_DIRENT_NID_METABOX) != 0); } int erofs_bread(struct erofs_mount *em, uint64_t off, size_t len, void **bufp); int erofs_read_physical(struct erofs_mount *em, unsigned int device_id, uint64_t off, size_t len, void **bufp); void erofs_brelse(void *buf); int erofs_read_metadata(struct erofs_mount *em, erofs_nid_t nid, uint64_t off, size_t len, void **bufp); int erofs_read_inode(struct erofs_mount *em, uint64_t nid, struct erofs_node *en); int erofs_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp); int erofs_read_data(struct erofs_mount *em, struct erofs_node *en, uint64_t loff, size_t len, void **bufp); int erofs_read_file(struct vnode *vp, struct uio *uio, int ioflag); int erofs_readdir_block(struct vnode *vp, struct uio *uio, int *eofflag, int *ncookies, uint64_t **cookies); int erofs_dirent_namelen(const char *blk, uint32_t nameoff, uint32_t endoff, bool trailing, size_t *namelenp); int erofs_validate_dirblock(const char *blk, uint32_t blksz, uint32_t maxsize, uint32_t *ndirentsp); int erofs_readlink_target(struct vnode *vp, struct uio *uio); int erofs_lookup(struct vop_cachedlookup_args *ap); uint64_t erofs_iloc(struct erofs_mount *em, uint64_t nid); bool erofs_nid_is_valid(struct erofs_mount *em, uint64_t nid); int erofs_map_blocks(struct erofs_mount *em, struct erofs_node *en, uint64_t loff, uint64_t *phys_off, unsigned int *device_id, size_t *run_len, bool *hole, bool *metadata); int erofs_map_dev(struct erofs_mount *em, struct erofs_map_dev *map); int z_erofs_fill_inode(struct erofs_mount *em, struct erofs_node *en); int z_erofs_map_blocks_iter(struct erofs_mount *em, struct erofs_node *en, struct erofs_map_blocks *map, int flags); int z_erofs_read_data(struct erofs_mount *em, struct erofs_node *en, uint64_t loff, size_t len, void **bufp); int z_erofs_read_uio(struct erofs_mount *em, struct erofs_node *en, struct uio *uio); void z_erofs_extent_cache_init(struct erofs_mount *em); void z_erofs_extent_cache_fini(struct erofs_mount *em); int z_erofs_decompress(struct erofs_mount *em, const struct erofs_map_blocks *map, const void *src, size_t srclen, void *dst, size_t dstlen, bool partial); int z_erofs_parse_cfgs(struct erofs_mount *em, const struct erofs_super_block *dsb); int lz4_decompress(void *src, void *dst, size_t srclen, size_t dstlen, int partial); int z_erofs_load_lzma_config(struct erofs_mount *em, const void *data, size_t size); int lzma_decompress(const void *src, size_t srclen, void *dst, size_t dstlen, uint32_t dict_size, bool partial); int z_erofs_load_deflate_config(struct erofs_mount *em, const void *data, size_t size); int deflate_decompress(void *src, size_t srclen, void *dst, size_t dstlen, int windowbits, bool partial); bool erofs_zstd_available(void); int z_erofs_load_zstd_config(struct erofs_mount *em, const void *data, size_t size); int zstd_decompress(void *src, size_t srclen, void *dst, size_t dstlen, int windowlog, bool partial); extern struct vop_vector erofs_vnodeops; extern struct vop_vector erofs_fifoops; #endif /* __EROFS_INTERNAL_H */