]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bcachefs: Split out accounting in transaction commit
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 17 May 2025 00:26:01 +0000 (20:26 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 22 May 2025 00:15:06 +0000 (20:15 -0400)
There can be a lot of rendundancy in accounting updates within a single
btree transaction.

Split out accounting updates so that they can be deduped, in the next
commit.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_trans_commit.c
fs/bcachefs/btree_types.h
fs/bcachefs/btree_update.h
fs/bcachefs/disk_accounting.c
fs/bcachefs/disk_accounting.h
fs/bcachefs/recovery.c

index abbecddb18ee9320e302613a1ada9d164119b7af..1c03c965d836b0fae971835fb3ec90cd0af10fd8 100644 (file)
@@ -663,19 +663,17 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
                h = h->next;
        }
 
-       struct jset_entry *entry;
+       struct bkey_i *accounting;
 
        percpu_down_read(&c->mark_lock);
-       for (entry = btree_trans_journal_entries_start(trans);
-            entry != btree_trans_journal_entries_top(trans);
-            entry = vstruct_next(entry))
-               if (entry->type == BCH_JSET_ENTRY_write_buffer_keys &&
-                   entry->start->k.type == KEY_TYPE_accounting) {
-                       ret = bch2_accounting_trans_commit_hook(trans,
-                                               bkey_i_to_accounting(entry->start), flags);
-                       if (ret)
-                               goto revert_fs_usage;
-               }
+       for (accounting = btree_trans_subbuf_base(trans, &trans->accounting);
+            accounting != btree_trans_subbuf_top(trans, &trans->accounting);
+            accounting = bkey_next(accounting)) {
+               ret = bch2_accounting_trans_commit_hook(trans,
+                                       bkey_i_to_accounting(accounting), flags);
+               if (ret)
+                       goto revert_fs_usage;
+       }
        percpu_up_read(&c->mark_lock);
 
        /* XXX: we only want to run this if deltas are nonzero */
@@ -761,6 +759,13 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
                trans->journal_res.offset       += trans->journal_entries.u64s;
                trans->journal_res.u64s         -= trans->journal_entries.u64s;
 
+               memcpy_u64s_small(bch2_journal_add_entry(j, &trans->journal_res,
+                                               BCH_JSET_ENTRY_write_buffer_keys,
+                                               BTREE_ID_accounting, 0,
+                                               trans->accounting.u64s)->_data,
+                                 btree_trans_subbuf_base(trans, &trans->accounting),
+                                 trans->accounting.u64s);
+
                if (trans->journal_seq)
                        *trans->journal_seq = trans->journal_res.seq;
        }
@@ -781,13 +786,10 @@ fatal_err:
        bch2_fs_fatal_error(c, "fatal error in transaction commit: %s", bch2_err_str(ret));
        percpu_down_read(&c->mark_lock);
 revert_fs_usage:
-       for (struct jset_entry *entry2 = btree_trans_journal_entries_start(trans);
-            entry2 != entry;
-            entry2 = vstruct_next(entry2))
-               if (entry2->type == BCH_JSET_ENTRY_write_buffer_keys &&
-                   entry2->start->k.type == KEY_TYPE_accounting)
-                       bch2_accounting_trans_commit_revert(trans,
-                                       bkey_i_to_accounting(entry2->start), flags);
+       for (struct bkey_i *i = btree_trans_subbuf_base(trans, &trans->accounting);
+            i != accounting;
+            i = bkey_next(i))
+               bch2_accounting_trans_commit_revert(trans, bkey_i_to_accounting(i), flags);
        percpu_up_read(&c->mark_lock);
        return ret;
 }
@@ -972,6 +974,14 @@ do_bch2_trans_commit_to_journal_replay(struct btree_trans *trans)
                                return ret;
                }
 
+       for (struct bkey_i *i = btree_trans_subbuf_base(trans, &trans->accounting);
+            i != btree_trans_subbuf_top(trans, &trans->accounting);
+            i = bkey_next(i)) {
+               int ret = bch2_journal_key_insert(c, BTREE_ID_accounting, 0, i);
+               if (ret)
+                       return ret;
+       }
+
        return 0;
 }
 
@@ -988,7 +998,8 @@ int __bch2_trans_commit(struct btree_trans *trans, unsigned flags)
                goto out_reset;
 
        if (!trans->nr_updates &&
-           !trans->journal_entries.u64s)
+           !trans->journal_entries.u64s &&
+           !trans->accounting.u64s)
                goto out_reset;
 
        ret = bch2_trans_commit_run_triggers(trans);
@@ -1006,7 +1017,7 @@ int __bch2_trans_commit(struct btree_trans *trans, unsigned flags)
 
        EBUG_ON(test_bit(BCH_FS_clean_shutdown, &c->flags));
 
