compression.h 6.1 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
C
Chris Mason 已提交
2 3 4 5
/*
 * Copyright (C) 2008 Oracle.  All rights reserved.
 */

6 7
#ifndef BTRFS_COMPRESSION_H
#define BTRFS_COMPRESSION_H
C
Chris Mason 已提交
8

9 10
#include <linux/sizes.h>

11 12
struct btrfs_inode;

13 14 15 16 17 18 19 20 21 22 23 24
/*
 * We want to make sure that amount of RAM required to uncompress an extent is
 * reasonable, so we limit the total size in ram of a compressed extent to
 * 128k.  This is a crucial number because it also controls how easily we can
 * spread reads across cpus for decompression.
 *
 * We also want to make sure the amount of IO required to do a random read is
 * reasonably small, so we limit the size of a compressed extent to 128k.
 */

/* Maximum length of compressed data stored on disk */
#define BTRFS_MAX_COMPRESSED		(SZ_128K)
25 26
static_assert((BTRFS_MAX_COMPRESSED % PAGE_SIZE) == 0);

27 28 29
/* Maximum size of data before compression */
#define BTRFS_MAX_UNCOMPRESSED		(SZ_128K)

30 31
#define	BTRFS_ZLIB_DEFAULT_LEVEL		3

32
struct compressed_bio {
33 34
	/* Number of sectors with unfinished IO (unsubmitted or unfinished) */
	refcount_t pending_sectors;
35

36 37 38
	/* Number of compressed pages in the array */
	unsigned int nr_pages;

39 40 41 42 43 44 45 46 47
	/* the pages with the compressed data on them */
	struct page **compressed_pages;

	/* inode that owns this data */
	struct inode *inode;

	/* starting offset in the inode for our pages */
	u64 start;

48 49
	/* Number of bytes in the inode we're working on */
	unsigned int len;
50

51 52
	/* Number of bytes on disk */
	unsigned int compressed_len;
53

54 55
	/* The compression algorithm for this bio */
	u8 compress_type;
56

57 58 59
	/* Whether this is a write for writeback. */
	bool writeback;

60
	/* IO errors */
61
	blk_status_t status;
62 63 64 65 66 67 68 69 70
	int mirror_num;

	/* for reads, this is the bio we are copying the data into */
	struct bio *orig_bio;

	/*
	 * the start of a variable length array of checksums only
	 * used by reads
	 */
71
	u8 sums[];
72 73
};

74 75 76 77 78 79 80 81 82 83
static inline unsigned int btrfs_compress_type(unsigned int type_level)
{
	return (type_level & 0xF);
}

static inline unsigned int btrfs_compress_level(unsigned int type_level)
{
	return ((type_level & 0xF0) >> 4);
}

84
void __init btrfs_init_compress(void);
85
void __cold btrfs_exit_compress(void);
86

87
int btrfs_compress_pages(unsigned int type_level, struct address_space *mapping,
88
			 u64 start, struct page **pages,
89 90
			 unsigned long *out_pages,
			 unsigned long *total_in,
91
			 unsigned long *total_out);
92 93
int btrfs_decompress(int type, unsigned char *data_in, struct page *dest_page,
		     unsigned long start_byte, size_t srclen, size_t destlen);
94 95
int btrfs_decompress_buf2page(const char *buf, u32 buf_len,
			      struct compressed_bio *cb, u32 decompressed);
96

97
blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
98 99
				  unsigned int len, u64 disk_start,
				  unsigned int compressed_len,
C
Chris Mason 已提交
100
				  struct page **compressed_pages,
101
				  unsigned int nr_pages,
102
				  unsigned int write_flags,
103 104
				  struct cgroup_subsys_state *blkcg_css,
				  bool writeback);
105 106
void btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
				  int mirror_num, unsigned long bio_flags);
107

108
unsigned int btrfs_compress_str2level(unsigned int type, const char *str);
109

110 111 112 113
enum btrfs_compression_type {
	BTRFS_COMPRESS_NONE  = 0,
	BTRFS_COMPRESS_ZLIB  = 1,
	BTRFS_COMPRESS_LZO   = 2,
N
Nick Terrell 已提交
114
	BTRFS_COMPRESS_ZSTD  = 3,
115
	BTRFS_NR_COMPRESS_TYPES = 4,
116 117
};

118 119 120 121 122 123 124 125 126 127 128
struct workspace_manager {
	struct list_head idle_ws;
	spinlock_t ws_lock;
	/* Number of free workspaces */
	int free_ws;
	/* Total number of allocated workspaces */
	atomic_t total_ws;
	/* Waiters for a free workspace */
	wait_queue_head_t ws_wait;
};

129
struct list_head *btrfs_get_workspace(int type, unsigned int level);
130
void btrfs_put_workspace(int type, struct list_head *ws);
131

132
struct btrfs_compress_op {
133
	struct workspace_manager *workspace_manager;
134 135 136
	/* Maximum level supported by the compression algorithm */
	unsigned int max_level;
	unsigned int default_level;
137 138
};

139
/* The heuristic workspaces are managed via the 0th workspace manager */
140
#define BTRFS_NR_WORKSPACE_MANAGERS	BTRFS_NR_COMPRESS_TYPES
141 142

extern const struct btrfs_compress_op btrfs_heuristic_compress;
143 144
extern const struct btrfs_compress_op btrfs_zlib_compress;
extern const struct btrfs_compress_op btrfs_lzo_compress;
N
Nick Terrell 已提交
145
extern const struct btrfs_compress_op btrfs_zstd_compress;
146

147
const char* btrfs_compress_type2str(enum btrfs_compression_type type);
148
bool btrfs_compress_is_valid_type(const char *str, size_t len);
149

150 151
int btrfs_compress_heuristic(struct inode *inode, u64 start, u64 end);

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
int zlib_compress_pages(struct list_head *ws, struct address_space *mapping,
		u64 start, struct page **pages, unsigned long *out_pages,
		unsigned long *total_in, unsigned long *total_out);
int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb);
int zlib_decompress(struct list_head *ws, unsigned char *data_in,
		struct page *dest_page, unsigned long start_byte, size_t srclen,
		size_t destlen);
struct list_head *zlib_alloc_workspace(unsigned int level);
void zlib_free_workspace(struct list_head *ws);
struct list_head *zlib_get_workspace(unsigned int level);

int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
		u64 start, struct page **pages, unsigned long *out_pages,
		unsigned long *total_in, unsigned long *total_out);
int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb);
int lzo_decompress(struct list_head *ws, unsigned char *data_in,
		struct page *dest_page, unsigned long start_byte, size_t srclen,
		size_t destlen);
struct list_head *lzo_alloc_workspace(unsigned int level);
void lzo_free_workspace(struct list_head *ws);

int zstd_compress_pages(struct list_head *ws, struct address_space *mapping,
		u64 start, struct page **pages, unsigned long *out_pages,
		unsigned long *total_in, unsigned long *total_out);
int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb);
int zstd_decompress(struct list_head *ws, unsigned char *data_in,
		struct page *dest_page, unsigned long start_byte, size_t srclen,
		size_t destlen);
void zstd_init_workspace_manager(void);
void zstd_cleanup_workspace_manager(void);
struct list_head *zstd_alloc_workspace(unsigned int level);
void zstd_free_workspace(struct list_head *ws);
struct list_head *zstd_get_workspace(unsigned int level);
void zstd_put_workspace(struct list_head *ws);

C
Chris Mason 已提交
187
#endif