]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/recovery.c
Update bcachefs sources to 7e03c1ab0e bcachefs: Kill bchfs_extent_update()
[bcachefs-tools-debian] / libbcachefs / recovery.c
index 535e2b6a15fbbbc7727077078aa999aeb6eaa4a3..095eef3828ceca486ee6020cc73cc7f793f4e8f5 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 
 #include "bcachefs.h"
 #include "alloc_background.h"
@@ -9,6 +10,7 @@
 #include "dirent.h"
 #include "ec.h"
 #include "error.h"
+#include "fs-common.h"
 #include "fsck.h"
 #include "journal_io.h"
 #include "journal_reclaim.h"
 
 #define QSTR(n) { { { .len = strlen(n) } }, .name = n }
 
+/* iterate over keys read from the journal: */
+
+struct journal_iter bch2_journal_iter_init(struct journal_keys *keys,
+                                          enum btree_id id)
+{
+       return (struct journal_iter) {
+               .keys           = keys,
+               .k              = keys->d,
+               .btree_id       = id,
+       };
+}
+
+struct bkey_s_c bch2_journal_iter_peek(struct journal_iter *iter)
+{
+       while (1) {
+               if (iter->k == iter->keys->d + iter->keys->nr)
+                       return bkey_s_c_null;
+
+               if (iter->k->btree_id == iter->btree_id)
+                       return bkey_i_to_s_c(iter->k->k);
+
+               iter->k++;
+       }
+
+       return bkey_s_c_null;
+}
+
+struct bkey_s_c bch2_journal_iter_next(struct journal_iter *iter)
+{
+       if (iter->k == iter->keys->d + iter->keys->nr)
+               return bkey_s_c_null;
+
+       iter->k++;
+       return bch2_journal_iter_peek(iter);
+}
+
 /* sort and dedup all keys in the journal: */
 
 static void journal_entries_free(struct list_head *list)
@@ -199,7 +237,8 @@ static void replay_now_at(struct journal *j, u64 seq)
                bch2_journal_pin_put(j, j->replay_journal_seq++);
 }
 
