mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 17:57:38 -04:00
btrfs: defrag: extend ioctl to accept compression levels
The zstd and zlib compression types support setting compression levels. Enhance the defrag interface to specify the levels as well. For zstd the negative (realtime) levels are also accepted. Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Daniel Vacek <neelx@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
committed by
David Sterba
parent
08f340767d
commit
fc5c0c5825
@@ -145,6 +145,7 @@ struct btrfs_inode {
|
||||
* different from prop_compress and takes precedence if set.
|
||||
*/
|
||||
u8 defrag_compress;
|
||||
s8 defrag_compress_level;
|
||||
|
||||
/*
|
||||
* Lock for counters and all fields used to determine if the inode is in
|
||||
|
||||
@@ -980,6 +980,16 @@ static int btrfs_compress_set_level(unsigned int type, int level)
|
||||
return level;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the @level is within the valid range for the given type.
|
||||
*/
|
||||
bool btrfs_compress_level_valid(unsigned int type, int level)
|
||||
{
|
||||
const struct btrfs_compress_op *ops = btrfs_compress_op[type];
|
||||
|
||||
return ops->min_level <= level && level <= ops->max_level;
|
||||
}
|
||||
|
||||
/* Wrapper around find_get_page(), with extra error message. */
|
||||
int btrfs_compress_filemap_get_folio(struct address_space *mapping, u64 start,
|
||||
struct folio **in_folio_ret)
|
||||
|
||||
@@ -83,6 +83,7 @@ static inline u32 btrfs_calc_input_length(u64 range_end, u64 cur)
|
||||
int __init btrfs_init_compress(void);
|
||||
void __cold btrfs_exit_compress(void);
|
||||
|
||||
bool btrfs_compress_level_valid(unsigned int type, int level);
|
||||
int btrfs_compress_folios(unsigned int type, int level, struct address_space *mapping,
|
||||
u64 start, struct folio **folios, unsigned long *out_folios,
|
||||
unsigned long *total_in, unsigned long *total_out);
|
||||
|
||||
@@ -1363,6 +1363,7 @@ int btrfs_defrag_file(struct btrfs_inode *inode, struct file_ra_state *ra,
|
||||
u64 last_byte;
|
||||
bool do_compress = (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS);
|
||||
int compress_type = BTRFS_COMPRESS_ZLIB;
|
||||
int compress_level = 0;
|
||||
int ret = 0;
|
||||
u32 extent_thresh = range->extent_thresh;
|
||||
pgoff_t start_index;
|
||||
@@ -1376,10 +1377,21 @@ int btrfs_defrag_file(struct btrfs_inode *inode, struct file_ra_state *ra,
|
||||
return -EINVAL;
|
||||
|
||||
if (do_compress) {
|
||||
if (range->compress_type >= BTRFS_NR_COMPRESS_TYPES)
|
||||
return -EINVAL;
|
||||
if (range->compress_type)
|
||||
compress_type = range->compress_type;
|
||||
if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS_LEVEL) {
|
||||
if (range->compress.type >= BTRFS_NR_COMPRESS_TYPES)
|
||||
return -EINVAL;
|
||||
if (range->compress.type) {
|
||||
compress_type = range->compress.type;
|
||||
compress_level = range->compress.level;
|
||||
if (!btrfs_compress_level_valid(compress_type, compress_level))
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if (range->compress_type >= BTRFS_NR_COMPRESS_TYPES)
|
||||
return -EINVAL;
|
||||
if (range->compress_type)
|
||||
compress_type = range->compress_type;
|
||||
}
|
||||
}
|
||||
|
||||
if (extent_thresh == 0)
|
||||
@@ -1430,8 +1442,10 @@ int btrfs_defrag_file(struct btrfs_inode *inode, struct file_ra_state *ra,
|
||||
btrfs_inode_unlock(inode, 0);
|
||||
break;
|
||||
}
|
||||
if (do_compress)
|
||||
if (do_compress) {
|
||||
inode->defrag_compress = compress_type;
|
||||
inode->defrag_compress_level = compress_level;
|
||||
}
|
||||
ret = defrag_one_cluster(inode, ra, cur,
|
||||
cluster_end + 1 - cur, extent_thresh,
|
||||
newer_than, do_compress, §ors_defragged,
|
||||
|
||||
@@ -497,7 +497,7 @@ struct btrfs_fs_info {
|
||||
u64 last_trans_log_full_commit;
|
||||
unsigned long long mount_opt;
|
||||
|
||||
unsigned long compress_type:4;
|
||||
int compress_type;
|
||||
int compress_level;
|
||||
u32 commit_interval;
|
||||
/*
|
||||
|
||||
@@ -877,6 +877,7 @@ static void compress_file_range(struct btrfs_work *work)
|
||||
unsigned int poff;
|
||||
int i;
|
||||
int compress_type = fs_info->compress_type;
|
||||
int compress_level = fs_info->compress_level;
|
||||
|
||||
inode_should_defrag(inode, start, end, end - start + 1, SZ_16K);
|
||||
|
||||
@@ -959,13 +960,15 @@ static void compress_file_range(struct btrfs_work *work)
|
||||
goto cleanup_and_bail_uncompressed;
|
||||
}
|
||||
|
||||
if (inode->defrag_compress)
|
||||
if (inode->defrag_compress) {
|
||||
compress_type = inode->defrag_compress;
|
||||
else if (inode->prop_compress)
|
||||
compress_level = inode->defrag_compress_level;
|
||||
} else if (inode->prop_compress) {
|
||||
compress_type = inode->prop_compress;
|
||||
}
|
||||
|
||||
/* Compression level is applied here. */
|
||||
ret = btrfs_compress_folios(compress_type, fs_info->compress_level,
|
||||
ret = btrfs_compress_folios(compress_type, compress_level,
|
||||
mapping, start, folios, &nr_folios, &total_in,
|
||||
&total_compressed);
|
||||
if (ret)
|
||||
|
||||
@@ -615,7 +615,9 @@ struct btrfs_ioctl_clone_range_args {
|
||||
*/
|
||||
#define BTRFS_DEFRAG_RANGE_COMPRESS 1
|
||||
#define BTRFS_DEFRAG_RANGE_START_IO 2
|
||||
#define BTRFS_DEFRAG_RANGE_COMPRESS_LEVEL 4
|
||||
#define BTRFS_DEFRAG_RANGE_FLAGS_SUPP (BTRFS_DEFRAG_RANGE_COMPRESS | \
|
||||
BTRFS_DEFRAG_RANGE_COMPRESS_LEVEL | \
|
||||
BTRFS_DEFRAG_RANGE_START_IO)
|
||||
|
||||
struct btrfs_ioctl_defrag_range_args {
|
||||
@@ -640,10 +642,18 @@ struct btrfs_ioctl_defrag_range_args {
|
||||
|
||||
/*
|
||||
* which compression method to use if turning on compression
|
||||
* for this defrag operation. If unspecified, zlib will
|
||||
* be used
|
||||
* for this defrag operation. If unspecified, zlib will be
|
||||
* used. If compression level is also being specified, set the
|
||||
* BTRFS_DEFRAG_RANGE_COMPRESS_LEVEL flag and fill the compress
|
||||
* member structure instead of the compress_type field.
|
||||
*/
|
||||
__u32 compress_type;
|
||||
union {
|
||||
__u32 compress_type;
|
||||
struct {
|
||||
__u8 type;
|
||||
__s8 level;
|
||||
} compress;
|
||||
};
|
||||
|
||||
/* spare for later */
|
||||
__u32 unused[4];
|
||||
|
||||
Reference in New Issue
Block a user