diff options
author | David Sterba <dsterba@suse.com> | 2015-10-10 11:16:50 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-10-26 22:38:28 -0400 |
commit | 12907fc79818a62a2478f84f7795afa774bf7f9c (patch) | |
tree | c7df6fd783c99feef090a00c38e7268515488430 | |
parent | 2849a854224487bc578b73b64422c3cb3ef93ff5 (diff) |
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>
-rw-r--r-- | fs/btrfs/ctree.h | 14 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 42 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/btrfs.h | 13 |
4 files changed, 67 insertions, 3 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 3fa3c3b7bb66..460cd69b405e 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -846,8 +846,18 @@ struct btrfs_disk_balance_args { | |||
846 | /* BTRFS_BALANCE_ARGS_* */ | 846 | /* BTRFS_BALANCE_ARGS_* */ |
847 | __le64 flags; | 847 | __le64 flags; |
848 | 848 | ||
849 | /* BTRFS_BALANCE_ARGS_LIMIT value */ | 849 | /* |
850 | __le64 limit; | 850 | * BTRFS_BALANCE_ARGS_LIMIT with value 'limit' |
851 | * BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum | ||
852 | * and maximum | ||
853 | */ | ||
854 | union { | ||
855 | __le64 limit; | ||
856 | struct { | ||
857 | __le32 limit_min; | ||
858 | __le32 limit_max; | ||
859 | }; | ||
860 | }; | ||
851 | 861 | ||
852 | __le64 unused[7]; | 862 | __le64 unused[7]; |
853 | } __attribute__ ((__packed__)); | 863 | } __attribute__ ((__packed__)); |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index f86d83805b44..e2fdd2e01104 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -3300,6 +3300,16 @@ static int should_balance_chunk(struct btrfs_root *root, | |||
3300 | return 0; | 3300 | return 0; |
3301 | else | 3301 | else |
3302 | bargs->limit--; | 3302 | bargs->limit--; |
3303 | } else if ((bargs->flags & BTRFS_BALANCE_ARGS_LIMIT_RANGE)) { | ||
3304 | /* | ||
3305 | * Same logic as the 'limit' filter; the minimum cannot be | ||
3306 | * determined here because we do not have the global informatoin | ||
3307 | * about the count of all chunks that satisfy the filters. | ||
3308 | */ | ||
3309 | if (bargs->limit_max == 0) | ||
3310 | return 0; | ||
3311 | else | ||
3312 | bargs->limit_max--; | ||
3303 | } | 3313 | } |
3304 | 3314 | ||
3305 | return 1; | 3315 | return 1; |
@@ -3314,6 +3324,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info) | |||
3314 | struct btrfs_device *device; | 3324 | struct btrfs_device *device; |
3315 | u64 old_size; | 3325 | u64 old_size; |
3316 | u64 size_to_free; | 3326 | u64 size_to_free; |
3327 | u64 chunk_type; | ||
3317 | struct btrfs_chunk *chunk; | 3328 | struct btrfs_chunk *chunk; |
3318 | struct btrfs_path *path; | 3329 | struct btrfs_path *path; |
3319 | struct btrfs_key key; | 3330 | struct btrfs_key key; |
@@ -3324,9 +3335,13 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info) | |||
3324 | int ret; | 3335 | int ret; |
3325 | int enospc_errors = 0; | 3336 | int enospc_errors = 0; |
3326 | bool counting = true; | 3337 | bool counting = true; |
3338 | /* The single value limit and min/max limits use the same bytes in the */ | ||
3327 | u64 limit_data = bctl->data.limit; | 3339 | u64 limit_data = bctl->data.limit; |
3328 | u64 limit_meta = bctl->meta.limit; | 3340 | u64 limit_meta = bctl->meta.limit; |
3329 | u64 limit_sys = bctl->sys.limit; | 3341 | u64 limit_sys = bctl->sys.limit; |
3342 | u32 count_data = 0; | ||
3343 | u32 count_meta = 0; | ||
3344 | u32 count_sys = 0; | ||
3330 | 3345 | ||
3331 | /* step one make some room on all the devices */ | 3346 | /* step one make some room on all the devices */ |
3332 | devices = &fs_info->fs_devices->devices; | 3347 | devices = &fs_info->fs_devices->devices; |
@@ -3367,6 +3382,10 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info) | |||
3367 | spin_unlock(&fs_info->balance_lock); | 3382 | spin_unlock(&fs_info->balance_lock); |
3368 | again: | 3383 | again: |
3369 | if (!counting) { | 3384 | if (!counting) { |
3385 | /* | ||
3386 | * The single value limit and min/max limits use the same bytes | ||
3387 | * in the | ||
3388 | */ | ||
3370 | bctl->data.limit = limit_data; | 3389 | bctl->data.limit = limit_data; |
3371 | bctl->meta.limit = limit_meta; | 3390 | bctl->meta.limit = limit_meta; |
3372 | bctl->sys.limit = limit_sys; | 3391 | bctl->sys.limit = limit_sys; |
@@ -3414,6 +3433,7 @@ again: | |||
3414 | } | 3433 | } |
3415 | 3434 | ||
3416 | chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); | 3435 | chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); |
3436 | chunk_type = btrfs_chunk_type(leaf, chunk); | ||
3417 | 3437 | ||
3418 | if (!counting) { | 3438 | if (!counting) { |
3419 | spin_lock(&fs_info->balance_lock); | 3439 | spin_lock(&fs_info->balance_lock); |
@@ -3434,6 +3454,28 @@ again: | |||
3434 | spin_lock(&fs_info->balance_lock); | 3454 | spin_lock(&fs_info->balance_lock); |
3435 | bctl->stat.expected++; | 3455 | bctl->stat.expected++; |
3436 | spin_unlock(&fs_info->balance_lock); | 3456 | spin_unlock(&fs_info->balance_lock); |
3457 | |||
3458 | if (chunk_type & BTRFS_BLOCK_GROUP_DATA) | ||
3459 | count_data++; | ||
3460 | else if (chunk_type & BTRFS_BLOCK_GROUP_SYSTEM) | ||
3461 | count_sys++; | ||
3462 | else if (chunk_type & BTRFS_BLOCK_GROUP_METADATA) | ||
3463 | count_meta++; | ||
3464 | |||
3465 | goto loop; | ||
3466 | } | ||
3467 | |||
3468 | /* | ||
3469 | * Apply limit_min filter, no need to check if the LIMITS | ||
3470 | * filter is used, limit_min is 0 by default | ||
3471 | */ | ||
3472 | if (((chunk_type & BTRFS_BLOCK_GROUP_DATA) && | ||
3473 | count_data < bctl->data.limit_min) | ||
3474 | || ((chunk_type & BTRFS_BLOCK_GROUP_METADATA) && | ||
3475 | count_meta < bctl->meta.limit_min) | ||
3476 | || ((chunk_type & BTRFS_BLOCK_GROUP_SYSTEM) && | ||
3477 | count_sys < bctl->sys.limit_min)) { | ||
3478 | mutex_unlock(&fs_info->delete_unused_bgs_mutex); | ||
3437 | goto loop; | 3479 | goto loop; |
3438 | } | 3480 | } |
3439 | 3481 | ||
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index b8e64ea984f1..628d4e17019d 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -380,6 +380,7 @@ struct map_lookup { | |||
380 | #define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3) | 380 | #define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3) |
381 | #define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4) | 381 | #define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4) |
382 | #define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5) | 382 | #define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5) |
383 | #define BTRFS_BALANCE_ARGS_LIMIT_RANGE (1ULL << 6) | ||
383 | 384 | ||
384 | #define BTRFS_BALANCE_ARGS_MASK \ | 385 | #define BTRFS_BALANCE_ARGS_MASK \ |
385 | (BTRFS_BALANCE_ARGS_PROFILES | \ | 386 | (BTRFS_BALANCE_ARGS_PROFILES | \ |
diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index b6dec05c7196..11f13108b78b 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h | |||
@@ -217,7 +217,18 @@ struct btrfs_balance_args { | |||
217 | 217 | ||
218 | __u64 flags; | 218 | __u64 flags; |
219 | 219 | ||
220 | __u64 limit; /* limit number of processed chunks */ | 220 | /* |
221 | * BTRFS_BALANCE_ARGS_LIMIT with value 'limit' | ||
222 | * BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum | ||
223 | * and maximum | ||
224 | */ | ||
225 | union { | ||
226 | __u64 limit; /* limit number of processed chunks */ | ||
227 | struct { | ||
228 | __u32 limit_min; | ||
229 | __u32 limit_max; | ||
230 | }; | ||
231 | }; | ||
221 | __u64 unused[7]; | 232 | __u64 unused[7]; |
222 | } __attribute__ ((__packed__)); | 233 | } __attribute__ ((__packed__)); |
223 | 234 | ||