| .. | .. | 
|---|
| 8 | 8 |  | 
|---|
| 9 | 9 | #include <linux/sizes.h> | 
|---|
| 10 | 10 |  | 
|---|
|  | 11 | +struct btrfs_inode; | 
|---|
|  | 12 | + | 
|---|
| 11 | 13 | /* | 
|---|
| 12 | 14 | * We want to make sure that amount of RAM required to uncompress an extent is | 
|---|
| 13 | 15 | * reasonable, so we limit the total size in ram of a compressed extent to | 
|---|
| .. | .. | 
|---|
| 61 | 63 | * the start of a variable length array of checksums only | 
|---|
| 62 | 64 | * used by reads | 
|---|
| 63 | 65 | */ | 
|---|
| 64 |  | -	u32 sums; | 
|---|
|  | 66 | +	u8 sums[]; | 
|---|
| 65 | 67 | }; | 
|---|
|  | 68 | + | 
|---|
|  | 69 | +static inline unsigned int btrfs_compress_type(unsigned int type_level) | 
|---|
|  | 70 | +{ | 
|---|
|  | 71 | +	return (type_level & 0xF); | 
|---|
|  | 72 | +} | 
|---|
|  | 73 | + | 
|---|
|  | 74 | +static inline unsigned int btrfs_compress_level(unsigned int type_level) | 
|---|
|  | 75 | +{ | 
|---|
|  | 76 | +	return ((type_level & 0xF0) >> 4); | 
|---|
|  | 77 | +} | 
|---|
| 66 | 78 |  | 
|---|
| 67 | 79 | void __init btrfs_init_compress(void); | 
|---|
| 68 | 80 | void __cold btrfs_exit_compress(void); | 
|---|
| .. | .. | 
|---|
| 78 | 90 | unsigned long total_out, u64 disk_start, | 
|---|
| 79 | 91 | struct bio *bio); | 
|---|
| 80 | 92 |  | 
|---|
| 81 |  | -blk_status_t btrfs_submit_compressed_write(struct inode *inode, u64 start, | 
|---|
|  | 93 | +blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start, | 
|---|
| 82 | 94 | unsigned long len, u64 disk_start, | 
|---|
| 83 | 95 | unsigned long compressed_len, | 
|---|
| 84 | 96 | struct page **compressed_pages, | 
|---|
| 85 | 97 | unsigned long nr_pages, | 
|---|
| 86 |  | -				  unsigned int write_flags); | 
|---|
|  | 98 | +				  unsigned int write_flags, | 
|---|
|  | 99 | +				  struct cgroup_subsys_state *blkcg_css); | 
|---|
| 87 | 100 | blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | 
|---|
| 88 | 101 | int mirror_num, unsigned long bio_flags); | 
|---|
| 89 | 102 |  | 
|---|
| 90 |  | -unsigned btrfs_compress_str2level(const char *str); | 
|---|
|  | 103 | +unsigned int btrfs_compress_str2level(unsigned int type, const char *str); | 
|---|
| 91 | 104 |  | 
|---|
| 92 | 105 | enum btrfs_compression_type { | 
|---|
| 93 | 106 | BTRFS_COMPRESS_NONE  = 0, | 
|---|
| 94 | 107 | BTRFS_COMPRESS_ZLIB  = 1, | 
|---|
| 95 | 108 | BTRFS_COMPRESS_LZO   = 2, | 
|---|
| 96 | 109 | BTRFS_COMPRESS_ZSTD  = 3, | 
|---|
| 97 |  | -	BTRFS_COMPRESS_TYPES = 3, | 
|---|
|  | 110 | +	BTRFS_NR_COMPRESS_TYPES = 4, | 
|---|
| 98 | 111 | }; | 
|---|
|  | 112 | + | 
|---|
|  | 113 | +struct workspace_manager { | 
|---|
|  | 114 | +	struct list_head idle_ws; | 
|---|
|  | 115 | +	spinlock_t ws_lock; | 
|---|
|  | 116 | +	/* Number of free workspaces */ | 
|---|
|  | 117 | +	int free_ws; | 
|---|
|  | 118 | +	/* Total number of allocated workspaces */ | 
|---|
|  | 119 | +	atomic_t total_ws; | 
|---|
|  | 120 | +	/* Waiters for a free workspace */ | 
|---|
|  | 121 | +	wait_queue_head_t ws_wait; | 
|---|
|  | 122 | +}; | 
|---|
|  | 123 | + | 
|---|
|  | 124 | +struct list_head *btrfs_get_workspace(int type, unsigned int level); | 
|---|
|  | 125 | +void btrfs_put_workspace(int type, struct list_head *ws); | 
|---|
| 99 | 126 |  | 
|---|
| 100 | 127 | struct btrfs_compress_op { | 
|---|
| 101 |  | -	struct list_head *(*alloc_workspace)(void); | 
|---|
| 102 |  | - | 
|---|
| 103 |  | -	void (*free_workspace)(struct list_head *workspace); | 
|---|
| 104 |  | - | 
|---|
| 105 |  | -	int (*compress_pages)(struct list_head *workspace, | 
|---|
| 106 |  | -			      struct address_space *mapping, | 
|---|
| 107 |  | -			      u64 start, | 
|---|
| 108 |  | -			      struct page **pages, | 
|---|
| 109 |  | -			      unsigned long *out_pages, | 
|---|
| 110 |  | -			      unsigned long *total_in, | 
|---|
| 111 |  | -			      unsigned long *total_out); | 
|---|
| 112 |  | - | 
|---|
| 113 |  | -	int (*decompress_bio)(struct list_head *workspace, | 
|---|
| 114 |  | -				struct compressed_bio *cb); | 
|---|
| 115 |  | - | 
|---|
| 116 |  | -	int (*decompress)(struct list_head *workspace, | 
|---|
| 117 |  | -			  unsigned char *data_in, | 
|---|
| 118 |  | -			  struct page *dest_page, | 
|---|
| 119 |  | -			  unsigned long start_byte, | 
|---|
| 120 |  | -			  size_t srclen, size_t destlen); | 
|---|
| 121 |  | - | 
|---|
| 122 |  | -	void (*set_level)(struct list_head *ws, unsigned int type); | 
|---|
|  | 128 | +	struct workspace_manager *workspace_manager; | 
|---|
|  | 129 | +	/* Maximum level supported by the compression algorithm */ | 
|---|
|  | 130 | +	unsigned int max_level; | 
|---|
|  | 131 | +	unsigned int default_level; | 
|---|
| 123 | 132 | }; | 
|---|
| 124 | 133 |  | 
|---|
|  | 134 | +/* The heuristic workspaces are managed via the 0th workspace manager */ | 
|---|
|  | 135 | +#define BTRFS_NR_WORKSPACE_MANAGERS	BTRFS_NR_COMPRESS_TYPES | 
|---|
|  | 136 | + | 
|---|
|  | 137 | +extern const struct btrfs_compress_op btrfs_heuristic_compress; | 
|---|
| 125 | 138 | extern const struct btrfs_compress_op btrfs_zlib_compress; | 
|---|
| 126 | 139 | extern const struct btrfs_compress_op btrfs_lzo_compress; | 
|---|
| 127 | 140 | extern const struct btrfs_compress_op btrfs_zstd_compress; | 
|---|
| .. | .. | 
|---|
| 131 | 144 |  | 
|---|
| 132 | 145 | int btrfs_compress_heuristic(struct inode *inode, u64 start, u64 end); | 
|---|
| 133 | 146 |  | 
|---|
|  | 147 | +int zlib_compress_pages(struct list_head *ws, struct address_space *mapping, | 
|---|
|  | 148 | +		u64 start, struct page **pages, unsigned long *out_pages, | 
|---|
|  | 149 | +		unsigned long *total_in, unsigned long *total_out); | 
|---|
|  | 150 | +int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb); | 
|---|
|  | 151 | +int zlib_decompress(struct list_head *ws, unsigned char *data_in, | 
|---|
|  | 152 | +		struct page *dest_page, unsigned long start_byte, size_t srclen, | 
|---|
|  | 153 | +		size_t destlen); | 
|---|
|  | 154 | +struct list_head *zlib_alloc_workspace(unsigned int level); | 
|---|
|  | 155 | +void zlib_free_workspace(struct list_head *ws); | 
|---|
|  | 156 | +struct list_head *zlib_get_workspace(unsigned int level); | 
|---|
|  | 157 | + | 
|---|
|  | 158 | +int lzo_compress_pages(struct list_head *ws, struct address_space *mapping, | 
|---|
|  | 159 | +		u64 start, struct page **pages, unsigned long *out_pages, | 
|---|
|  | 160 | +		unsigned long *total_in, unsigned long *total_out); | 
|---|
|  | 161 | +int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb); | 
|---|
|  | 162 | +int lzo_decompress(struct list_head *ws, unsigned char *data_in, | 
|---|
|  | 163 | +		struct page *dest_page, unsigned long start_byte, size_t srclen, | 
|---|
|  | 164 | +		size_t destlen); | 
|---|
|  | 165 | +struct list_head *lzo_alloc_workspace(unsigned int level); | 
|---|
|  | 166 | +void lzo_free_workspace(struct list_head *ws); | 
|---|
|  | 167 | + | 
|---|
|  | 168 | +int zstd_compress_pages(struct list_head *ws, struct address_space *mapping, | 
|---|
|  | 169 | +		u64 start, struct page **pages, unsigned long *out_pages, | 
|---|
|  | 170 | +		unsigned long *total_in, unsigned long *total_out); | 
|---|
|  | 171 | +int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb); | 
|---|
|  | 172 | +int zstd_decompress(struct list_head *ws, unsigned char *data_in, | 
|---|
|  | 173 | +		struct page *dest_page, unsigned long start_byte, size_t srclen, | 
|---|
|  | 174 | +		size_t destlen); | 
|---|
|  | 175 | +void zstd_init_workspace_manager(void); | 
|---|
|  | 176 | +void zstd_cleanup_workspace_manager(void); | 
|---|
|  | 177 | +struct list_head *zstd_alloc_workspace(unsigned int level); | 
|---|
|  | 178 | +void zstd_free_workspace(struct list_head *ws); | 
|---|
|  | 179 | +struct list_head *zstd_get_workspace(unsigned int level); | 
|---|
|  | 180 | +void zstd_put_workspace(struct list_head *ws); | 
|---|
|  | 181 | + | 
|---|
| 134 | 182 | #endif | 
|---|