]> Git Repo - linux.git/commitdiff
bcachefs: Proper refcounting for journal_keys
authorKent Overstreet <[email protected]>
Sat, 18 Nov 2023 04:13:49 +0000 (23:13 -0500)
committerKent Overstreet <[email protected]>
Fri, 24 Nov 2023 07:43:12 +0000 (02:43 -0500)
The btree iterator code overlays keys from the journal until journal
replay is finished; since we're now starting copygc/rebalance etc.
before replay is finished, this is multithreaded access and thus needs
refcounting.

Signed-off-by: Kent Overstreet <[email protected]>
fs/bcachefs/bcachefs.h
fs/bcachefs/btree_iter.c
fs/bcachefs/btree_journal_iter.c
fs/bcachefs/btree_journal_iter.h
fs/bcachefs/recovery.c
fs/bcachefs/super.c

index 403aa3389fccfd2a60ceb3edf53d81877a9144df..e9d753b04a90e4545be4cc2b57b6f042b5ecaab9 100644 (file)
@@ -638,6 +638,8 @@ struct journal_keys {
        size_t                  gap;
        size_t                  nr;
        size_t                  size;
+       atomic_t                ref;
+       bool                    initial_ref_held;
 };
 
 struct btree_trans_buf {
index 6fa90bcd70168258384b1912f8eb7ed2aaf6e8c7..8e0fe65f6101bb237bf4aea173e8deaf8496550b 100644 (file)
@@ -2981,7 +2981,8 @@ struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx)
        trans->fn_idx           = fn_idx;
        trans->locking_wait.task = current;
        trans->journal_replay_not_finished =
-               !test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags);
+               unlikely(!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags)) &&
+               atomic_inc_not_zero(&c->journal_keys.ref);
        closure_init_stack(&trans->ref);
 
        s = btree_trans_stats(trans);
@@ -3098,6 +3099,9 @@ void bch2_trans_put(struct btree_trans *trans)
                        kfree(trans->fs_usage_deltas);
        }
 
+       if (unlikely(trans->journal_replay_not_finished))
+               bch2_journal_keys_put(c);
+
        if (trans->mem_bytes == BTREE_TRANS_MEM_MAX)
                mempool_free(trans->mem, &c->btree_trans_mem_pool);
        else
index 58a981bcf3aa8ca6749c41ca9e22655098adee14..ec52f50d249d075f4fae6ad60976c330ba7e46f0 100644 (file)
@@ -80,6 +80,8 @@ struct bkey_i *bch2_journal_keys_peek_upto(struct bch_fs *c, enum btree_id btree
        struct journal_keys *keys = &c->journal_keys;
        unsigned iters = 0;
        struct journal_key *k;
+
+       BUG_ON(*idx > keys->nr);
 search:
        if (!*idx)
                *idx = __bch2_journal_key_search(keys, btree_id, level, pos);
@@ -189,10 +191,12 @@ int bch2_journal_key_insert_take(struct bch_fs *c, enum btree_id id,
                /* Since @keys was full, there was no gap: */
                memcpy(new_keys.d, keys->d, sizeof(keys->d[0]) * keys->nr);
                kvfree(keys->d);
-               *keys = new_keys;
+               keys->d         = new_keys.d;
+               keys->nr        = new_keys.nr;
+               keys->size      = new_keys.size;
 
                /* And now the gap is at the end: */
-               keys->gap = keys->nr;
+               keys->gap       = keys->nr;
        }
 
        journal_iters_move_gap(c, keys->gap, idx);
@@ -415,10 +419,16 @@ static int journal_sort_key_cmp(const void *_l, const void *_r)
                cmp_int(l->journal_offset, r->journal_offset);
 }
 