-static int bch2_extent_replay_key(struct bch_fs *c, struct bkey_i *k)
+static int bch2_extent_replay_key(struct bch_fs *c, enum btree_id btree_id,
+                                 struct bkey_i *k)
 {
        struct btree_trans trans;
        struct btree_iter *iter, *split_iter;
@@ -210,14 +249,21 @@ static int bch2_extent_replay_key(struct bch_fs *c, struct bkey_i *k)
        struct disk_reservation disk_res =
                bch2_disk_reservation_init(c, 0);
        struct bkey_i *split;
-       bool split_compressed = false;
+       struct bpos atomic_end;
+       /*
+        * Some extents aren't equivalent - w.r.t. what the triggers do
+        * - if they're split:
+        */
+       bool remark_if_split = bch2_extent_is_compressed(bkey_i_to_s_c(k)) ||
+               k->k.type == KEY_TYPE_reflink_p;
+       bool remark = false;
        int ret;
 
        bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
 retry:
        bch2_trans_begin(&trans);
 
-       iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
+       iter = bch2_trans_get_iter(&trans, btree_id,
                                   bkey_start_pos(&k->k),
                                   BTREE_ITER_INTENT);
 
@@ -226,6 +272,8 @@ retry:
                if (ret)
                        goto err;
 
+               atomic_end = bpos_min(k->k.p, iter->l[0].b->key.k.p);
+
                split_iter = bch2_trans_copy_iter(&trans, iter);
                ret = PTR_ERR_OR_ZERO(split_iter);
                if (ret)
@@ -236,29 +284,29 @@ retry:
                if (ret)
                        goto err;
 
-               if (!split_compressed &&
-                   bch2_extent_is_compressed(bkey_i_to_s_c(k)) &&
-                   !bch2_extent_is_atomic(k, split_iter)) {
+               if (!remark &&
+                   remark_if_split &&
+                   bkey_cmp(atomic_end, k->k.p) < 0) {
                        ret = bch2_disk_reservation_add(c, &disk_res,
                                        k->k.size *
                                        bch2_bkey_nr_dirty_ptrs(bkey_i_to_s_c(k)),
                                        BCH_DISK_RESERVATION_NOFAIL);
                        BUG_ON(ret);
 
-                       split_compressed = true;
+                       remark = true;
                }
 
                bkey_copy(split, k);
                bch2_cut_front(split_iter->pos, split);
-               bch2_extent_trim_atomic(split, split_iter);
+               bch2_cut_back(atomic_end, &split->k);
 
-               bch2_trans_update(&trans, BTREE_INSERT_ENTRY(split_iter, split));
+               bch2_trans_update(&trans, split_iter, split);
                bch2_btree_iter_set_pos(iter, split->k.p);
        } while (bkey_cmp(iter->pos, k->k.p) < 0);
 
-       if (split_compressed) {
+       if (remark) {
                ret = bch2_trans_mark_key(&trans, bkey_i_to_s_c(k),
-                                         -((s64) k->k.size),
+                                         0, -((s64) k->k.size),
                                          BCH_BUCKET_MARK_OVERWRITE) ?:
                      bch2_trans_commit(&trans, &disk_res, NULL,
                                        BTREE_INSERT_ATOMIC|
@@ -298,22 +346,17 @@ static int bch2_journal_replay(struct bch_fs *c,
        for_each_journal_key(keys, i) {
                replay_now_at(j, keys.journal_seq_base + i->journal_seq);
 
-               switch (i->btree_id) {
-               case BTREE_ID_ALLOC:
+               if (i->btree_id == BTREE_ID_ALLOC)
                        ret = bch2_alloc_replay_key(c, i->k);
-                       break;
-               case BTREE_ID_EXTENTS:
-                       ret = bch2_extent_replay_key(c, i->k);
-                       break;
-               default:
+               else if (btree_node_type_is_extents(i->btree_id))
+                       ret = bch2_extent_replay_key(c, i->btree_id, i->k);
+               else
                        ret = bch2_btree_insert(c, i->btree_id, i->k,
                                                NULL, NULL,
                                                BTREE_INSERT_NOFAIL|
                                                BTREE_INSERT_LAZY_RW|
                                                BTREE_INSERT_JOURNAL_REPLAY|
                                                BTREE_INSERT_NOMARK);
-                       break;
-               }
 
                if (ret) {
                        bch_err(c, "journal replay: error %d while replaying key",
@@ -378,7 +421,15 @@ static int journal_replay_entry_early(struct bch_fs *c,
 
        switch (entry->type) {
        case BCH_JSET_ENTRY_btree_root: {
-               struct btree_root *r = &c->btree_roots[entry->btree_id];
+               struct btree_root *r;
+
+               if (entry->btree_id >= BTREE_ID_NR) {
+                       bch_err(c, "filesystem has unknown btree type %u",
+                               entry->btree_id);
+                       return -EINVAL;
+               }
+
+               r = &c->btree_roots[entry->btree_id];
 
                if (entry->u64s) {
                        r->level = entry->level;
@@ -606,7 +657,7 @@ static int read_btree_roots(struct bch_fs *c)
                        continue;
 
                if (i == BTREE_ID_ALLOC &&
-                   test_reconstruct_alloc(c)) {
+                   c->opts.reconstruct_alloc) {
                        c->sb.compat &= ~(1ULL << BCH_COMPAT_FEAT_ALLOC_INFO);
                        continue;
                }
@@ -720,10 +771,12 @@ int bch2_fs_recovery(struct bch_fs *c)
 
        ret = bch2_blacklist_table_initialize(c);
 
-       ret = verify_journal_entries_not_blacklisted_or_missing(c,
-                                               &journal_entries);
-       if (ret)
-               goto err;
+       if (!list_empty(&journal_entries)) {
+               ret = verify_journal_entries_not_blacklisted_or_missing(c,
+                                                       &journal_entries);
+               if (ret)
+                       goto err;
+       }
 
        ret = bch2_fs_journal_start(&c->journal, journal_seq,
                                    &journal_entries);
@@ -881,7 +934,9 @@ out:
        ret = 0;
 err:
 fsck_err:
+       set_bit(BCH_FS_FSCK_DONE, &c->flags);
        bch2_flush_fsck_errs(c);
+
        journal_keys_free(&journal_keys);
        journal_entries_free(&journal_entries);
        kfree(clean);
@@ -896,7 +951,6 @@ int bch2_fs_initialize(struct bch_fs *c)
 {
        struct bch_inode_unpacked root_inode, lostfound_inode;
        struct bkey_inode_buf packed_inode;
-       struct bch_hash_info root_hash_info;
        struct qstr lostfound = QSTR("lost+found");
        const char *err = "cannot allocate memory";
        struct bch_dev *ca;
@@ -941,7 +995,6 @@ int bch2_fs_initialize(struct bch_fs *c)
        bch2_inode_init(c, &root_inode, 0, 0,
                        S_IFDIR|S_IRWXU|S_IRUGO|S_IXUGO, 0, NULL);
        root_inode.bi_inum = BCACHEFS_ROOT_INO;
-       root_inode.bi_nlink++; /* lost+found */
        bch2_inode_pack(&packed_inode, &root_inode);
 
        err = "error creating root directory";
@@ -951,24 +1004,15 @@ int bch2_fs_initialize(struct bch_fs *c)
        if (ret)
                goto err;
 
-       bch2_inode_init(c, &lostfound_inode, 0, 0,
-                       S_IFDIR|S_IRWXU|S_IRUGO|S_IXUGO, 0,
-                       &root_inode);
-       lostfound_inode.bi_inum = BCACHEFS_ROOT_INO + 1;
-       bch2_inode_pack(&packed_inode, &lostfound_inode);
+       bch2_inode_init_early(c, &lostfound_inode);
 
        err = "error creating lost+found";
-       ret = bch2_btree_insert(c, BTREE_ID_INODES,
-                               &packed_inode.inode.k_i,
-                               NULL, NULL, 0);
-       if (ret)
-               goto err;
-
-       root_hash_info = bch2_hash_info_init(c, &root_inode);
-
-       ret = bch2_dirent_create(c, BCACHEFS_ROOT_INO, &root_hash_info, DT_DIR,
-                                &lostfound, lostfound_inode.bi_inum, NULL,
-                                BTREE_INSERT_NOFAIL);
+       ret = bch2_trans_do(c, NULL, BTREE_INSERT_ATOMIC,
+               bch2_create_trans(&trans, BCACHEFS_ROOT_INO,
+                                 &root_inode, &lostfound_inode,
+                                 &lostfound,
+                                 0, 0, 0755, 0,
+                                 NULL, NULL));
        if (ret)
                goto err;