Commit 3838be78 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Don't use a fixed size buffer for fs_usage_deltas

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 61011ea2
...@@ -1949,6 +1949,7 @@ void bch2_trans_init(struct btree_trans *trans, struct bch_fs *c, ...@@ -1949,6 +1949,7 @@ void bch2_trans_init(struct btree_trans *trans, struct bch_fs *c,
trans->size = ARRAY_SIZE(trans->iters_onstack); trans->size = ARRAY_SIZE(trans->iters_onstack);
trans->iters = trans->iters_onstack; trans->iters = trans->iters_onstack;
trans->updates = trans->updates_onstack; trans->updates = trans->updates_onstack;
trans->fs_usage_deltas = NULL;
if (expected_nr_iters > trans->size) if (expected_nr_iters > trans->size)
bch2_trans_realloc_iters(trans, expected_nr_iters); bch2_trans_realloc_iters(trans, expected_nr_iters);
...@@ -1961,6 +1962,7 @@ int bch2_trans_exit(struct btree_trans *trans) ...@@ -1961,6 +1962,7 @@ int bch2_trans_exit(struct btree_trans *trans)
{ {
bch2_trans_unlock(trans); bch2_trans_unlock(trans);
kfree(trans->fs_usage_deltas);
kfree(trans->mem); kfree(trans->mem);
if (trans->used_mempool) if (trans->used_mempool)
mempool_free(trans->iters, &trans->c->btree_iters_pool); mempool_free(trans->iters, &trans->c->btree_iters_pool);
......
...@@ -305,7 +305,7 @@ struct btree_trans { ...@@ -305,7 +305,7 @@ struct btree_trans {
struct btree_iter iters_onstack[2]; struct btree_iter iters_onstack[2];
struct btree_insert_entry updates_onstack[6]; struct btree_insert_entry updates_onstack[6];
struct replicas_delta_list fs_usage_deltas; struct replicas_delta_list *fs_usage_deltas;
}; };
#define BTREE_FLAG(flag) \ #define BTREE_FLAG(flag) \
......
...@@ -544,10 +544,11 @@ static inline int do_btree_insert_at(struct btree_trans *trans, ...@@ -544,10 +544,11 @@ static inline int do_btree_insert_at(struct btree_trans *trans,
struct btree_insert_entry *i; struct btree_insert_entry *i;
int ret; int ret;
if (likely(!(trans->flags & BTREE_INSERT_NO_CLEAR_REPLICAS))) { if (likely(!(trans->flags & BTREE_INSERT_NO_CLEAR_REPLICAS)) &&
memset(&trans->fs_usage_deltas.fs_usage, 0, trans->fs_usage_deltas) {
sizeof(trans->fs_usage_deltas.fs_usage)); memset(&trans->fs_usage_deltas->fs_usage, 0,
trans->fs_usage_deltas.top = trans->fs_usage_deltas.d; sizeof(trans->fs_usage_deltas->fs_usage));
trans->fs_usage_deltas->used = 0;
} }
trans_for_each_update_iter(trans, i) trans_for_each_update_iter(trans, i)
...@@ -556,8 +557,7 @@ static inline int do_btree_insert_at(struct btree_trans *trans, ...@@ -556,8 +557,7 @@ static inline int do_btree_insert_at(struct btree_trans *trans,
trans_for_each_update_iter(trans, i) trans_for_each_update_iter(trans, i)
if (update_has_triggers(trans, i) && if (update_has_triggers(trans, i) &&
update_triggers_transactional(trans, i)) { update_triggers_transactional(trans, i)) {
ret = bch2_trans_mark_update(trans, i, ret = bch2_trans_mark_update(trans, i);
&trans->fs_usage_deltas);
if (ret == -EINTR) if (ret == -EINTR)
trace_trans_restart_mark(trans->ip); trace_trans_restart_mark(trans->ip);
if (ret) if (ret)
...@@ -627,9 +627,9 @@ static inline int do_btree_insert_at(struct btree_trans *trans, ...@@ -627,9 +627,9 @@ static inline int do_btree_insert_at(struct btree_trans *trans,
!update_triggers_transactional(trans, i)) !update_triggers_transactional(trans, i))
bch2_mark_update(trans, i, &fs_usage->u, 0); bch2_mark_update(trans, i, &fs_usage->u, 0);
if (fs_usage) { if (fs_usage && trans->fs_usage_deltas) {
bch2_replicas_delta_list_apply(c, &fs_usage->u, bch2_replicas_delta_list_apply(c, &fs_usage->u,
&trans->fs_usage_deltas); trans->fs_usage_deltas);
bch2_trans_fs_usage_apply(trans, fs_usage); bch2_trans_fs_usage_apply(trans, fs_usage);
} }
......
...@@ -1260,26 +1260,45 @@ void bch2_trans_fs_usage_apply(struct btree_trans *trans, ...@@ -1260,26 +1260,45 @@ void bch2_trans_fs_usage_apply(struct btree_trans *trans,
/* trans_mark: */ /* trans_mark: */
static inline void update_replicas_list(struct replicas_delta_list *d, static void replicas_deltas_realloc(struct btree_trans *trans)
{
struct replicas_delta_list *d = trans->fs_usage_deltas;
unsigned new_size = d ? d->size * 2 : 128;
d = krealloc(d, sizeof(*d) + new_size, GFP_NOIO|__GFP_ZERO);
BUG_ON(!d);
d->size = new_size;
trans->fs_usage_deltas = d;
}
static inline void update_replicas_list(struct btree_trans *trans,
struct bch_replicas_entry *r, struct bch_replicas_entry *r,
s64 sectors) s64 sectors)
{ {
d->top->delta = sectors; struct replicas_delta_list *d = trans->fs_usage_deltas;
memcpy(&d->top->r, r, replicas_entry_bytes(r)); struct replicas_delta *n;
unsigned b = replicas_entry_bytes(r) + 8;
d->top = (void *) d->top + replicas_entry_bytes(r) + 8; if (!d || d->used + b > d->size) {
replicas_deltas_realloc(trans);
d = trans->fs_usage_deltas;
}
BUG_ON((void *) d->top > (void *) d->d + sizeof(d->pad)); n = (void *) d->d + d->used;
n->delta = sectors;
memcpy(&n->r, r, replicas_entry_bytes(r));
d->used += b;
} }
static inline void update_cached_sectors_list(struct replicas_delta_list *d, static inline void update_cached_sectors_list(struct btree_trans *trans,
unsigned dev, s64 sectors) unsigned dev, s64 sectors)
{ {
struct bch_replicas_padded r; struct bch_replicas_padded r;
bch2_replicas_entry_cached(&r.e, dev); bch2_replicas_entry_cached(&r.e, dev);
update_replicas_list(d, &r.e, sectors); update_replicas_list(trans, &r.e, sectors);
} }
void bch2_replicas_delta_list_apply(struct bch_fs *c, void bch2_replicas_delta_list_apply(struct bch_fs *c,
...@@ -1287,12 +1306,13 @@ void bch2_replicas_delta_list_apply(struct bch_fs *c, ...@@ -1287,12 +1306,13 @@ void bch2_replicas_delta_list_apply(struct bch_fs *c,
struct replicas_delta_list *r) struct replicas_delta_list *r)
{ {
struct replicas_delta *d = r->d; struct replicas_delta *d = r->d;
struct replicas_delta *top = (void *) r->d + r->used;
acc_u64s((u64 *) fs_usage, acc_u64s((u64 *) fs_usage,
(u64 *) &r->fs_usage, sizeof(*fs_usage) / sizeof(u64)); (u64 *) &r->fs_usage, sizeof(*fs_usage) / sizeof(u64));
while (d != r->top) { while (d != top) {
BUG_ON((void *) d > (void *) r->top); BUG_ON((void *) d > (void *) top);
update_replicas(c, fs_usage, &d->r, d->delta); update_replicas(c, fs_usage, &d->r, d->delta);
...@@ -1361,8 +1381,7 @@ static int trans_update_key(struct btree_trans *trans, ...@@ -1361,8 +1381,7 @@ static int trans_update_key(struct btree_trans *trans,
static int bch2_trans_mark_pointer(struct btree_trans *trans, static int bch2_trans_mark_pointer(struct btree_trans *trans,
struct extent_ptr_decoded p, struct extent_ptr_decoded p,
s64 sectors, enum bch_data_type data_type, s64 sectors, enum bch_data_type data_type)
struct replicas_delta_list *d)
{ {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev); struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
...@@ -1423,8 +1442,7 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans, ...@@ -1423,8 +1442,7 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans, static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans,
struct bch_extent_stripe_ptr p, struct bch_extent_stripe_ptr p,
s64 sectors, enum bch_data_type data_type, s64 sectors, enum bch_data_type data_type)
struct replicas_delta_list *d)
{ {
struct bch_replicas_padded r; struct bch_replicas_padded r;
struct btree_insert_entry *insert; struct btree_insert_entry *insert;
...@@ -1469,7 +1487,7 @@ static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans, ...@@ -1469,7 +1487,7 @@ static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans,
bch2_bkey_to_replicas(&r.e, s.s_c); bch2_bkey_to_replicas(&r.e, s.s_c);
update_replicas_list(d, &r.e, sectors); update_replicas_list(trans, &r.e, sectors);
out: out:
bch2_trans_iter_put(trans, iter); bch2_trans_iter_put(trans, iter);
return ret; return ret;
...@@ -1477,8 +1495,7 @@ static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans, ...@@ -1477,8 +1495,7 @@ static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans,
static int bch2_trans_mark_extent(struct btree_trans *trans, static int bch2_trans_mark_extent(struct btree_trans *trans,
struct bkey_s_c k, struct bkey_s_c k,
s64 sectors, enum bch_data_type data_type, s64 sectors, enum bch_data_type data_type)
struct replicas_delta_list *d)
{ {
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
const union bch_extent_entry *entry; const union bch_extent_entry *entry;
...@@ -1501,7 +1518,7 @@ static int bch2_trans_mark_extent(struct btree_trans *trans, ...@@ -1501,7 +1518,7 @@ static int bch2_trans_mark_extent(struct btree_trans *trans,
: ptr_disk_sectors_delta(p, sectors); : ptr_disk_sectors_delta(p, sectors);
ret = bch2_trans_mark_pointer(trans, p, disk_sectors, ret = bch2_trans_mark_pointer(trans, p, disk_sectors,
data_type, d); data_type);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1509,7 +1526,7 @@ static int bch2_trans_mark_extent(struct btree_trans *trans, ...@@ -1509,7 +1526,7 @@ static int bch2_trans_mark_extent(struct btree_trans *trans,
if (p.ptr.cached) { if (p.ptr.cached) {
if (disk_sectors && !stale) if (disk_sectors && !stale)
update_cached_sectors_list(d, p.ptr.dev, update_cached_sectors_list(trans, p.ptr.dev,
disk_sectors); disk_sectors);
} else if (!p.ec_nr) { } else if (!p.ec_nr) {
dirty_sectors += disk_sectors; dirty_sectors += disk_sectors;
...@@ -1517,7 +1534,7 @@ static int bch2_trans_mark_extent(struct btree_trans *trans, ...@@ -1517,7 +1534,7 @@ static int bch2_trans_mark_extent(struct btree_trans *trans,
} else { } else {
for (i = 0; i < p.ec_nr; i++) { for (i = 0; i < p.ec_nr; i++) {
ret = bch2_trans_mark_stripe_ptr(trans, p.ec[i], ret = bch2_trans_mark_stripe_ptr(trans, p.ec[i],
disk_sectors, data_type, d); disk_sectors, data_type);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -1527,16 +1544,16 @@ static int bch2_trans_mark_extent(struct btree_trans *trans, ...@@ -1527,16 +1544,16 @@ static int bch2_trans_mark_extent(struct btree_trans *trans,
} }
if (dirty_sectors) if (dirty_sectors)
update_replicas_list(d, &r.e, dirty_sectors); update_replicas_list(trans, &r.e, dirty_sectors);
return 0; return 0;
} }
int bch2_trans_mark_key(struct btree_trans *trans, int bch2_trans_mark_key(struct btree_trans *trans,
struct bkey_s_c k, struct bkey_s_c k,
bool inserting, s64 sectors, bool inserting, s64 sectors)
struct replicas_delta_list *d)
{ {
struct replicas_delta_list *d;
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
switch (k.k->type) { switch (k.k->type) {
...@@ -1544,11 +1561,15 @@ int bch2_trans_mark_key(struct btree_trans *trans, ...@@ -1544,11 +1561,15 @@ int bch2_trans_mark_key(struct btree_trans *trans,
return bch2_trans_mark_extent(trans, k, inserting return bch2_trans_mark_extent(trans, k, inserting
? c->opts.btree_node_size ? c->opts.btree_node_size
: -c->opts.btree_node_size, : -c->opts.btree_node_size,
BCH_DATA_BTREE, d); BCH_DATA_BTREE);
case KEY_TYPE_extent: case KEY_TYPE_extent:
return bch2_trans_mark_extent(trans, k, return bch2_trans_mark_extent(trans, k,
sectors, BCH_DATA_USER, d); sectors, BCH_DATA_USER);
case KEY_TYPE_inode: case KEY_TYPE_inode:
if (!trans->fs_usage_deltas)
replicas_deltas_realloc(trans);
d = trans->fs_usage_deltas;
if (inserting) if (inserting)
d->fs_usage.nr_inodes++; d->fs_usage.nr_inodes++;
else else
...@@ -1557,6 +1578,10 @@ int bch2_trans_mark_key(struct btree_trans *trans, ...@@ -1557,6 +1578,10 @@ int bch2_trans_mark_key(struct btree_trans *trans,
case KEY_TYPE_reservation: { case KEY_TYPE_reservation: {
unsigned replicas = bkey_s_c_to_reservation(k).v->nr_replicas; unsigned replicas = bkey_s_c_to_reservation(k).v->nr_replicas;
if (!trans->fs_usage_deltas)
replicas_deltas_realloc(trans);
d = trans->fs_usage_deltas;
sectors *= replicas; sectors *= replicas;
replicas = clamp_t(unsigned, replicas, 1, replicas = clamp_t(unsigned, replicas, 1,
ARRAY_SIZE(d->fs_usage.persistent_reserved)); ARRAY_SIZE(d->fs_usage.persistent_reserved));
...@@ -1571,8 +1596,7 @@ int bch2_trans_mark_key(struct btree_trans *trans, ...@@ -1571,8 +1596,7 @@ int bch2_trans_mark_key(struct btree_trans *trans,
} }
int bch2_trans_mark_update(struct btree_trans *trans, int bch2_trans_mark_update(struct btree_trans *trans,
struct btree_insert_entry *insert, struct btree_insert_entry *insert)
struct replicas_delta_list *d)
{ {
struct btree_iter *iter = insert->iter; struct btree_iter *iter = insert->iter;
struct btree *b = iter->l[0].b; struct btree *b = iter->l[0].b;
...@@ -1586,7 +1610,7 @@ int bch2_trans_mark_update(struct btree_trans *trans, ...@@ -1586,7 +1610,7 @@ int bch2_trans_mark_update(struct btree_trans *trans,
ret = bch2_trans_mark_key(trans, ret = bch2_trans_mark_key(trans,
bkey_i_to_s_c(insert->k), true, bkey_i_to_s_c(insert->k), true,
bpos_min(insert->k->k.p, b->key.k.p).offset - bpos_min(insert->k->k.p, b->key.k.p).offset -
bkey_start_offset(&insert->k->k), d); bkey_start_offset(&insert->k->k));
if (ret) if (ret)
return ret; return ret;
...@@ -1621,7 +1645,7 @@ int bch2_trans_mark_update(struct btree_trans *trans, ...@@ -1621,7 +1645,7 @@ int bch2_trans_mark_update(struct btree_trans *trans,
BUG_ON(sectors <= 0); BUG_ON(sectors <= 0);
ret = bch2_trans_mark_key(trans, k, true, ret = bch2_trans_mark_key(trans, k, true,
sectors, d); sectors);
if (ret) if (ret)
return ret; return ret;
...@@ -1633,7 +1657,7 @@ int bch2_trans_mark_update(struct btree_trans *trans, ...@@ -1633,7 +1657,7 @@ int bch2_trans_mark_update(struct btree_trans *trans,
BUG_ON(sectors >= 0); BUG_ON(sectors >= 0);
} }
ret = bch2_trans_mark_key(trans, k, false, sectors, d); ret = bch2_trans_mark_key(trans, k, false, sectors);
if (ret) if (ret)
return ret; return ret;
......
...@@ -271,11 +271,9 @@ int bch2_mark_update(struct btree_trans *, struct btree_insert_entry *, ...@@ -271,11 +271,9 @@ int bch2_mark_update(struct btree_trans *, struct btree_insert_entry *,
void bch2_replicas_delta_list_apply(struct bch_fs *, void bch2_replicas_delta_list_apply(struct bch_fs *,
struct bch_fs_usage *, struct bch_fs_usage *,
struct replicas_delta_list *); struct replicas_delta_list *);
int bch2_trans_mark_key(struct btree_trans *, struct bkey_s_c, int bch2_trans_mark_key(struct btree_trans *, struct bkey_s_c, bool, s64);
bool, s64, struct replicas_delta_list *);
int bch2_trans_mark_update(struct btree_trans *, int bch2_trans_mark_update(struct btree_trans *,
struct btree_insert_entry *, struct btree_insert_entry *);
struct replicas_delta_list *);
void bch2_trans_fs_usage_apply(struct btree_trans *, struct bch_fs_usage_online *); void bch2_trans_fs_usage_apply(struct btree_trans *, struct bch_fs_usage_online *);
/* disk reservations: */ /* disk reservations: */
......
...@@ -99,11 +99,10 @@ struct replicas_delta { ...@@ -99,11 +99,10 @@ struct replicas_delta {
} __packed; } __packed;
struct replicas_delta_list { struct replicas_delta_list {
unsigned size;
unsigned used;
struct bch_fs_usage fs_usage; struct bch_fs_usage fs_usage;
struct replicas_delta *top;
struct replicas_delta d[0]; struct replicas_delta d[0];
u8 pad[256];
}; };
/* /*
......
...@@ -258,13 +258,8 @@ static int bch2_extent_replay_key(struct bch_fs *c, struct bkey_i *k) ...@@ -258,13 +258,8 @@ static int bch2_extent_replay_key(struct bch_fs *c, struct bkey_i *k)
} while (bkey_cmp(iter->pos, k->k.p) < 0); } while (bkey_cmp(iter->pos, k->k.p) < 0);
if (split_compressed) { if (split_compressed) {
memset(&trans.fs_usage_deltas.fs_usage, 0,
sizeof(trans.fs_usage_deltas.fs_usage));
trans.fs_usage_deltas.top = trans.fs_usage_deltas.d;
ret = bch2_trans_mark_key(&trans, bkey_i_to_s_c(k), false, ret = bch2_trans_mark_key(&trans, bkey_i_to_s_c(k), false,
-((s64) k->k.size), -((s64) k->k.size)) ?:
&trans.fs_usage_deltas) ?:
bch2_trans_commit(&trans, &disk_res, NULL, bch2_trans_commit(&trans, &disk_res, NULL,
BTREE_INSERT_ATOMIC| BTREE_INSERT_ATOMIC|
BTREE_INSERT_NOFAIL| BTREE_INSERT_NOFAIL|
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment