mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:09:29 +02:00
LZ4 rolling decompression [1] was introduced to reduce the memory footprint of temporary pages: For many cases, it is needed for users to read small data within a compressed extent (pcluster), either due to random small read, or since uptodate folios (typically order-0) cannot be reused for decompression again since decompression algorithm refills already-uptodate folios. Rolling decompression works because LZ4 is LZ77-based and only refers to the most recent 64 KiB of decompressed data, so in theory only a bounded rolling window of temporary pages is needed when decompressing. It can save a lot of temporary memory, e.g. 601,960-byte data can be compressed into a 256k LZ4 compressed extent, which means it needs 146 extra pages per request in the worst case if rolling decompression is disabled. However, the upstream LZ4 implementation is not under EROFS' control: For example, the literal copy memmove() may still **copy long literals backward** on x86 based on the address comparison even when the source and destination ranges do not overlap (IOWs, inline decompression doesn't need to be considered here). That breaks the rolling assumption and makes the optimization broken. Disable it for now to make sure the data correctness first since EROFS is used everywhere now: The rolling window approach can be revived once we either ensure that the official LZ4 code always copies forward for non-overlapping ranges or maintain our own LZ4 implementation in EROFS. The main impact is a higher runtime memory footprint; However, recent commit0f6273ab46("erofs: add a reserved buffer pool for lz4 decompression") helps mitigate this when enabled but it's still not perfect. [1] https://www.usenix.org/conference/atc19/presentation/gao § 3.3 Decompression Reported-by: "Walther, Jens-Uwe" <waltju@amazon.de> Closes: https://lore.kernel.org/r/BEZP281MB2102E57CD31862B8D958B33DD2AC2@BEZP281MB2102.DEUP281.PROD.OUTLOOK.COM Fixes:8e6c8fa9f2("erofs: enable big pcluster feature") Cc: Yann Collet <yann.collet.73@gmail.com> Signed-off-by: Gao Xiang <xiang@kernel.org>
537 lines
17 KiB
C
537 lines
17 KiB
C
/* 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 <linux/fs.h>
|
|
#include <linux/dax.h>
|
|
#include <linux/dcache.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/module.h>
|
|
#include <linux/pagemap.h>
|
|
#include <linux/bio.h>
|
|
#include <linux/magic.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/iomap.h>
|
|
#include "erofs_fs.h"
|
|
|
|
__printf(2, 3) void _erofs_printk(struct super_block *sb, const char *fmt, ...);
|
|
#define erofs_err(sb, fmt, ...) \
|
|
_erofs_printk(sb, KERN_ERR fmt "\n", ##__VA_ARGS__)
|
|
#define erofs_warn(sb, fmt, ...) \
|
|
_erofs_printk(sb, KERN_WARNING fmt "\n", ##__VA_ARGS__)
|
|
#define erofs_info(sb, fmt, ...) \
|
|
_erofs_printk(sb, KERN_INFO fmt "\n", ##__VA_ARGS__)
|
|
|
|
#ifdef CONFIG_EROFS_FS_DEBUG
|
|
#define DBG_BUGON BUG_ON
|
|
#else
|
|
#define DBG_BUGON(x) ((void)(x))
|
|
#endif /* !CONFIG_EROFS_FS_DEBUG */
|
|
|
|
/* EROFS_SUPER_MAGIC_V1 to represent the whole file system */
|
|
#define EROFS_SUPER_MAGIC EROFS_SUPER_MAGIC_V1
|
|
|
|
typedef u64 erofs_nid_t;
|
|
typedef u64 erofs_off_t;
|
|
typedef u64 erofs_blk_t;
|
|
|
|
struct erofs_device_info {
|
|
char *path;
|
|
struct file *file;
|
|
struct dax_device *dax_dev;
|
|
u64 fsoff, dax_part_off;
|
|
|
|
erofs_blk_t blocks;
|
|
erofs_blk_t uniaddr;
|
|
};
|
|
|
|
enum {
|
|
EROFS_SYNC_DECOMPRESS_AUTO,
|
|
EROFS_SYNC_DECOMPRESS_FORCE_ON,
|
|
EROFS_SYNC_DECOMPRESS_FORCE_OFF
|
|
};
|
|
|
|
struct erofs_mount_opts {
|
|
/* current strategy of how to use managed cache */
|
|
unsigned char cache_strategy;
|
|
unsigned int mount_opt;
|
|
};
|
|
|
|
struct erofs_dev_context {
|
|
struct idr tree;
|
|
struct rw_semaphore rwsem;
|
|
|
|
unsigned int extra_devices;
|
|
bool flatdev;
|
|
};
|
|
|
|
struct erofs_sb_lz4_info {
|
|
u16 max_pclusterblks; /* maximum physical blocks for LZ4 pclusters */
|
|
};
|
|
|
|
struct erofs_xattr_prefix_item {
|
|
struct erofs_xattr_long_prefix *prefix;
|
|
u8 infix_len;
|
|
};
|
|
|
|
struct erofs_sb_info {
|
|
struct erofs_device_info dif0;
|
|
struct erofs_mount_opts opt; /* options */
|
|
#ifdef CONFIG_EROFS_FS_ZIP
|
|
/* list for all registered superblocks, mainly for shrinker */
|
|
struct list_head list;
|
|
struct mutex umount_mutex;
|
|
|
|
/* managed XArray arranged in physical block number */
|
|
struct xarray managed_pslots;
|
|
|
|
unsigned int sync_decompress; /* strategy for sync decompression */
|
|
unsigned int shrinker_run_no;
|
|
|
|
struct erofs_sb_lz4_info lz4;
|
|
#endif /* CONFIG_EROFS_FS_ZIP */
|
|
struct inode *managed_cache; /* pseudo inode to cache physical data */
|
|
struct inode *packed_inode;
|
|
struct inode *metabox_inode;
|
|
struct erofs_dev_context *devs;
|
|
u64 total_blocks;
|
|
|
|
u32 meta_blkaddr;
|
|
#ifdef CONFIG_EROFS_FS_XATTR
|
|
u32 xattr_blkaddr;
|
|
u32 xattr_prefix_start;
|
|
u8 xattr_prefix_count;
|
|
u8 ishare_xattr_prefix_id;
|
|
struct erofs_xattr_prefix_item *xattr_prefixes;
|
|
unsigned int xattr_filter_reserved;
|
|
#endif
|
|
u16 device_id_mask; /* valid bits of device id to be used */
|
|
|
|
unsigned char islotbits; /* inode slot unit size in bit shift */
|
|
unsigned char blkszbits; /* filesystem block size in bit shift */
|
|
|
|
u32 sb_size; /* total superblock size */
|
|
u32 fixed_nsec;
|
|
s64 epoch;
|
|
|
|
/* what we really care is nid, rather than ino.. */
|
|
erofs_nid_t root_nid;
|
|
erofs_nid_t packed_nid;
|
|
erofs_nid_t metabox_nid;
|
|
/* used for statfs, f_files - f_favail */
|
|
u64 inos;
|
|
|
|
char *volume_name;
|
|
u32 feature_compat;
|
|
u32 feature_incompat;
|
|
u16 available_compr_algs;
|
|
|
|
/* sysfs support */
|
|
struct kobject s_kobj; /* /sys/fs/erofs/<devname> */
|
|
struct completion s_kobj_unregister;
|
|
erofs_off_t dir_ra_bytes;
|
|
|
|
char *domain_id;
|
|
};
|
|
|
|
#define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info)
|
|
#define EROFS_I_SB(inode) ((struct erofs_sb_info *)(inode)->i_sb->s_fs_info)
|
|
|
|
/* Mount flags set via mount options or defaults */
|
|
#define EROFS_MOUNT_XATTR_USER 0x00000010
|
|
#define EROFS_MOUNT_POSIX_ACL 0x00000020
|
|
#define EROFS_MOUNT_DAX_ALWAYS 0x00000040
|
|
#define EROFS_MOUNT_DAX_NEVER 0x00000080
|
|
#define EROFS_MOUNT_DIRECT_IO 0x00000100
|
|
#define EROFS_MOUNT_INODE_SHARE 0x00000200
|
|
|
|
#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)
|
|
|
|
static inline bool erofs_is_fileio_mode(struct erofs_sb_info *sbi)
|
|
{
|
|
return IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) && sbi->dif0.file;
|
|
}
|
|
|
|
extern struct file_system_type erofs_anon_fs_type;
|
|
|
|
enum {
|
|
EROFS_ZIP_CACHE_DISABLED,
|
|
EROFS_ZIP_CACHE_READAHEAD,
|
|
EROFS_ZIP_CACHE_READAROUND
|
|
};
|
|
|
|
struct erofs_buf {
|
|
struct address_space *mapping;
|
|
u64 off;
|
|
struct page *page;
|
|
void *base;
|
|
bool mc;
|
|
};
|
|
#define __EROFS_BUF_INITIALIZER ((struct erofs_buf){ .page = NULL })
|
|
|
|
#define erofs_blknr(sb, pos) ((erofs_blk_t)((pos) >> (sb)->s_blocksize_bits))
|
|
#define erofs_blkoff(sb, pos) ((pos) & ((sb)->s_blocksize - 1))
|
|
#define erofs_pos(sb, blk) ((erofs_off_t)(blk) << (sb)->s_blocksize_bits)
|
|
#define erofs_iblks(i) (round_up((i)->i_size, i_blocksize(i)) >> (i)->i_blkbits)
|
|
|
|
#define EROFS_FEATURE_FUNCS(name, compat, feature) \
|
|
static inline bool erofs_sb_has_##name(struct erofs_sb_info *sbi) \
|
|
{ \
|
|
return sbi->feature_##compat & EROFS_FEATURE_##feature; \
|
|
}
|
|
|
|
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)
|
|
|
|
static inline u64 erofs_nid_to_ino64(struct erofs_sb_info *sbi, erofs_nid_t nid)
|
|
{
|
|
if (!erofs_sb_has_metabox(sbi))
|
|
return nid;
|
|
|
|
/*
|
|
* When metadata compression is enabled, avoid generating excessively
|
|
* large inode numbers for metadata-compressed inodes. Shift NIDs in
|
|
* the 31-62 bit range left by one and move the metabox flag to bit 31.
|
|
*
|
|
* Note: on-disk NIDs remain unchanged as they are primarily used for
|
|
* compatibility with non-LFS 32-bit applications.
|
|
*/
|
|
return ((nid << 1) & GENMASK_ULL(63, 32)) | (nid & GENMASK(30, 0)) |
|
|
((nid >> EROFS_DIRENT_NID_METABOX_BIT) << 31);
|
|
}
|
|
|
|
/* atomic flag definitions */
|
|
#define EROFS_I_EA_INITED_BIT 0
|
|
#define EROFS_I_Z_INITED_BIT 1
|
|
|
|
/* bitlock definitions (arranged in reverse order) */
|
|
#define EROFS_I_BL_XATTR_BIT (BITS_PER_LONG - 1)
|
|
#define EROFS_I_BL_Z_BIT (BITS_PER_LONG - 2)
|
|
|
|
/* default readahead size of directories */
|
|
#define EROFS_DIR_RA_BYTES 16384
|
|
|
|
struct erofs_inode_fingerprint {
|
|
u8 *opaque;
|
|
int size;
|
|
};
|
|
|
|
struct erofs_inode {
|
|
erofs_nid_t nid;
|
|
|
|
/* atomic flags (including bitlocks) */
|
|
unsigned long flags;
|
|
|
|
unsigned char datalayout;
|
|
unsigned char inode_isize;
|
|
bool dot_omitted;
|
|
unsigned int xattr_isize;
|
|
|
|
unsigned int xattr_name_filter;
|
|
unsigned int xattr_shared_count;
|
|
unsigned int *xattr_shared_xattrs;
|
|
|
|
union {
|
|
erofs_blk_t startblk;
|
|
struct {
|
|
unsigned short chunkformat;
|
|
unsigned char chunkbits;
|
|
};
|
|
#ifdef CONFIG_EROFS_FS_ZIP
|
|
struct {
|
|
unsigned short z_advise;
|
|
unsigned char z_algofmt[2];
|
|
unsigned char z_lclusterbits;
|
|
union {
|
|
u64 z_tailextent_headlcn;
|
|
u64 z_extents;
|
|
};
|
|
erofs_off_t z_fragmentoff;
|
|
unsigned short z_idata_size;
|
|
};
|
|
#endif /* CONFIG_EROFS_FS_ZIP */
|
|
};
|
|
#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE
|
|
struct list_head ishare_list;
|
|
union {
|
|
/* for each anon shared inode */
|
|
struct {
|
|
struct erofs_inode_fingerprint fingerprint;
|
|
spinlock_t ishare_lock;
|
|
};
|
|
/* for each real filesystem inode */
|
|
struct dentry *sharedentry;
|
|
};
|
|
#endif
|
|
/* the corresponding vfs inode */
|
|
struct inode vfs_inode;
|
|
};
|
|
|
|
#define EROFS_I(ptr) container_of(ptr, struct erofs_inode, vfs_inode)
|
|
|
|
static inline bool erofs_inode_in_metabox(struct inode *inode)
|
|
{
|
|
return EROFS_I(inode)->nid & BIT_ULL(EROFS_DIRENT_NID_METABOX_BIT);
|
|
}
|
|
|
|
static inline erofs_off_t erofs_iloc(struct inode *inode)
|
|
{
|
|
struct erofs_sb_info *sbi = EROFS_I_SB(inode);
|
|
erofs_nid_t nid_lo = EROFS_I(inode)->nid & EROFS_DIRENT_NID_MASK;
|
|
|
|
if (erofs_inode_in_metabox(inode))
|
|
return nid_lo << sbi->islotbits;
|
|
return erofs_pos(inode->i_sb, sbi->meta_blkaddr) +
|
|
(nid_lo << sbi->islotbits);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/* reclaiming is never triggered when allocating new folios. */
|
|
static inline struct folio *erofs_grab_folio_nowait(struct address_space *as,
|
|
pgoff_t index)
|
|
{
|
|
return __filemap_get_folio(as, index,
|
|
FGP_LOCK|FGP_CREAT|FGP_NOFS|FGP_NOWAIT,
|
|
readahead_gfp_mask(as) & ~__GFP_RECLAIM);
|
|
}
|
|
|
|
/* Allocated on disk at @m_pa (e.g. NOT a fragment extent) */
|
|
#define EROFS_MAP_MAPPED 0x0001
|
|
/* Located in metadata (could be copied from bd_inode) */
|
|
#define EROFS_MAP_META 0x0002
|
|
/* @m_llen may be truncated by the runtime compared to the on-disk record */
|
|
#define EROFS_MAP_PARTIAL_MAPPED 0x0004
|
|
/* The on-disk @m_llen may cover only part of the encoded data */
|
|
#define EROFS_MAP_PARTIAL_REF 0x0008
|
|
/* Located in the special packed inode */
|
|
#define EROFS_MAP_FRAGMENT 0x0010
|
|
/* The encoded on-disk data will be fully handled (decompressed) */
|
|
#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;
|
|
u64 m_plen, m_llen;
|
|
|
|
unsigned short m_deviceid;
|
|
char m_algorithmformat;
|
|
unsigned int m_flags;
|
|
};
|
|
|
|
/*
|
|
* Used to get the exact decompressed length, e.g. fiemap (consider lookback
|
|
* approach instead if possible since it's more metadata lightweight.)
|
|
*/
|
|
#define EROFS_GET_BLOCKS_FIEMAP 0x0001
|
|
/* Used to map the whole extent if non-negligible data is requested for LZMA */
|
|
#define EROFS_GET_BLOCKS_READMORE 0x0002
|
|
/* Used to map tail extent for tailpacking inline or fragment pcluster */
|
|
#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 super_block *m_sb;
|
|
struct erofs_device_info *m_dif;
|
|
struct block_device *m_bdev;
|
|
|
|
erofs_off_t m_pa;
|
|
unsigned int m_deviceid;
|
|
};
|
|
|
|
extern const struct super_operations erofs_sops;
|
|
extern const struct address_space_operations erofs_aops;
|
|
extern const struct address_space_operations erofs_fileio_aops;
|
|
extern const struct address_space_operations z_erofs_aops;
|
|
|
|
extern const struct inode_operations erofs_generic_iops;
|
|
extern const struct inode_operations erofs_symlink_iops;
|
|
extern const struct inode_operations erofs_fast_symlink_iops;
|
|
extern const struct inode_operations erofs_dir_iops;
|
|
|
|
extern const struct file_operations erofs_file_fops;
|
|
extern const struct file_operations erofs_dir_fops;
|
|
extern const struct file_operations erofs_ishare_fops;
|
|
|
|
extern const struct iomap_ops z_erofs_iomap_report_ops;
|
|
|
|
int erofs_setup_managed_cache(struct super_block *sb);
|
|
#ifdef CONFIG_EROFS_FS_BACKED_BY_FILE
|
|
int erofs_read_meta_folio(struct file *file, struct folio *folio);
|
|
#else
|
|
#define erofs_read_meta_folio NULL
|
|
#endif
|
|
void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
|
|
erofs_off_t *offset, int *lengthp);
|
|
void erofs_unmap_metabuf(struct erofs_buf *buf);
|
|
void erofs_put_metabuf(struct erofs_buf *buf);
|
|
void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset, bool need_kmap);
|
|
int erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb,
|
|
bool in_metabox);
|
|
void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
|
|
erofs_off_t offset, bool in_metabox);
|
|
int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *dev);
|
|
int erofs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
|
u64 start, u64 len);
|
|
loff_t erofs_file_llseek(struct file *file, loff_t offset, int whence);
|
|
int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map);
|
|
void erofs_onlinefolio_init(struct folio *folio);
|
|
void erofs_onlinefolio_split(struct folio *folio);
|
|
void erofs_onlinefolio_end(struct folio *folio, int err, bool dirty);
|
|
struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid);
|
|
int erofs_getattr(struct mnt_idmap *idmap, const struct path *path,
|
|
struct kstat *stat, u32 request_mask,
|
|
unsigned int query_flags);
|
|
int erofs_namei(struct inode *dir, const struct qstr *name,
|
|
erofs_nid_t *nid, unsigned int *d_type);
|
|
|
|
static inline void *erofs_vm_map_ram(struct page **pages, unsigned int count)
|
|
{
|
|
int retried = 0;
|
|
|
|
while (1) {
|
|
void *p = vm_map_ram(pages, count, -1);
|
|
|
|
/* retry two more times (totally 3 times) */
|
|
if (p || ++retried >= 3)
|
|
return p;
|
|
vm_unmap_aliases();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static inline const struct address_space_operations *
|
|
erofs_get_aops(struct inode *realinode)
|
|
{
|
|
if (erofs_inode_is_data_compressed(EROFS_I(realinode)->datalayout)) {
|
|
if (!IS_ENABLED(CONFIG_EROFS_FS_ZIP))
|
|
return ERR_PTR(-EOPNOTSUPP);
|
|
DO_ONCE_LITE_IF(realinode->i_blkbits != PAGE_SHIFT,
|
|
erofs_info, realinode->i_sb,
|
|
"EXPERIMENTAL EROFS subpage compressed block support in use. Use at your own risk!");
|
|
return &z_erofs_aops;
|
|
}
|
|
if (IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) &&
|
|
erofs_is_fileio_mode(EROFS_SB(realinode->i_sb)))
|
|
return &erofs_fileio_aops;
|
|
return &erofs_aops;
|
|
}
|
|
|
|
int erofs_register_sysfs(struct super_block *sb);
|
|
void erofs_unregister_sysfs(struct super_block *sb);
|
|
int __init erofs_init_sysfs(void);
|
|
void erofs_exit_sysfs(void);
|
|
|
|
struct page *__erofs_allocpage(struct page **pagepool, gfp_t gfp, bool tryrsv);
|
|
static inline struct page *erofs_allocpage(struct page **pagepool, gfp_t gfp)
|
|
{
|
|
return __erofs_allocpage(pagepool, gfp, false);
|
|
}
|
|
static inline void erofs_pagepool_add(struct page **pagepool, struct page *page)
|
|
{
|
|
set_page_private(page, (unsigned long)*pagepool);
|
|
*pagepool = page;
|
|
}
|
|
void erofs_release_pages(struct page **pagepool);
|
|
|
|
#ifdef CONFIG_EROFS_FS_ZIP
|
|
#define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping)
|
|
|
|
extern atomic_long_t erofs_global_shrink_cnt;
|
|
void erofs_shrinker_register(struct super_block *sb);
|
|
void erofs_shrinker_unregister(struct super_block *sb);
|
|
int __init erofs_init_shrinker(void);
|
|
void erofs_exit_shrinker(void);
|
|
int __init z_erofs_init_subsystem(void);
|
|
void z_erofs_exit_subsystem(void);
|
|
int z_erofs_init_super(struct super_block *sb);
|
|
unsigned long z_erofs_shrink_scan(struct erofs_sb_info *sbi,
|
|
unsigned long nr_shrink);
|
|
int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map,
|
|
int flags);
|
|
void *z_erofs_get_gbuf(unsigned int requiredpages);
|
|
void z_erofs_put_gbuf(void *ptr);
|
|
int z_erofs_gbuf_growsize(unsigned int nrpages);
|
|
int __init z_erofs_gbuf_init(void);
|
|
void z_erofs_gbuf_exit(void);
|
|
#else
|
|
static inline void erofs_shrinker_register(struct super_block *sb) {}
|
|
static inline void erofs_shrinker_unregister(struct super_block *sb) {}
|
|
static inline int erofs_init_shrinker(void) { return 0; }
|
|
static inline void erofs_exit_shrinker(void) {}
|
|
static inline int z_erofs_init_subsystem(void) { return 0; }
|
|
static inline void z_erofs_exit_subsystem(void) {}
|
|
static inline int z_erofs_init_super(struct super_block *sb) { return 0; }
|
|
#endif /* !CONFIG_EROFS_FS_ZIP */
|
|
int z_erofs_parse_cfgs(struct super_block *sb, struct erofs_super_block *dsb);
|
|
|
|
#ifdef CONFIG_EROFS_FS_BACKED_BY_FILE
|
|
struct bio *erofs_fileio_bio_alloc(struct erofs_map_dev *mdev);
|
|
void erofs_fileio_submit_bio(struct bio *bio);
|
|
#else
|
|
static inline struct bio *erofs_fileio_bio_alloc(struct erofs_map_dev *mdev) { return NULL; }
|
|
static inline void erofs_fileio_submit_bio(struct bio *bio) {}
|
|
#endif
|
|
|
|
#ifdef CONFIG_EROFS_FS_PAGE_CACHE_SHARE
|
|
int __init erofs_init_ishare(void);
|
|
void erofs_exit_ishare(void);
|
|
bool erofs_ishare_fill_inode(struct inode *inode);
|
|
void erofs_ishare_free_inode(struct inode *inode);
|
|
struct inode *erofs_real_inode(struct inode *inode, bool *need_iput);
|
|
#else
|
|
static inline int erofs_init_ishare(void) { return 0; }
|
|
static inline void erofs_exit_ishare(void) {}
|
|
static inline bool erofs_ishare_fill_inode(struct inode *inode) { return false; }
|
|
static inline void erofs_ishare_free_inode(struct inode *inode) {}
|
|
static inline struct inode *erofs_real_inode(struct inode *inode, bool *need_iput)
|
|
{
|
|
*need_iput = false;
|
|
return inode;
|
|
}
|
|
#endif
|
|
|
|
long erofs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
|
long erofs_compat_ioctl(struct file *filp, unsigned int cmd,
|
|
unsigned long arg);
|
|
|
|
#endif /* __EROFS_INTERNAL_H */
|