From ffbf806d5ccd6af99ef14ac970b5dc973c50432b Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 11 Jun 2022 18:13:40 -0400 Subject: [PATCH] Update bcachefs sources to 3704d0779c bcachefs: Improved human readable integer parsing --- .bcachefs_revision | 2 +- include/linux/printbuf.h | 2 + libbcachefs/alloc_background.c | 19 ++++- libbcachefs/util.c | 130 +++++++++++++++++++++++++++++---- libbcachefs/util.h | 2 +- 5 files changed, 136 insertions(+), 19 deletions(-) diff --git a/.bcachefs_revision b/.bcachefs_revision index 5b9e732..8e176a6 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -24f7e08cd8a8b62fc467f1b359bd934ad943f0b7 +3704d0779c7885dd74ab345aa7017a4430231e1a diff --git a/include/linux/printbuf.h b/include/linux/printbuf.h index c898faa..fa8e73d 100644 --- a/include/linux/printbuf.h +++ b/include/linux/printbuf.h @@ -225,6 +225,8 @@ static inline void printbuf_reset(struct printbuf *buf) { buf->pos = 0; buf->allocation_failure = 0; + buf->indent = 0; + buf->tabstop = 0; } /** diff --git a/libbcachefs/alloc_background.c b/libbcachefs/alloc_background.c index d114ba0..86df10e 100644 --- a/libbcachefs/alloc_background.c +++ b/libbcachefs/alloc_background.c @@ -1190,12 +1190,26 @@ void bch2_do_invalidates(struct bch_fs *c) queue_work(system_long_wq, &c->invalidate_work); } +static int bucket_freespace_init(struct btree_trans *trans, struct btree_iter *iter) +{ + struct bch_alloc_v4 a; + struct bkey_s_c k; + int ret; + + k = bch2_btree_iter_peek_slot(iter); + ret = bkey_err(k); + if (ret) + return ret; + + bch2_alloc_to_v4(k, &a); + return bch2_bucket_do_index(trans, k, &a, true); +} + static int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca) { struct btree_trans trans; struct btree_iter iter; struct bkey_s_c k; - struct bch_alloc_v4 a; struct bch_member *m; int ret; @@ -1208,10 +1222,9 @@ static int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca) if (iter.pos.offset >= ca->mi.nbuckets) break; - bch2_alloc_to_v4(k, &a); ret = __bch2_trans_do(&trans, NULL, NULL, BTREE_INSERT_LAZY_RW, - bch2_bucket_do_index(&trans, k, &a, true)); + bucket_freespace_init(&trans, &iter)); if (ret) break; } diff --git a/libbcachefs/util.c b/libbcachefs/util.c index 37ef709..85b8f3d 100644 --- a/libbcachefs/util.c +++ b/libbcachefs/util.c @@ -27,16 +27,19 @@ static const char si_units[] = "?kMGTPEZY"; -static int __bch2_strtoh(const char *cp, u64 *res, - u64 t_max, bool t_signed) +/* string_get_size units: */ +static const char *const units_2[] = { + "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB" +}; +static const char *const units_10[] = { + "B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" +}; + +static int parse_u64(const char *cp, u64 *res) { - bool positive = *cp != '-'; - unsigned u; + const char *start = cp; u64 v = 0; - if (*cp == '+' || *cp == '-') - cp++; - if (!isdigit(*cp)) return -EINVAL; @@ -50,22 +53,121 @@ static int __bch2_strtoh(const char *cp, u64 *res, cp++; } while (isdigit(*cp)); + *res = v; + return cp - start; +} + +static int bch2_pow(u64 n, u64 p, u64 *res) +{ + *res = 1; + + while (p--) { + if (*res > div_u64(U64_MAX, n)) + return -ERANGE; + *res *= n; + } + return 0; +} + +static int parse_unit_suffix(const char *cp, u64 *res) +{ + const char *start = cp; + u64 base = 1024; + unsigned u; + int ret; + + if (*cp == ' ') + cp++; + for (u = 1; u < strlen(si_units); u++) if (*cp == si_units[u]) { cp++; goto got_unit; } - u = 0; + + for (u = 0; u < ARRAY_SIZE(units_2); u++) + if (!strncmp(cp, units_2[u], strlen(units_2[u]))) { + cp += strlen(units_2[u]); + goto got_unit; + } + + for (u = 0; u < ARRAY_SIZE(units_10); u++) + if (!strncmp(cp, units_10[u], strlen(units_10[u]))) { + cp += strlen(units_10[u]); + base = 1000; + goto got_unit; + } + + *res = 1; + return 0; got_unit: - if (*cp == '\n') + ret = bch2_pow(base, u, res); + if (ret) + return ret; + + return cp - start; +} + +#define parse_or_ret(cp, _f) \ +do { \ + int ret = _f; \ + if (ret < 0) \ + return ret; \ + cp += ret; \ +} while (0) + +static int __bch2_strtou64_h(const char *cp, u64 *res) +{ + const char *start = cp; + u64 v = 0, b, f_n = 0, f_d = 1; + int ret; + + parse_or_ret(cp, parse_u64(cp, &v)); + + if (*cp == '.') { cp++; - if (*cp) - return -EINVAL; + ret = parse_u64(cp, &f_n); + if (ret < 0) + return ret; + cp += ret; + + ret = bch2_pow(10, ret, &f_d); + if (ret) + return ret; + } + + parse_or_ret(cp, parse_unit_suffix(cp, &b)); + + if (v > div_u64(U64_MAX, b)) + return -ERANGE; + v *= b; + + if (f_n > div_u64(U64_MAX, b)) + return -ERANGE; - if (fls64(v) + u * 10 > 64) + if (v + (f_n * b) / f_d < v) return -ERANGE; + v += (f_n * b) / f_d; - v <<= u * 10; + *res = v; + return cp - start; +} + +static int __bch2_strtoh(const char *cp, u64 *res, + u64 t_max, bool t_signed) +{ + bool positive = *cp != '-'; + u64 v = 0; + + if (*cp == '+' || *cp == '-') + cp++; + + parse_or_ret(cp, __bch2_strtou64_h(cp, &v)); + + if (*cp == '\n') + cp++; + if (*cp) + return -EINVAL; if (positive) { if (v > t_max) @@ -86,7 +188,7 @@ got_unit: #define STRTO_H(name, type) \ int bch2_ ## name ## _h(const char *cp, type *res) \ { \ - u64 v; \ + u64 v = 0; \ int ret = __bch2_strtoh(cp, &v, ANYSINT_MAX(type), \ ANYSINT_MAX(type) != ((type) ~0ULL)); \ *res = v; \ diff --git a/libbcachefs/util.h b/libbcachefs/util.h index bbef474..1fe66fd 100644 --- a/libbcachefs/util.h +++ b/libbcachefs/util.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 u*/ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _BCACHEFS_UTIL_H #define _BCACHEFS_UTIL_H -- 2.39.2