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_* */
|
/* BTRFS_BALANCE_ARGS_* */
|
||||||
__le64 flags;
|
__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];
|
__le64 unused[7];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
|
@ -3300,6 +3300,16 @@ static int should_balance_chunk(struct btrfs_root *root,
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
bargs->limit--;
|
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;
|
return 1;
|
||||||
|
@ -3314,6 +3324,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
|
||||||
struct btrfs_device *device;
|
struct btrfs_device *device;
|
||||||
u64 old_size;
|
u64 old_size;
|
||||||
u64 size_to_free;
|
u64 size_to_free;
|
||||||
|
u64 chunk_type;
|
||||||
struct btrfs_chunk *chunk;
|
struct btrfs_chunk *chunk;
|
||||||
struct btrfs_path *path;
|
struct btrfs_path *path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
|
@ -3324,9 +3335,13 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
|
||||||
int ret;
|
int ret;
|
||||||
int enospc_errors = 0;
|
int enospc_errors = 0;
|
||||||
bool counting = true;
|
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_data = bctl->data.limit;
|
||||||
u64 limit_meta = bctl->meta.limit;
|
u64 limit_meta = bctl->meta.limit;
|
||||||
u64 limit_sys = bctl->sys.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 */
|
/* step one make some room on all the devices */
|
||||||
devices = &fs_info->fs_devices->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);
|
spin_unlock(&fs_info->balance_lock);
|
||||||
again:
|
again:
|
||||||
if (!counting) {
|
if (!counting) {
|
||||||
|
/*
|
||||||
|
* The single value limit and min/max limits use the same bytes
|
||||||
|
* in the
|
||||||
|
*/
|
||||||
bctl->data.limit = limit_data;
|
bctl->data.limit = limit_data;
|
||||||
bctl->meta.limit = limit_meta;
|
bctl->meta.limit = limit_meta;
|
||||||
bctl->sys.limit = limit_sys;
|
bctl->sys.limit = limit_sys;
|
||||||
|
@ -3414,6 +3433,7 @@ again:
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
|
chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
|
||||||
|
chunk_type = btrfs_chunk_type(leaf, chunk);
|
||||||
|
|
||||||
if (!counting) {
|
if (!counting) {
|
||||||
spin_lock(&fs_info->balance_lock);
|
spin_lock(&fs_info->balance_lock);
|
||||||
|
@ -3434,6 +3454,28 @@ again:
|
||||||
spin_lock(&fs_info->balance_lock);
|
spin_lock(&fs_info->balance_lock);
|
||||||
bctl->stat.expected++;
|
bctl->stat.expected++;
|
||||||
spin_unlock(&fs_info->balance_lock);
|
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;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -380,6 +380,7 @@ struct map_lookup {
|
||||||
#define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3)
|
#define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3)
|
||||||
#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4)
|
#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4)
|
||||||
#define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5)
|
#define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5)
|
||||||
|
#define BTRFS_BALANCE_ARGS_LIMIT_RANGE (1ULL << 6)
|
||||||
|
|
||||||
#define BTRFS_BALANCE_ARGS_MASK \
|
#define BTRFS_BALANCE_ARGS_MASK \
|
||||||
(BTRFS_BALANCE_ARGS_PROFILES | \
|
(BTRFS_BALANCE_ARGS_PROFILES | \
|
||||||
|
|
|
@ -217,7 +217,18 @@ struct btrfs_balance_args {
|
||||||
|
|
||||||
__u64 flags;
|
__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];
|
__u64 unused[7];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue