]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/btree_journal_iter.c
Merge remote-tracking branch 'amoz/devel'
[bcachefs-tools-debian] / libbcachefs / btree_journal_iter.c
index 58a981bcf3aa8ca6749c41ca9e22655098adee14..4c084ce493a4a16eb30821a712b5ac74bb8fca67 100644 (file)
@@ -73,6 +73,7 @@ static size_t bch2_journal_key_search(struct journal_keys *keys,
        return idx_to_pos(keys, __bch2_journal_key_search(keys, id, level, pos));
 }
 
+/* Returns first non-overwritten key >= search key: */
 struct bkey_i *bch2_journal_keys_peek_upto(struct bch_fs *c, enum btree_id btree_id,
                                           unsigned level, struct bpos pos,
                                           struct bpos end_pos, size_t *idx)
@@ -80,16 +81,32 @@ 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);
 
+       while (*idx &&
+              __journal_key_cmp(btree_id, level, end_pos, idx_to_key(keys, *idx - 1)) <= 0) {
+               --(*idx);
+               iters++;
+               if (iters == 10) {
+                       *idx = 0;
+                       goto search;
+               }
+       }
+
        while ((k = *idx < keys->nr ? idx_to_key(keys, *idx) : NULL)) {
                if (__journal_key_cmp(btree_id, level, end_pos, k) < 0)
                        return NULL;
 
-               if (__journal_key_cmp(btree_id, level, pos, k) <= 0 &&
-                   !k->overwritten)
+               if (k->overwritten) {
+                       (*idx)++;
+                       continue;
+               }
+
+               if (__journal_key_cmp(btree_id, level, pos, k) <= 0)
                        return k->k;
 
                (*idx)++;
@@ -160,7 +177,7 @@ int bch2_journal_key_insert_take(struct bch_fs *c, enum btree_id id,
        struct journal_keys *keys = &c->journal_keys;
        size_t idx = bch2_journal_key_search(keys, id, level, k->k.p);
 
-       BUG_ON(test_bit(BCH_FS_RW, &c->flags));
+       BUG_ON(test_bit(BCH_FS_rw, &c->flags));
 
        if (idx < keys->size &&
            journal_key_cmp(&n, &keys->d[idx]) == 0) {
@@ -189,10 +206,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 +434,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 +454,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)