-       trans->journal_u64s             = trans->journal_entries.u64s;
+       trans->journal_u64s             = trans->journal_entries.u64s + jset_u64s(trans->accounting.u64s);
        trans->journal_transaction_names = READ_ONCE(c->opts.journal_transaction_names);
        if (trans->journal_transaction_names)
                trans->journal_u64s += jset_u64s(JSET_ENTRY_LOG_U64s);
index 7ebf43fc8baebcfd5bd9a063ac0d9acee9231750..9d641bf9d2a2b80ead12cb9201f71e2ede346f93 100644 (file)
@@ -541,6 +541,7 @@ struct btree_trans {
 
        /* update path: */
        struct btree_trans_subbuf journal_entries;
+       struct btree_trans_subbuf accounting;
 
        struct btree_trans_commit_hook *hooks;
        struct journal_entry_pin *journal_pin;
index 8964b321804ccb21ce1ee8e42a60296d752127fb..a54dc7277177ed6167690ecf5ce7bbad16ad5786 100644 (file)
@@ -255,6 +255,8 @@ static inline void bch2_trans_reset_updates(struct btree_trans *trans)
        trans->nr_updates               = 0;
        trans->journal_entries.u64s     = 0;
        trans->journal_entries.size     = 0;
+       trans->accounting.u64s          = 0;
+       trans->accounting.size          = 0;
        trans->hooks                    = NULL;
        trans->extra_disk_res           = 0;
 }
index 04e0d2ac27276c9e4c413ff104230abfb387d814..088b015fc198fc02ffd471a4e9d3bd79d8e7f54c 100644 (file)
@@ -96,13 +96,13 @@ int bch2_disk_accounting_mod(struct btree_trans *trans,
 
        if (likely(!gc)) {
                unsigned u64s = sizeof(struct bkey_i_accounting) / sizeof(u64) + nr;
-               struct jset_entry *e = bch2_trans_jset_entry_alloc(trans, jset_u64s(u64s));
-               int ret = PTR_ERR_OR_ZERO(e);
+               struct bkey_i_accounting *a =
+                       bch2_trans_subbuf_alloc(trans, &trans->accounting, u64s);
+               int ret = PTR_ERR_OR_ZERO(a);
                if (ret)
                        return ret;
 
-               journal_entry_init(e, BCH_JSET_ENTRY_write_buffer_keys, BTREE_ID_accounting, 0, u64s);
-               accounting_key_init(e->start, k, d, nr);
+               accounting_key_init(&a->k_i, k, d, nr);
                return 0;
        } else {
                struct { __BKEY_PADDED(k, BCH_ACCOUNTING_MAX_COUNTERS); } k_i;
@@ -307,14 +307,13 @@ static int bch2_accounting_update_sb_one(struct bch_fs *c, struct bpos p)
  */
 int bch2_accounting_update_sb(struct btree_trans *trans)
 {
-       for (struct jset_entry *i = btree_trans_journal_entries_start(trans);
-            i != btree_trans_journal_entries_top(trans);
-            i = vstruct_next(i))
-               if (jset_entry_is_key(i) && i->start->k.type == KEY_TYPE_accounting) {
-                       int ret = bch2_accounting_update_sb_one(trans->c, i->start->k.p);
-                       if (ret)
-                               return ret;
-               }
+       for (struct bkey_i *i = btree_trans_subbuf_base(trans, &trans->accounting);
+            i != btree_trans_subbuf_top(trans, &trans->accounting);
+            i = bkey_next(i)) {
+               int ret = bch2_accounting_update_sb_one(trans->c, i->k.p);
+               if (ret)
+                       return ret;
+       }
 
        return 0;
 }
index 54fa3e098c30ede4374a57a860661995c911dcb0..f6098e33ab3069cfbd88320004ab1264ad0e44c9 100644 (file)
@@ -259,7 +259,7 @@ static inline int bch2_accounting_trans_commit_hook(struct btree_trans *trans,
                                                    struct bkey_i_accounting *a,
                                                    unsigned commit_flags)
 {
-       u64 *base = (u64 *) btree_trans_subbuf_base(trans, &trans->journal_entries);
+       u64 *base = (u64 *) btree_trans_subbuf_base(trans, &trans->accounting);
        a->k.bversion = journal_pos_to_bversion(&trans->journal_res, (u64 *) a - base);
 
        EBUG_ON(bversion_zero(a->k.bversion));
index 0f954567ea45f99c46b822542253a5104058763b..4fca575755657482260f9bd53bfab065155143bb 100644 (file)
@@ -286,7 +286,12 @@ static int bch2_journal_replay_key(struct btree_trans *trans,
                goto out;
 
        if (k->k->k.type == KEY_TYPE_accounting) {
-               ret = bch2_trans_update_buffered(trans, BTREE_ID_accounting, k->k);
+               struct bkey_i *n = bch2_trans_subbuf_alloc(trans, &trans->accounting, k->k->k.u64s);
+               ret = PTR_ERR_OR_ZERO(n);
+               if (ret)
+                       goto out;
+
+               bkey_copy(n, k->k);
                goto out;
        }