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#include <linux/kernel.h> 78c2ecf20Sopenharmony_ci#include <linux/bio.h> 88c2ecf20Sopenharmony_ci#include <linux/file.h> 98c2ecf20Sopenharmony_ci#include <linux/fs.h> 108c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 118c2ecf20Sopenharmony_ci#include <linux/highmem.h> 128c2ecf20Sopenharmony_ci#include <linux/time.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/string.h> 158c2ecf20Sopenharmony_ci#include <linux/backing-dev.h> 168c2ecf20Sopenharmony_ci#include <linux/writeback.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/sched/mm.h> 198c2ecf20Sopenharmony_ci#include <linux/log2.h> 208c2ecf20Sopenharmony_ci#include <crypto/hash.h> 218c2ecf20Sopenharmony_ci#include "misc.h" 228c2ecf20Sopenharmony_ci#include "ctree.h" 238c2ecf20Sopenharmony_ci#include "disk-io.h" 248c2ecf20Sopenharmony_ci#include "transaction.h" 258c2ecf20Sopenharmony_ci#include "btrfs_inode.h" 268c2ecf20Sopenharmony_ci#include "volumes.h" 278c2ecf20Sopenharmony_ci#include "ordered-data.h" 288c2ecf20Sopenharmony_ci#include "compression.h" 298c2ecf20Sopenharmony_ci#include "extent_io.h" 308c2ecf20Sopenharmony_ci#include "extent_map.h" 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic const char* const btrfs_compress_types[] = { "", "zlib", "lzo", "zstd" }; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ciconst char* btrfs_compress_type2str(enum btrfs_compression_type type) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci switch (type) { 378c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZLIB: 388c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_LZO: 398c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZSTD: 408c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_NONE: 418c2ecf20Sopenharmony_ci return btrfs_compress_types[type]; 428c2ecf20Sopenharmony_ci default: 438c2ecf20Sopenharmony_ci break; 448c2ecf20Sopenharmony_ci } 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci return NULL; 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cibool btrfs_compress_is_valid_type(const char *str, size_t len) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci int i; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci for (i = 1; i < ARRAY_SIZE(btrfs_compress_types); i++) { 548c2ecf20Sopenharmony_ci size_t comp_len = strlen(btrfs_compress_types[i]); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci if (len < comp_len) 578c2ecf20Sopenharmony_ci continue; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci if (!strncmp(btrfs_compress_types[i], str, comp_len)) 608c2ecf20Sopenharmony_ci return true; 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci return false; 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic int compression_compress_pages(int type, struct list_head *ws, 668c2ecf20Sopenharmony_ci struct address_space *mapping, u64 start, struct page **pages, 678c2ecf20Sopenharmony_ci unsigned long *out_pages, unsigned long *total_in, 688c2ecf20Sopenharmony_ci unsigned long *total_out) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci switch (type) { 718c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZLIB: 728c2ecf20Sopenharmony_ci return zlib_compress_pages(ws, mapping, start, pages, 738c2ecf20Sopenharmony_ci out_pages, total_in, total_out); 748c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_LZO: 758c2ecf20Sopenharmony_ci return lzo_compress_pages(ws, mapping, start, pages, 768c2ecf20Sopenharmony_ci out_pages, total_in, total_out); 778c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZSTD: 788c2ecf20Sopenharmony_ci return zstd_compress_pages(ws, mapping, start, pages, 798c2ecf20Sopenharmony_ci out_pages, total_in, total_out); 808c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_NONE: 818c2ecf20Sopenharmony_ci default: 828c2ecf20Sopenharmony_ci /* 838c2ecf20Sopenharmony_ci * This can happen when compression races with remount setting 848c2ecf20Sopenharmony_ci * it to 'no compress', while caller doesn't call 858c2ecf20Sopenharmony_ci * inode_need_compress() to check if we really need to 868c2ecf20Sopenharmony_ci * compress. 878c2ecf20Sopenharmony_ci * 888c2ecf20Sopenharmony_ci * Not a big deal, just need to inform caller that we 898c2ecf20Sopenharmony_ci * haven't allocated any pages yet. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_ci *out_pages = 0; 928c2ecf20Sopenharmony_ci return -E2BIG; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic int compression_decompress_bio(int type, struct list_head *ws, 978c2ecf20Sopenharmony_ci struct compressed_bio *cb) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci switch (type) { 1008c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZLIB: return zlib_decompress_bio(ws, cb); 1018c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_LZO: return lzo_decompress_bio(ws, cb); 1028c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZSTD: return zstd_decompress_bio(ws, cb); 1038c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_NONE: 1048c2ecf20Sopenharmony_ci default: 1058c2ecf20Sopenharmony_ci /* 1068c2ecf20Sopenharmony_ci * This can't happen, the type is validated several times 1078c2ecf20Sopenharmony_ci * before we get here. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ci BUG(); 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic int compression_decompress(int type, struct list_head *ws, 1148c2ecf20Sopenharmony_ci unsigned char *data_in, struct page *dest_page, 1158c2ecf20Sopenharmony_ci unsigned long start_byte, size_t srclen, size_t destlen) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci switch (type) { 1188c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZLIB: return zlib_decompress(ws, data_in, dest_page, 1198c2ecf20Sopenharmony_ci start_byte, srclen, destlen); 1208c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_LZO: return lzo_decompress(ws, data_in, dest_page, 1218c2ecf20Sopenharmony_ci start_byte, srclen, destlen); 1228c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZSTD: return zstd_decompress(ws, data_in, dest_page, 1238c2ecf20Sopenharmony_ci start_byte, srclen, destlen); 1248c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_NONE: 1258c2ecf20Sopenharmony_ci default: 1268c2ecf20Sopenharmony_ci /* 1278c2ecf20Sopenharmony_ci * This can't happen, the type is validated several times 1288c2ecf20Sopenharmony_ci * before we get here. 1298c2ecf20Sopenharmony_ci */ 1308c2ecf20Sopenharmony_ci BUG(); 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic int btrfs_decompress_bio(struct compressed_bio *cb); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic inline int compressed_bio_size(struct btrfs_fs_info *fs_info, 1378c2ecf20Sopenharmony_ci unsigned long disk_size) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci return sizeof(struct compressed_bio) + 1428c2ecf20Sopenharmony_ci (DIV_ROUND_UP(disk_size, fs_info->sectorsize)) * csum_size; 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic int check_compressed_csum(struct btrfs_inode *inode, struct bio *bio, 1468c2ecf20Sopenharmony_ci u64 disk_start) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = inode->root->fs_info; 1498c2ecf20Sopenharmony_ci SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); 1508c2ecf20Sopenharmony_ci const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); 1518c2ecf20Sopenharmony_ci struct page *page; 1528c2ecf20Sopenharmony_ci unsigned long i; 1538c2ecf20Sopenharmony_ci char *kaddr; 1548c2ecf20Sopenharmony_ci u8 csum[BTRFS_CSUM_SIZE]; 1558c2ecf20Sopenharmony_ci struct compressed_bio *cb = bio->bi_private; 1568c2ecf20Sopenharmony_ci u8 *cb_sum = cb->sums; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci if (inode->flags & BTRFS_INODE_NODATASUM) 1598c2ecf20Sopenharmony_ci return 0; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci shash->tfm = fs_info->csum_shash; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci for (i = 0; i < cb->nr_pages; i++) { 1648c2ecf20Sopenharmony_ci page = cb->compressed_pages[i]; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci kaddr = kmap_atomic(page); 1678c2ecf20Sopenharmony_ci crypto_shash_digest(shash, kaddr, PAGE_SIZE, csum); 1688c2ecf20Sopenharmony_ci kunmap_atomic(kaddr); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci if (memcmp(&csum, cb_sum, csum_size)) { 1718c2ecf20Sopenharmony_ci btrfs_print_data_csum_error(inode, disk_start, 1728c2ecf20Sopenharmony_ci csum, cb_sum, cb->mirror_num); 1738c2ecf20Sopenharmony_ci if (btrfs_io_bio(bio)->device) 1748c2ecf20Sopenharmony_ci btrfs_dev_stat_inc_and_print( 1758c2ecf20Sopenharmony_ci btrfs_io_bio(bio)->device, 1768c2ecf20Sopenharmony_ci BTRFS_DEV_STAT_CORRUPTION_ERRS); 1778c2ecf20Sopenharmony_ci return -EIO; 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci cb_sum += csum_size; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci return 0; 1828c2ecf20Sopenharmony_ci} 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci/* when we finish reading compressed pages from the disk, we 1858c2ecf20Sopenharmony_ci * decompress them and then run the bio end_io routines on the 1868c2ecf20Sopenharmony_ci * decompressed pages (in the inode address space). 1878c2ecf20Sopenharmony_ci * 1888c2ecf20Sopenharmony_ci * This allows the checksumming and other IO error handling routines 1898c2ecf20Sopenharmony_ci * to work normally 1908c2ecf20Sopenharmony_ci * 1918c2ecf20Sopenharmony_ci * The compressed pages are freed here, and it must be run 1928c2ecf20Sopenharmony_ci * in process context 1938c2ecf20Sopenharmony_ci */ 1948c2ecf20Sopenharmony_cistatic void end_compressed_bio_read(struct bio *bio) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci struct compressed_bio *cb = bio->bi_private; 1978c2ecf20Sopenharmony_ci struct inode *inode; 1988c2ecf20Sopenharmony_ci struct page *page; 1998c2ecf20Sopenharmony_ci unsigned long index; 2008c2ecf20Sopenharmony_ci unsigned int mirror = btrfs_io_bio(bio)->mirror_num; 2018c2ecf20Sopenharmony_ci int ret = 0; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci if (bio->bi_status) 2048c2ecf20Sopenharmony_ci cb->errors = 1; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci /* if there are more bios still pending for this compressed 2078c2ecf20Sopenharmony_ci * extent, just exit 2088c2ecf20Sopenharmony_ci */ 2098c2ecf20Sopenharmony_ci if (!refcount_dec_and_test(&cb->pending_bios)) 2108c2ecf20Sopenharmony_ci goto out; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci /* 2138c2ecf20Sopenharmony_ci * Record the correct mirror_num in cb->orig_bio so that 2148c2ecf20Sopenharmony_ci * read-repair can work properly. 2158c2ecf20Sopenharmony_ci */ 2168c2ecf20Sopenharmony_ci btrfs_io_bio(cb->orig_bio)->mirror_num = mirror; 2178c2ecf20Sopenharmony_ci cb->mirror_num = mirror; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci /* 2208c2ecf20Sopenharmony_ci * Some IO in this cb have failed, just skip checksum as there 2218c2ecf20Sopenharmony_ci * is no way it could be correct. 2228c2ecf20Sopenharmony_ci */ 2238c2ecf20Sopenharmony_ci if (cb->errors == 1) 2248c2ecf20Sopenharmony_ci goto csum_failed; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci inode = cb->inode; 2278c2ecf20Sopenharmony_ci ret = check_compressed_csum(BTRFS_I(inode), bio, 2288c2ecf20Sopenharmony_ci (u64)bio->bi_iter.bi_sector << 9); 2298c2ecf20Sopenharmony_ci if (ret) 2308c2ecf20Sopenharmony_ci goto csum_failed; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* ok, we're the last bio for this extent, lets start 2338c2ecf20Sopenharmony_ci * the decompression. 2348c2ecf20Sopenharmony_ci */ 2358c2ecf20Sopenharmony_ci ret = btrfs_decompress_bio(cb); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cicsum_failed: 2388c2ecf20Sopenharmony_ci if (ret) 2398c2ecf20Sopenharmony_ci cb->errors = 1; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci /* release the compressed pages */ 2428c2ecf20Sopenharmony_ci index = 0; 2438c2ecf20Sopenharmony_ci for (index = 0; index < cb->nr_pages; index++) { 2448c2ecf20Sopenharmony_ci page = cb->compressed_pages[index]; 2458c2ecf20Sopenharmony_ci page->mapping = NULL; 2468c2ecf20Sopenharmony_ci put_page(page); 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* do io completion on the original bio */ 2508c2ecf20Sopenharmony_ci if (cb->errors) { 2518c2ecf20Sopenharmony_ci bio_io_error(cb->orig_bio); 2528c2ecf20Sopenharmony_ci } else { 2538c2ecf20Sopenharmony_ci struct bio_vec *bvec; 2548c2ecf20Sopenharmony_ci struct bvec_iter_all iter_all; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci /* 2578c2ecf20Sopenharmony_ci * we have verified the checksum already, set page 2588c2ecf20Sopenharmony_ci * checked so the end_io handlers know about it 2598c2ecf20Sopenharmony_ci */ 2608c2ecf20Sopenharmony_ci ASSERT(!bio_flagged(bio, BIO_CLONED)); 2618c2ecf20Sopenharmony_ci bio_for_each_segment_all(bvec, cb->orig_bio, iter_all) 2628c2ecf20Sopenharmony_ci SetPageChecked(bvec->bv_page); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci bio_endio(cb->orig_bio); 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* finally free the cb struct */ 2688c2ecf20Sopenharmony_ci kfree(cb->compressed_pages); 2698c2ecf20Sopenharmony_ci kfree(cb); 2708c2ecf20Sopenharmony_ciout: 2718c2ecf20Sopenharmony_ci bio_put(bio); 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci/* 2758c2ecf20Sopenharmony_ci * Clear the writeback bits on all of the file 2768c2ecf20Sopenharmony_ci * pages for a compressed write 2778c2ecf20Sopenharmony_ci */ 2788c2ecf20Sopenharmony_cistatic noinline void end_compressed_writeback(struct inode *inode, 2798c2ecf20Sopenharmony_ci const struct compressed_bio *cb) 2808c2ecf20Sopenharmony_ci{ 2818c2ecf20Sopenharmony_ci unsigned long index = cb->start >> PAGE_SHIFT; 2828c2ecf20Sopenharmony_ci unsigned long end_index = (cb->start + cb->len - 1) >> PAGE_SHIFT; 2838c2ecf20Sopenharmony_ci struct page *pages[16]; 2848c2ecf20Sopenharmony_ci unsigned long nr_pages = end_index - index + 1; 2858c2ecf20Sopenharmony_ci int i; 2868c2ecf20Sopenharmony_ci int ret; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci if (cb->errors) 2898c2ecf20Sopenharmony_ci mapping_set_error(inode->i_mapping, -EIO); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci while (nr_pages > 0) { 2928c2ecf20Sopenharmony_ci ret = find_get_pages_contig(inode->i_mapping, index, 2938c2ecf20Sopenharmony_ci min_t(unsigned long, 2948c2ecf20Sopenharmony_ci nr_pages, ARRAY_SIZE(pages)), pages); 2958c2ecf20Sopenharmony_ci if (ret == 0) { 2968c2ecf20Sopenharmony_ci nr_pages -= 1; 2978c2ecf20Sopenharmony_ci index += 1; 2988c2ecf20Sopenharmony_ci continue; 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci for (i = 0; i < ret; i++) { 3018c2ecf20Sopenharmony_ci if (cb->errors) 3028c2ecf20Sopenharmony_ci SetPageError(pages[i]); 3038c2ecf20Sopenharmony_ci end_page_writeback(pages[i]); 3048c2ecf20Sopenharmony_ci put_page(pages[i]); 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci nr_pages -= ret; 3078c2ecf20Sopenharmony_ci index += ret; 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci /* the inode may be gone now */ 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci/* 3138c2ecf20Sopenharmony_ci * do the cleanup once all the compressed pages hit the disk. 3148c2ecf20Sopenharmony_ci * This will clear writeback on the file pages and free the compressed 3158c2ecf20Sopenharmony_ci * pages. 3168c2ecf20Sopenharmony_ci * 3178c2ecf20Sopenharmony_ci * This also calls the writeback end hooks for the file pages so that 3188c2ecf20Sopenharmony_ci * metadata and checksums can be updated in the file. 3198c2ecf20Sopenharmony_ci */ 3208c2ecf20Sopenharmony_cistatic void end_compressed_bio_write(struct bio *bio) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci struct compressed_bio *cb = bio->bi_private; 3238c2ecf20Sopenharmony_ci struct inode *inode; 3248c2ecf20Sopenharmony_ci struct page *page; 3258c2ecf20Sopenharmony_ci unsigned long index; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (bio->bi_status) 3288c2ecf20Sopenharmony_ci cb->errors = 1; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* if there are more bios still pending for this compressed 3318c2ecf20Sopenharmony_ci * extent, just exit 3328c2ecf20Sopenharmony_ci */ 3338c2ecf20Sopenharmony_ci if (!refcount_dec_and_test(&cb->pending_bios)) 3348c2ecf20Sopenharmony_ci goto out; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci /* ok, we're the last bio for this extent, step one is to 3378c2ecf20Sopenharmony_ci * call back into the FS and do all the end_io operations 3388c2ecf20Sopenharmony_ci */ 3398c2ecf20Sopenharmony_ci inode = cb->inode; 3408c2ecf20Sopenharmony_ci cb->compressed_pages[0]->mapping = cb->inode->i_mapping; 3418c2ecf20Sopenharmony_ci btrfs_writepage_endio_finish_ordered(cb->compressed_pages[0], 3428c2ecf20Sopenharmony_ci cb->start, cb->start + cb->len - 1, 3438c2ecf20Sopenharmony_ci !cb->errors); 3448c2ecf20Sopenharmony_ci cb->compressed_pages[0]->mapping = NULL; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci end_compressed_writeback(inode, cb); 3478c2ecf20Sopenharmony_ci /* note, our inode could be gone now */ 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci /* 3508c2ecf20Sopenharmony_ci * release the compressed pages, these came from alloc_page and 3518c2ecf20Sopenharmony_ci * are not attached to the inode at all 3528c2ecf20Sopenharmony_ci */ 3538c2ecf20Sopenharmony_ci index = 0; 3548c2ecf20Sopenharmony_ci for (index = 0; index < cb->nr_pages; index++) { 3558c2ecf20Sopenharmony_ci page = cb->compressed_pages[index]; 3568c2ecf20Sopenharmony_ci page->mapping = NULL; 3578c2ecf20Sopenharmony_ci put_page(page); 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci /* finally free the cb struct */ 3618c2ecf20Sopenharmony_ci kfree(cb->compressed_pages); 3628c2ecf20Sopenharmony_ci kfree(cb); 3638c2ecf20Sopenharmony_ciout: 3648c2ecf20Sopenharmony_ci bio_put(bio); 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci/* 3688c2ecf20Sopenharmony_ci * worker function to build and submit bios for previously compressed pages. 3698c2ecf20Sopenharmony_ci * The corresponding pages in the inode should be marked for writeback 3708c2ecf20Sopenharmony_ci * and the compressed pages should have a reference on them for dropping 3718c2ecf20Sopenharmony_ci * when the IO is complete. 3728c2ecf20Sopenharmony_ci * 3738c2ecf20Sopenharmony_ci * This also checksums the file bytes and gets things ready for 3748c2ecf20Sopenharmony_ci * the end io hooks. 3758c2ecf20Sopenharmony_ci */ 3768c2ecf20Sopenharmony_ciblk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start, 3778c2ecf20Sopenharmony_ci unsigned long len, u64 disk_start, 3788c2ecf20Sopenharmony_ci unsigned long compressed_len, 3798c2ecf20Sopenharmony_ci struct page **compressed_pages, 3808c2ecf20Sopenharmony_ci unsigned long nr_pages, 3818c2ecf20Sopenharmony_ci unsigned int write_flags, 3828c2ecf20Sopenharmony_ci struct cgroup_subsys_state *blkcg_css) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = inode->root->fs_info; 3858c2ecf20Sopenharmony_ci struct bio *bio = NULL; 3868c2ecf20Sopenharmony_ci struct compressed_bio *cb; 3878c2ecf20Sopenharmony_ci unsigned long bytes_left; 3888c2ecf20Sopenharmony_ci int pg_index = 0; 3898c2ecf20Sopenharmony_ci struct page *page; 3908c2ecf20Sopenharmony_ci u64 first_byte = disk_start; 3918c2ecf20Sopenharmony_ci blk_status_t ret; 3928c2ecf20Sopenharmony_ci int skip_sum = inode->flags & BTRFS_INODE_NODATASUM; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci WARN_ON(!PAGE_ALIGNED(start)); 3958c2ecf20Sopenharmony_ci cb = kmalloc(compressed_bio_size(fs_info, compressed_len), GFP_NOFS); 3968c2ecf20Sopenharmony_ci if (!cb) 3978c2ecf20Sopenharmony_ci return BLK_STS_RESOURCE; 3988c2ecf20Sopenharmony_ci refcount_set(&cb->pending_bios, 0); 3998c2ecf20Sopenharmony_ci cb->errors = 0; 4008c2ecf20Sopenharmony_ci cb->inode = &inode->vfs_inode; 4018c2ecf20Sopenharmony_ci cb->start = start; 4028c2ecf20Sopenharmony_ci cb->len = len; 4038c2ecf20Sopenharmony_ci cb->mirror_num = 0; 4048c2ecf20Sopenharmony_ci cb->compressed_pages = compressed_pages; 4058c2ecf20Sopenharmony_ci cb->compressed_len = compressed_len; 4068c2ecf20Sopenharmony_ci cb->orig_bio = NULL; 4078c2ecf20Sopenharmony_ci cb->nr_pages = nr_pages; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci bio = btrfs_bio_alloc(first_byte); 4108c2ecf20Sopenharmony_ci bio->bi_opf = REQ_OP_WRITE | write_flags; 4118c2ecf20Sopenharmony_ci bio->bi_private = cb; 4128c2ecf20Sopenharmony_ci bio->bi_end_io = end_compressed_bio_write; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci if (blkcg_css) { 4158c2ecf20Sopenharmony_ci bio->bi_opf |= REQ_CGROUP_PUNT; 4168c2ecf20Sopenharmony_ci kthread_associate_blkcg(blkcg_css); 4178c2ecf20Sopenharmony_ci } 4188c2ecf20Sopenharmony_ci refcount_set(&cb->pending_bios, 1); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci /* create and submit bios for the compressed pages */ 4218c2ecf20Sopenharmony_ci bytes_left = compressed_len; 4228c2ecf20Sopenharmony_ci for (pg_index = 0; pg_index < cb->nr_pages; pg_index++) { 4238c2ecf20Sopenharmony_ci int submit = 0; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci page = compressed_pages[pg_index]; 4268c2ecf20Sopenharmony_ci page->mapping = inode->vfs_inode.i_mapping; 4278c2ecf20Sopenharmony_ci if (bio->bi_iter.bi_size) 4288c2ecf20Sopenharmony_ci submit = btrfs_bio_fits_in_stripe(page, PAGE_SIZE, bio, 4298c2ecf20Sopenharmony_ci 0); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci page->mapping = NULL; 4328c2ecf20Sopenharmony_ci if (submit || bio_add_page(bio, page, PAGE_SIZE, 0) < 4338c2ecf20Sopenharmony_ci PAGE_SIZE) { 4348c2ecf20Sopenharmony_ci /* 4358c2ecf20Sopenharmony_ci * inc the count before we submit the bio so 4368c2ecf20Sopenharmony_ci * we know the end IO handler won't happen before 4378c2ecf20Sopenharmony_ci * we inc the count. Otherwise, the cb might get 4388c2ecf20Sopenharmony_ci * freed before we're done setting it up 4398c2ecf20Sopenharmony_ci */ 4408c2ecf20Sopenharmony_ci refcount_inc(&cb->pending_bios); 4418c2ecf20Sopenharmony_ci ret = btrfs_bio_wq_end_io(fs_info, bio, 4428c2ecf20Sopenharmony_ci BTRFS_WQ_ENDIO_DATA); 4438c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci if (!skip_sum) { 4468c2ecf20Sopenharmony_ci ret = btrfs_csum_one_bio(inode, bio, start, 1); 4478c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 4488c2ecf20Sopenharmony_ci } 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci ret = btrfs_map_bio(fs_info, bio, 0); 4518c2ecf20Sopenharmony_ci if (ret) { 4528c2ecf20Sopenharmony_ci bio->bi_status = ret; 4538c2ecf20Sopenharmony_ci bio_endio(bio); 4548c2ecf20Sopenharmony_ci } 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci bio = btrfs_bio_alloc(first_byte); 4578c2ecf20Sopenharmony_ci bio->bi_opf = REQ_OP_WRITE | write_flags; 4588c2ecf20Sopenharmony_ci bio->bi_private = cb; 4598c2ecf20Sopenharmony_ci bio->bi_end_io = end_compressed_bio_write; 4608c2ecf20Sopenharmony_ci if (blkcg_css) 4618c2ecf20Sopenharmony_ci bio->bi_opf |= REQ_CGROUP_PUNT; 4628c2ecf20Sopenharmony_ci bio_add_page(bio, page, PAGE_SIZE, 0); 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci if (bytes_left < PAGE_SIZE) { 4658c2ecf20Sopenharmony_ci btrfs_info(fs_info, 4668c2ecf20Sopenharmony_ci "bytes left %lu compress len %lu nr %lu", 4678c2ecf20Sopenharmony_ci bytes_left, cb->compressed_len, cb->nr_pages); 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci bytes_left -= PAGE_SIZE; 4708c2ecf20Sopenharmony_ci first_byte += PAGE_SIZE; 4718c2ecf20Sopenharmony_ci cond_resched(); 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci ret = btrfs_bio_wq_end_io(fs_info, bio, BTRFS_WQ_ENDIO_DATA); 4758c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci if (!skip_sum) { 4788c2ecf20Sopenharmony_ci ret = btrfs_csum_one_bio(inode, bio, start, 1); 4798c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci ret = btrfs_map_bio(fs_info, bio, 0); 4838c2ecf20Sopenharmony_ci if (ret) { 4848c2ecf20Sopenharmony_ci bio->bi_status = ret; 4858c2ecf20Sopenharmony_ci bio_endio(bio); 4868c2ecf20Sopenharmony_ci } 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci if (blkcg_css) 4898c2ecf20Sopenharmony_ci kthread_associate_blkcg(NULL); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci return 0; 4928c2ecf20Sopenharmony_ci} 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_cistatic u64 bio_end_offset(struct bio *bio) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci struct bio_vec *last = bio_last_bvec_all(bio); 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci return page_offset(last->bv_page) + last->bv_len + last->bv_offset; 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_cistatic noinline int add_ra_bio_pages(struct inode *inode, 5028c2ecf20Sopenharmony_ci u64 compressed_end, 5038c2ecf20Sopenharmony_ci struct compressed_bio *cb) 5048c2ecf20Sopenharmony_ci{ 5058c2ecf20Sopenharmony_ci unsigned long end_index; 5068c2ecf20Sopenharmony_ci unsigned long pg_index; 5078c2ecf20Sopenharmony_ci u64 last_offset; 5088c2ecf20Sopenharmony_ci u64 isize = i_size_read(inode); 5098c2ecf20Sopenharmony_ci int ret; 5108c2ecf20Sopenharmony_ci struct page *page; 5118c2ecf20Sopenharmony_ci unsigned long nr_pages = 0; 5128c2ecf20Sopenharmony_ci struct extent_map *em; 5138c2ecf20Sopenharmony_ci struct address_space *mapping = inode->i_mapping; 5148c2ecf20Sopenharmony_ci struct extent_map_tree *em_tree; 5158c2ecf20Sopenharmony_ci struct extent_io_tree *tree; 5168c2ecf20Sopenharmony_ci u64 end; 5178c2ecf20Sopenharmony_ci int misses = 0; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci last_offset = bio_end_offset(cb->orig_bio); 5208c2ecf20Sopenharmony_ci em_tree = &BTRFS_I(inode)->extent_tree; 5218c2ecf20Sopenharmony_ci tree = &BTRFS_I(inode)->io_tree; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci if (isize == 0) 5248c2ecf20Sopenharmony_ci return 0; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci end_index = (i_size_read(inode) - 1) >> PAGE_SHIFT; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci while (last_offset < compressed_end) { 5298c2ecf20Sopenharmony_ci pg_index = last_offset >> PAGE_SHIFT; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci if (pg_index > end_index) 5328c2ecf20Sopenharmony_ci break; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci page = xa_load(&mapping->i_pages, pg_index); 5358c2ecf20Sopenharmony_ci if (page && !xa_is_value(page)) { 5368c2ecf20Sopenharmony_ci misses++; 5378c2ecf20Sopenharmony_ci if (misses > 4) 5388c2ecf20Sopenharmony_ci break; 5398c2ecf20Sopenharmony_ci goto next; 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci page = __page_cache_alloc(mapping_gfp_constraint(mapping, 5438c2ecf20Sopenharmony_ci ~__GFP_FS)); 5448c2ecf20Sopenharmony_ci if (!page) 5458c2ecf20Sopenharmony_ci break; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci if (add_to_page_cache_lru(page, mapping, pg_index, GFP_NOFS)) { 5488c2ecf20Sopenharmony_ci put_page(page); 5498c2ecf20Sopenharmony_ci goto next; 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci end = last_offset + PAGE_SIZE - 1; 5538c2ecf20Sopenharmony_ci /* 5548c2ecf20Sopenharmony_ci * at this point, we have a locked page in the page cache 5558c2ecf20Sopenharmony_ci * for these bytes in the file. But, we have to make 5568c2ecf20Sopenharmony_ci * sure they map to this compressed extent on disk. 5578c2ecf20Sopenharmony_ci */ 5588c2ecf20Sopenharmony_ci set_page_extent_mapped(page); 5598c2ecf20Sopenharmony_ci lock_extent(tree, last_offset, end); 5608c2ecf20Sopenharmony_ci read_lock(&em_tree->lock); 5618c2ecf20Sopenharmony_ci em = lookup_extent_mapping(em_tree, last_offset, 5628c2ecf20Sopenharmony_ci PAGE_SIZE); 5638c2ecf20Sopenharmony_ci read_unlock(&em_tree->lock); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci if (!em || last_offset < em->start || 5668c2ecf20Sopenharmony_ci (last_offset + PAGE_SIZE > extent_map_end(em)) || 5678c2ecf20Sopenharmony_ci (em->block_start >> 9) != cb->orig_bio->bi_iter.bi_sector) { 5688c2ecf20Sopenharmony_ci free_extent_map(em); 5698c2ecf20Sopenharmony_ci unlock_extent(tree, last_offset, end); 5708c2ecf20Sopenharmony_ci unlock_page(page); 5718c2ecf20Sopenharmony_ci put_page(page); 5728c2ecf20Sopenharmony_ci break; 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci free_extent_map(em); 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci if (page->index == end_index) { 5778c2ecf20Sopenharmony_ci char *userpage; 5788c2ecf20Sopenharmony_ci size_t zero_offset = offset_in_page(isize); 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci if (zero_offset) { 5818c2ecf20Sopenharmony_ci int zeros; 5828c2ecf20Sopenharmony_ci zeros = PAGE_SIZE - zero_offset; 5838c2ecf20Sopenharmony_ci userpage = kmap_atomic(page); 5848c2ecf20Sopenharmony_ci memset(userpage + zero_offset, 0, zeros); 5858c2ecf20Sopenharmony_ci flush_dcache_page(page); 5868c2ecf20Sopenharmony_ci kunmap_atomic(userpage); 5878c2ecf20Sopenharmony_ci } 5888c2ecf20Sopenharmony_ci } 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci ret = bio_add_page(cb->orig_bio, page, 5918c2ecf20Sopenharmony_ci PAGE_SIZE, 0); 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci if (ret == PAGE_SIZE) { 5948c2ecf20Sopenharmony_ci nr_pages++; 5958c2ecf20Sopenharmony_ci put_page(page); 5968c2ecf20Sopenharmony_ci } else { 5978c2ecf20Sopenharmony_ci unlock_extent(tree, last_offset, end); 5988c2ecf20Sopenharmony_ci unlock_page(page); 5998c2ecf20Sopenharmony_ci put_page(page); 6008c2ecf20Sopenharmony_ci break; 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_cinext: 6038c2ecf20Sopenharmony_ci last_offset += PAGE_SIZE; 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci return 0; 6068c2ecf20Sopenharmony_ci} 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci/* 6098c2ecf20Sopenharmony_ci * for a compressed read, the bio we get passed has all the inode pages 6108c2ecf20Sopenharmony_ci * in it. We don't actually do IO on those pages but allocate new ones 6118c2ecf20Sopenharmony_ci * to hold the compressed pages on disk. 6128c2ecf20Sopenharmony_ci * 6138c2ecf20Sopenharmony_ci * bio->bi_iter.bi_sector points to the compressed extent on disk 6148c2ecf20Sopenharmony_ci * bio->bi_io_vec points to all of the inode pages 6158c2ecf20Sopenharmony_ci * 6168c2ecf20Sopenharmony_ci * After the compressed pages are read, we copy the bytes into the 6178c2ecf20Sopenharmony_ci * bio we were passed and then call the bio end_io calls 6188c2ecf20Sopenharmony_ci */ 6198c2ecf20Sopenharmony_ciblk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, 6208c2ecf20Sopenharmony_ci int mirror_num, unsigned long bio_flags) 6218c2ecf20Sopenharmony_ci{ 6228c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); 6238c2ecf20Sopenharmony_ci struct extent_map_tree *em_tree; 6248c2ecf20Sopenharmony_ci struct compressed_bio *cb; 6258c2ecf20Sopenharmony_ci unsigned long compressed_len; 6268c2ecf20Sopenharmony_ci unsigned long nr_pages; 6278c2ecf20Sopenharmony_ci unsigned long pg_index; 6288c2ecf20Sopenharmony_ci struct page *page; 6298c2ecf20Sopenharmony_ci struct bio *comp_bio; 6308c2ecf20Sopenharmony_ci u64 cur_disk_byte = (u64)bio->bi_iter.bi_sector << 9; 6318c2ecf20Sopenharmony_ci u64 em_len; 6328c2ecf20Sopenharmony_ci u64 em_start; 6338c2ecf20Sopenharmony_ci struct extent_map *em; 6348c2ecf20Sopenharmony_ci blk_status_t ret = BLK_STS_RESOURCE; 6358c2ecf20Sopenharmony_ci int faili = 0; 6368c2ecf20Sopenharmony_ci const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); 6378c2ecf20Sopenharmony_ci u8 *sums; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci em_tree = &BTRFS_I(inode)->extent_tree; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci /* we need the actual starting offset of this extent in the file */ 6428c2ecf20Sopenharmony_ci read_lock(&em_tree->lock); 6438c2ecf20Sopenharmony_ci em = lookup_extent_mapping(em_tree, 6448c2ecf20Sopenharmony_ci page_offset(bio_first_page_all(bio)), 6458c2ecf20Sopenharmony_ci PAGE_SIZE); 6468c2ecf20Sopenharmony_ci read_unlock(&em_tree->lock); 6478c2ecf20Sopenharmony_ci if (!em) 6488c2ecf20Sopenharmony_ci return BLK_STS_IOERR; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci compressed_len = em->block_len; 6518c2ecf20Sopenharmony_ci cb = kmalloc(compressed_bio_size(fs_info, compressed_len), GFP_NOFS); 6528c2ecf20Sopenharmony_ci if (!cb) 6538c2ecf20Sopenharmony_ci goto out; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci refcount_set(&cb->pending_bios, 0); 6568c2ecf20Sopenharmony_ci cb->errors = 0; 6578c2ecf20Sopenharmony_ci cb->inode = inode; 6588c2ecf20Sopenharmony_ci cb->mirror_num = mirror_num; 6598c2ecf20Sopenharmony_ci sums = cb->sums; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci cb->start = em->orig_start; 6628c2ecf20Sopenharmony_ci em_len = em->len; 6638c2ecf20Sopenharmony_ci em_start = em->start; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci free_extent_map(em); 6668c2ecf20Sopenharmony_ci em = NULL; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci cb->len = bio->bi_iter.bi_size; 6698c2ecf20Sopenharmony_ci cb->compressed_len = compressed_len; 6708c2ecf20Sopenharmony_ci cb->compress_type = extent_compress_type(bio_flags); 6718c2ecf20Sopenharmony_ci cb->orig_bio = bio; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci nr_pages = DIV_ROUND_UP(compressed_len, PAGE_SIZE); 6748c2ecf20Sopenharmony_ci cb->compressed_pages = kcalloc(nr_pages, sizeof(struct page *), 6758c2ecf20Sopenharmony_ci GFP_NOFS); 6768c2ecf20Sopenharmony_ci if (!cb->compressed_pages) 6778c2ecf20Sopenharmony_ci goto fail1; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci for (pg_index = 0; pg_index < nr_pages; pg_index++) { 6808c2ecf20Sopenharmony_ci cb->compressed_pages[pg_index] = alloc_page(GFP_NOFS | 6818c2ecf20Sopenharmony_ci __GFP_HIGHMEM); 6828c2ecf20Sopenharmony_ci if (!cb->compressed_pages[pg_index]) { 6838c2ecf20Sopenharmony_ci faili = pg_index - 1; 6848c2ecf20Sopenharmony_ci ret = BLK_STS_RESOURCE; 6858c2ecf20Sopenharmony_ci goto fail2; 6868c2ecf20Sopenharmony_ci } 6878c2ecf20Sopenharmony_ci } 6888c2ecf20Sopenharmony_ci faili = nr_pages - 1; 6898c2ecf20Sopenharmony_ci cb->nr_pages = nr_pages; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci add_ra_bio_pages(inode, em_start + em_len, cb); 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci /* include any pages we added in add_ra-bio_pages */ 6948c2ecf20Sopenharmony_ci cb->len = bio->bi_iter.bi_size; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci comp_bio = btrfs_bio_alloc(cur_disk_byte); 6978c2ecf20Sopenharmony_ci comp_bio->bi_opf = REQ_OP_READ; 6988c2ecf20Sopenharmony_ci comp_bio->bi_private = cb; 6998c2ecf20Sopenharmony_ci comp_bio->bi_end_io = end_compressed_bio_read; 7008c2ecf20Sopenharmony_ci refcount_set(&cb->pending_bios, 1); 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci for (pg_index = 0; pg_index < nr_pages; pg_index++) { 7038c2ecf20Sopenharmony_ci int submit = 0; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci page = cb->compressed_pages[pg_index]; 7068c2ecf20Sopenharmony_ci page->mapping = inode->i_mapping; 7078c2ecf20Sopenharmony_ci page->index = em_start >> PAGE_SHIFT; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci if (comp_bio->bi_iter.bi_size) 7108c2ecf20Sopenharmony_ci submit = btrfs_bio_fits_in_stripe(page, PAGE_SIZE, 7118c2ecf20Sopenharmony_ci comp_bio, 0); 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci page->mapping = NULL; 7148c2ecf20Sopenharmony_ci if (submit || bio_add_page(comp_bio, page, PAGE_SIZE, 0) < 7158c2ecf20Sopenharmony_ci PAGE_SIZE) { 7168c2ecf20Sopenharmony_ci unsigned int nr_sectors; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci ret = btrfs_bio_wq_end_io(fs_info, comp_bio, 7198c2ecf20Sopenharmony_ci BTRFS_WQ_ENDIO_DATA); 7208c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci /* 7238c2ecf20Sopenharmony_ci * inc the count before we submit the bio so 7248c2ecf20Sopenharmony_ci * we know the end IO handler won't happen before 7258c2ecf20Sopenharmony_ci * we inc the count. Otherwise, the cb might get 7268c2ecf20Sopenharmony_ci * freed before we're done setting it up 7278c2ecf20Sopenharmony_ci */ 7288c2ecf20Sopenharmony_ci refcount_inc(&cb->pending_bios); 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { 7318c2ecf20Sopenharmony_ci ret = btrfs_lookup_bio_sums(inode, comp_bio, 7328c2ecf20Sopenharmony_ci (u64)-1, sums); 7338c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 7348c2ecf20Sopenharmony_ci } 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci nr_sectors = DIV_ROUND_UP(comp_bio->bi_iter.bi_size, 7378c2ecf20Sopenharmony_ci fs_info->sectorsize); 7388c2ecf20Sopenharmony_ci sums += csum_size * nr_sectors; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci ret = btrfs_map_bio(fs_info, comp_bio, mirror_num); 7418c2ecf20Sopenharmony_ci if (ret) { 7428c2ecf20Sopenharmony_ci comp_bio->bi_status = ret; 7438c2ecf20Sopenharmony_ci bio_endio(comp_bio); 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci comp_bio = btrfs_bio_alloc(cur_disk_byte); 7478c2ecf20Sopenharmony_ci comp_bio->bi_opf = REQ_OP_READ; 7488c2ecf20Sopenharmony_ci comp_bio->bi_private = cb; 7498c2ecf20Sopenharmony_ci comp_bio->bi_end_io = end_compressed_bio_read; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci bio_add_page(comp_bio, page, PAGE_SIZE, 0); 7528c2ecf20Sopenharmony_ci } 7538c2ecf20Sopenharmony_ci cur_disk_byte += PAGE_SIZE; 7548c2ecf20Sopenharmony_ci } 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci ret = btrfs_bio_wq_end_io(fs_info, comp_bio, BTRFS_WQ_ENDIO_DATA); 7578c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { 7608c2ecf20Sopenharmony_ci ret = btrfs_lookup_bio_sums(inode, comp_bio, (u64)-1, sums); 7618c2ecf20Sopenharmony_ci BUG_ON(ret); /* -ENOMEM */ 7628c2ecf20Sopenharmony_ci } 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci ret = btrfs_map_bio(fs_info, comp_bio, mirror_num); 7658c2ecf20Sopenharmony_ci if (ret) { 7668c2ecf20Sopenharmony_ci comp_bio->bi_status = ret; 7678c2ecf20Sopenharmony_ci bio_endio(comp_bio); 7688c2ecf20Sopenharmony_ci } 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci return 0; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_cifail2: 7738c2ecf20Sopenharmony_ci while (faili >= 0) { 7748c2ecf20Sopenharmony_ci __free_page(cb->compressed_pages[faili]); 7758c2ecf20Sopenharmony_ci faili--; 7768c2ecf20Sopenharmony_ci } 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci kfree(cb->compressed_pages); 7798c2ecf20Sopenharmony_cifail1: 7808c2ecf20Sopenharmony_ci kfree(cb); 7818c2ecf20Sopenharmony_ciout: 7828c2ecf20Sopenharmony_ci free_extent_map(em); 7838c2ecf20Sopenharmony_ci return ret; 7848c2ecf20Sopenharmony_ci} 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci/* 7878c2ecf20Sopenharmony_ci * Heuristic uses systematic sampling to collect data from the input data 7888c2ecf20Sopenharmony_ci * range, the logic can be tuned by the following constants: 7898c2ecf20Sopenharmony_ci * 7908c2ecf20Sopenharmony_ci * @SAMPLING_READ_SIZE - how many bytes will be copied from for each sample 7918c2ecf20Sopenharmony_ci * @SAMPLING_INTERVAL - range from which the sampled data can be collected 7928c2ecf20Sopenharmony_ci */ 7938c2ecf20Sopenharmony_ci#define SAMPLING_READ_SIZE (16) 7948c2ecf20Sopenharmony_ci#define SAMPLING_INTERVAL (256) 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci/* 7978c2ecf20Sopenharmony_ci * For statistical analysis of the input data we consider bytes that form a 7988c2ecf20Sopenharmony_ci * Galois Field of 256 objects. Each object has an attribute count, ie. how 7998c2ecf20Sopenharmony_ci * many times the object appeared in the sample. 8008c2ecf20Sopenharmony_ci */ 8018c2ecf20Sopenharmony_ci#define BUCKET_SIZE (256) 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci/* 8048c2ecf20Sopenharmony_ci * The size of the sample is based on a statistical sampling rule of thumb. 8058c2ecf20Sopenharmony_ci * The common way is to perform sampling tests as long as the number of 8068c2ecf20Sopenharmony_ci * elements in each cell is at least 5. 8078c2ecf20Sopenharmony_ci * 8088c2ecf20Sopenharmony_ci * Instead of 5, we choose 32 to obtain more accurate results. 8098c2ecf20Sopenharmony_ci * If the data contain the maximum number of symbols, which is 256, we obtain a 8108c2ecf20Sopenharmony_ci * sample size bound by 8192. 8118c2ecf20Sopenharmony_ci * 8128c2ecf20Sopenharmony_ci * For a sample of at most 8KB of data per data range: 16 consecutive bytes 8138c2ecf20Sopenharmony_ci * from up to 512 locations. 8148c2ecf20Sopenharmony_ci */ 8158c2ecf20Sopenharmony_ci#define MAX_SAMPLE_SIZE (BTRFS_MAX_UNCOMPRESSED * \ 8168c2ecf20Sopenharmony_ci SAMPLING_READ_SIZE / SAMPLING_INTERVAL) 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_cistruct bucket_item { 8198c2ecf20Sopenharmony_ci u32 count; 8208c2ecf20Sopenharmony_ci}; 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_cistruct heuristic_ws { 8238c2ecf20Sopenharmony_ci /* Partial copy of input data */ 8248c2ecf20Sopenharmony_ci u8 *sample; 8258c2ecf20Sopenharmony_ci u32 sample_size; 8268c2ecf20Sopenharmony_ci /* Buckets store counters for each byte value */ 8278c2ecf20Sopenharmony_ci struct bucket_item *bucket; 8288c2ecf20Sopenharmony_ci /* Sorting buffer */ 8298c2ecf20Sopenharmony_ci struct bucket_item *bucket_b; 8308c2ecf20Sopenharmony_ci struct list_head list; 8318c2ecf20Sopenharmony_ci}; 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_cistatic struct workspace_manager heuristic_wsm; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_cistatic void free_heuristic_ws(struct list_head *ws) 8368c2ecf20Sopenharmony_ci{ 8378c2ecf20Sopenharmony_ci struct heuristic_ws *workspace; 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci workspace = list_entry(ws, struct heuristic_ws, list); 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci kvfree(workspace->sample); 8428c2ecf20Sopenharmony_ci kfree(workspace->bucket); 8438c2ecf20Sopenharmony_ci kfree(workspace->bucket_b); 8448c2ecf20Sopenharmony_ci kfree(workspace); 8458c2ecf20Sopenharmony_ci} 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_cistatic struct list_head *alloc_heuristic_ws(unsigned int level) 8488c2ecf20Sopenharmony_ci{ 8498c2ecf20Sopenharmony_ci struct heuristic_ws *ws; 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci ws = kzalloc(sizeof(*ws), GFP_KERNEL); 8528c2ecf20Sopenharmony_ci if (!ws) 8538c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci ws->sample = kvmalloc(MAX_SAMPLE_SIZE, GFP_KERNEL); 8568c2ecf20Sopenharmony_ci if (!ws->sample) 8578c2ecf20Sopenharmony_ci goto fail; 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci ws->bucket = kcalloc(BUCKET_SIZE, sizeof(*ws->bucket), GFP_KERNEL); 8608c2ecf20Sopenharmony_ci if (!ws->bucket) 8618c2ecf20Sopenharmony_ci goto fail; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci ws->bucket_b = kcalloc(BUCKET_SIZE, sizeof(*ws->bucket_b), GFP_KERNEL); 8648c2ecf20Sopenharmony_ci if (!ws->bucket_b) 8658c2ecf20Sopenharmony_ci goto fail; 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ws->list); 8688c2ecf20Sopenharmony_ci return &ws->list; 8698c2ecf20Sopenharmony_cifail: 8708c2ecf20Sopenharmony_ci free_heuristic_ws(&ws->list); 8718c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 8728c2ecf20Sopenharmony_ci} 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ciconst struct btrfs_compress_op btrfs_heuristic_compress = { 8758c2ecf20Sopenharmony_ci .workspace_manager = &heuristic_wsm, 8768c2ecf20Sopenharmony_ci}; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_cistatic const struct btrfs_compress_op * const btrfs_compress_op[] = { 8798c2ecf20Sopenharmony_ci /* The heuristic is represented as compression type 0 */ 8808c2ecf20Sopenharmony_ci &btrfs_heuristic_compress, 8818c2ecf20Sopenharmony_ci &btrfs_zlib_compress, 8828c2ecf20Sopenharmony_ci &btrfs_lzo_compress, 8838c2ecf20Sopenharmony_ci &btrfs_zstd_compress, 8848c2ecf20Sopenharmony_ci}; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_cistatic struct list_head *alloc_workspace(int type, unsigned int level) 8878c2ecf20Sopenharmony_ci{ 8888c2ecf20Sopenharmony_ci switch (type) { 8898c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_NONE: return alloc_heuristic_ws(level); 8908c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZLIB: return zlib_alloc_workspace(level); 8918c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_LZO: return lzo_alloc_workspace(level); 8928c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZSTD: return zstd_alloc_workspace(level); 8938c2ecf20Sopenharmony_ci default: 8948c2ecf20Sopenharmony_ci /* 8958c2ecf20Sopenharmony_ci * This can't happen, the type is validated several times 8968c2ecf20Sopenharmony_ci * before we get here. 8978c2ecf20Sopenharmony_ci */ 8988c2ecf20Sopenharmony_ci BUG(); 8998c2ecf20Sopenharmony_ci } 9008c2ecf20Sopenharmony_ci} 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_cistatic void free_workspace(int type, struct list_head *ws) 9038c2ecf20Sopenharmony_ci{ 9048c2ecf20Sopenharmony_ci switch (type) { 9058c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_NONE: return free_heuristic_ws(ws); 9068c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZLIB: return zlib_free_workspace(ws); 9078c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_LZO: return lzo_free_workspace(ws); 9088c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZSTD: return zstd_free_workspace(ws); 9098c2ecf20Sopenharmony_ci default: 9108c2ecf20Sopenharmony_ci /* 9118c2ecf20Sopenharmony_ci * This can't happen, the type is validated several times 9128c2ecf20Sopenharmony_ci * before we get here. 9138c2ecf20Sopenharmony_ci */ 9148c2ecf20Sopenharmony_ci BUG(); 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci} 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_cistatic void btrfs_init_workspace_manager(int type) 9198c2ecf20Sopenharmony_ci{ 9208c2ecf20Sopenharmony_ci struct workspace_manager *wsm; 9218c2ecf20Sopenharmony_ci struct list_head *workspace; 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci wsm = btrfs_compress_op[type]->workspace_manager; 9248c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&wsm->idle_ws); 9258c2ecf20Sopenharmony_ci spin_lock_init(&wsm->ws_lock); 9268c2ecf20Sopenharmony_ci atomic_set(&wsm->total_ws, 0); 9278c2ecf20Sopenharmony_ci init_waitqueue_head(&wsm->ws_wait); 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci /* 9308c2ecf20Sopenharmony_ci * Preallocate one workspace for each compression type so we can 9318c2ecf20Sopenharmony_ci * guarantee forward progress in the worst case 9328c2ecf20Sopenharmony_ci */ 9338c2ecf20Sopenharmony_ci workspace = alloc_workspace(type, 0); 9348c2ecf20Sopenharmony_ci if (IS_ERR(workspace)) { 9358c2ecf20Sopenharmony_ci pr_warn( 9368c2ecf20Sopenharmony_ci "BTRFS: cannot preallocate compression workspace, will try later\n"); 9378c2ecf20Sopenharmony_ci } else { 9388c2ecf20Sopenharmony_ci atomic_set(&wsm->total_ws, 1); 9398c2ecf20Sopenharmony_ci wsm->free_ws = 1; 9408c2ecf20Sopenharmony_ci list_add(workspace, &wsm->idle_ws); 9418c2ecf20Sopenharmony_ci } 9428c2ecf20Sopenharmony_ci} 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_cistatic void btrfs_cleanup_workspace_manager(int type) 9458c2ecf20Sopenharmony_ci{ 9468c2ecf20Sopenharmony_ci struct workspace_manager *wsman; 9478c2ecf20Sopenharmony_ci struct list_head *ws; 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci wsman = btrfs_compress_op[type]->workspace_manager; 9508c2ecf20Sopenharmony_ci while (!list_empty(&wsman->idle_ws)) { 9518c2ecf20Sopenharmony_ci ws = wsman->idle_ws.next; 9528c2ecf20Sopenharmony_ci list_del(ws); 9538c2ecf20Sopenharmony_ci free_workspace(type, ws); 9548c2ecf20Sopenharmony_ci atomic_dec(&wsman->total_ws); 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci} 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci/* 9598c2ecf20Sopenharmony_ci * This finds an available workspace or allocates a new one. 9608c2ecf20Sopenharmony_ci * If it's not possible to allocate a new one, waits until there's one. 9618c2ecf20Sopenharmony_ci * Preallocation makes a forward progress guarantees and we do not return 9628c2ecf20Sopenharmony_ci * errors. 9638c2ecf20Sopenharmony_ci */ 9648c2ecf20Sopenharmony_cistruct list_head *btrfs_get_workspace(int type, unsigned int level) 9658c2ecf20Sopenharmony_ci{ 9668c2ecf20Sopenharmony_ci struct workspace_manager *wsm; 9678c2ecf20Sopenharmony_ci struct list_head *workspace; 9688c2ecf20Sopenharmony_ci int cpus = num_online_cpus(); 9698c2ecf20Sopenharmony_ci unsigned nofs_flag; 9708c2ecf20Sopenharmony_ci struct list_head *idle_ws; 9718c2ecf20Sopenharmony_ci spinlock_t *ws_lock; 9728c2ecf20Sopenharmony_ci atomic_t *total_ws; 9738c2ecf20Sopenharmony_ci wait_queue_head_t *ws_wait; 9748c2ecf20Sopenharmony_ci int *free_ws; 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci wsm = btrfs_compress_op[type]->workspace_manager; 9778c2ecf20Sopenharmony_ci idle_ws = &wsm->idle_ws; 9788c2ecf20Sopenharmony_ci ws_lock = &wsm->ws_lock; 9798c2ecf20Sopenharmony_ci total_ws = &wsm->total_ws; 9808c2ecf20Sopenharmony_ci ws_wait = &wsm->ws_wait; 9818c2ecf20Sopenharmony_ci free_ws = &wsm->free_ws; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ciagain: 9848c2ecf20Sopenharmony_ci spin_lock(ws_lock); 9858c2ecf20Sopenharmony_ci if (!list_empty(idle_ws)) { 9868c2ecf20Sopenharmony_ci workspace = idle_ws->next; 9878c2ecf20Sopenharmony_ci list_del(workspace); 9888c2ecf20Sopenharmony_ci (*free_ws)--; 9898c2ecf20Sopenharmony_ci spin_unlock(ws_lock); 9908c2ecf20Sopenharmony_ci return workspace; 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci } 9938c2ecf20Sopenharmony_ci if (atomic_read(total_ws) > cpus) { 9948c2ecf20Sopenharmony_ci DEFINE_WAIT(wait); 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci spin_unlock(ws_lock); 9978c2ecf20Sopenharmony_ci prepare_to_wait(ws_wait, &wait, TASK_UNINTERRUPTIBLE); 9988c2ecf20Sopenharmony_ci if (atomic_read(total_ws) > cpus && !*free_ws) 9998c2ecf20Sopenharmony_ci schedule(); 10008c2ecf20Sopenharmony_ci finish_wait(ws_wait, &wait); 10018c2ecf20Sopenharmony_ci goto again; 10028c2ecf20Sopenharmony_ci } 10038c2ecf20Sopenharmony_ci atomic_inc(total_ws); 10048c2ecf20Sopenharmony_ci spin_unlock(ws_lock); 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci /* 10078c2ecf20Sopenharmony_ci * Allocation helpers call vmalloc that can't use GFP_NOFS, so we have 10088c2ecf20Sopenharmony_ci * to turn it off here because we might get called from the restricted 10098c2ecf20Sopenharmony_ci * context of btrfs_compress_bio/btrfs_compress_pages 10108c2ecf20Sopenharmony_ci */ 10118c2ecf20Sopenharmony_ci nofs_flag = memalloc_nofs_save(); 10128c2ecf20Sopenharmony_ci workspace = alloc_workspace(type, level); 10138c2ecf20Sopenharmony_ci memalloc_nofs_restore(nofs_flag); 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci if (IS_ERR(workspace)) { 10168c2ecf20Sopenharmony_ci atomic_dec(total_ws); 10178c2ecf20Sopenharmony_ci wake_up(ws_wait); 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci /* 10208c2ecf20Sopenharmony_ci * Do not return the error but go back to waiting. There's a 10218c2ecf20Sopenharmony_ci * workspace preallocated for each type and the compression 10228c2ecf20Sopenharmony_ci * time is bounded so we get to a workspace eventually. This 10238c2ecf20Sopenharmony_ci * makes our caller's life easier. 10248c2ecf20Sopenharmony_ci * 10258c2ecf20Sopenharmony_ci * To prevent silent and low-probability deadlocks (when the 10268c2ecf20Sopenharmony_ci * initial preallocation fails), check if there are any 10278c2ecf20Sopenharmony_ci * workspaces at all. 10288c2ecf20Sopenharmony_ci */ 10298c2ecf20Sopenharmony_ci if (atomic_read(total_ws) == 0) { 10308c2ecf20Sopenharmony_ci static DEFINE_RATELIMIT_STATE(_rs, 10318c2ecf20Sopenharmony_ci /* once per minute */ 60 * HZ, 10328c2ecf20Sopenharmony_ci /* no burst */ 1); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci if (__ratelimit(&_rs)) { 10358c2ecf20Sopenharmony_ci pr_warn("BTRFS: no compression workspaces, low memory, retrying\n"); 10368c2ecf20Sopenharmony_ci } 10378c2ecf20Sopenharmony_ci } 10388c2ecf20Sopenharmony_ci goto again; 10398c2ecf20Sopenharmony_ci } 10408c2ecf20Sopenharmony_ci return workspace; 10418c2ecf20Sopenharmony_ci} 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_cistatic struct list_head *get_workspace(int type, int level) 10448c2ecf20Sopenharmony_ci{ 10458c2ecf20Sopenharmony_ci switch (type) { 10468c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_NONE: return btrfs_get_workspace(type, level); 10478c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZLIB: return zlib_get_workspace(level); 10488c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_LZO: return btrfs_get_workspace(type, level); 10498c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZSTD: return zstd_get_workspace(level); 10508c2ecf20Sopenharmony_ci default: 10518c2ecf20Sopenharmony_ci /* 10528c2ecf20Sopenharmony_ci * This can't happen, the type is validated several times 10538c2ecf20Sopenharmony_ci * before we get here. 10548c2ecf20Sopenharmony_ci */ 10558c2ecf20Sopenharmony_ci BUG(); 10568c2ecf20Sopenharmony_ci } 10578c2ecf20Sopenharmony_ci} 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci/* 10608c2ecf20Sopenharmony_ci * put a workspace struct back on the list or free it if we have enough 10618c2ecf20Sopenharmony_ci * idle ones sitting around 10628c2ecf20Sopenharmony_ci */ 10638c2ecf20Sopenharmony_civoid btrfs_put_workspace(int type, struct list_head *ws) 10648c2ecf20Sopenharmony_ci{ 10658c2ecf20Sopenharmony_ci struct workspace_manager *wsm; 10668c2ecf20Sopenharmony_ci struct list_head *idle_ws; 10678c2ecf20Sopenharmony_ci spinlock_t *ws_lock; 10688c2ecf20Sopenharmony_ci atomic_t *total_ws; 10698c2ecf20Sopenharmony_ci wait_queue_head_t *ws_wait; 10708c2ecf20Sopenharmony_ci int *free_ws; 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci wsm = btrfs_compress_op[type]->workspace_manager; 10738c2ecf20Sopenharmony_ci idle_ws = &wsm->idle_ws; 10748c2ecf20Sopenharmony_ci ws_lock = &wsm->ws_lock; 10758c2ecf20Sopenharmony_ci total_ws = &wsm->total_ws; 10768c2ecf20Sopenharmony_ci ws_wait = &wsm->ws_wait; 10778c2ecf20Sopenharmony_ci free_ws = &wsm->free_ws; 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci spin_lock(ws_lock); 10808c2ecf20Sopenharmony_ci if (*free_ws <= num_online_cpus()) { 10818c2ecf20Sopenharmony_ci list_add(ws, idle_ws); 10828c2ecf20Sopenharmony_ci (*free_ws)++; 10838c2ecf20Sopenharmony_ci spin_unlock(ws_lock); 10848c2ecf20Sopenharmony_ci goto wake; 10858c2ecf20Sopenharmony_ci } 10868c2ecf20Sopenharmony_ci spin_unlock(ws_lock); 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci free_workspace(type, ws); 10898c2ecf20Sopenharmony_ci atomic_dec(total_ws); 10908c2ecf20Sopenharmony_ciwake: 10918c2ecf20Sopenharmony_ci cond_wake_up(ws_wait); 10928c2ecf20Sopenharmony_ci} 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_cistatic void put_workspace(int type, struct list_head *ws) 10958c2ecf20Sopenharmony_ci{ 10968c2ecf20Sopenharmony_ci switch (type) { 10978c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_NONE: return btrfs_put_workspace(type, ws); 10988c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZLIB: return btrfs_put_workspace(type, ws); 10998c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_LZO: return btrfs_put_workspace(type, ws); 11008c2ecf20Sopenharmony_ci case BTRFS_COMPRESS_ZSTD: return zstd_put_workspace(ws); 11018c2ecf20Sopenharmony_ci default: 11028c2ecf20Sopenharmony_ci /* 11038c2ecf20Sopenharmony_ci * This can't happen, the type is validated several times 11048c2ecf20Sopenharmony_ci * before we get here. 11058c2ecf20Sopenharmony_ci */ 11068c2ecf20Sopenharmony_ci BUG(); 11078c2ecf20Sopenharmony_ci } 11088c2ecf20Sopenharmony_ci} 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci/* 11118c2ecf20Sopenharmony_ci * Adjust @level according to the limits of the compression algorithm or 11128c2ecf20Sopenharmony_ci * fallback to default 11138c2ecf20Sopenharmony_ci */ 11148c2ecf20Sopenharmony_cistatic unsigned int btrfs_compress_set_level(int type, unsigned level) 11158c2ecf20Sopenharmony_ci{ 11168c2ecf20Sopenharmony_ci const struct btrfs_compress_op *ops = btrfs_compress_op[type]; 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci if (level == 0) 11198c2ecf20Sopenharmony_ci level = ops->default_level; 11208c2ecf20Sopenharmony_ci else 11218c2ecf20Sopenharmony_ci level = min(level, ops->max_level); 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci return level; 11248c2ecf20Sopenharmony_ci} 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci/* 11278c2ecf20Sopenharmony_ci * Given an address space and start and length, compress the bytes into @pages 11288c2ecf20Sopenharmony_ci * that are allocated on demand. 11298c2ecf20Sopenharmony_ci * 11308c2ecf20Sopenharmony_ci * @type_level is encoded algorithm and level, where level 0 means whatever 11318c2ecf20Sopenharmony_ci * default the algorithm chooses and is opaque here; 11328c2ecf20Sopenharmony_ci * - compression algo are 0-3 11338c2ecf20Sopenharmony_ci * - the level are bits 4-7 11348c2ecf20Sopenharmony_ci * 11358c2ecf20Sopenharmony_ci * @out_pages is an in/out parameter, holds maximum number of pages to allocate 11368c2ecf20Sopenharmony_ci * and returns number of actually allocated pages 11378c2ecf20Sopenharmony_ci * 11388c2ecf20Sopenharmony_ci * @total_in is used to return the number of bytes actually read. It 11398c2ecf20Sopenharmony_ci * may be smaller than the input length if we had to exit early because we 11408c2ecf20Sopenharmony_ci * ran out of room in the pages array or because we cross the 11418c2ecf20Sopenharmony_ci * max_out threshold. 11428c2ecf20Sopenharmony_ci * 11438c2ecf20Sopenharmony_ci * @total_out is an in/out parameter, must be set to the input length and will 11448c2ecf20Sopenharmony_ci * be also used to return the total number of compressed bytes 11458c2ecf20Sopenharmony_ci * 11468c2ecf20Sopenharmony_ci * @max_out tells us the max number of bytes that we're allowed to 11478c2ecf20Sopenharmony_ci * stuff into pages 11488c2ecf20Sopenharmony_ci */ 11498c2ecf20Sopenharmony_ciint btrfs_compress_pages(unsigned int type_level, struct address_space *mapping, 11508c2ecf20Sopenharmony_ci u64 start, struct page **pages, 11518c2ecf20Sopenharmony_ci unsigned long *out_pages, 11528c2ecf20Sopenharmony_ci unsigned long *total_in, 11538c2ecf20Sopenharmony_ci unsigned long *total_out) 11548c2ecf20Sopenharmony_ci{ 11558c2ecf20Sopenharmony_ci int type = btrfs_compress_type(type_level); 11568c2ecf20Sopenharmony_ci int level = btrfs_compress_level(type_level); 11578c2ecf20Sopenharmony_ci struct list_head *workspace; 11588c2ecf20Sopenharmony_ci int ret; 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci level = btrfs_compress_set_level(type, level); 11618c2ecf20Sopenharmony_ci workspace = get_workspace(type, level); 11628c2ecf20Sopenharmony_ci ret = compression_compress_pages(type, workspace, mapping, start, pages, 11638c2ecf20Sopenharmony_ci out_pages, total_in, total_out); 11648c2ecf20Sopenharmony_ci put_workspace(type, workspace); 11658c2ecf20Sopenharmony_ci return ret; 11668c2ecf20Sopenharmony_ci} 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci/* 11698c2ecf20Sopenharmony_ci * pages_in is an array of pages with compressed data. 11708c2ecf20Sopenharmony_ci * 11718c2ecf20Sopenharmony_ci * disk_start is the starting logical offset of this array in the file 11728c2ecf20Sopenharmony_ci * 11738c2ecf20Sopenharmony_ci * orig_bio contains the pages from the file that we want to decompress into 11748c2ecf20Sopenharmony_ci * 11758c2ecf20Sopenharmony_ci * srclen is the number of bytes in pages_in 11768c2ecf20Sopenharmony_ci * 11778c2ecf20Sopenharmony_ci * The basic idea is that we have a bio that was created by readpages. 11788c2ecf20Sopenharmony_ci * The pages in the bio are for the uncompressed data, and they may not 11798c2ecf20Sopenharmony_ci * be contiguous. They all correspond to the range of bytes covered by 11808c2ecf20Sopenharmony_ci * the compressed extent. 11818c2ecf20Sopenharmony_ci */ 11828c2ecf20Sopenharmony_cistatic int btrfs_decompress_bio(struct compressed_bio *cb) 11838c2ecf20Sopenharmony_ci{ 11848c2ecf20Sopenharmony_ci struct list_head *workspace; 11858c2ecf20Sopenharmony_ci int ret; 11868c2ecf20Sopenharmony_ci int type = cb->compress_type; 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci workspace = get_workspace(type, 0); 11898c2ecf20Sopenharmony_ci ret = compression_decompress_bio(type, workspace, cb); 11908c2ecf20Sopenharmony_ci put_workspace(type, workspace); 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci return ret; 11938c2ecf20Sopenharmony_ci} 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci/* 11968c2ecf20Sopenharmony_ci * a less complex decompression routine. Our compressed data fits in a 11978c2ecf20Sopenharmony_ci * single page, and we want to read a single page out of it. 11988c2ecf20Sopenharmony_ci * start_byte tells us the offset into the compressed data we're interested in 11998c2ecf20Sopenharmony_ci */ 12008c2ecf20Sopenharmony_ciint btrfs_decompress(int type, unsigned char *data_in, struct page *dest_page, 12018c2ecf20Sopenharmony_ci unsigned long start_byte, size_t srclen, size_t destlen) 12028c2ecf20Sopenharmony_ci{ 12038c2ecf20Sopenharmony_ci struct list_head *workspace; 12048c2ecf20Sopenharmony_ci int ret; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci workspace = get_workspace(type, 0); 12078c2ecf20Sopenharmony_ci ret = compression_decompress(type, workspace, data_in, dest_page, 12088c2ecf20Sopenharmony_ci start_byte, srclen, destlen); 12098c2ecf20Sopenharmony_ci put_workspace(type, workspace); 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci return ret; 12128c2ecf20Sopenharmony_ci} 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_civoid __init btrfs_init_compress(void) 12158c2ecf20Sopenharmony_ci{ 12168c2ecf20Sopenharmony_ci btrfs_init_workspace_manager(BTRFS_COMPRESS_NONE); 12178c2ecf20Sopenharmony_ci btrfs_init_workspace_manager(BTRFS_COMPRESS_ZLIB); 12188c2ecf20Sopenharmony_ci btrfs_init_workspace_manager(BTRFS_COMPRESS_LZO); 12198c2ecf20Sopenharmony_ci zstd_init_workspace_manager(); 12208c2ecf20Sopenharmony_ci} 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_civoid __cold btrfs_exit_compress(void) 12238c2ecf20Sopenharmony_ci{ 12248c2ecf20Sopenharmony_ci btrfs_cleanup_workspace_manager(BTRFS_COMPRESS_NONE); 12258c2ecf20Sopenharmony_ci btrfs_cleanup_workspace_manager(BTRFS_COMPRESS_ZLIB); 12268c2ecf20Sopenharmony_ci btrfs_cleanup_workspace_manager(BTRFS_COMPRESS_LZO); 12278c2ecf20Sopenharmony_ci zstd_cleanup_workspace_manager(); 12288c2ecf20Sopenharmony_ci} 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci/* 12318c2ecf20Sopenharmony_ci * Copy uncompressed data from working buffer to pages. 12328c2ecf20Sopenharmony_ci * 12338c2ecf20Sopenharmony_ci * buf_start is the byte offset we're of the start of our workspace buffer. 12348c2ecf20Sopenharmony_ci * 12358c2ecf20Sopenharmony_ci * total_out is the last byte of the buffer 12368c2ecf20Sopenharmony_ci */ 12378c2ecf20Sopenharmony_ciint btrfs_decompress_buf2page(const char *buf, unsigned long buf_start, 12388c2ecf20Sopenharmony_ci unsigned long total_out, u64 disk_start, 12398c2ecf20Sopenharmony_ci struct bio *bio) 12408c2ecf20Sopenharmony_ci{ 12418c2ecf20Sopenharmony_ci unsigned long buf_offset; 12428c2ecf20Sopenharmony_ci unsigned long current_buf_start; 12438c2ecf20Sopenharmony_ci unsigned long start_byte; 12448c2ecf20Sopenharmony_ci unsigned long prev_start_byte; 12458c2ecf20Sopenharmony_ci unsigned long working_bytes = total_out - buf_start; 12468c2ecf20Sopenharmony_ci unsigned long bytes; 12478c2ecf20Sopenharmony_ci char *kaddr; 12488c2ecf20Sopenharmony_ci struct bio_vec bvec = bio_iter_iovec(bio, bio->bi_iter); 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci /* 12518c2ecf20Sopenharmony_ci * start byte is the first byte of the page we're currently 12528c2ecf20Sopenharmony_ci * copying into relative to the start of the compressed data. 12538c2ecf20Sopenharmony_ci */ 12548c2ecf20Sopenharmony_ci start_byte = page_offset(bvec.bv_page) - disk_start; 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci /* we haven't yet hit data corresponding to this page */ 12578c2ecf20Sopenharmony_ci if (total_out <= start_byte) 12588c2ecf20Sopenharmony_ci return 1; 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci /* 12618c2ecf20Sopenharmony_ci * the start of the data we care about is offset into 12628c2ecf20Sopenharmony_ci * the middle of our working buffer 12638c2ecf20Sopenharmony_ci */ 12648c2ecf20Sopenharmony_ci if (total_out > start_byte && buf_start < start_byte) { 12658c2ecf20Sopenharmony_ci buf_offset = start_byte - buf_start; 12668c2ecf20Sopenharmony_ci working_bytes -= buf_offset; 12678c2ecf20Sopenharmony_ci } else { 12688c2ecf20Sopenharmony_ci buf_offset = 0; 12698c2ecf20Sopenharmony_ci } 12708c2ecf20Sopenharmony_ci current_buf_start = buf_start; 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci /* copy bytes from the working buffer into the pages */ 12738c2ecf20Sopenharmony_ci while (working_bytes > 0) { 12748c2ecf20Sopenharmony_ci bytes = min_t(unsigned long, bvec.bv_len, 12758c2ecf20Sopenharmony_ci PAGE_SIZE - (buf_offset % PAGE_SIZE)); 12768c2ecf20Sopenharmony_ci bytes = min(bytes, working_bytes); 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci kaddr = kmap_atomic(bvec.bv_page); 12798c2ecf20Sopenharmony_ci memcpy(kaddr + bvec.bv_offset, buf + buf_offset, bytes); 12808c2ecf20Sopenharmony_ci kunmap_atomic(kaddr); 12818c2ecf20Sopenharmony_ci flush_dcache_page(bvec.bv_page); 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci buf_offset += bytes; 12848c2ecf20Sopenharmony_ci working_bytes -= bytes; 12858c2ecf20Sopenharmony_ci current_buf_start += bytes; 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci /* check if we need to pick another page */ 12888c2ecf20Sopenharmony_ci bio_advance(bio, bytes); 12898c2ecf20Sopenharmony_ci if (!bio->bi_iter.bi_size) 12908c2ecf20Sopenharmony_ci return 0; 12918c2ecf20Sopenharmony_ci bvec = bio_iter_iovec(bio, bio->bi_iter); 12928c2ecf20Sopenharmony_ci prev_start_byte = start_byte; 12938c2ecf20Sopenharmony_ci start_byte = page_offset(bvec.bv_page) - disk_start; 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci /* 12968c2ecf20Sopenharmony_ci * We need to make sure we're only adjusting 12978c2ecf20Sopenharmony_ci * our offset into compression working buffer when 12988c2ecf20Sopenharmony_ci * we're switching pages. Otherwise we can incorrectly 12998c2ecf20Sopenharmony_ci * keep copying when we were actually done. 13008c2ecf20Sopenharmony_ci */ 13018c2ecf20Sopenharmony_ci if (start_byte != prev_start_byte) { 13028c2ecf20Sopenharmony_ci /* 13038c2ecf20Sopenharmony_ci * make sure our new page is covered by this 13048c2ecf20Sopenharmony_ci * working buffer 13058c2ecf20Sopenharmony_ci */ 13068c2ecf20Sopenharmony_ci if (total_out <= start_byte) 13078c2ecf20Sopenharmony_ci return 1; 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci /* 13108c2ecf20Sopenharmony_ci * the next page in the biovec might not be adjacent 13118c2ecf20Sopenharmony_ci * to the last page, but it might still be found 13128c2ecf20Sopenharmony_ci * inside this working buffer. bump our offset pointer 13138c2ecf20Sopenharmony_ci */ 13148c2ecf20Sopenharmony_ci if (total_out > start_byte && 13158c2ecf20Sopenharmony_ci current_buf_start < start_byte) { 13168c2ecf20Sopenharmony_ci buf_offset = start_byte - buf_start; 13178c2ecf20Sopenharmony_ci working_bytes = total_out - start_byte; 13188c2ecf20Sopenharmony_ci current_buf_start = buf_start + buf_offset; 13198c2ecf20Sopenharmony_ci } 13208c2ecf20Sopenharmony_ci } 13218c2ecf20Sopenharmony_ci } 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci return 1; 13248c2ecf20Sopenharmony_ci} 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci/* 13278c2ecf20Sopenharmony_ci * Shannon Entropy calculation 13288c2ecf20Sopenharmony_ci * 13298c2ecf20Sopenharmony_ci * Pure byte distribution analysis fails to determine compressibility of data. 13308c2ecf20Sopenharmony_ci * Try calculating entropy to estimate the average minimum number of bits 13318c2ecf20Sopenharmony_ci * needed to encode the sampled data. 13328c2ecf20Sopenharmony_ci * 13338c2ecf20Sopenharmony_ci * For convenience, return the percentage of needed bits, instead of amount of 13348c2ecf20Sopenharmony_ci * bits directly. 13358c2ecf20Sopenharmony_ci * 13368c2ecf20Sopenharmony_ci * @ENTROPY_LVL_ACEPTABLE - below that threshold, sample has low byte entropy 13378c2ecf20Sopenharmony_ci * and can be compressible with high probability 13388c2ecf20Sopenharmony_ci * 13398c2ecf20Sopenharmony_ci * @ENTROPY_LVL_HIGH - data are not compressible with high probability 13408c2ecf20Sopenharmony_ci * 13418c2ecf20Sopenharmony_ci * Use of ilog2() decreases precision, we lower the LVL to 5 to compensate. 13428c2ecf20Sopenharmony_ci */ 13438c2ecf20Sopenharmony_ci#define ENTROPY_LVL_ACEPTABLE (65) 13448c2ecf20Sopenharmony_ci#define ENTROPY_LVL_HIGH (80) 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci/* 13478c2ecf20Sopenharmony_ci * For increasead precision in shannon_entropy calculation, 13488c2ecf20Sopenharmony_ci * let's do pow(n, M) to save more digits after comma: 13498c2ecf20Sopenharmony_ci * 13508c2ecf20Sopenharmony_ci * - maximum int bit length is 64 13518c2ecf20Sopenharmony_ci * - ilog2(MAX_SAMPLE_SIZE) -> 13 13528c2ecf20Sopenharmony_ci * - 13 * 4 = 52 < 64 -> M = 4 13538c2ecf20Sopenharmony_ci * 13548c2ecf20Sopenharmony_ci * So use pow(n, 4). 13558c2ecf20Sopenharmony_ci */ 13568c2ecf20Sopenharmony_cistatic inline u32 ilog2_w(u64 n) 13578c2ecf20Sopenharmony_ci{ 13588c2ecf20Sopenharmony_ci return ilog2(n * n * n * n); 13598c2ecf20Sopenharmony_ci} 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_cistatic u32 shannon_entropy(struct heuristic_ws *ws) 13628c2ecf20Sopenharmony_ci{ 13638c2ecf20Sopenharmony_ci const u32 entropy_max = 8 * ilog2_w(2); 13648c2ecf20Sopenharmony_ci u32 entropy_sum = 0; 13658c2ecf20Sopenharmony_ci u32 p, p_base, sz_base; 13668c2ecf20Sopenharmony_ci u32 i; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci sz_base = ilog2_w(ws->sample_size); 13698c2ecf20Sopenharmony_ci for (i = 0; i < BUCKET_SIZE && ws->bucket[i].count > 0; i++) { 13708c2ecf20Sopenharmony_ci p = ws->bucket[i].count; 13718c2ecf20Sopenharmony_ci p_base = ilog2_w(p); 13728c2ecf20Sopenharmony_ci entropy_sum += p * (sz_base - p_base); 13738c2ecf20Sopenharmony_ci } 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci entropy_sum /= ws->sample_size; 13768c2ecf20Sopenharmony_ci return entropy_sum * 100 / entropy_max; 13778c2ecf20Sopenharmony_ci} 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci#define RADIX_BASE 4U 13808c2ecf20Sopenharmony_ci#define COUNTERS_SIZE (1U << RADIX_BASE) 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_cistatic u8 get4bits(u64 num, int shift) { 13838c2ecf20Sopenharmony_ci u8 low4bits; 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci num >>= shift; 13868c2ecf20Sopenharmony_ci /* Reverse order */ 13878c2ecf20Sopenharmony_ci low4bits = (COUNTERS_SIZE - 1) - (num % COUNTERS_SIZE); 13888c2ecf20Sopenharmony_ci return low4bits; 13898c2ecf20Sopenharmony_ci} 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci/* 13928c2ecf20Sopenharmony_ci * Use 4 bits as radix base 13938c2ecf20Sopenharmony_ci * Use 16 u32 counters for calculating new position in buf array 13948c2ecf20Sopenharmony_ci * 13958c2ecf20Sopenharmony_ci * @array - array that will be sorted 13968c2ecf20Sopenharmony_ci * @array_buf - buffer array to store sorting results 13978c2ecf20Sopenharmony_ci * must be equal in size to @array 13988c2ecf20Sopenharmony_ci * @num - array size 13998c2ecf20Sopenharmony_ci */ 14008c2ecf20Sopenharmony_cistatic void radix_sort(struct bucket_item *array, struct bucket_item *array_buf, 14018c2ecf20Sopenharmony_ci int num) 14028c2ecf20Sopenharmony_ci{ 14038c2ecf20Sopenharmony_ci u64 max_num; 14048c2ecf20Sopenharmony_ci u64 buf_num; 14058c2ecf20Sopenharmony_ci u32 counters[COUNTERS_SIZE]; 14068c2ecf20Sopenharmony_ci u32 new_addr; 14078c2ecf20Sopenharmony_ci u32 addr; 14088c2ecf20Sopenharmony_ci int bitlen; 14098c2ecf20Sopenharmony_ci int shift; 14108c2ecf20Sopenharmony_ci int i; 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci /* 14138c2ecf20Sopenharmony_ci * Try avoid useless loop iterations for small numbers stored in big 14148c2ecf20Sopenharmony_ci * counters. Example: 48 33 4 ... in 64bit array 14158c2ecf20Sopenharmony_ci */ 14168c2ecf20Sopenharmony_ci max_num = array[0].count; 14178c2ecf20Sopenharmony_ci for (i = 1; i < num; i++) { 14188c2ecf20Sopenharmony_ci buf_num = array[i].count; 14198c2ecf20Sopenharmony_ci if (buf_num > max_num) 14208c2ecf20Sopenharmony_ci max_num = buf_num; 14218c2ecf20Sopenharmony_ci } 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci buf_num = ilog2(max_num); 14248c2ecf20Sopenharmony_ci bitlen = ALIGN(buf_num, RADIX_BASE * 2); 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci shift = 0; 14278c2ecf20Sopenharmony_ci while (shift < bitlen) { 14288c2ecf20Sopenharmony_ci memset(counters, 0, sizeof(counters)); 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 14318c2ecf20Sopenharmony_ci buf_num = array[i].count; 14328c2ecf20Sopenharmony_ci addr = get4bits(buf_num, shift); 14338c2ecf20Sopenharmony_ci counters[addr]++; 14348c2ecf20Sopenharmony_ci } 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci for (i = 1; i < COUNTERS_SIZE; i++) 14378c2ecf20Sopenharmony_ci counters[i] += counters[i - 1]; 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_ci for (i = num - 1; i >= 0; i--) { 14408c2ecf20Sopenharmony_ci buf_num = array[i].count; 14418c2ecf20Sopenharmony_ci addr = get4bits(buf_num, shift); 14428c2ecf20Sopenharmony_ci counters[addr]--; 14438c2ecf20Sopenharmony_ci new_addr = counters[addr]; 14448c2ecf20Sopenharmony_ci array_buf[new_addr] = array[i]; 14458c2ecf20Sopenharmony_ci } 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci shift += RADIX_BASE; 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci /* 14508c2ecf20Sopenharmony_ci * Normal radix expects to move data from a temporary array, to 14518c2ecf20Sopenharmony_ci * the main one. But that requires some CPU time. Avoid that 14528c2ecf20Sopenharmony_ci * by doing another sort iteration to original array instead of 14538c2ecf20Sopenharmony_ci * memcpy() 14548c2ecf20Sopenharmony_ci */ 14558c2ecf20Sopenharmony_ci memset(counters, 0, sizeof(counters)); 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci for (i = 0; i < num; i ++) { 14588c2ecf20Sopenharmony_ci buf_num = array_buf[i].count; 14598c2ecf20Sopenharmony_ci addr = get4bits(buf_num, shift); 14608c2ecf20Sopenharmony_ci counters[addr]++; 14618c2ecf20Sopenharmony_ci } 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci for (i = 1; i < COUNTERS_SIZE; i++) 14648c2ecf20Sopenharmony_ci counters[i] += counters[i - 1]; 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci for (i = num - 1; i >= 0; i--) { 14678c2ecf20Sopenharmony_ci buf_num = array_buf[i].count; 14688c2ecf20Sopenharmony_ci addr = get4bits(buf_num, shift); 14698c2ecf20Sopenharmony_ci counters[addr]--; 14708c2ecf20Sopenharmony_ci new_addr = counters[addr]; 14718c2ecf20Sopenharmony_ci array[new_addr] = array_buf[i]; 14728c2ecf20Sopenharmony_ci } 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci shift += RADIX_BASE; 14758c2ecf20Sopenharmony_ci } 14768c2ecf20Sopenharmony_ci} 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_ci/* 14798c2ecf20Sopenharmony_ci * Size of the core byte set - how many bytes cover 90% of the sample 14808c2ecf20Sopenharmony_ci * 14818c2ecf20Sopenharmony_ci * There are several types of structured binary data that use nearly all byte 14828c2ecf20Sopenharmony_ci * values. The distribution can be uniform and counts in all buckets will be 14838c2ecf20Sopenharmony_ci * nearly the same (eg. encrypted data). Unlikely to be compressible. 14848c2ecf20Sopenharmony_ci * 14858c2ecf20Sopenharmony_ci * Other possibility is normal (Gaussian) distribution, where the data could 14868c2ecf20Sopenharmony_ci * be potentially compressible, but we have to take a few more steps to decide 14878c2ecf20Sopenharmony_ci * how much. 14888c2ecf20Sopenharmony_ci * 14898c2ecf20Sopenharmony_ci * @BYTE_CORE_SET_LOW - main part of byte values repeated frequently, 14908c2ecf20Sopenharmony_ci * compression algo can easy fix that 14918c2ecf20Sopenharmony_ci * @BYTE_CORE_SET_HIGH - data have uniform distribution and with high 14928c2ecf20Sopenharmony_ci * probability is not compressible 14938c2ecf20Sopenharmony_ci */ 14948c2ecf20Sopenharmony_ci#define BYTE_CORE_SET_LOW (64) 14958c2ecf20Sopenharmony_ci#define BYTE_CORE_SET_HIGH (200) 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_cistatic int byte_core_set_size(struct heuristic_ws *ws) 14988c2ecf20Sopenharmony_ci{ 14998c2ecf20Sopenharmony_ci u32 i; 15008c2ecf20Sopenharmony_ci u32 coreset_sum = 0; 15018c2ecf20Sopenharmony_ci const u32 core_set_threshold = ws->sample_size * 90 / 100; 15028c2ecf20Sopenharmony_ci struct bucket_item *bucket = ws->bucket; 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci /* Sort in reverse order */ 15058c2ecf20Sopenharmony_ci radix_sort(ws->bucket, ws->bucket_b, BUCKET_SIZE); 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci for (i = 0; i < BYTE_CORE_SET_LOW; i++) 15088c2ecf20Sopenharmony_ci coreset_sum += bucket[i].count; 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci if (coreset_sum > core_set_threshold) 15118c2ecf20Sopenharmony_ci return i; 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_ci for (; i < BYTE_CORE_SET_HIGH && bucket[i].count > 0; i++) { 15148c2ecf20Sopenharmony_ci coreset_sum += bucket[i].count; 15158c2ecf20Sopenharmony_ci if (coreset_sum > core_set_threshold) 15168c2ecf20Sopenharmony_ci break; 15178c2ecf20Sopenharmony_ci } 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci return i; 15208c2ecf20Sopenharmony_ci} 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci/* 15238c2ecf20Sopenharmony_ci * Count byte values in buckets. 15248c2ecf20Sopenharmony_ci * This heuristic can detect textual data (configs, xml, json, html, etc). 15258c2ecf20Sopenharmony_ci * Because in most text-like data byte set is restricted to limited number of 15268c2ecf20Sopenharmony_ci * possible characters, and that restriction in most cases makes data easy to 15278c2ecf20Sopenharmony_ci * compress. 15288c2ecf20Sopenharmony_ci * 15298c2ecf20Sopenharmony_ci * @BYTE_SET_THRESHOLD - consider all data within this byte set size: 15308c2ecf20Sopenharmony_ci * less - compressible 15318c2ecf20Sopenharmony_ci * more - need additional analysis 15328c2ecf20Sopenharmony_ci */ 15338c2ecf20Sopenharmony_ci#define BYTE_SET_THRESHOLD (64) 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_cistatic u32 byte_set_size(const struct heuristic_ws *ws) 15368c2ecf20Sopenharmony_ci{ 15378c2ecf20Sopenharmony_ci u32 i; 15388c2ecf20Sopenharmony_ci u32 byte_set_size = 0; 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci for (i = 0; i < BYTE_SET_THRESHOLD; i++) { 15418c2ecf20Sopenharmony_ci if (ws->bucket[i].count > 0) 15428c2ecf20Sopenharmony_ci byte_set_size++; 15438c2ecf20Sopenharmony_ci } 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci /* 15468c2ecf20Sopenharmony_ci * Continue collecting count of byte values in buckets. If the byte 15478c2ecf20Sopenharmony_ci * set size is bigger then the threshold, it's pointless to continue, 15488c2ecf20Sopenharmony_ci * the detection technique would fail for this type of data. 15498c2ecf20Sopenharmony_ci */ 15508c2ecf20Sopenharmony_ci for (; i < BUCKET_SIZE; i++) { 15518c2ecf20Sopenharmony_ci if (ws->bucket[i].count > 0) { 15528c2ecf20Sopenharmony_ci byte_set_size++; 15538c2ecf20Sopenharmony_ci if (byte_set_size > BYTE_SET_THRESHOLD) 15548c2ecf20Sopenharmony_ci return byte_set_size; 15558c2ecf20Sopenharmony_ci } 15568c2ecf20Sopenharmony_ci } 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_ci return byte_set_size; 15598c2ecf20Sopenharmony_ci} 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_cistatic bool sample_repeated_patterns(struct heuristic_ws *ws) 15628c2ecf20Sopenharmony_ci{ 15638c2ecf20Sopenharmony_ci const u32 half_of_sample = ws->sample_size / 2; 15648c2ecf20Sopenharmony_ci const u8 *data = ws->sample; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci return memcmp(&data[0], &data[half_of_sample], half_of_sample) == 0; 15678c2ecf20Sopenharmony_ci} 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_cistatic void heuristic_collect_sample(struct inode *inode, u64 start, u64 end, 15708c2ecf20Sopenharmony_ci struct heuristic_ws *ws) 15718c2ecf20Sopenharmony_ci{ 15728c2ecf20Sopenharmony_ci struct page *page; 15738c2ecf20Sopenharmony_ci u64 index, index_end; 15748c2ecf20Sopenharmony_ci u32 i, curr_sample_pos; 15758c2ecf20Sopenharmony_ci u8 *in_data; 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci /* 15788c2ecf20Sopenharmony_ci * Compression handles the input data by chunks of 128KiB 15798c2ecf20Sopenharmony_ci * (defined by BTRFS_MAX_UNCOMPRESSED) 15808c2ecf20Sopenharmony_ci * 15818c2ecf20Sopenharmony_ci * We do the same for the heuristic and loop over the whole range. 15828c2ecf20Sopenharmony_ci * 15838c2ecf20Sopenharmony_ci * MAX_SAMPLE_SIZE - calculated under assumption that heuristic will 15848c2ecf20Sopenharmony_ci * process no more than BTRFS_MAX_UNCOMPRESSED at a time. 15858c2ecf20Sopenharmony_ci */ 15868c2ecf20Sopenharmony_ci if (end - start > BTRFS_MAX_UNCOMPRESSED) 15878c2ecf20Sopenharmony_ci end = start + BTRFS_MAX_UNCOMPRESSED; 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci index = start >> PAGE_SHIFT; 15908c2ecf20Sopenharmony_ci index_end = end >> PAGE_SHIFT; 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci /* Don't miss unaligned end */ 15938c2ecf20Sopenharmony_ci if (!IS_ALIGNED(end, PAGE_SIZE)) 15948c2ecf20Sopenharmony_ci index_end++; 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci curr_sample_pos = 0; 15978c2ecf20Sopenharmony_ci while (index < index_end) { 15988c2ecf20Sopenharmony_ci page = find_get_page(inode->i_mapping, index); 15998c2ecf20Sopenharmony_ci in_data = kmap(page); 16008c2ecf20Sopenharmony_ci /* Handle case where the start is not aligned to PAGE_SIZE */ 16018c2ecf20Sopenharmony_ci i = start % PAGE_SIZE; 16028c2ecf20Sopenharmony_ci while (i < PAGE_SIZE - SAMPLING_READ_SIZE) { 16038c2ecf20Sopenharmony_ci /* Don't sample any garbage from the last page */ 16048c2ecf20Sopenharmony_ci if (start > end - SAMPLING_READ_SIZE) 16058c2ecf20Sopenharmony_ci break; 16068c2ecf20Sopenharmony_ci memcpy(&ws->sample[curr_sample_pos], &in_data[i], 16078c2ecf20Sopenharmony_ci SAMPLING_READ_SIZE); 16088c2ecf20Sopenharmony_ci i += SAMPLING_INTERVAL; 16098c2ecf20Sopenharmony_ci start += SAMPLING_INTERVAL; 16108c2ecf20Sopenharmony_ci curr_sample_pos += SAMPLING_READ_SIZE; 16118c2ecf20Sopenharmony_ci } 16128c2ecf20Sopenharmony_ci kunmap(page); 16138c2ecf20Sopenharmony_ci put_page(page); 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci index++; 16168c2ecf20Sopenharmony_ci } 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci ws->sample_size = curr_sample_pos; 16198c2ecf20Sopenharmony_ci} 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci/* 16228c2ecf20Sopenharmony_ci * Compression heuristic. 16238c2ecf20Sopenharmony_ci * 16248c2ecf20Sopenharmony_ci * For now is's a naive and optimistic 'return true', we'll extend the logic to 16258c2ecf20Sopenharmony_ci * quickly (compared to direct compression) detect data characteristics 16268c2ecf20Sopenharmony_ci * (compressible/uncompressible) to avoid wasting CPU time on uncompressible 16278c2ecf20Sopenharmony_ci * data. 16288c2ecf20Sopenharmony_ci * 16298c2ecf20Sopenharmony_ci * The following types of analysis can be performed: 16308c2ecf20Sopenharmony_ci * - detect mostly zero data 16318c2ecf20Sopenharmony_ci * - detect data with low "byte set" size (text, etc) 16328c2ecf20Sopenharmony_ci * - detect data with low/high "core byte" set 16338c2ecf20Sopenharmony_ci * 16348c2ecf20Sopenharmony_ci * Return non-zero if the compression should be done, 0 otherwise. 16358c2ecf20Sopenharmony_ci */ 16368c2ecf20Sopenharmony_ciint btrfs_compress_heuristic(struct inode *inode, u64 start, u64 end) 16378c2ecf20Sopenharmony_ci{ 16388c2ecf20Sopenharmony_ci struct list_head *ws_list = get_workspace(0, 0); 16398c2ecf20Sopenharmony_ci struct heuristic_ws *ws; 16408c2ecf20Sopenharmony_ci u32 i; 16418c2ecf20Sopenharmony_ci u8 byte; 16428c2ecf20Sopenharmony_ci int ret = 0; 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci ws = list_entry(ws_list, struct heuristic_ws, list); 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci heuristic_collect_sample(inode, start, end, ws); 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci if (sample_repeated_patterns(ws)) { 16498c2ecf20Sopenharmony_ci ret = 1; 16508c2ecf20Sopenharmony_ci goto out; 16518c2ecf20Sopenharmony_ci } 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci memset(ws->bucket, 0, sizeof(*ws->bucket)*BUCKET_SIZE); 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci for (i = 0; i < ws->sample_size; i++) { 16568c2ecf20Sopenharmony_ci byte = ws->sample[i]; 16578c2ecf20Sopenharmony_ci ws->bucket[byte].count++; 16588c2ecf20Sopenharmony_ci } 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ci i = byte_set_size(ws); 16618c2ecf20Sopenharmony_ci if (i < BYTE_SET_THRESHOLD) { 16628c2ecf20Sopenharmony_ci ret = 2; 16638c2ecf20Sopenharmony_ci goto out; 16648c2ecf20Sopenharmony_ci } 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci i = byte_core_set_size(ws); 16678c2ecf20Sopenharmony_ci if (i <= BYTE_CORE_SET_LOW) { 16688c2ecf20Sopenharmony_ci ret = 3; 16698c2ecf20Sopenharmony_ci goto out; 16708c2ecf20Sopenharmony_ci } 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci if (i >= BYTE_CORE_SET_HIGH) { 16738c2ecf20Sopenharmony_ci ret = 0; 16748c2ecf20Sopenharmony_ci goto out; 16758c2ecf20Sopenharmony_ci } 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci i = shannon_entropy(ws); 16788c2ecf20Sopenharmony_ci if (i <= ENTROPY_LVL_ACEPTABLE) { 16798c2ecf20Sopenharmony_ci ret = 4; 16808c2ecf20Sopenharmony_ci goto out; 16818c2ecf20Sopenharmony_ci } 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci /* 16848c2ecf20Sopenharmony_ci * For the levels below ENTROPY_LVL_HIGH, additional analysis would be 16858c2ecf20Sopenharmony_ci * needed to give green light to compression. 16868c2ecf20Sopenharmony_ci * 16878c2ecf20Sopenharmony_ci * For now just assume that compression at that level is not worth the 16888c2ecf20Sopenharmony_ci * resources because: 16898c2ecf20Sopenharmony_ci * 16908c2ecf20Sopenharmony_ci * 1. it is possible to defrag the data later 16918c2ecf20Sopenharmony_ci * 16928c2ecf20Sopenharmony_ci * 2. the data would turn out to be hardly compressible, eg. 150 byte 16938c2ecf20Sopenharmony_ci * values, every bucket has counter at level ~54. The heuristic would 16948c2ecf20Sopenharmony_ci * be confused. This can happen when data have some internal repeated 16958c2ecf20Sopenharmony_ci * patterns like "abbacbbc...". This can be detected by analyzing 16968c2ecf20Sopenharmony_ci * pairs of bytes, which is too costly. 16978c2ecf20Sopenharmony_ci */ 16988c2ecf20Sopenharmony_ci if (i < ENTROPY_LVL_HIGH) { 16998c2ecf20Sopenharmony_ci ret = 5; 17008c2ecf20Sopenharmony_ci goto out; 17018c2ecf20Sopenharmony_ci } else { 17028c2ecf20Sopenharmony_ci ret = 0; 17038c2ecf20Sopenharmony_ci goto out; 17048c2ecf20Sopenharmony_ci } 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ciout: 17078c2ecf20Sopenharmony_ci put_workspace(0, ws_list); 17088c2ecf20Sopenharmony_ci return ret; 17098c2ecf20Sopenharmony_ci} 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_ci/* 17128c2ecf20Sopenharmony_ci * Convert the compression suffix (eg. after "zlib" starting with ":") to 17138c2ecf20Sopenharmony_ci * level, unrecognized string will set the default level 17148c2ecf20Sopenharmony_ci */ 17158c2ecf20Sopenharmony_ciunsigned int btrfs_compress_str2level(unsigned int type, const char *str) 17168c2ecf20Sopenharmony_ci{ 17178c2ecf20Sopenharmony_ci unsigned int level = 0; 17188c2ecf20Sopenharmony_ci int ret; 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci if (!type) 17218c2ecf20Sopenharmony_ci return 0; 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci if (str[0] == ':') { 17248c2ecf20Sopenharmony_ci ret = kstrtouint(str + 1, 10, &level); 17258c2ecf20Sopenharmony_ci if (ret) 17268c2ecf20Sopenharmony_ci level = 0; 17278c2ecf20Sopenharmony_ci } 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci level = btrfs_compress_set_level(type, level); 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci return level; 17328c2ecf20Sopenharmony_ci} 1733