From 3838be78410cfe52a067b8e88dfcff922084e627 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 15 May 2019 15:47:43 -0400 Subject: bcachefs: Don't use a fixed size buffer for fs_usage_deltas Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_iter.c | 2 + fs/bcachefs/btree_types.h | 2 +- fs/bcachefs/btree_update_leaf.c | 16 ++++---- fs/bcachefs/buckets.c | 82 ++++++++++++++++++++++++++--------------- fs/bcachefs/buckets.h | 6 +-- fs/bcachefs/buckets_types.h | 5 +-- fs/bcachefs/recovery.c | 7 +--- 7 files changed, 69 insertions(+), 51 deletions(-) (limited to 'fs/bcachefs') diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 10c8350618bc..2579944bb8c1 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.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->iters = trans->iters_onstack; trans->updates = trans->updates_onstack; + trans->fs_usage_deltas = NULL; if (expected_nr_iters > trans->size) bch2_trans_realloc_iters(trans, expected_nr_iters); @@ -1961,6 +1962,7 @@ int bch2_trans_exit(struct btree_trans *trans) { bch2_trans_unlock(trans); + kfree(trans->fs_usage_deltas); kfree(trans->mem); if (trans->used_mempool) mempool_free(trans->iters, &trans->c->btree_iters_pool); diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index d27d33a5666d..bdcf9288d749 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -305,7 +305,7 @@ struct btree_trans { struct btree_iter iters_onstack[2]; 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) \ diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index 2266c7da58d3..e6fbe8a7413a 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -544,10 +544,11 @@ static inline int do_btree_insert_at(struct btree_trans *trans, struct btree_insert_entry *i; int ret; - if (likely(!(trans->flags & BTREE_INSERT_NO_CLEAR_REPLICAS))) { - 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; + if (likely(!(trans->flags & BTREE_INSERT_NO_CLEAR_REPLICAS)) && + trans->fs_usage_deltas) { + memset(&trans->fs_usage_deltas->fs_usage, 0, + sizeof(trans->fs_usage_deltas->fs_usage)); + trans->fs_usage_deltas->used = 0; } trans_for_each_update_iter(trans, i) @@ -556,8 +557,7 @@ static inline int do_btree_insert_at(struct btree_trans *trans, trans_for_each_update_iter(trans, i) if (update_has_triggers(trans, i) && update_triggers_transactional(trans, i)) { - ret = bch2_trans_mark_update(trans, i, - &trans->fs_usage_deltas); + ret = bch2_trans_mark_update(trans, i); if (ret == -EINTR) trace_trans_restart_mark(trans->ip); if (ret) @@ -627,9 +627,9 @@ static inline int do_btree_insert_at(struct btree_trans *trans, !update_triggers_transactional(trans, i)) 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, - &trans->fs_usage_deltas); + trans->fs_usage_deltas); bch2_trans_fs_usage_apply(trans, fs_usage); } diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index 78b4c93a7170..5c18cebeb180 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -1260,26 +1260,45 @@ void bch2_trans_fs_usage_apply(struct btree_trans *trans, /* 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, s64 sectors) { - d->top->delta = sectors; - memcpy(&d->top->r, r, replicas_entry_bytes(r)); + struct replicas_delta_list *d = trans->fs_usage_deltas; + 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) { struct bch_replicas_padded r; 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, @@ -1287,12 +1306,13 @@ void bch2_replicas_delta_list_apply(struct bch_fs *c, struct replicas_delta_list *r) { struct replicas_delta *d = r->d; + struct replicas_delta *top = (void *) r->d + r->used; acc_u64s((u64 *) fs_usage, (u64 *) &r->fs_usage, sizeof(*fs_usage) / sizeof(u64)); - while (d != r->top) { - BUG_ON((void *) d > (void *) r->top); + while (d != top) { + BUG_ON((void *) d > (void *) top); update_replicas(c, fs_usage, &d->r, d->delta); @@ -1361,8 +1381,7 @@ static int trans_update_key(struct btree_trans *trans, static int bch2_trans_mark_pointer(struct btree_trans *trans, struct extent_ptr_decoded p, - s64 sectors, enum bch_data_type data_type, - struct replicas_delta_list *d) + s64 sectors, enum bch_data_type data_type) { struct bch_fs *c = trans->c; struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev); @@ -1423,8 +1442,7 @@ out: static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans, struct bch_extent_stripe_ptr p, - s64 sectors, enum bch_data_type data_type, - struct replicas_delta_list *d) + s64 sectors, enum bch_data_type data_type) { struct bch_replicas_padded r; struct btree_insert_entry *insert; @@ -1469,7 +1487,7 @@ static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans, bch2_bkey_to_replicas(&r.e, s.s_c); - update_replicas_list(d, &r.e, sectors); + update_replicas_list(trans, &r.e, sectors); out: bch2_trans_iter_put(trans, iter); return ret; @@ -1477,8 +1495,7 @@ out: static int bch2_trans_mark_extent(struct btree_trans *trans, struct bkey_s_c k, - s64 sectors, enum bch_data_type data_type, - struct replicas_delta_list *d) + s64 sectors, enum bch_data_type data_type) { struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); const union bch_extent_entry *entry; @@ -1501,7 +1518,7 @@ static int bch2_trans_mark_extent(struct btree_trans *trans, : ptr_disk_sectors_delta(p, sectors); ret = bch2_trans_mark_pointer(trans, p, disk_sectors, - data_type, d); + data_type); if (ret < 0) return ret; @@ -1509,7 +1526,7 @@ static int bch2_trans_mark_extent(struct btree_trans *trans, if (p.ptr.cached) { if (disk_sectors && !stale) - update_cached_sectors_list(d, p.ptr.dev, + update_cached_sectors_list(trans, p.ptr.dev, disk_sectors); } else if (!p.ec_nr) { dirty_sectors += disk_sectors; @@ -1517,7 +1534,7 @@ static int bch2_trans_mark_extent(struct btree_trans *trans, } else { for (i = 0; i < p.ec_nr; i++) { ret = bch2_trans_mark_stripe_ptr(trans, p.ec[i], - disk_sectors, data_type, d); + disk_sectors, data_type); if (ret) return ret; } @@ -1527,16 +1544,16 @@ static int bch2_trans_mark_extent(struct btree_trans *trans, } if (dirty_sectors) - update_replicas_list(d, &r.e, dirty_sectors); + update_replicas_list(trans, &r.e, dirty_sectors); return 0; } int bch2_trans_mark_key(struct btree_trans *trans, struct bkey_s_c k, - bool inserting, s64 sectors, - struct replicas_delta_list *d) + bool inserting, s64 sectors) { + struct replicas_delta_list *d; struct bch_fs *c = trans->c; switch (k.k->type) { @@ -1544,11 +1561,15 @@ int bch2_trans_mark_key(struct btree_trans *trans, return bch2_trans_mark_extent(trans, k, inserting ? c->opts.btree_node_size : -c->opts.btree_node_size, - BCH_DATA_BTREE, d); + BCH_DATA_BTREE); case KEY_TYPE_extent: return bch2_trans_mark_extent(trans, k, - sectors, BCH_DATA_USER, d); + sectors, BCH_DATA_USER); case KEY_TYPE_inode: + if (!trans->fs_usage_deltas) + replicas_deltas_realloc(trans); + d = trans->fs_usage_deltas; + if (inserting) d->fs_usage.nr_inodes++; else @@ -1557,6 +1578,10 @@ int bch2_trans_mark_key(struct btree_trans *trans, case KEY_TYPE_reservation: { 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; replicas = clamp_t(unsigned, replicas, 1, ARRAY_SIZE(d->fs_usage.persistent_reserved)); @@ -1571,8 +1596,7 @@ int bch2_trans_mark_key(struct btree_trans *trans, } int bch2_trans_mark_update(struct btree_trans *trans, - struct btree_insert_entry *insert, - struct replicas_delta_list *d) + struct btree_insert_entry *insert) { struct btree_iter *iter = insert->iter; struct btree *b = iter->l[0].b; @@ -1586,7 +1610,7 @@ int bch2_trans_mark_update(struct btree_trans *trans, ret = bch2_trans_mark_key(trans, bkey_i_to_s_c(insert->k), true, 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) return ret; @@ -1621,7 +1645,7 @@ int bch2_trans_mark_update(struct btree_trans *trans, BUG_ON(sectors <= 0); ret = bch2_trans_mark_key(trans, k, true, - sectors, d); + sectors); if (ret) return ret; @@ -1633,7 +1657,7 @@ int bch2_trans_mark_update(struct btree_trans *trans, 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) return ret; diff --git a/fs/bcachefs/buckets.h b/fs/bcachefs/buckets.h index 9f53fe6280f3..9b264514bfcb 100644 --- a/fs/bcachefs/buckets.h +++ b/fs/bcachefs/buckets.h @@ -271,11 +271,9 @@ int bch2_mark_update(struct btree_trans *, struct btree_insert_entry *, void bch2_replicas_delta_list_apply(struct bch_fs *, struct bch_fs_usage *, struct replicas_delta_list *); -int bch2_trans_mark_key(struct btree_trans *, struct bkey_s_c, - bool, s64, struct replicas_delta_list *); +int bch2_trans_mark_key(struct btree_trans *, struct bkey_s_c, bool, s64); int bch2_trans_mark_update(struct btree_trans *, - struct btree_insert_entry *, - struct replicas_delta_list *); + struct btree_insert_entry *); void bch2_trans_fs_usage_apply(struct btree_trans *, struct bch_fs_usage_online *); /* disk reservations: */ diff --git a/fs/bcachefs/buckets_types.h b/fs/bcachefs/buckets_types.h index ec4294d41518..efed658abc6a 100644 --- a/fs/bcachefs/buckets_types.h +++ b/fs/bcachefs/buckets_types.h @@ -99,11 +99,10 @@ struct replicas_delta { } __packed; struct replicas_delta_list { + unsigned size; + unsigned used; struct bch_fs_usage fs_usage; - - struct replicas_delta *top; struct replicas_delta d[0]; - u8 pad[256]; }; /* diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index 59f678596a64..8c656308826b 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -258,13 +258,8 @@ retry: } while (bkey_cmp(iter->pos, k->k.p) < 0); 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, - -((s64) k->k.size), - &trans.fs_usage_deltas) ?: + -((s64) k->k.size)) ?: bch2_trans_commit(&trans, &disk_res, NULL, BTREE_INSERT_ATOMIC| BTREE_INSERT_NOFAIL| -- cgit v1.2.3