18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2008 Oracle. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#ifndef BTRFS_COMPRESSION_H 78c2ecf20Sopenharmony_ci#define BTRFS_COMPRESSION_H 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/sizes.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cistruct btrfs_inode; 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * We want to make sure that amount of RAM required to uncompress an extent is 158c2ecf20Sopenharmony_ci * reasonable, so we limit the total size in ram of a compressed extent to 168c2ecf20Sopenharmony_ci * 128k. This is a crucial number because it also controls how easily we can 178c2ecf20Sopenharmony_ci * spread reads across cpus for decompression. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * We also want to make sure the amount of IO required to do a random read is 208c2ecf20Sopenharmony_ci * reasonably small, so we limit the size of a compressed extent to 128k. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* Maximum length of compressed data stored on disk */ 248c2ecf20Sopenharmony_ci#define BTRFS_MAX_COMPRESSED (SZ_128K) 258c2ecf20Sopenharmony_ci/* Maximum size of data before compression */ 268c2ecf20Sopenharmony_ci#define BTRFS_MAX_UNCOMPRESSED (SZ_128K) 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define BTRFS_ZLIB_DEFAULT_LEVEL 3 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistruct compressed_bio { 318c2ecf20Sopenharmony_ci /* number of bios pending for this compressed extent */ 328c2ecf20Sopenharmony_ci refcount_t pending_bios; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci /* the pages with the compressed data on them */ 358c2ecf20Sopenharmony_ci struct page **compressed_pages; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci /* inode that owns this data */ 388c2ecf20Sopenharmony_ci struct inode *inode; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* starting offset in the inode for our pages */ 418c2ecf20Sopenharmony_ci u64 start; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci /* number of bytes in the inode we're working on */ 448c2ecf20Sopenharmony_ci unsigned long len; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci /* number of bytes on disk */ 478c2ecf20Sopenharmony_ci unsigned long compressed_len; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci /* the compression algorithm for this bio */ 508c2ecf20Sopenharmony_ci int compress_type; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci /* number of compressed pages in the array */ 538c2ecf20Sopenharmony_ci unsigned long nr_pages; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci /* IO errors */ 568c2ecf20Sopenharmony_ci int errors; 578c2ecf20Sopenharmony_ci int mirror_num; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* for reads, this is the bio we are copying the data into */ 608c2ecf20Sopenharmony_ci struct bio *orig_bio; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci /* 638c2ecf20Sopenharmony_ci * the start of a variable length array of checksums only 648c2ecf20Sopenharmony_ci * used by reads 658c2ecf20Sopenharmony_ci */ 668c2ecf20Sopenharmony_ci u8 sums[]; 678c2ecf20Sopenharmony_ci}; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic inline unsigned int btrfs_compress_type(unsigned int type_level) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci return (type_level & 0xF); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic inline unsigned int btrfs_compress_level(unsigned int type_level) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci return ((type_level & 0xF0) >> 4); 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_civoid __init btrfs_init_compress(void); 808c2ecf20Sopenharmony_civoid __cold btrfs_exit_compress(void); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ciint btrfs_compress_pages(unsigned int type_level, struct address_space *mapping, 838c2ecf20Sopenharmony_ci u64 start, struct page **pages, 848c2ecf20Sopenharmony_ci unsigned long *out_pages, 858c2ecf20Sopenharmony_ci unsigned long *total_in, 868c2ecf20Sopenharmony_ci unsigned long *total_out); 878c2ecf20Sopenharmony_ciint btrfs_decompress(int type, unsigned char *data_in, struct page *dest_page, 888c2ecf20Sopenharmony_ci unsigned long start_byte, size_t srclen, size_t destlen); 898c2ecf20Sopenharmony_ciint btrfs_decompress_buf2page(const char *buf, unsigned long buf_start, 908c2ecf20Sopenharmony_ci unsigned long total_out, u64 disk_start, 918c2ecf20Sopenharmony_ci struct bio *bio); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ciblk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start, 948c2ecf20Sopenharmony_ci unsigned long len, u64 disk_start, 958c2ecf20Sopenharmony_ci unsigned long compressed_len, 968c2ecf20Sopenharmony_ci struct page **compressed_pages, 978c2ecf20Sopenharmony_ci unsigned long nr_pages, 988c2ecf20Sopenharmony_ci unsigned int write_flags, 998c2ecf20Sopenharmony_ci struct cgroup_subsys_state *blkcg_css); 1008c2ecf20Sopenharmony_ciblk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, 1018c2ecf20Sopenharmony_ci int mirror_num, unsigned long bio_flags); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ciunsigned int btrfs_compress_str2level(unsigned int type, const char *str); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cienum btrfs_compression_type { 1068c2ecf20Sopenharmony_ci BTRFS_COMPRESS_NONE = 0, 1078c2ecf20Sopenharmony_ci BTRFS_COMPRESS_ZLIB = 1, 1088c2ecf20Sopenharmony_ci BTRFS_COMPRESS_LZO = 2, 1098c2ecf20Sopenharmony_ci BTRFS_COMPRESS_ZSTD = 3, 1108c2ecf20Sopenharmony_ci BTRFS_NR_COMPRESS_TYPES = 4, 1118c2ecf20Sopenharmony_ci}; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistruct workspace_manager { 1148c2ecf20Sopenharmony_ci struct list_head idle_ws; 1158c2ecf20Sopenharmony_ci spinlock_t ws_lock; 1168c2ecf20Sopenharmony_ci /* Number of free workspaces */ 1178c2ecf20Sopenharmony_ci int free_ws; 1188c2ecf20Sopenharmony_ci /* Total number of allocated workspaces */ 1198c2ecf20Sopenharmony_ci atomic_t total_ws; 1208c2ecf20Sopenharmony_ci /* Waiters for a free workspace */ 1218c2ecf20Sopenharmony_ci wait_queue_head_t ws_wait; 1228c2ecf20Sopenharmony_ci}; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistruct list_head *btrfs_get_workspace(int type, unsigned int level); 1258c2ecf20Sopenharmony_civoid btrfs_put_workspace(int type, struct list_head *ws); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistruct btrfs_compress_op { 1288c2ecf20Sopenharmony_ci struct workspace_manager *workspace_manager; 1298c2ecf20Sopenharmony_ci /* Maximum level supported by the compression algorithm */ 1308c2ecf20Sopenharmony_ci unsigned int max_level; 1318c2ecf20Sopenharmony_ci unsigned int default_level; 1328c2ecf20Sopenharmony_ci}; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci/* The heuristic workspaces are managed via the 0th workspace manager */ 1358c2ecf20Sopenharmony_ci#define BTRFS_NR_WORKSPACE_MANAGERS BTRFS_NR_COMPRESS_TYPES 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ciextern const struct btrfs_compress_op btrfs_heuristic_compress; 1388c2ecf20Sopenharmony_ciextern const struct btrfs_compress_op btrfs_zlib_compress; 1398c2ecf20Sopenharmony_ciextern const struct btrfs_compress_op btrfs_lzo_compress; 1408c2ecf20Sopenharmony_ciextern const struct btrfs_compress_op btrfs_zstd_compress; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ciconst char* btrfs_compress_type2str(enum btrfs_compression_type type); 1438c2ecf20Sopenharmony_cibool btrfs_compress_is_valid_type(const char *str, size_t len); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ciint btrfs_compress_heuristic(struct inode *inode, u64 start, u64 end); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ciint zlib_compress_pages(struct list_head *ws, struct address_space *mapping, 1488c2ecf20Sopenharmony_ci u64 start, struct page **pages, unsigned long *out_pages, 1498c2ecf20Sopenharmony_ci unsigned long *total_in, unsigned long *total_out); 1508c2ecf20Sopenharmony_ciint zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb); 1518c2ecf20Sopenharmony_ciint zlib_decompress(struct list_head *ws, unsigned char *data_in, 1528c2ecf20Sopenharmony_ci struct page *dest_page, unsigned long start_byte, size_t srclen, 1538c2ecf20Sopenharmony_ci size_t destlen); 1548c2ecf20Sopenharmony_cistruct list_head *zlib_alloc_workspace(unsigned int level); 1558c2ecf20Sopenharmony_civoid zlib_free_workspace(struct list_head *ws); 1568c2ecf20Sopenharmony_cistruct list_head *zlib_get_workspace(unsigned int level); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ciint lzo_compress_pages(struct list_head *ws, struct address_space *mapping, 1598c2ecf20Sopenharmony_ci u64 start, struct page **pages, unsigned long *out_pages, 1608c2ecf20Sopenharmony_ci unsigned long *total_in, unsigned long *total_out); 1618c2ecf20Sopenharmony_ciint lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb); 1628c2ecf20Sopenharmony_ciint lzo_decompress(struct list_head *ws, unsigned char *data_in, 1638c2ecf20Sopenharmony_ci struct page *dest_page, unsigned long start_byte, size_t srclen, 1648c2ecf20Sopenharmony_ci size_t destlen); 1658c2ecf20Sopenharmony_cistruct list_head *lzo_alloc_workspace(unsigned int level); 1668c2ecf20Sopenharmony_civoid lzo_free_workspace(struct list_head *ws); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ciint zstd_compress_pages(struct list_head *ws, struct address_space *mapping, 1698c2ecf20Sopenharmony_ci u64 start, struct page **pages, unsigned long *out_pages, 1708c2ecf20Sopenharmony_ci unsigned long *total_in, unsigned long *total_out); 1718c2ecf20Sopenharmony_ciint zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb); 1728c2ecf20Sopenharmony_ciint zstd_decompress(struct list_head *ws, unsigned char *data_in, 1738c2ecf20Sopenharmony_ci struct page *dest_page, unsigned long start_byte, size_t srclen, 1748c2ecf20Sopenharmony_ci size_t destlen); 1758c2ecf20Sopenharmony_civoid zstd_init_workspace_manager(void); 1768c2ecf20Sopenharmony_civoid zstd_cleanup_workspace_manager(void); 1778c2ecf20Sopenharmony_cistruct list_head *zstd_alloc_workspace(unsigned int level); 1788c2ecf20Sopenharmony_civoid zstd_free_workspace(struct list_head *ws); 1798c2ecf20Sopenharmony_cistruct list_head *zstd_get_workspace(unsigned int level); 1808c2ecf20Sopenharmony_civoid zstd_put_workspace(struct list_head *ws); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci#endif 183