-void bch2_journal_keys_free(struct journal_keys *keys)
+void bch2_journal_keys_put(struct bch_fs *c)
 {
+       struct journal_keys *keys = &c->journal_keys;
        struct journal_key *i;
 
+       BUG_ON(atomic_read(&keys->ref) <= 0);
+
+       if (!atomic_dec_and_test(&keys->ref))
+               return;
+
        move_gap(keys->d, keys->nr, keys->size, keys->gap, keys->nr);
        keys->gap = keys->nr;
 
@@ -429,6 +439,8 @@ void bch2_journal_keys_free(struct journal_keys *keys)
        kvfree(keys->d);
        keys->d = NULL;
        keys->nr = keys->gap = keys->size = 0;
+
+       bch2_journal_entries_free(c);
 }
 
 static void __journal_keys_sort(struct journal_keys *keys)
index 5d64e7e22f262df66076bddd982d1b6cc8b4c85a..8ca4c100b2e3e413d7adbb8dd5599d9f42de6d30 100644 (file)
@@ -49,7 +49,15 @@ void bch2_btree_and_journal_iter_init_node_iter(struct btree_and_journal_iter *,
                                                struct bch_fs *,
                                                struct btree *);
 
-void bch2_journal_keys_free(struct journal_keys *);
+void bch2_journal_keys_put(struct bch_fs *);
+
+static inline void bch2_journal_keys_put_initial(struct bch_fs *c)
+{
+       if (c->journal_keys.initial_ref_held)
+               bch2_journal_keys_put(c);
+       c->journal_keys.initial_ref_held = false;
+}
+
 void bch2_journal_entries_free(struct bch_fs *);
 
 int bch2_journal_keys_sort(struct bch_fs *);
index 9c30500ce9200af8be8f71a50f5fa02c356e4400..770ced1c62850d317eb991c8723401456735cc90 100644 (file)
@@ -167,6 +167,8 @@ static int bch2_journal_replay(struct bch_fs *c)
                        goto err;
        }
 
+       BUG_ON(!atomic_read(&keys->ref));
+
        for (i = 0; i < keys->nr; i++) {
                k = keys_sorted[i];
 
@@ -188,6 +190,9 @@ static int bch2_journal_replay(struct bch_fs *c)
                }
        }
 
+       if (!c->opts.keep_journal)
+               bch2_journal_keys_put_initial(c);
+
        replay_now_at(j, j->replay_journal_seq_end);
        j->replay_journal_seq = 0;
 
@@ -909,10 +914,8 @@ out:
        bch2_flush_fsck_errs(c);
 
        if (!c->opts.keep_journal &&
-           test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags)) {
-               bch2_journal_keys_free(&c->journal_keys);
-               bch2_journal_entries_free(c);
-       }
+           test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags))
+               bch2_journal_keys_put_initial(c);
        kfree(clean);
 
        if (!ret && test_bit(BCH_FS_NEED_DELETE_DEAD_SNAPSHOTS, &c->flags)) {
index 14f4eff421cf7498a79859bbeed6f231a6f12b88..f63474c5c5a2937d89a6f6316d2ed4d49e6b454c 100644 (file)
@@ -508,8 +508,8 @@ static void __bch2_fs_free(struct bch_fs *c)
        bch2_io_clock_exit(&c->io_clock[WRITE]);
        bch2_io_clock_exit(&c->io_clock[READ]);
        bch2_fs_compress_exit(c);
-       bch2_journal_keys_free(&c->journal_keys);
-       bch2_journal_entries_free(c);
+       bch2_journal_keys_put_initial(c);
+       BUG_ON(atomic_read(&c->journal_keys.ref));
        bch2_fs_btree_write_buffer_exit(c);
        percpu_free_rwsem(&c->mark_lock);
        free_percpu(c->online_reserved);
@@ -706,6 +706,8 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
 
        init_rwsem(&c->gc_lock);
        mutex_init(&c->gc_gens_lock);
+       atomic_set(&c->journal_keys.ref, 1);
+       c->journal_keys.initial_ref_held = true;
 
        for (i = 0; i < BCH_TIME_STAT_NR; i++)
                bch2_time_stats_init(&c->times[i]);
This page took 0.068577 seconds and 4 git commands to generate.