| 1 |
|
| 2 | |
| 3 | * Copyright (C) 2008 Oracle. All rights reserved.
|
| 4 |
|
| 5 |
|
| 6 | #ifndef BTRFS_COMPRESSION_H
|
| 7 | #define BTRFS_COMPRESSION_H
|
| 8 |
|
| 9 | #include <linux/sizes.h>
|
| 10 | #include <linux/mm.h>
|
| 11 | #include <linux/list.h>
|
| 12 | #include <linux/workqueue.h>
|
| 13 | #include <linux/wait.h>
|
| 14 | #include <linux/pagemap.h>
|
| 15 | #include "bio.h"
|
| 16 | #include "fs.h"
|
| 17 | #include "btrfs_inode.h"
|
| 18 |
|
| 19 | struct address_space;
|
| 20 | struct inode;
|
| 21 | struct btrfs_inode;
|
| 22 | struct btrfs_ordered_extent;
|
| 23 |
|
| 24 | |
| 25 | * We want to make sure that amount of RAM required to uncompress an extent is
|
| 26 | * reasonable, so we limit the total size in ram of a compressed extent to
|
| 27 | * 128k. This is a crucial number because it also controls how easily we can
|
| 28 | * spread reads across cpus for decompression.
|
| 29 | *
|
| 30 | * We also want to make sure the amount of IO required to do a random read is
|
| 31 | * reasonably small, so we limit the size of a compressed extent to 128k.
|
| 32 |
|
| 33 |
|
| 34 |
|
| 35 | #define BTRFS_MAX_COMPRESSED (SZ_128K)
|
| 36 | #define BTRFS_MAX_COMPRESSED_PAGES (BTRFS_MAX_COMPRESSED / PAGE_SIZE)
|
| 37 | static_assert((BTRFS_MAX_COMPRESSED % PAGE_SIZE) == 0);
|
| 38 |
|
| 39 |
|
| 40 | #define BTRFS_COMPRESSION_CHUNK_SIZE (SZ_512K)
|
| 41 |
|
| 42 |
|
| 43 | #define BTRFS_MAX_UNCOMPRESSED (SZ_128K)
|
| 44 |
|
| 45 | #define BTRFS_ZLIB_DEFAULT_LEVEL 3
|
| 46 |
|
| 47 | struct compressed_bio {
|
| 48 |
|
| 49 | u64 start;
|
| 50 |
|
| 51 |
|
| 52 | unsigned int len;
|
| 53 |
|
| 54 |
|
| 55 | u8 compress_type;
|
| 56 |
|
| 57 |
|
| 58 | bool writeback;
|
| 59 |
|
| 60 |
|
| 61 | struct btrfs_bio *orig_bbio;
|
| 62 |
|
| 63 |
|
| 64 | struct btrfs_bio bbio;
|
| 65 | };
|
| 66 |
|
| 67 | static inline struct btrfs_fs_info *cb_to_fs_info(const struct compressed_bio *cb)
|
| 68 | {
|
| 69 | return cb->bbio.inode->root->fs_info;
|
| 70 | }
|
| 71 |
|
| 72 |
|
| 73 | static inline u32 btrfs_calc_input_length(struct folio *folio, u64 range_end, u64 cur)
|
| 74 | {
|
| 75 |
|
| 76 | ASSERT(folio_pos(folio) <= cur);
|
| 77 | ASSERT(cur < folio_next_pos(folio));
|
| 78 | return umin(range_end, folio_next_pos(folio)) - cur;
|
| 79 | }
|
| 80 |
|
| 81 | int btrfs_alloc_compress_wsm(struct btrfs_fs_info *fs_info);
|
| 82 | void btrfs_free_compress_wsm(struct btrfs_fs_info *fs_info);
|
| 83 |
|
| 84 | int __init btrfs_init_compress(void);
|
| 85 | void __cold btrfs_exit_compress(void);
|
| 86 |
|
| 87 | bool btrfs_compress_level_valid(unsigned int type, int level);
|
| 88 | int btrfs_decompress(int type, const u8 *data_in, struct folio *dest_folio,
|
| 89 | unsigned long dest_pgoff, size_t srclen, size_t destlen);
|
| 90 | int btrfs_decompress_buf2page(const char *buf, u32 buf_len,
|
| 91 | struct compressed_bio *cb, u32 decompressed);
|
| 92 |
|
| 93 | struct compressed_bio *btrfs_alloc_compressed_write(struct btrfs_inode *inode,
|
| 94 | u64 start, u64 len);
|
| 95 | void btrfs_submit_compressed_write(struct btrfs_ordered_extent *ordered,
|
| 96 | struct compressed_bio *cb);
|
| 97 | void btrfs_submit_compressed_read(struct btrfs_bio *bbio);
|
| 98 |
|
| 99 | int btrfs_compress_str2level(unsigned int type, const char *str, int *level_ret);
|
| 100 |
|
| 101 | struct folio *btrfs_alloc_compr_folio(struct btrfs_fs_info *fs_info, gfp_t gfp);
|
| 102 | void btrfs_free_compr_folio(struct folio *folio);
|
| 103 |
|
| 104 | struct workspace_manager {
|
| 105 | struct list_head idle_ws;
|
| 106 | spinlock_t ws_lock;
|
| 107 |
|
| 108 | int free_ws;
|
| 109 |
|
| 110 | atomic_t total_ws;
|
| 111 |
|
| 112 | wait_queue_head_t ws_wait;
|
| 113 | };
|
| 114 |
|
| 115 | struct list_head *btrfs_get_workspace(struct btrfs_fs_info *fs_info, int type, int level);
|
| 116 | void btrfs_put_workspace(struct btrfs_fs_info *fs_info, int type, struct list_head *ws);
|
| 117 |
|
| 118 | struct btrfs_compress_levels {
|
| 119 |
|
| 120 | int min_level;
|
| 121 | int max_level;
|
| 122 | int default_level;
|
| 123 | };
|
| 124 |
|
| 125 |
|
| 126 | #define BTRFS_NR_WORKSPACE_MANAGERS BTRFS_NR_COMPRESS_TYPES
|
| 127 |
|
| 128 | extern const struct btrfs_compress_levels btrfs_heuristic_compress;
|
| 129 | extern const struct btrfs_compress_levels btrfs_zlib_compress;
|
| 130 | extern const struct btrfs_compress_levels btrfs_lzo_compress;
|
| 131 | extern const struct btrfs_compress_levels btrfs_zstd_compress;
|
| 132 |
|
| 133 | const char* btrfs_compress_type2str(enum btrfs_compression_type type);
|
| 134 | bool btrfs_compress_is_valid_type(const char *str, size_t len);
|
| 135 |
|
| 136 | int btrfs_compress_heuristic(struct btrfs_inode *inode, u64 start, u64 end);
|
| 137 |
|
| 138 | int btrfs_compress_filemap_get_folio(struct address_space *mapping, u64 start,
|
| 139 | struct folio **in_folio_ret);
|
| 140 | struct compressed_bio *btrfs_compress_bio(struct btrfs_inode *inode,
|
| 141 | u64 start, u32 len, unsigned int type,
|
| 142 | int level, blk_opf_t write_flags);
|
| 143 |
|
| 144 | static inline void cleanup_compressed_bio(struct compressed_bio *cb)
|
| 145 | {
|
| 146 | struct bio *bio = &cb->bbio.bio;
|
| 147 | struct folio_iter fi;
|
| 148 |
|
| 149 | bio_for_each_folio_all(fi, bio)
|
| 150 | btrfs_free_compr_folio(fi.folio);
|
| 151 | bio_put(bio);
|
| 152 | }
|
| 153 |
|
| 154 | int zlib_compress_bio(struct list_head *ws, struct compressed_bio *cb);
|
| 155 | int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb);
|
| 156 | int zlib_decompress(struct list_head *ws, const u8 *data_in,
|
| 157 | struct folio *dest_folio, unsigned long dest_pgoff, size_t srclen,
|
| 158 | size_t destlen);
|
| 159 | struct list_head *zlib_alloc_workspace(struct btrfs_fs_info *fs_info, unsigned int level);
|
| 160 | void zlib_free_workspace(struct list_head *ws);
|
| 161 | struct list_head *zlib_get_workspace(struct btrfs_fs_info *fs_info, unsigned int level);
|
| 162 |
|
| 163 | int lzo_compress_bio(struct list_head *ws, struct compressed_bio *cb);
|
| 164 | int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb);
|
| 165 | int lzo_decompress(struct list_head *ws, const u8 *data_in,
|
| 166 | struct folio *dest_folio, unsigned long dest_pgoff, size_t srclen,
|
| 167 | size_t destlen);
|
| 168 | struct list_head *lzo_alloc_workspace(struct btrfs_fs_info *fs_info);
|
| 169 | void lzo_free_workspace(struct list_head *ws);
|
| 170 |
|
| 171 | int zstd_compress_bio(struct list_head *ws, struct compressed_bio *cb);
|
| 172 | int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb);
|
| 173 | int zstd_decompress(struct list_head *ws, const u8 *data_in,
|
| 174 | struct folio *dest_folio, unsigned long dest_pgoff, size_t srclen,
|
| 175 | size_t destlen);
|
| 176 | int zstd_alloc_workspace_manager(struct btrfs_fs_info *fs_info);
|
| 177 | void zstd_free_workspace_manager(struct btrfs_fs_info *fs_info);
|
| 178 | struct list_head *zstd_alloc_workspace(struct btrfs_fs_info *fs_info, int level);
|
| 179 | void zstd_free_workspace(struct list_head *ws);
|
| 180 | struct list_head *zstd_get_workspace(struct btrfs_fs_info *fs_info, int level);
|
| 181 | void zstd_put_workspace(struct btrfs_fs_info *fs_info, struct list_head *ws);
|
| 182 |
|
| 183 | #endif
|