On Sat, Jul 01, 2017 at 07:56:02PM +0300, Timofey Titovets wrote: > Add a heuristic computation before compression, > for avoiding load resource heavy compression workspace, > if data are probably can't be compressed > > Signed-off-by: Timofey Titovets <nefelim...@gmail.com> > --- /dev/null > +++ b/fs/btrfs/heuristic.c
For the new heuristic-related code, please use the compression.h and .c files and don't add a new one. When we're going to add the clever heuristics, that could go to a separate file. > @@ -0,0 +1,336 @@ > +enum compression_advice btrfs_compress_heuristic(struct inode *inode, This returns enum but the caller treats it as a bool, this should be synced up. > + u64 start, u64 end) > +{ > + enum compression_advice ret = COMPRESS_COST_UNKNOWN; > + u64 input_size = end - start; > + u64 index = start >> PAGE_SHIFT; > + u64 end_index = end >> PAGE_SHIFT; > + struct page *page; > + u32 a, b, c; > + u32 offset_count, shift, sample_size; > + u8 *sample; > + u8 *input_data; > + > + /* > + * In data: 128K 64K 32K 4K > + * Sample: 4096b 3072b 2048b 1024b > + * Avoid allocating array bigger then 4kb > + */ > + if (input_size >= 96*1024) > + offset_count = 256; > + else > + offset_count = 64 + input_size/512; > + > + shift = input_size/offset_count; > + sample_size = offset_count*READ_SIZE; > + > + /* > + * speedup by copy data to sample array +30% > + * I think it's because of memcpy optimizations and > + * cpu cache hits > + */ > + sample = kmalloc(sample_size, GFP_NOFS); > + if (!sample) > + goto out; > + > + /* Read small subset of data 1024b-4096b */ > + a = 0; b = 0; > + while (index <= end_index) { > + page = find_get_page(inode->i_mapping, index); > + input_data = kmap(page); > + c = 0; > + while (c < PAGE_SIZE - READ_SIZE) { > + if (a >= input_size - READ_SIZE) > + break; > + if (b >= sample_size - READ_SIZE) > + break; > + memcpy(&sample[b], &input_data[c], READ_SIZE); > + c += shift; > + a += shift; > + b += READ_SIZE; > + } > + kunmap(page); > + put_page(page); > + index++; > + } As mentioned in the previous mail, we'll add the skeleton code only for now, which means this loop, that simply calls find_get_page, kunmap and put_page. > + > + ret = ___btrfs_compress_heuristic(sample, sample_size); > + > +out: > + kfree(sample); > + return ret; > +} > diff --git a/fs/btrfs/heuristic.h b/fs/btrfs/heuristic.h > new file mode 100644 > index 000000000000..3565a6219b2a > --- /dev/null > +++ b/fs/btrfs/heuristic.h > @@ -0,0 +1,14 @@ > +#include <linux/kernel.h> > +#include <linux/types.h> > +#include <linux/fs.h> > + > +enum compression_advice { > + COMPRESS_NONE, > + COMPRESS_COST_UNKNOWN, > + COMPRESS_COST_EASY, > + COMPRESS_COST_MEDIUM, > + COMPRESS_COST_HARD I don't find the naming good, as the cost is not easy or hard, but rather low/medium/high. Or you can rename the whole prefix if you find a better naming scheme. > +}; > + > +enum compression_advice btrfs_compress_heuristic(struct inode *inode, > + u64 start, u64 end); > diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c > index ef3c98c527c1..19654a83da36 100644 > --- a/fs/btrfs/inode.c > +++ b/fs/btrfs/inode.c > @@ -60,6 +60,7 @@ > #include "props.h" > #include "qgroup.h" > #include "dedupe.h" > +#include "heuristic.h" > > struct btrfs_iget_args { > struct btrfs_key *location; > @@ -458,16 +459,16 @@ static noinline void compress_file_range(struct inode > *inode, > unsigned long total_compressed = 0; > unsigned long total_in = 0; > int i; > - int will_compress; > + bool will_compress; Please remove this change. > int compress_type = fs_info->compress_type; > - int redirty = 0; > + bool redirty = false; And this. > inode_should_defrag(BTRFS_I(inode), start, end, end - start + 1, > SZ_16K); > > actual_end = min_t(u64, isize, end + 1); > again: > - will_compress = 0; > + will_compress = false; > nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1; > BUILD_BUG_ON((BTRFS_MAX_COMPRESSED % PAGE_SIZE) != 0); > nr_pages = min_t(unsigned long, nr_pages, > @@ -510,15 +511,6 @@ static noinline void compress_file_range(struct inode > *inode, > */ > if (inode_need_compress(inode)) { > WARN_ON(pages); > - pages = kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS); > - if (!pages) { > - /* just bail out to the uncompressed code */ > - goto cont; > - } > - > - if (BTRFS_I(inode)->force_compress) > - compress_type = BTRFS_I(inode)->force_compress; > - > /* > * we need to call clear_page_dirty_for_io on each > * page in the range. Otherwise applications with the file > @@ -529,7 +521,23 @@ static noinline void compress_file_range(struct inode > *inode, > * dirty again later on. > */ > extent_range_clear_dirty_for_io(inode, start, end); > - redirty = 1; > + redirty = true; > + > + ret = btrfs_compress_heuristic(inode, start, end); > + > + /* Heuristic say: dont try compress that */ > + if (!ret) > + goto cont; > + > + pages = kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS); > + if (!pages) { > + /* just bail out to the uncompressed code */ > + goto cont; > + } > + > + if (BTRFS_I(inode)->force_compress) > + compress_type = BTRFS_I(inode)->force_compress; > + > ret = btrfs_compress_pages(compress_type, > inode->i_mapping, start, > pages, > @@ -552,7 +560,7 @@ static noinline void compress_file_range(struct inode > *inode, > PAGE_SIZE - offset); > kunmap_atomic(kaddr); > } > - will_compress = 1; > + will_compress = true; > } > } -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html