xref: /openbmc/linux/fs/erofs/internal.h (revision a5876e24)
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 #ifndef __EROFS_INTERNAL_H
847e4937aSGao Xiang #define __EROFS_INTERNAL_H
947e4937aSGao Xiang 
1047e4937aSGao Xiang #include <linux/fs.h>
1147e4937aSGao Xiang #include <linux/dcache.h>
1247e4937aSGao Xiang #include <linux/mm.h>
1347e4937aSGao Xiang #include <linux/pagemap.h>
1447e4937aSGao Xiang #include <linux/bio.h>
1547e4937aSGao Xiang #include <linux/buffer_head.h>
1647e4937aSGao Xiang #include <linux/magic.h>
1747e4937aSGao Xiang #include <linux/slab.h>
1847e4937aSGao Xiang #include <linux/vmalloc.h>
1947e4937aSGao Xiang #include "erofs_fs.h"
2047e4937aSGao Xiang 
2147e4937aSGao Xiang /* redefine pr_fmt "erofs: " */
2247e4937aSGao Xiang #undef pr_fmt
2347e4937aSGao Xiang #define pr_fmt(fmt) "erofs: " fmt
2447e4937aSGao Xiang 
2547e4937aSGao Xiang #define errln(x, ...)   pr_err(x "\n", ##__VA_ARGS__)
2647e4937aSGao Xiang #define infoln(x, ...)  pr_info(x "\n", ##__VA_ARGS__)
2747e4937aSGao Xiang #ifdef CONFIG_EROFS_FS_DEBUG
2847e4937aSGao Xiang #define debugln(x, ...) pr_debug(x "\n", ##__VA_ARGS__)
2947e4937aSGao Xiang #define DBG_BUGON               BUG_ON
3047e4937aSGao Xiang #else
3147e4937aSGao Xiang #define debugln(x, ...)         ((void)0)
3247e4937aSGao Xiang #define DBG_BUGON(x)            ((void)(x))
3347e4937aSGao Xiang #endif	/* !CONFIG_EROFS_FS_DEBUG */
3447e4937aSGao Xiang 
3547e4937aSGao Xiang enum {
3647e4937aSGao Xiang 	FAULT_KMALLOC,
3747e4937aSGao Xiang 	FAULT_READ_IO,
3847e4937aSGao Xiang 	FAULT_MAX,
3947e4937aSGao Xiang };
4047e4937aSGao Xiang 
4147e4937aSGao Xiang #ifdef CONFIG_EROFS_FAULT_INJECTION
4247e4937aSGao Xiang extern const char *erofs_fault_name[FAULT_MAX];
4347e4937aSGao Xiang #define IS_FAULT_SET(fi, type) ((fi)->inject_type & (1 << (type)))
4447e4937aSGao Xiang 
4547e4937aSGao Xiang struct erofs_fault_info {
4647e4937aSGao Xiang 	atomic_t inject_ops;
4747e4937aSGao Xiang 	unsigned int inject_rate;
4847e4937aSGao Xiang 	unsigned int inject_type;
4947e4937aSGao Xiang };
5047e4937aSGao Xiang #endif	/* CONFIG_EROFS_FAULT_INJECTION */
5147e4937aSGao Xiang 
5247e4937aSGao Xiang /* EROFS_SUPER_MAGIC_V1 to represent the whole file system */
5347e4937aSGao Xiang #define EROFS_SUPER_MAGIC   EROFS_SUPER_MAGIC_V1
5447e4937aSGao Xiang 
5547e4937aSGao Xiang typedef u64 erofs_nid_t;
5647e4937aSGao Xiang typedef u64 erofs_off_t;
5747e4937aSGao Xiang /* data type for filesystem-wide blocks number */
5847e4937aSGao Xiang typedef u32 erofs_blk_t;
5947e4937aSGao Xiang 
6047e4937aSGao Xiang struct erofs_sb_info {
6147e4937aSGao Xiang #ifdef CONFIG_EROFS_FS_ZIP
6247e4937aSGao Xiang 	/* list for all registered superblocks, mainly for shrinker */
6347e4937aSGao Xiang 	struct list_head list;
6447e4937aSGao Xiang 	struct mutex umount_mutex;
6547e4937aSGao Xiang 
6647e4937aSGao Xiang 	/* the dedicated workstation for compression */
6747e4937aSGao Xiang 	struct radix_tree_root workstn_tree;
6847e4937aSGao Xiang 
6947e4937aSGao Xiang 	/* threshold for decompression synchronously */
7047e4937aSGao Xiang 	unsigned int max_sync_decompress_pages;
7147e4937aSGao Xiang 
7247e4937aSGao Xiang 	unsigned int shrinker_run_no;
7347e4937aSGao Xiang 
7447e4937aSGao Xiang 	/* current strategy of how to use managed cache */
7547e4937aSGao Xiang 	unsigned char cache_strategy;
7647e4937aSGao Xiang 
7747e4937aSGao Xiang 	/* pseudo inode to manage cached pages */
7847e4937aSGao Xiang 	struct inode *managed_cache;
7947e4937aSGao Xiang #endif	/* CONFIG_EROFS_FS_ZIP */
8047e4937aSGao Xiang 	u32 blocks;
8147e4937aSGao Xiang 	u32 meta_blkaddr;
8247e4937aSGao Xiang #ifdef CONFIG_EROFS_FS_XATTR
8347e4937aSGao Xiang 	u32 xattr_blkaddr;
8447e4937aSGao Xiang #endif
8547e4937aSGao Xiang 
8647e4937aSGao Xiang 	/* inode slot unit size in bit shift */
8747e4937aSGao Xiang 	unsigned char islotbits;
8847e4937aSGao Xiang 
8947e4937aSGao Xiang 	u32 build_time_nsec;
9047e4937aSGao Xiang 	u64 build_time;
9147e4937aSGao Xiang 
9247e4937aSGao Xiang 	/* what we really care is nid, rather than ino.. */
9347e4937aSGao Xiang 	erofs_nid_t root_nid;
9447e4937aSGao Xiang 	/* used for statfs, f_files - f_favail */
9547e4937aSGao Xiang 	u64 inos;
9647e4937aSGao Xiang 
9747e4937aSGao Xiang 	u8 uuid[16];                    /* 128-bit uuid for volume */
9847e4937aSGao Xiang 	u8 volume_name[16];             /* volume name */
99426a9308SGao Xiang 	u32 feature_incompat;
10047e4937aSGao Xiang 
10147e4937aSGao Xiang 	unsigned int mount_opt;
10247e4937aSGao Xiang 
10347e4937aSGao Xiang #ifdef CONFIG_EROFS_FAULT_INJECTION
10447e4937aSGao Xiang 	struct erofs_fault_info fault_info;	/* For fault injection */
10547e4937aSGao Xiang #endif
10647e4937aSGao Xiang };
10747e4937aSGao Xiang 
10847e4937aSGao Xiang #ifdef CONFIG_EROFS_FAULT_INJECTION
10947e4937aSGao Xiang #define erofs_show_injection_info(type)					\
11047e4937aSGao Xiang 	infoln("inject %s in %s of %pS", erofs_fault_name[type],        \
11147e4937aSGao Xiang 		__func__, __builtin_return_address(0))
11247e4937aSGao Xiang 
11347e4937aSGao Xiang static inline bool time_to_inject(struct erofs_sb_info *sbi, int type)
11447e4937aSGao Xiang {
11547e4937aSGao Xiang 	struct erofs_fault_info *ffi = &sbi->fault_info;
11647e4937aSGao Xiang 
11747e4937aSGao Xiang 	if (!ffi->inject_rate)
11847e4937aSGao Xiang 		return false;
11947e4937aSGao Xiang 
12047e4937aSGao Xiang 	if (!IS_FAULT_SET(ffi, type))
12147e4937aSGao Xiang 		return false;
12247e4937aSGao Xiang 
12347e4937aSGao Xiang 	atomic_inc(&ffi->inject_ops);
12447e4937aSGao Xiang 	if (atomic_read(&ffi->inject_ops) >= ffi->inject_rate) {
12547e4937aSGao Xiang 		atomic_set(&ffi->inject_ops, 0);
12647e4937aSGao Xiang 		return true;
12747e4937aSGao Xiang 	}
12847e4937aSGao Xiang 	return false;
12947e4937aSGao Xiang }
13047e4937aSGao Xiang #else
13147e4937aSGao Xiang static inline bool time_to_inject(struct erofs_sb_info *sbi, int type)
13247e4937aSGao Xiang {
13347e4937aSGao Xiang 	return false;
13447e4937aSGao Xiang }
13547e4937aSGao Xiang 
13647e4937aSGao Xiang static inline void erofs_show_injection_info(int type)
13747e4937aSGao Xiang {
13847e4937aSGao Xiang }
13947e4937aSGao Xiang #endif	/* !CONFIG_EROFS_FAULT_INJECTION */
14047e4937aSGao Xiang 
14147e4937aSGao Xiang static inline void *erofs_kmalloc(struct erofs_sb_info *sbi,
14247e4937aSGao Xiang 					size_t size, gfp_t flags)
14347e4937aSGao Xiang {
14447e4937aSGao Xiang 	if (time_to_inject(sbi, FAULT_KMALLOC)) {
14547e4937aSGao Xiang 		erofs_show_injection_info(FAULT_KMALLOC);
14647e4937aSGao Xiang 		return NULL;
14747e4937aSGao Xiang 	}
14847e4937aSGao Xiang 	return kmalloc(size, flags);
14947e4937aSGao Xiang }
15047e4937aSGao Xiang 
15147e4937aSGao Xiang #define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info)
15247e4937aSGao Xiang #define EROFS_I_SB(inode) ((struct erofs_sb_info *)(inode)->i_sb->s_fs_info)
15347e4937aSGao Xiang 
15447e4937aSGao Xiang /* Mount flags set via mount options or defaults */
15547e4937aSGao Xiang #define EROFS_MOUNT_XATTR_USER		0x00000010
15647e4937aSGao Xiang #define EROFS_MOUNT_POSIX_ACL		0x00000020
15747e4937aSGao Xiang #define EROFS_MOUNT_FAULT_INJECTION	0x00000040
15847e4937aSGao Xiang 
15947e4937aSGao Xiang #define clear_opt(sbi, option)	((sbi)->mount_opt &= ~EROFS_MOUNT_##option)
16047e4937aSGao Xiang #define set_opt(sbi, option)	((sbi)->mount_opt |= EROFS_MOUNT_##option)
16147e4937aSGao Xiang #define test_opt(sbi, option)	((sbi)->mount_opt & EROFS_MOUNT_##option)
16247e4937aSGao Xiang 
16347e4937aSGao Xiang #ifdef CONFIG_EROFS_FS_ZIP
16447e4937aSGao Xiang enum {
16547e4937aSGao Xiang 	EROFS_ZIP_CACHE_DISABLED,
16647e4937aSGao Xiang 	EROFS_ZIP_CACHE_READAHEAD,
16747e4937aSGao Xiang 	EROFS_ZIP_CACHE_READAROUND
16847e4937aSGao Xiang };
16947e4937aSGao Xiang 
17047e4937aSGao Xiang #define EROFS_LOCKED_MAGIC     (INT_MIN | 0xE0F510CCL)
17147e4937aSGao Xiang 
17247e4937aSGao Xiang /* basic unit of the workstation of a super_block */
17347e4937aSGao Xiang struct erofs_workgroup {
17447e4937aSGao Xiang 	/* the workgroup index in the workstation */
17547e4937aSGao Xiang 	pgoff_t index;
17647e4937aSGao Xiang 
17747e4937aSGao Xiang 	/* overall workgroup reference count */
17847e4937aSGao Xiang 	atomic_t refcount;
17947e4937aSGao Xiang };
18047e4937aSGao Xiang 
18147e4937aSGao Xiang #if defined(CONFIG_SMP)
18247e4937aSGao Xiang static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp,
18347e4937aSGao Xiang 						 int val)
18447e4937aSGao Xiang {
18547e4937aSGao Xiang 	preempt_disable();
18647e4937aSGao Xiang 	if (val != atomic_cmpxchg(&grp->refcount, val, EROFS_LOCKED_MAGIC)) {
18747e4937aSGao Xiang 		preempt_enable();
18847e4937aSGao Xiang 		return false;
18947e4937aSGao Xiang 	}
19047e4937aSGao Xiang 	return true;
19147e4937aSGao Xiang }
19247e4937aSGao Xiang 
19347e4937aSGao Xiang static inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp,
19447e4937aSGao Xiang 					    int orig_val)
19547e4937aSGao Xiang {
19647e4937aSGao Xiang 	/*
19747e4937aSGao Xiang 	 * other observers should notice all modifications
19847e4937aSGao Xiang 	 * in the freezing period.
19947e4937aSGao Xiang 	 */
20047e4937aSGao Xiang 	smp_mb();
20147e4937aSGao Xiang 	atomic_set(&grp->refcount, orig_val);
20247e4937aSGao Xiang 	preempt_enable();
20347e4937aSGao Xiang }
20447e4937aSGao Xiang 
20547e4937aSGao Xiang static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
20647e4937aSGao Xiang {
20747e4937aSGao Xiang 	return atomic_cond_read_relaxed(&grp->refcount,
20847e4937aSGao Xiang 					VAL != EROFS_LOCKED_MAGIC);
20947e4937aSGao Xiang }
21047e4937aSGao Xiang #else
21147e4937aSGao Xiang static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp,
21247e4937aSGao Xiang 						 int val)
21347e4937aSGao Xiang {
21447e4937aSGao Xiang 	preempt_disable();
21547e4937aSGao Xiang 	/* no need to spin on UP platforms, let's just disable preemption. */
21647e4937aSGao Xiang 	if (val != atomic_read(&grp->refcount)) {
21747e4937aSGao Xiang 		preempt_enable();
21847e4937aSGao Xiang 		return false;
21947e4937aSGao Xiang 	}
22047e4937aSGao Xiang 	return true;
22147e4937aSGao Xiang }
22247e4937aSGao Xiang 
22347e4937aSGao Xiang static inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp,
22447e4937aSGao Xiang 					    int orig_val)
22547e4937aSGao Xiang {
22647e4937aSGao Xiang 	preempt_enable();
22747e4937aSGao Xiang }
22847e4937aSGao Xiang 
22947e4937aSGao Xiang static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
23047e4937aSGao Xiang {
23147e4937aSGao Xiang 	int v = atomic_read(&grp->refcount);
23247e4937aSGao Xiang 
23347e4937aSGao Xiang 	/* workgroup is never freezed on uniprocessor systems */
23447e4937aSGao Xiang 	DBG_BUGON(v == EROFS_LOCKED_MAGIC);
23547e4937aSGao Xiang 	return v;
23647e4937aSGao Xiang }
23747e4937aSGao Xiang #endif	/* !CONFIG_SMP */
23847e4937aSGao Xiang 
23947e4937aSGao Xiang /* hard limit of pages per compressed cluster */
24047e4937aSGao Xiang #define Z_EROFS_CLUSTER_MAX_PAGES       (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT)
24147e4937aSGao Xiang #define EROFS_PCPUBUF_NR_PAGES          Z_EROFS_CLUSTER_MAX_PAGES
24247e4937aSGao Xiang #else
24347e4937aSGao Xiang #define EROFS_PCPUBUF_NR_PAGES          0
24447e4937aSGao Xiang #endif	/* !CONFIG_EROFS_FS_ZIP */
24547e4937aSGao Xiang 
24647e4937aSGao Xiang /* we strictly follow PAGE_SIZE and no buffer head yet */
24747e4937aSGao Xiang #define LOG_BLOCK_SIZE		PAGE_SHIFT
24847e4937aSGao Xiang 
24947e4937aSGao Xiang #undef LOG_SECTORS_PER_BLOCK
25047e4937aSGao Xiang #define LOG_SECTORS_PER_BLOCK	(PAGE_SHIFT - 9)
25147e4937aSGao Xiang 
25247e4937aSGao Xiang #undef SECTORS_PER_BLOCK
25347e4937aSGao Xiang #define SECTORS_PER_BLOCK	(1 << SECTORS_PER_BLOCK)
25447e4937aSGao Xiang 
25547e4937aSGao Xiang #define EROFS_BLKSIZ		(1 << LOG_BLOCK_SIZE)
25647e4937aSGao Xiang 
25747e4937aSGao Xiang #if (EROFS_BLKSIZ % 4096 || !EROFS_BLKSIZ)
25847e4937aSGao Xiang #error erofs cannot be used in this platform
25947e4937aSGao Xiang #endif
26047e4937aSGao Xiang 
26147e4937aSGao Xiang #define EROFS_IO_MAX_RETRIES_NOFAIL     5
26247e4937aSGao Xiang 
26347e4937aSGao Xiang #define ROOT_NID(sb)		((sb)->root_nid)
26447e4937aSGao Xiang 
26547e4937aSGao Xiang #define erofs_blknr(addr)       ((addr) / EROFS_BLKSIZ)
26647e4937aSGao Xiang #define erofs_blkoff(addr)      ((addr) % EROFS_BLKSIZ)
26747e4937aSGao Xiang #define blknr_to_addr(nr)       ((erofs_off_t)(nr) * EROFS_BLKSIZ)
26847e4937aSGao Xiang 
26947e4937aSGao Xiang static inline erofs_off_t iloc(struct erofs_sb_info *sbi, erofs_nid_t nid)
27047e4937aSGao Xiang {
27147e4937aSGao Xiang 	return blknr_to_addr(sbi->meta_blkaddr) + (nid << sbi->islotbits);
27247e4937aSGao Xiang }
27347e4937aSGao Xiang 
27447e4937aSGao Xiang /* atomic flag definitions */
275a5876e24SGao Xiang #define EROFS_I_EA_INITED_BIT	0
276a5876e24SGao Xiang #define EROFS_I_Z_INITED_BIT	1
27747e4937aSGao Xiang 
27847e4937aSGao Xiang /* bitlock definitions (arranged in reverse order) */
279a5876e24SGao Xiang #define EROFS_I_BL_XATTR_BIT	(BITS_PER_LONG - 1)
280a5876e24SGao Xiang #define EROFS_I_BL_Z_BIT	(BITS_PER_LONG - 2)
28147e4937aSGao Xiang 
282a5876e24SGao Xiang struct erofs_inode {
28347e4937aSGao Xiang 	erofs_nid_t nid;
28447e4937aSGao Xiang 
28547e4937aSGao Xiang 	/* atomic flags (including bitlocks) */
28647e4937aSGao Xiang 	unsigned long flags;
28747e4937aSGao Xiang 
2888a765682SGao Xiang 	unsigned char datalayout;
28947e4937aSGao Xiang 	unsigned char inode_isize;
29047e4937aSGao Xiang 	unsigned short xattr_isize;
29147e4937aSGao Xiang 
29247e4937aSGao Xiang 	unsigned int xattr_shared_count;
29347e4937aSGao Xiang 	unsigned int *xattr_shared_xattrs;
29447e4937aSGao Xiang 
29547e4937aSGao Xiang 	union {
29647e4937aSGao Xiang 		erofs_blk_t raw_blkaddr;
29747e4937aSGao Xiang #ifdef CONFIG_EROFS_FS_ZIP
29847e4937aSGao Xiang 		struct {
29947e4937aSGao Xiang 			unsigned short z_advise;
30047e4937aSGao Xiang 			unsigned char  z_algorithmtype[2];
30147e4937aSGao Xiang 			unsigned char  z_logical_clusterbits;
30247e4937aSGao Xiang 			unsigned char  z_physical_clusterbits[2];
30347e4937aSGao Xiang 		};
30447e4937aSGao Xiang #endif	/* CONFIG_EROFS_FS_ZIP */
30547e4937aSGao Xiang 	};
30647e4937aSGao Xiang 	/* the corresponding vfs inode */
30747e4937aSGao Xiang 	struct inode vfs_inode;
30847e4937aSGao Xiang };
30947e4937aSGao Xiang 
310a5876e24SGao Xiang #define EROFS_I(ptr)	\
311a5876e24SGao Xiang 	container_of(ptr, struct erofs_inode, vfs_inode)
31247e4937aSGao Xiang 
31347e4937aSGao Xiang static inline unsigned long inode_datablocks(struct inode *inode)
31447e4937aSGao Xiang {
31547e4937aSGao Xiang 	/* since i_size cannot be changed */
31647e4937aSGao Xiang 	return DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ);
31747e4937aSGao Xiang }
31847e4937aSGao Xiang 
3198a765682SGao Xiang static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit,
3208a765682SGao Xiang 					  unsigned int bits)
32147e4937aSGao Xiang {
3228a765682SGao Xiang 
3238a765682SGao Xiang 	return (value >> bit) & ((1 << bits) - 1);
32447e4937aSGao Xiang }
32547e4937aSGao Xiang 
3268a765682SGao Xiang 
3278a765682SGao Xiang static inline unsigned int erofs_inode_version(unsigned int value)
32847e4937aSGao Xiang {
3298a765682SGao Xiang 	return erofs_bitrange(value, EROFS_I_VERSION_BIT,
3308a765682SGao Xiang 			      EROFS_I_VERSION_BITS);
3318a765682SGao Xiang }
3328a765682SGao Xiang 
3338a765682SGao Xiang static inline unsigned int erofs_inode_datalayout(unsigned int value)
3348a765682SGao Xiang {
3358a765682SGao Xiang 	return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT,
3368a765682SGao Xiang 			      EROFS_I_DATALAYOUT_BITS);
33747e4937aSGao Xiang }
33847e4937aSGao Xiang 
33947e4937aSGao Xiang extern const struct super_operations erofs_sops;
34047e4937aSGao Xiang 
34147e4937aSGao Xiang extern const struct address_space_operations erofs_raw_access_aops;
34247e4937aSGao Xiang #ifdef CONFIG_EROFS_FS_ZIP
34347e4937aSGao Xiang extern const struct address_space_operations z_erofs_vle_normalaccess_aops;
34447e4937aSGao Xiang #endif
34547e4937aSGao Xiang 
34647e4937aSGao Xiang /*
34747e4937aSGao Xiang  * Logical to physical block mapping, used by erofs_map_blocks()
34847e4937aSGao Xiang  *
34947e4937aSGao Xiang  * Different with other file systems, it is used for 2 access modes:
35047e4937aSGao Xiang  *
35147e4937aSGao Xiang  * 1) RAW access mode:
35247e4937aSGao Xiang  *
35347e4937aSGao Xiang  * Users pass a valid (m_lblk, m_lofs -- usually 0) pair,
35447e4937aSGao Xiang  * and get the valid m_pblk, m_pofs and the longest m_len(in bytes).
35547e4937aSGao Xiang  *
35647e4937aSGao Xiang  * Note that m_lblk in the RAW access mode refers to the number of
35747e4937aSGao Xiang  * the compressed ondisk block rather than the uncompressed
35847e4937aSGao Xiang  * in-memory block for the compressed file.
35947e4937aSGao Xiang  *
36047e4937aSGao Xiang  * m_pofs equals to m_lofs except for the inline data page.
36147e4937aSGao Xiang  *
36247e4937aSGao Xiang  * 2) Normal access mode:
36347e4937aSGao Xiang  *
36447e4937aSGao Xiang  * If the inode is not compressed, it has no difference with
36547e4937aSGao Xiang  * the RAW access mode. However, if the inode is compressed,
36647e4937aSGao Xiang  * users should pass a valid (m_lblk, m_lofs) pair, and get
36747e4937aSGao Xiang  * the needed m_pblk, m_pofs, m_len to get the compressed data
36847e4937aSGao Xiang  * and the updated m_lblk, m_lofs which indicates the start
36947e4937aSGao Xiang  * of the corresponding uncompressed data in the file.
37047e4937aSGao Xiang  */
37147e4937aSGao Xiang enum {
37247e4937aSGao Xiang 	BH_Zipped = BH_PrivateStart,
37347e4937aSGao Xiang 	BH_FullMapped,
37447e4937aSGao Xiang };
37547e4937aSGao Xiang 
37647e4937aSGao Xiang /* Has a disk mapping */
37747e4937aSGao Xiang #define EROFS_MAP_MAPPED	(1 << BH_Mapped)
37847e4937aSGao Xiang /* Located in metadata (could be copied from bd_inode) */
37947e4937aSGao Xiang #define EROFS_MAP_META		(1 << BH_Meta)
38047e4937aSGao Xiang /* The extent has been compressed */
38147e4937aSGao Xiang #define EROFS_MAP_ZIPPED	(1 << BH_Zipped)
38247e4937aSGao Xiang /* The length of extent is full */
38347e4937aSGao Xiang #define EROFS_MAP_FULL_MAPPED	(1 << BH_FullMapped)
38447e4937aSGao Xiang 
38547e4937aSGao Xiang struct erofs_map_blocks {
38647e4937aSGao Xiang 	erofs_off_t m_pa, m_la;
38747e4937aSGao Xiang 	u64 m_plen, m_llen;
38847e4937aSGao Xiang 
38947e4937aSGao Xiang 	unsigned int m_flags;
39047e4937aSGao Xiang 
39147e4937aSGao Xiang 	struct page *mpage;
39247e4937aSGao Xiang };
39347e4937aSGao Xiang 
39447e4937aSGao Xiang /* Flags used by erofs_map_blocks() */
39547e4937aSGao Xiang #define EROFS_GET_BLOCKS_RAW    0x0001
39647e4937aSGao Xiang 
39747e4937aSGao Xiang /* zmap.c */
39847e4937aSGao Xiang #ifdef CONFIG_EROFS_FS_ZIP
39947e4937aSGao Xiang int z_erofs_fill_inode(struct inode *inode);
40047e4937aSGao Xiang int z_erofs_map_blocks_iter(struct inode *inode,
40147e4937aSGao Xiang 			    struct erofs_map_blocks *map,
40247e4937aSGao Xiang 			    int flags);
40347e4937aSGao Xiang #else
40447e4937aSGao Xiang static inline int z_erofs_fill_inode(struct inode *inode) { return -EOPNOTSUPP; }
40547e4937aSGao Xiang static inline int z_erofs_map_blocks_iter(struct inode *inode,
40647e4937aSGao Xiang 					  struct erofs_map_blocks *map,
40747e4937aSGao Xiang 					  int flags)
40847e4937aSGao Xiang {
40947e4937aSGao Xiang 	return -EOPNOTSUPP;
41047e4937aSGao Xiang }
41147e4937aSGao Xiang #endif	/* !CONFIG_EROFS_FS_ZIP */
41247e4937aSGao Xiang 
41347e4937aSGao Xiang /* data.c */
41447e4937aSGao Xiang static inline struct bio *erofs_grab_bio(struct super_block *sb,
41547e4937aSGao Xiang 					 erofs_blk_t blkaddr,
41647e4937aSGao Xiang 					 unsigned int nr_pages,
41747e4937aSGao Xiang 					 void *bi_private, bio_end_io_t endio,
41847e4937aSGao Xiang 					 bool nofail)
41947e4937aSGao Xiang {
42047e4937aSGao Xiang 	const gfp_t gfp = GFP_NOIO;
42147e4937aSGao Xiang 	struct bio *bio;
42247e4937aSGao Xiang 
42347e4937aSGao Xiang 	do {
42447e4937aSGao Xiang 		if (nr_pages == 1) {
42547e4937aSGao Xiang 			bio = bio_alloc(gfp | (nofail ? __GFP_NOFAIL : 0), 1);
4268d8a09b0SGao Xiang 			if (!bio) {
42747e4937aSGao Xiang 				DBG_BUGON(nofail);
42847e4937aSGao Xiang 				return ERR_PTR(-ENOMEM);
42947e4937aSGao Xiang 			}
43047e4937aSGao Xiang 			break;
43147e4937aSGao Xiang 		}
43247e4937aSGao Xiang 		bio = bio_alloc(gfp, nr_pages);
43347e4937aSGao Xiang 		nr_pages /= 2;
4348d8a09b0SGao Xiang 	} while (!bio);
43547e4937aSGao Xiang 
43647e4937aSGao Xiang 	bio->bi_end_io = endio;
43747e4937aSGao Xiang 	bio_set_dev(bio, sb->s_bdev);
43847e4937aSGao Xiang 	bio->bi_iter.bi_sector = (sector_t)blkaddr << LOG_SECTORS_PER_BLOCK;
43947e4937aSGao Xiang 	bio->bi_private = bi_private;
44047e4937aSGao Xiang 	return bio;
44147e4937aSGao Xiang }
44247e4937aSGao Xiang 
44347e4937aSGao Xiang static inline void __submit_bio(struct bio *bio, unsigned int op,
44447e4937aSGao Xiang 				unsigned int op_flags)
44547e4937aSGao Xiang {
44647e4937aSGao Xiang 	bio_set_op_attrs(bio, op, op_flags);
44747e4937aSGao Xiang 	submit_bio(bio);
44847e4937aSGao Xiang }
44947e4937aSGao Xiang 
45047e4937aSGao Xiang struct page *__erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr,
45147e4937aSGao Xiang 				   bool prio, bool nofail);
45247e4937aSGao Xiang 
45347e4937aSGao Xiang static inline struct page *erofs_get_meta_page(struct super_block *sb,
45447e4937aSGao Xiang 	erofs_blk_t blkaddr, bool prio)
45547e4937aSGao Xiang {
45647e4937aSGao Xiang 	return __erofs_get_meta_page(sb, blkaddr, prio, false);
45747e4937aSGao Xiang }
45847e4937aSGao Xiang 
45947e4937aSGao Xiang int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int);
46047e4937aSGao Xiang 
46147e4937aSGao Xiang static inline struct page *erofs_get_inline_page(struct inode *inode,
46247e4937aSGao Xiang 						 erofs_blk_t blkaddr)
46347e4937aSGao Xiang {
46447e4937aSGao Xiang 	return erofs_get_meta_page(inode->i_sb, blkaddr,
46547e4937aSGao Xiang 				   S_ISDIR(inode->i_mode));
46647e4937aSGao Xiang }
46747e4937aSGao Xiang 
46847e4937aSGao Xiang /* inode.c */
46947e4937aSGao Xiang static inline unsigned long erofs_inode_hash(erofs_nid_t nid)
47047e4937aSGao Xiang {
47147e4937aSGao Xiang #if BITS_PER_LONG == 32
47247e4937aSGao Xiang 	return (nid >> 32) ^ (nid & 0xffffffff);
47347e4937aSGao Xiang #else
47447e4937aSGao Xiang 	return nid;
47547e4937aSGao Xiang #endif
47647e4937aSGao Xiang }
47747e4937aSGao Xiang 
47847e4937aSGao Xiang extern const struct inode_operations erofs_generic_iops;
47947e4937aSGao Xiang extern const struct inode_operations erofs_symlink_iops;
48047e4937aSGao Xiang extern const struct inode_operations erofs_fast_symlink_iops;
48147e4937aSGao Xiang 
48247e4937aSGao Xiang static inline void set_inode_fast_symlink(struct inode *inode)
48347e4937aSGao Xiang {
48447e4937aSGao Xiang 	inode->i_op = &erofs_fast_symlink_iops;
48547e4937aSGao Xiang }
48647e4937aSGao Xiang 
48747e4937aSGao Xiang static inline bool is_inode_fast_symlink(struct inode *inode)
48847e4937aSGao Xiang {
48947e4937aSGao Xiang 	return inode->i_op == &erofs_fast_symlink_iops;
49047e4937aSGao Xiang }
49147e4937aSGao Xiang 
49247e4937aSGao Xiang struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid, bool dir);
49347e4937aSGao Xiang int erofs_getattr(const struct path *path, struct kstat *stat,
49447e4937aSGao Xiang 		  u32 request_mask, unsigned int query_flags);
49547e4937aSGao Xiang 
49647e4937aSGao Xiang /* namei.c */
49747e4937aSGao Xiang extern const struct inode_operations erofs_dir_iops;
49847e4937aSGao Xiang 
49947e4937aSGao Xiang int erofs_namei(struct inode *dir, struct qstr *name,
50047e4937aSGao Xiang 		erofs_nid_t *nid, unsigned int *d_type);
50147e4937aSGao Xiang 
50247e4937aSGao Xiang /* dir.c */
50347e4937aSGao Xiang extern const struct file_operations erofs_dir_fops;
50447e4937aSGao Xiang 
50547e4937aSGao Xiang /* utils.c / zdata.c */
50647e4937aSGao Xiang struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail);
50747e4937aSGao Xiang 
50847e4937aSGao Xiang #if (EROFS_PCPUBUF_NR_PAGES > 0)
50947e4937aSGao Xiang void *erofs_get_pcpubuf(unsigned int pagenr);
51047e4937aSGao Xiang #define erofs_put_pcpubuf(buf) do { \
51147e4937aSGao Xiang 	(void)&(buf);	\
51247e4937aSGao Xiang 	preempt_enable();	\
51347e4937aSGao Xiang } while (0)
51447e4937aSGao Xiang #else
51547e4937aSGao Xiang static inline void *erofs_get_pcpubuf(unsigned int pagenr)
51647e4937aSGao Xiang {
51747e4937aSGao Xiang 	return ERR_PTR(-EOPNOTSUPP);
51847e4937aSGao Xiang }
51947e4937aSGao Xiang 
52047e4937aSGao Xiang #define erofs_put_pcpubuf(buf) do {} while (0)
52147e4937aSGao Xiang #endif
52247e4937aSGao Xiang 
52347e4937aSGao Xiang #ifdef CONFIG_EROFS_FS_ZIP
52447e4937aSGao Xiang int erofs_workgroup_put(struct erofs_workgroup *grp);
52547e4937aSGao Xiang struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb,
52647e4937aSGao Xiang 					     pgoff_t index, bool *tag);
52747e4937aSGao Xiang int erofs_register_workgroup(struct super_block *sb,
52847e4937aSGao Xiang 			     struct erofs_workgroup *grp, bool tag);
52947e4937aSGao Xiang void erofs_workgroup_free_rcu(struct erofs_workgroup *grp);
53047e4937aSGao Xiang void erofs_shrinker_register(struct super_block *sb);
53147e4937aSGao Xiang void erofs_shrinker_unregister(struct super_block *sb);
53247e4937aSGao Xiang int __init erofs_init_shrinker(void);
53347e4937aSGao Xiang void erofs_exit_shrinker(void);
53447e4937aSGao Xiang int __init z_erofs_init_zip_subsystem(void);
53547e4937aSGao Xiang void z_erofs_exit_zip_subsystem(void);
53647e4937aSGao Xiang int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi,
53747e4937aSGao Xiang 				       struct erofs_workgroup *egrp);
53847e4937aSGao Xiang int erofs_try_to_free_cached_page(struct address_space *mapping,
53947e4937aSGao Xiang 				  struct page *page);
54047e4937aSGao Xiang #else
54147e4937aSGao Xiang static inline void erofs_shrinker_register(struct super_block *sb) {}
54247e4937aSGao Xiang static inline void erofs_shrinker_unregister(struct super_block *sb) {}
54347e4937aSGao Xiang static inline int erofs_init_shrinker(void) { return 0; }
54447e4937aSGao Xiang static inline void erofs_exit_shrinker(void) {}
54547e4937aSGao Xiang static inline int z_erofs_init_zip_subsystem(void) { return 0; }
54647e4937aSGao Xiang static inline void z_erofs_exit_zip_subsystem(void) {}
54747e4937aSGao Xiang #endif	/* !CONFIG_EROFS_FS_ZIP */
54847e4937aSGao Xiang 
54947e4937aSGao Xiang #define EFSCORRUPTED    EUCLEAN         /* Filesystem is corrupted */
55047e4937aSGao Xiang 
55147e4937aSGao Xiang #endif	/* __EROFS_INTERNAL_H */
55247e4937aSGao Xiang 
553