btrfs: extend balance filter limit to take minimum and maximum
The 'limit' filter is underdesigned, it should have been a range for [min,max], with some relaxed semantics when one of the bounds is missing. Besides that, using a full u64 for a single value is a waste of bytes. Let's fix both by extending the use of the u64 bytes for the [min,max] range. This can be done in a backward compatible way, the range will be interpreted only if the appropriate flag is set (BTRFS_BALANCE_ARGS_LIMIT_RANGE). Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
This commit is contained in:
parent
2849a85422
commit
12907fc798
|
@ -846,8 +846,18 @@ struct btrfs_disk_balance_args {
|
|||
/* BTRFS_BALANCE_ARGS_* */
|
||||
__le64 flags;
|
||||
|
||||
/* BTRFS_BALANCE_ARGS_LIMIT value */
|
||||
__le64 limit;
|
||||
/*
|
||||
* BTRFS_BALANCE_ARGS_LIMIT with value 'limit'
|
||||
* BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum
|
||||
* and maximum
|
||||
*/
|
||||
union {
|
||||
__le64 limit;
|
||||
struct {
|
||||
__le32 limit_min;
|
||||
__le32 limit_max;
|
||||
};
|
||||
};
|
||||
|
||||
__le64 unused[7];
|
||||
} __attribute__ ((__packed__));
|
||||
|
|
|
@ -3300,6 +3300,16 @@ static int should_balance_chunk(struct btrfs_root *root,
|
|||
return 0;
|
||||
else
|
||||
bargs->limit--;
|
||||
} else if ((bargs->flags & BTRFS_BALANCE_ARGS_LIMIT_RANGE)) {
|
||||
/*
|
||||
* Same logic as the 'limit' filter; the minimum cannot be
|
||||
* determined here because we do not have the global informatoin
|
||||
* about the count of all chunks that satisfy the filters.
|
||||
*/
|
||||
if (bargs->limit_max == 0)
|
||||
return 0;
|
||||
else
|
||||
bargs->limit_max--;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -3314,6 +3324,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
|
|||
struct btrfs_device *device;
|
||||
u64 old_size;
|
||||
u64 size_to_free;
|
||||
u64 chunk_type;
|
||||
struct btrfs_chunk *chunk;
|
||||
struct btrfs_path *path;
|
||||
struct btrfs_key key;
|
||||
|
@ -3324,9 +3335,13 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
|
|||
int ret;
|
||||
int enospc_errors = 0;
|
||||
bool counting = true;
|
||||
/* The single value limit and min/max limits use the same bytes in the */
|
||||
u64 limit_data = bctl->data.limit;
|
||||
u64 limit_meta = bctl->meta.limit;
|
||||
u64 limit_sys = bctl->sys.limit;
|
||||
u32 count_data = 0;
|
||||
u32 count_meta = 0;
|
||||
u32 count_sys = 0;
|
||||
|
||||
/* step one make some room on all the devices */
|
||||
devices = &fs_info->fs_devices->devices;
|
||||
|
@ -3367,6 +3382,10 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
|
|||
spin_unlock(&fs_info->balance_lock);
|
||||
again:
|
||||
if (!counting) {
|
||||
/*
|
||||
* The single value limit and min/max limits use the same bytes
|
||||
* in the
|
||||
*/
|
||||
bctl->data.limit = limit_data;
|
||||
bctl->meta.limit = limit_meta;
|
||||
bctl->sys.limit = limit_sys;
|
||||
|
@ -3414,6 +3433,7 @@ again:
|
|||
}
|
||||
|
||||
chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
|
||||
chunk_type = btrfs_chunk_type(leaf, chunk);
|
||||
|
||||
if (!counting) {
|
||||
spin_lock(&fs_info->balance_lock);
|
||||
|
@ -3434,6 +3454,28 @@ again:
|
|||
spin_lock(&fs_info->balance_lock);
|
||||
bctl->stat.expected++;
|
||||
spin_unlock(&fs_info->balance_lock);
|
||||
|
||||
if (chunk_type & BTRFS_BLOCK_GROUP_DATA)
|
||||
count_data++;
|
||||
else if (chunk_type & BTRFS_BLOCK_GROUP_SYSTEM)
|
||||
count_sys++;
|
||||
else if (chunk_type & BTRFS_BLOCK_GROUP_METADATA)
|
||||
count_meta++;
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply limit_min filter, no need to check if the LIMITS
|
||||
* filter is used, limit_min is 0 by default
|
||||
*/
|
||||
if (((chunk_type & BTRFS_BLOCK_GROUP_DATA) &&
|
||||
count_data < bctl->data.limit_min)
|
||||
|| ((chunk_type & BTRFS_BLOCK_GROUP_METADATA) &&
|
||||
count_meta < bctl->meta.limit_min)
|
||||
|| ((chunk_type & BTRFS_BLOCK_GROUP_SYSTEM) &&
|
||||
count_sys < bctl->sys.limit_min)) {
|
||||
mutex_unlock(&fs_info->delete_unused_bgs_mutex);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
|
|
|
@ -380,6 +380,7 @@ struct map_lookup {
|
|||
#define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3)
|
||||
#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4)
|
||||
#define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5)
|
||||
#define BTRFS_BALANCE_ARGS_LIMIT_RANGE (1ULL << 6)
|
||||
|
||||
#define BTRFS_BALANCE_ARGS_MASK \
|
||||
(BTRFS_BALANCE_ARGS_PROFILES | \
|
||||
|
|
|
@ -217,7 +217,18 @@ struct btrfs_balance_args {
|
|||
|
||||
__u64 flags;
|
||||
|
||||
__u64 limit; /* limit number of processed chunks */
|
||||
/*
|
||||
* BTRFS_BALANCE_ARGS_LIMIT with value 'limit'
|
||||
* BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum
|
||||
* and maximum
|
||||
*/
|
||||
union {
|
||||
__u64 limit; /* limit number of processed chunks */
|
||||
struct {
|
||||
__u32 limit_min;
|
||||
__u32 limit_max;
|
||||
};
|
||||
};
|
||||
__u64 unused[7];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
|
|
Loading…
Reference in a new issue