Btrfs-progs, balance filters: stripes, limits
Subsystems (2)
David Sterba
maintainerv2 cover Btrfs-progs, balance filters: stripes, limits
An updated version that actually works.
David Sterba (7):
btrfs-progs: cleanup and comment parse_range
btrfs-progs: do not modify the string in parse_range
btrfs-progs: extend parse_range API to accept a relaxed range
btrfs-progs: add helpers for parsing 32bit ranges
btrfs-progs: add helpers to print ranges
btrfs-progs: extend balance args to take min/max limit filter
btrfs-progs: balance: enhance the limit fiter with range
Gabríel Arthúr Pétursson (1):
btrfs-progs: balance: add stripes filter
Documentation/btrfs-balance.asciidoc | 8 ++ cmds-balance.c | 167 +++++++++++++++++++++++++++++------ ioctl.h | 17 +++- volumes.h | 2 + 4 files changed, 164 insertions(+), 30 deletions(-)
Signature · 1 line
2.6.1
David Sterba
maintainerPATCH v2 1/8 btrfs-progs: cleanup and comment parse_range
Simplify a check and unindent some code.
--- cmds-balance.c | 63 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 26 deletions(-)
cmds-balance.c +37 -26
@@ -88,43 +88,54 @@ static int parse_u64(const char *str, u64 *result)return 0 ; } +/* +* Parse range that's missing some part that can be implicit: +* a..b - exact range, a can be equal to b +* a.. - implicitly unbounded maximum (end == (u64)-1) +* ..b - implicitly starting at 0 +* a - invalid; unclear semantics, use parse_u64 instead +* +* Returned values are u64, value validation and interpretation should be done +* by the caller. +*/ static int parse_range (const char *range,u64 *start,u64 *end) {char *dots; +const char *rest; +int skipped =0 ; dots =strstr (range,".." ); -if (dots) { -const char *rest = dots +2 ; -int skipped =0 ; - - *dots =0 ; +if (!dots) +return 1 ; -if (!*rest) { - *end = (u64)-1 ; - skipped++; - }else { -if (parse_u64 (rest, end)) -return 1 ; - } -if (dots == range) { - *start =0 ; - skipped++; - }else { -if (parse_u64 (range, start)) -return 1 ; - } + rest = dots +2 ; + *dots =0 ; -if (*start >= *end) { -fprintf (stderr,"Range %llu..%llu doesn't make " -"sense\n" , (unsigned long long )*start, - (unsigned long long )*end); +if (!*rest) { + *end = (u64)-1 ; + skipped++; + }else { +if (parse_u64 (rest, end))return 1 ; - } + } +if (dots == range) { + *start =0 ; + skipped++; + }else { +if (parse_u64 (range, start)) +return 1 ; + } -if (skipped <=1 ) -return 0 ; +if (*start >= *end) { +fprintf (stderr,"Range %llu..%llu doesn't make " +"sense\n" , (unsigned long long )*start, + (unsigned long long )*end); +return 1 ; } +if (skipped <=1 ) +return 0 ; +return 1 ; }
Signature · 1 line
2.6.1
David Sterba
maintainerPATCH v2 2/8 btrfs-progs: do not modify the string in parse_range
In reply to David SterbaIt's passed as const but we modify it through 'dots'. This would break parsing the string multiple times.
--- cmds-balance.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
cmds-balance.c +5 -3
@@ -101,6 +101,7 @@ static int parse_u64(const char *str, u64 *result)static int parse_range (const char *range,u64 *start,u64 *end) {char *dots; +char *endptr;const char *rest;int skipped =0 ;
@@ -109,20 +110,21 @@ static int parse_range(const char *range, u64 *start, u64 *end)return 1 ; rest = dots +2 ; - *dots =0 ;if (!*rest) { *end = (u64)-1 ; skipped++; }else { -if (parse_u64 (rest, end)) + *end =strtoull (rest, &endptr,10 ); +if (*endptr)return 1 ; }if (dots == range) { *start =0 ; skipped++; }else { -if (parse_u64 (range, start)) + *end =strtoull (range, &endptr,10 ); +if (*endptr !=0 && *endptr !='.' )return 1 ; }
Signature · 1 line
2.6.1
David Sterba
maintainerPATCH v2 3/8 btrfs-progs: extend parse_range API to accept a relaxed range
In reply to David SterbaIn some cases we want to accept a range of type [a..a]. Add a new function to do the 'a < b' check for the caller and use it.
--- cmds-balance.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-)
cmds-balance.c +25 -5
@@ -128,9 +128,10 @@ static int parse_range(const char *range, u64 *start, u64 *end)return 1 ; } -if (*start >= *end) { -fprintf (stderr,"Range %llu..%llu doesn't make " -"sense\n" , (unsigned long long )*start, +if (*start > *end) { +fprintf (stderr, +"ERROR: range %llu..%llu doesn't make sense\n" , + (unsigned long long )*start, (unsigned long long )*end);return 1 ; }
@@ -141,6 +142,25 @@ static int parse_range(const char *range, u64 *start, u64 *end)return 1 ; } +/* +* Parse range and check if start < end +*/ +static int parse_range_strict (const char *range,u64 *start,u64 *end) +{ +if (parse_range (range, start, end) ==0 ) { +if (*start >= *end) { +fprintf (stderr, +"ERROR: range %llu..%llu not allowed\n" , + (unsigned long long )*start, + (unsigned long long )*end); +return 1 ; + } +return 0 ; + } + +return 1 ; +} +static int parse_filters (char *filters,struct btrfs_balance_args *args) {char *this_char;
@@ -198,7 +218,7 @@ static int parse_filters(char *filters, struct btrfs_balance_args *args) "an argument\n");return 1 ; } -if (parse_range (value, &args->pstart, &args->pend)) { +if (parse_range_strict (value, &args->pstart, &args->pend)) {fprintf (stderr,"Invalid drange argument\n" );return 1 ; }
@@ -209,7 +229,7 @@ static int parse_filters(char *filters, struct btrfs_balance_args *args) "an argument\n");return 1 ; } -if (parse_range (value, &args->vstart, &args->vend)) { +if (parse_range_strict (value, &args->vstart, &args->vend)) {fprintf (stderr,"Invalid vrange argument\n" );return 1 ; }
Signature · 1 line
2.6.1
David Sterba
maintainerPATCH v2 4/8 btrfs-progs: add helpers for parsing 32bit ranges
In reply to David Sterba--- cmds-balance.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
cmds-balance.c +31 -0
@@ -161,6 +161,37 @@ static int parse_range_strict(const char *range, u64 *start, u64 *end)return 1 ; } +/* +* Convert 64bit range to 32bit with boundary checkso +*/ +static int range_to_u32 (u64 start,u64 end,u32 *start32,u32 *end32) +{ +if (start > (u32)-1 ) +return 1 ; + +if (end != (u64)-1 && end > (u32)-1 ) +return 1 ; + + *start32 = (u32 )start; + *end32 = (u32 )end; + +return 0 ; +} + +static int parse_range_u32 (const char *range,u32 *start,u32 *end) +{ +u64 tmp_start; +u64 tmp_end; + +if (parse_range (range, &tmp_start, &tmp_end)) +return 1 ; + +if (range_to_u32 (tmp_start, tmp_end, start, end)) +return 1 ; + +return 0 ; +} +static int parse_filters (char *filters,struct btrfs_balance_args *args) {char *this_char;
Signature · 1 line
2.6.1
David Sterba
maintainerPATCH v2 5/8 btrfs-progs: add helpers to print ranges
In reply to David Sterba--- cmds-balance.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
cmds-balance.c +19 -0
@@ -192,6 +192,25 @@ static int parse_range_u32(const char *range, u32 *start, u32 *end)return 0 ; } +__attribute__ ((unused)) +static void print_range (u64 start,u64 end) +{ +if (start) +printf ("%llu" , (unsigned long long )start); +printf (".." ); +if (end != (u64)-1 ) +printf ("%llu" , (unsigned long long )end); +} + +static void print_range_u32 (u32 start,u32 end) +{ +if (start) +printf ("%u" , start); +printf (".." ); +if (end != (u32)-1 ) +printf ("%u" , end); +} +static int parse_filters (char *filters,struct btrfs_balance_args *args) {char *this_char;
Signature · 1 line
2.6.1
David Sterba
maintainerPATCH v2 6/8 btrfs-progs: extend balance args to take min/max limit filter
In reply to David SterbaAdd the overlapping limit and [limit_min, limit_max] members to the balance args. The min/max values are interpreted iff the corresponding flag BTRFS_BALANCE_ARGS_LIMITS is set.
Note that the values are only 32bit, but this should be enough for the foreseeable future.
--- Documentation/btrfs-balance.asciidoc | 4 ++++ cmds-balance.c | 4 ++++ ioctl.h | 13 ++++++++++++- volumes.h | 1 + 4 files changed, 21 insertions(+), 1 deletion(-)
Documentation/btrfs-balance.asciidoc +4 -0
@@ -109,6 +109,10 @@ parameters. Process only given number of chunks, after all filters apply. This can be used to specifically target a chunk in connection with other filters (drange, vrange) or just simply limit the amount of work done by a single balance run. ++ +The argument may be a single value or a range. The single value *N* means *at +most N chunks*, equivalent to *..N* range syntax. Kernels prior to 4.4 accept +only the single value format. *soft*:: Takes no parameters. Only has meaning when converting between profiles.
cmds-balance.c +4 -0
@@ -345,6 +345,10 @@ static void dump_balance_args(struct btrfs_balance_args *args) (unsigned long long)args->vend);if (args->flags &BTRFS_BALANCE_ARGS_LIMIT )printf (", limit=%llu" , (unsigned long long )args->limit); +if (args->flags &BTRFS_BALANCE_ARGS_LIMITS ) { +printf (", limit=" ); +print_range_u32 (args->limit_min, args->limit_max); + }printf ("\n" ); }
ioctl.h +12 -1
@@ -227,7 +227,18 @@ struct btrfs_balance_args {__u64 flags; -__u64 limit;/* limit number of processed chunks */ +/* +* BTRFS_BALANCE_ARGS_LIMIT with value 'limit' +* BTRFS_BALANCE_ARGS_LIMITS - 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__));
volumes.h +1 -0
@@ -136,6 +136,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_LIMITS (1ULL << 6)/* * Profile changing flags. When SOFT is set we won't relocate chunk if
Signature · 1 line
2.6.1
David Sterba
maintainerPATCH v2 7/8 btrfs-progs: balance: enhance the limit fiter with range
In reply to David SterbaWe can do more with the balance filer. Enhance it so we can specify also the minimum number of block groups to process. The 'limit' filter now accepts a range (a..b, can be partial) and needs kernel support.
The 'limit=value' filter is equivalent to 'limit=..value' but works on older kernels as well.
The min/max values are 32bit, unlike the single-value limit which is 64bit.
--- cmds-balance.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
cmds-balance.c +12 -4
@@ -304,11 +304,19 @@ static int parse_filters(char *filters, struct btrfs_balance_args *args)return 1 ; }if (parse_u64 (value, &args->limit)) { -fprintf (stderr,"Invalid limit argument: %s\n" , - value); -return 1 ; +if (parse_range_u32 (value, &args->limit_min, + &args->limit_max)) { +fprintf (stderr, +"Invalid limit argument: %s\n" , + value); +return 1 ; + } + args->flags &= ~BTRFS_BALANCE_ARGS_LIMIT ; + args->flags |=BTRFS_BALANCE_ARGS_LIMITS ; + }else { + args->flags &= ~BTRFS_BALANCE_ARGS_LIMITS ; + args->flags |=BTRFS_BALANCE_ARGS_LIMIT ; } - args->flags |=BTRFS_BALANCE_ARGS_LIMIT ; }else {fprintf (stderr,"Unrecognized balance option '%s'\n" , this_char);
Signature · 1 line
2.6.1
David Sterba
maintainerPATCH v2 8/8 btrfs-progs: balance: add stripes filter
In reply to David SterbaFrom: Gabríel Arthúr Pétursson <[email protected]>
Add new balance filter 'stripes=<range>' to process only chunks that are spread accross given number of chunks.
The range must be specified with both values, but they can be the same to denote exact number of stripes.
[ reworked a bit to use the range helpers, dropped the single value
for stripes ]
--- Documentation/btrfs-balance.asciidoc | 4 ++++ cmds-balance.c | 16 ++++++++++++++++ ioctl.h | 4 +++- volumes.h | 1 + 4 files changed, 24 insertions(+), 1 deletion(-)
Documentation/btrfs-balance.asciidoc +4 -0
@@ -114,6 +114,10 @@ The argument may be a single value or a range. The single value *N* means *at most N chunks*, equivalent to *..N* range syntax. Kernels prior to 4.4 accept only the single value format. +*stripes*:: +Balances only block groups which have the given number of stripes. The +parameter is a range specified as <start..end>. + *soft*:: Takes no parameters. Only has meaning when converting between profiles. When doing convert from one profile to another and soft mode is on,
cmds-balance.c +16 -0
@@ -317,6 +317,18 @@ static int parse_filters(char *filters, struct btrfs_balance_args *args) args->flags &= ~BTRFS_BALANCE_ARGS_LIMITS ; args->flags |=BTRFS_BALANCE_ARGS_LIMIT ; } + }else if (!strcmp (this_char,"stripes" )) { +if (!value || !*value) { +fprintf (stderr, +"the stripes filter requires an argument\n" ); +return 1 ; + } +if (parse_range_u32 (value, &args->stripes_min, + &args->stripes_max)) { +fprintf (stderr,"Invalid stripes argument\n" ); +return 1 ; + } + args->flags |=BTRFS_BALANCE_ARGS_STRIPES ; }else {fprintf (stderr,"Unrecognized balance option '%s'\n" , this_char);
@@ -357,6 +369,10 @@ static void dump_balance_args(struct btrfs_balance_args *args)printf (", limit=" );print_range_u32 (args->limit_min, args->limit_max); } +if (args->flags &BTRFS_BALANCE_ARGS_STRIPES ) { +printf (", stripes=" ); +print_range_u32 (args->stripes_min, args->stripes_max); + }printf ("\n" ); }
ioctl.h +3 -1
@@ -239,7 +239,9 @@ struct btrfs_balance_args {__u32 limit_max; }; }; -__u64 unused[7 ]; +__u32 stripes_min; +__u32 stripes_max; +__u64 unused[6 ]; } __attribute__ ((__packed__));/* report balance progress to userspace */
volumes.h +1 -0
@@ -137,6 +137,7 @@ struct map_lookup {#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4)#define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5)#define BTRFS_BALANCE_ARGS_LIMITS (1ULL << 6) +#define BTRFS_BALANCE_ARGS_STRIPES (1ULL << 7)/* * Profile changing flags. When SOFT is set we won't relocate chunk if
Signature · 1 line
2.6.1