]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/journal_seq_blacklist.c
move Rust sources to top level, C sources into c_src
[bcachefs-tools-debian] / libbcachefs / journal_seq_blacklist.c
diff --git a/libbcachefs/journal_seq_blacklist.c b/libbcachefs/journal_seq_blacklist.c
deleted file mode 100644 (file)
index 0200e29..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include "bcachefs.h"
-#include "btree_iter.h"
-#include "eytzinger.h"
-#include "journal_seq_blacklist.h"
-#include "super-io.h"
-
-/*
- * journal_seq_blacklist machinery:
- *
- * To guarantee order of btree updates after a crash, we need to detect when a
- * btree node entry (bset) is newer than the newest journal entry that was
- * successfully written, and ignore it - effectively ignoring any btree updates
- * that didn't make it into the journal.
- *
- * If we didn't do this, we might have two btree nodes, a and b, both with
- * updates that weren't written to the journal yet: if b was updated after a,
- * but b was flushed and not a - oops; on recovery we'll find that the updates
- * to b happened, but not the updates to a that happened before it.
- *
- * Ignoring bsets that are newer than the newest journal entry is always safe,
- * because everything they contain will also have been journalled - and must
- * still be present in the journal on disk until a journal entry has been
- * written _after_ that bset was written.
- *
- * To accomplish this, bsets record the newest journal sequence number they
- * contain updates for; then, on startup, the btree code queries the journal
- * code to ask "Is this sequence number newer than the newest journal entry? If
- * so, ignore it."
- *
- * When this happens, we must blacklist that journal sequence number: the
- * journal must not write any entries with that sequence number, and it must
- * record that it was blacklisted so that a) on recovery we don't think we have
- * missing journal entries and b) so that the btree code continues to ignore
- * that bset, until that btree node is rewritten.
- */
-
-static unsigned sb_blacklist_u64s(unsigned nr)
-{
-       struct bch_sb_field_journal_seq_blacklist *bl;
-
-       return (sizeof(*bl) + sizeof(bl->start[0]) * nr) / sizeof(u64);
-}
-
-static struct bch_sb_field_journal_seq_blacklist *
-blacklist_entry_try_merge(struct bch_fs *c,
-                         struct bch_sb_field_journal_seq_blacklist *bl,
-                         unsigned i)
-{
-       unsigned nr = blacklist_nr_entries(bl);
-
-       if (le64_to_cpu(bl->start[i].end) >=
-           le64_to_cpu(bl->start[i + 1].start)) {
-               bl->start[i].end = bl->start[i + 1].end;
-               --nr;
-               memmove(&bl->start[i],
-                       &bl->start[i + 1],
-                       sizeof(bl->start[0]) * (nr - i));
-
-               bl = bch2_sb_field_resize(&c->disk_sb, journal_seq_blacklist,
-                                         sb_blacklist_u64s(nr));
-               BUG_ON(!bl);
-       }
-
-       return bl;
-}
-
-static bool bl_entry_contig_or_overlaps(struct journal_seq_blacklist_entry *e,
-                                       u64 start, u64 end)
-{
-       return !(end < le64_to_cpu(e->start) || le64_to_cpu(e->end) < start);
-}
-
-int bch2_journal_seq_blacklist_add(struct bch_fs *c, u64 start, u64 end)
-{
-       struct bch_sb_field_journal_seq_blacklist *bl;
-       unsigned i, nr;
-       int ret = 0;
-
-       mutex_lock(&c->sb_lock);
-       bl = bch2_sb_field_get(c->disk_sb.sb, journal_seq_blacklist);
-       nr = blacklist_nr_entries(bl);
-
-       for (i = 0; i < nr; i++) {
-               struct journal_seq_blacklist_entry *e =
-                       bl->start + i;
-
-               if (bl_entry_contig_or_overlaps(e, start, end)) {
-                       e->start = cpu_to_le64(min(start, le64_to_cpu(e->start)));
-                       e->end  = cpu_to_le64(max(end, le64_to_cpu(e->end)));
-
-                       if (i + 1 < nr)
-                               bl = blacklist_entry_try_merge(c,
-                                                       bl, i);
-                       if (i)
-                               bl = blacklist_entry_try_merge(c,
-                                                       bl, i - 1);
-                       goto out_write_sb;
-               }
-       }
-
-       bl = bch2_sb_field_resize(&c->disk_sb, journal_seq_blacklist,
-                                 sb_blacklist_u64s(nr + 1));
-       if (!bl) {
-               ret = -BCH_ERR_ENOSPC_sb_journal_seq_blacklist;
-               goto out;
-       }
-
-       bl->start[nr].start     = cpu_to_le64(start);
-       bl->start[nr].end       = cpu_to_le64(end);
-out_write_sb:
-       c->disk_sb.sb->features[0] |= cpu_to_le64(1ULL << BCH_FEATURE_journal_seq_blacklist_v3);
-
-       ret = bch2_write_super(c);
-out:
-       mutex_unlock(&c->sb_lock);
-
-       return ret ?: bch2_blacklist_table_initialize(c);
-}
-
-static int journal_seq_blacklist_table_cmp(const void *_l,
-                                          const void *_r, size_t size)
-{
-       const struct journal_seq_blacklist_table_entry *l = _l;
-       const struct journal_seq_blacklist_table_entry *r = _r;
-
-       return cmp_int(l->start, r->start);
-}
-
-bool bch2_journal_seq_is_blacklisted(struct bch_fs *c, u64 seq,
-                                    bool dirty)
-{
-       struct journal_seq_blacklist_table *t = c->journal_seq_blacklist_table;
-       struct journal_seq_blacklist_table_entry search = { .start = seq };
-       int idx;
-
-       if (!t)
-               return false;
-
-       idx = eytzinger0_find_le(t->entries, t->nr,
-                                sizeof(t->entries[0]),
-                                journal_seq_blacklist_table_cmp,
-                                &search);
-       if (idx < 0)
-               return false;
-
-       BUG_ON(t->entries[idx].start > seq);
-
-       if (seq >= t->entries[idx].end)
-               return false;
-
-       if (dirty)
-               t->entries[idx].dirty = true;
-       return true;
-}
-
-int bch2_blacklist_table_initialize(struct bch_fs *c)
-{
-       struct bch_sb_field_journal_seq_blacklist *bl =
-               bch2_sb_field_get(c->disk_sb.sb, journal_seq_blacklist);
-       struct journal_seq_blacklist_table *t;
-       unsigned i, nr = blacklist_nr_entries(bl);
-
-       if (!bl)
-               return 0;
-
-       t = kzalloc(sizeof(*t) + sizeof(t->entries[0]) * nr,
-                   GFP_KERNEL);
-       if (!t)
-               return -BCH_ERR_ENOMEM_blacklist_table_init;
-
-       t->nr = nr;
-
-       for (i = 0; i < nr; i++) {
-               t->entries[i].start     = le64_to_cpu(bl->start[i].start);
-               t->entries[i].end       = le64_to_cpu(bl->start[i].end);
-       }
-
-       eytzinger0_sort(t->entries,
-                       t->nr,
-                       sizeof(t->entries[0]),
-                       journal_seq_blacklist_table_cmp,
-                       NULL);
-
-       kfree(c->journal_seq_blacklist_table);
-       c->journal_seq_blacklist_table = t;
-       return 0;
-}
-
-static int bch2_sb_journal_seq_blacklist_validate(struct bch_sb *sb,
-                                                 struct bch_sb_field *f,
-                                                 struct printbuf *err)
-{
-       struct bch_sb_field_journal_seq_blacklist *bl =
-               field_to_type(f, journal_seq_blacklist);
-       unsigned i, nr = blacklist_nr_entries(bl);
-
-       for (i = 0; i < nr; i++) {
-               struct journal_seq_blacklist_entry *e = bl->start + i;
-
-               if (le64_to_cpu(e->start) >=
-                   le64_to_cpu(e->end)) {
-                       prt_printf(err, "entry %u start >= end (%llu >= %llu)",
-                              i, le64_to_cpu(e->start), le64_to_cpu(e->end));
-                       return -BCH_ERR_invalid_sb_journal_seq_blacklist;
-               }
-
-               if (i + 1 < nr &&
-                   le64_to_cpu(e[0].end) >
-                   le64_to_cpu(e[1].start)) {
-                       prt_printf(err, "entry %u out of order with next entry (%llu > %llu)",
-                              i + 1, le64_to_cpu(e[0].end), le64_to_cpu(e[1].start));
-                       return -BCH_ERR_invalid_sb_journal_seq_blacklist;
-               }
-       }
-
-       return 0;
-}
-
-static void bch2_sb_journal_seq_blacklist_to_text(struct printbuf *out,
-                                                 struct bch_sb *sb,
-                                                 struct bch_sb_field *f)
-{
-       struct bch_sb_field_journal_seq_blacklist *bl =
-               field_to_type(f, journal_seq_blacklist);
-       struct journal_seq_blacklist_entry *i;
-       unsigned nr = blacklist_nr_entries(bl);
-
-       for (i = bl->start; i < bl->start + nr; i++) {
-               if (i != bl->start)
-                       prt_printf(out, " ");
-
-               prt_printf(out, "%llu-%llu",
-                      le64_to_cpu(i->start),
-                      le64_to_cpu(i->end));
-       }
-       prt_newline(out);
-}
-
-const struct bch_sb_field_ops bch_sb_field_ops_journal_seq_blacklist = {
-       .validate       = bch2_sb_journal_seq_blacklist_validate,
-       .to_text        = bch2_sb_journal_seq_blacklist_to_text
-};
-
-void bch2_blacklist_entries_gc(struct work_struct *work)
-{
-       struct bch_fs *c = container_of(work, struct bch_fs,
-                                       journal_seq_blacklist_gc_work);
-       struct journal_seq_blacklist_table *t;
-       struct bch_sb_field_journal_seq_blacklist *bl;
-       struct journal_seq_blacklist_entry *src, *dst;
-       struct btree_trans *trans = bch2_trans_get(c);
-       unsigned i, nr, new_nr;
-       int ret;
-
-       for (i = 0; i < BTREE_ID_NR; i++) {
-               struct btree_iter iter;
-               struct btree *b;
-
-               bch2_trans_node_iter_init(trans, &iter, i, POS_MIN,
-                                         0, 0, BTREE_ITER_PREFETCH);
-retry:
-               bch2_trans_begin(trans);
-
-               b = bch2_btree_iter_peek_node(&iter);
-
-               while (!(ret = PTR_ERR_OR_ZERO(b)) &&
-                      b &&
-                      !test_bit(BCH_FS_stopping, &c->flags))
-                       b = bch2_btree_iter_next_node(&iter);
-
-               if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
-                       goto retry;
-
-               bch2_trans_iter_exit(trans, &iter);
-       }
-
-       bch2_trans_put(trans);
-       if (ret)
-               return;
-
-       mutex_lock(&c->sb_lock);
-       bl = bch2_sb_field_get(c->disk_sb.sb, journal_seq_blacklist);
-       if (!bl)
-               goto out;
-
-       nr = blacklist_nr_entries(bl);
-       dst = bl->start;
-
-       t = c->journal_seq_blacklist_table;
-       BUG_ON(nr != t->nr);
-
-       for (src = bl->start, i = eytzinger0_first(t->nr);
-            src < bl->start + nr;
-            src++, i = eytzinger0_next(i, nr)) {
-               BUG_ON(t->entries[i].start      != le64_to_cpu(src->start));
-               BUG_ON(t->entries[i].end        != le64_to_cpu(src->end));
-
-               if (t->entries[i].dirty)
-                       *dst++ = *src;
-       }
-
-       new_nr = dst - bl->start;
-
-       bch_info(c, "nr blacklist entries was %u, now %u", nr, new_nr);
-
-       if (new_nr != nr) {
-               bl = bch2_sb_field_resize(&c->disk_sb, journal_seq_blacklist,
-                               new_nr ? sb_blacklist_u64s(new_nr) : 0);
-               BUG_ON(new_nr && !bl);
-
-               if (!new_nr)
-                       c->disk_sb.sb->features[0] &= cpu_to_le64(~(1ULL << BCH_FEATURE_journal_seq_blacklist_v3));
-
-               bch2_write_super(c);
-       }
-out:
-       mutex_unlock(&c->sb_lock);
-}