diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index bb374042d..e1603e1cf 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -67,7 +67,7 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, btrfs_set_file_extent_ram_bytes(leaf, item, ram_bytes); btrfs_set_file_extent_generation(leaf, item, trans->transid); btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG); - btrfs_set_file_extent_compression(leaf, item, compression); + btrfs_set_file_extent_compression(leaf, item, compression & 0xF); btrfs_set_file_extent_encryption(leaf, item, encryption); btrfs_set_file_extent_other_encoding(leaf, item, other_encoding); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index dbc9bcaf5..3285d4bd3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -227,7 +227,7 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, compressed_size -= cur_size; } btrfs_set_file_extent_compression(leaf, ei, - compress_type); + compress_type & 0XF); } else { page = find_get_page(inode->i_mapping, start >> PAGE_SHIFT); @@ -573,14 +573,31 @@ static noinline int compress_file_range(struct async_chunk *async_chunk) } /* Compression level is applied here and only here */ - ret = btrfs_compress_pages( - compress_type | (fs_info->compress_level << 4), - inode->i_mapping, start, - pages, - &nr_pages, - &total_in, - &total_compressed); - + /* + * Check if the upper bits are set, and if so, + * take them as the compression level. + * the inode compression level takes precendence, if set + */ + if ((compress_type & 0xF) == compress_type) { + ret = btrfs_compress_pages( + compress_type | (fs_info->compress_level << 4), + inode->i_mapping, start, + pages, + &nr_pages, + &total_in, + &total_compressed); + } else { + int compress_level = btrfs_compress_set_level( + compress_type & 0xF, + compress_type>>4); + ret = btrfs_compress_pages( + compress_type | (compress_level << 4), + inode->i_mapping, start, + pages, + &nr_pages, + &total_in, + &total_compressed); + } if (!ret) { unsigned long offset = offset_in_page(total_compressed); struct page *page = pages[nr_pages - 1]; @@ -2362,7 +2379,7 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, btrfs_set_file_extent_offset(leaf, fi, 0); btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes); btrfs_set_file_extent_ram_bytes(leaf, fi, ram_bytes); - btrfs_set_file_extent_compression(leaf, fi, compression); + btrfs_set_file_extent_compression(leaf, fi, compression & 0xF); btrfs_set_file_extent_encryption(leaf, fi, encryption); btrfs_set_file_extent_other_encoding(leaf, fi, other_encoding); diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 0fa1c386d..2a9c1f312 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1414,7 +1414,11 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, return -EINVAL; if (do_compress) { - if (range->compress_type >= BTRFS_NR_COMPRESS_TYPES) + /* + * The bottom 4 bits of compress_type are for used for the + * compression type, the other bits for the compression level + */ + if ((range->compress_type & 0xF) >= BTRFS_NR_COMPRESS_TYPES) return -EINVAL; if (range->compress_type) compress_type = range->compress_type; @@ -1572,9 +1576,9 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, filemap_flush(inode->i_mapping); } - if (range->compress_type == BTRFS_COMPRESS_LZO) { + if ((range->compress_type & 0xF) == BTRFS_COMPRESS_LZO) { btrfs_set_fs_incompat(fs_info, COMPRESS_LZO); - } else if (range->compress_type == BTRFS_COMPRESS_ZSTD) { + } else if ((range->compress_type & 0xF) == BTRFS_COMPRESS_ZSTD) { btrfs_set_fs_incompat(fs_info, COMPRESS_ZSTD); }