diff options
Diffstat (limited to 'libbcachefs/recovery.c')
-rw-r--r-- | libbcachefs/recovery.c | 36 |
1 files changed, 20 insertions, 16 deletions
diff --git a/libbcachefs/recovery.c b/libbcachefs/recovery.c index 5da6b3b4..7e4400cc 100644 --- a/libbcachefs/recovery.c +++ b/libbcachefs/recovery.c @@ -519,7 +519,7 @@ static int bch2_journal_replay(struct bch_fs *c) size_t i; int ret; - keys_sorted = kmalloc_array(sizeof(*keys_sorted), keys->nr, GFP_KERNEL); + keys_sorted = kvmalloc_array(sizeof(*keys_sorted), keys->nr, GFP_KERNEL); if (!keys_sorted) return -ENOMEM; @@ -530,10 +530,8 @@ static int bch2_journal_replay(struct bch_fs *c) sizeof(keys_sorted[0]), journal_sort_seq_cmp, NULL); - if (keys->nr) { - bch_verbose(c, "starting journal replay, %zu keys", keys->nr); + if (keys->nr) replay_now_at(j, keys->journal_seq_base); - } for (i = 0; i < keys->nr; i++) { k = keys_sorted[i]; @@ -563,7 +561,7 @@ static int bch2_journal_replay(struct bch_fs *c) bch2_journal_flush_all_pins(j); ret = bch2_journal_error(j); err: - kfree(keys_sorted); + kvfree(keys_sorted); return ret; } @@ -901,7 +899,6 @@ static int bch2_fs_initialize_subvolumes(struct bch_fs *c) static int bch2_fs_upgrade_for_subvolumes(struct btree_trans *trans) { - struct bch_fs *c = trans->c; struct btree_iter iter; struct bkey_s_c k; struct bch_inode_unpacked inode; @@ -915,7 +912,7 @@ static int bch2_fs_upgrade_for_subvolumes(struct btree_trans *trans) goto err; if (!bkey_is_inode(k.k)) { - bch_err(c, "root inode not found"); + bch_err(trans->c, "root inode not found"); ret = -ENOENT; goto err; } @@ -1008,6 +1005,7 @@ int bch2_fs_recovery(struct bch_fs *c) if (!c->sb.clean || c->opts.fsck || c->opts.keep_journal) { struct journal_replay *i; + bch_verbose(c, "starting journal read"); ret = bch2_journal_read(c, &c->journal_entries, &blacklist_seq, &journal_seq); if (ret) @@ -1067,6 +1065,16 @@ use_clean: if (ret) goto err; + /* + * After an unclean shutdown, skip then next few journal sequence + * numbers as they may have been referenced by btree writes that + * happened before their corresponding journal writes - those btree + * writes need to be ignored, by skipping and blacklisting the next few + * journal sequence numbers: + */ + if (!c->sb.clean) + journal_seq += 8; + if (blacklist_seq != journal_seq) { ret = bch2_journal_seq_blacklist_add(c, blacklist_seq, journal_seq); @@ -1141,7 +1149,7 @@ use_clean: if (c->opts.norecovery) goto out; - bch_verbose(c, "starting journal replay"); + bch_verbose(c, "starting journal replay, %zu keys", c->journal_keys.nr); err = "journal replay failed"; ret = bch2_journal_replay(c); if (ret) @@ -1199,14 +1207,6 @@ use_clean: } mutex_lock(&c->sb_lock); - /* - * With journal replay done, we can clear the journal seq blacklist - * table: - */ - BUG_ON(!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags)); - if (le16_to_cpu(c->sb.version_min) >= bcachefs_metadata_version_btree_ptr_sectors_written) - bch2_sb_resize_journal_seq_blacklist(&c->disk_sb, 0); - if (c->opts.version_upgrade) { c->disk_sb.sb->version = cpu_to_le16(bcachefs_metadata_version_current); c->disk_sb.sb->features[0] |= cpu_to_le64(BCH_SB_FEATURES_ALL); @@ -1248,6 +1248,10 @@ use_clean: bch_info(c, "scanning for old btree nodes done"); } + if (c->journal_seq_blacklist_table && + c->journal_seq_blacklist_table->nr > 128) + queue_work(system_long_wq, &c->journal_seq_blacklist_gc_work); + ret = 0; out: set_bit(BCH_FS_FSCK_DONE, &c->flags); |