diff --git a/.bcachefs_revision b/.bcachefs_revision index 5b9e7323..8e176a6f 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -24f7e08cd8a8b62fc467f1b359bd934ad943f0b7 +3704d0779c7885dd74ab345aa7017a4430231e1a diff --git a/include/linux/printbuf.h b/include/linux/printbuf.h index c898faac..fa8e73d5 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 d114ba09..86df10e6 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 37ef7094..85b8f3df 100644 --- a/libbcachefs/util.c +++ b/libbcachefs/util.c @@ -27,15 +27,18 @@ static const char si_units[] = "?kMGTPEZY"; -static int __bch2_strtoh(const char *cp, u64 *res, - u64 t_max, bool t_signed) -{ - bool positive = *cp != '-'; - unsigned u; - u64 v = 0; +/* 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" +}; - if (*cp == '+' || *cp == '-') - cp++; +static int parse_u64(const char *cp, u64 *res) +{ + const char *start = cp; + u64 v = 0; if (!isdigit(*cp)) return -EINVAL; @@ -50,23 +53,122 @@ 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: + 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++; + 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 (v + (f_n * b) / f_d < v) + return -ERANGE; + v += (f_n * b) / f_d; + + *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 (fls64(v) + u * 10 > 64) - return -ERANGE; - - v <<= u * 10; - if (positive) { if (v > t_max) return -ERANGE; @@ -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 bbef4745..1fe66fd9 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