On 2019/8/14 上午9:04, Jeff Mahoney wrote: > If a user attempts to resize a file system to a size under 256MiB, > it will be rejected with EINVAL and get then unhelpful error message > "ERROR: unable to resize '/path': Invalid argument." > > This commit performs that check before issuing the ioctl to report > a more sensible error message. We also do overflow/underflow > checking when -/+ size is used and report those errors as well. > > Signed-off-by: Jeff Mahoney <[email protected]> > --- > cmds/filesystem.c | 41 +++++++++++++++++++++++++++++++++++++++++ > common/utils.c | 2 +- > common/utils.h | 2 +- > 3 files changed, 43 insertions(+), 2 deletions(-) > > diff --git a/cmds/filesystem.c b/cmds/filesystem.c > index 4f22089a..e3415126 100644 > --- a/cmds/filesystem.c > +++ b/cmds/filesystem.c > @@ -34,10 +34,12 @@ > #include "kerncompat.h" > #include "ctree.h" > #include "common/utils.h" > +#include "common/device-utils.h" > #include "volumes.h" > #include "cmds/commands.h" > #include "cmds/filesystem-usage.h" > #include "kernel-lib/list_sort.h" > +#include "kernel-lib/overflow.h" > #include "disk-io.h" > #include "common/help.h" > #include "common/fsfeatures.h" > @@ -1062,6 +1064,41 @@ next: > } > static DEFINE_SIMPLE_COMMAND(filesystem_defrag, "defragment"); > > +static int check_resize_size(const char *path, const char *amount) > +{ > + int mod = 0; > + u64 oldsize = 0, size, newsize; > + > + if (*amount == '-') > + mod = -1; > + else if (*amount == '+') > + mod = 1; > + > + if (mod) { > + amount++; > + oldsize = disk_size(path); > + if (oldsize == 0) > + return -1; > + } > + > + size = parse_size(amount); > + > + if (mod == -1 && check_sub_overflow(oldsize, size, &newsize)) { > + error("can't resize to negative size"); > + return -1; > + } else if (mod == 1 && check_add_overflow(oldsize, size, &newsize)) { > + error("can't resize to larger than 16EiB"); > + return -1; > + } else > + newsize = size; > + > + if (newsize < SZ_256M) { > + error("can't resize to size smaller than 256MiB"); > + return -1; > + } > + return 0; > +} > + > static const char * const cmd_filesystem_resize_usage[] = { > "btrfs filesystem resize > [devid:][+/-]<newsize>[kKmMgGtTpPeE]|[devid:]max <path>", > "Resize a filesystem", > @@ -1110,6 +1147,10 @@ static int cmd_filesystem_resize(const struct > cmd_struct *cmd, > if (fd < 0) > return 1; > > + res = check_resize_size(path, amount); > + if (res < 0) > + return 1; > + > printf("Resize '%s' of '%s'\n", path, amount); > memset(&args, 0, sizeof(args)); > strncpy_null(args.name, amount); > diff --git a/common/utils.c b/common/utils.c > index ad938409..f2a10ccc 100644 > --- a/common/utils.c > +++ b/common/utils.c > @@ -638,7 +638,7 @@ static int fls64(u64 x) > return 64 - i; > } > > -u64 parse_size(char *s) > +u64 parse_size(const char *s)
Although a good change, not sure if David will ask for an explict patch for that. Despite that, looks good. Reviewed-by: Qu Wenruo <[email protected]> Thanks, Qu > { > char c; > char *endptr; > diff --git a/common/utils.h b/common/utils.h > index 7867fb0a..0ef1d6e8 100644 > --- a/common/utils.h > +++ b/common/utils.h > @@ -65,7 +65,7 @@ int pretty_size_snprintf(u64 size, char *str, size_t > str_bytes, unsigned unit_mo > #define pretty_size(size) pretty_size_mode(size, UNITS_DEFAULT) > const char *pretty_size_mode(u64 size, unsigned mode); > > -u64 parse_size(char *s); > +u64 parse_size(const char *s); > u64 parse_qgroupid(const char *p); > u64 arg_strtou64(const char *str); > int open_file_or_dir(const char *fname, DIR **dirstream); >
signature.asc
Description: OpenPGP digital signature
