bcachefs: Don't use a fixed size buffer for fs_usage_deltas
authorKent Overstreet <kent.overstreet@gmail.com>
Wed, 15 May 2019 19:47:43 +0000 (15:47 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:22 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_iter.c
fs/bcachefs/btree_types.h
fs/bcachefs/btree_update_leaf.c
fs/bcachefs/buckets.c
fs/bcachefs/buckets.h
fs/bcachefs/buckets_types.h
fs/bcachefs/recovery.c

index 10c8350618bc2fef86e66332189677a8da2e3238..2579944bb8c1144fcf2017c9a55e5823490203c3 100644 (file)
@@ -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);
index d27d33a5666da36d4aeaed02d0bfe47ba4f86dc4..bdcf9288d7493298b15c9684ce2ec3c933056566 100644 (file)
@@ -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)                                               \
index 2266c7da58d35876b220888992374c974df5c9fb..e6fbe8a7413a38254f6b7aefcaebdc4022096a75 100644 (file)
@@ -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);
        }
 
index 78b4c93a7170e5e1f642011e13d52c9cb4a1e254..5c18cebeb1804e5f54a543663e58b4ec499c7916 100644 (file)
@@ -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;
 
index 9f53fe6280f38deca44d13a3e95220027b6d35b0..9b264514bfcb579a42c6a167af8dd8b5fadcb022 100644 (file)
@@ -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: */
index ec4294d41518e275d45bc0520b87639bfc544fb2..efed658abc6aac717fdf1dbf3963ca402c458eb2 100644 (file)
@@ -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];
 };
 
 /*
index 59f678596a64562823032299e07d98df0a8abcea..8c656308826b9f0068e4a513c7c68ef1512e05c4 100644 (file)
@@ -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|