summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-06-07 23:11:26 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2018-06-11 11:35:24 -0400
commit210e5e5d91156066d2d9ba0ab49e9d689ecf0d0e (patch)
tree07e84675ffd7278c90c0d43a9673d240c5ef4dbf
parent452b9cf4ec14ee1278f8c375f7e0c4917e565b4d (diff)
bcachefs: split out recovery.c
-rw-r--r--fs/bcachefs/Makefile1
-rw-r--r--fs/bcachefs/recovery.c191
-rw-r--r--fs/bcachefs/recovery.h7
-rw-r--r--fs/bcachefs/super.c162
4 files changed, 205 insertions, 156 deletions
diff --git a/fs/bcachefs/Makefile b/fs/bcachefs/Makefile
index fb18fa79ba63..60aecf9ab299 100644
--- a/fs/bcachefs/Makefile
+++ b/fs/bcachefs/Makefile
@@ -41,6 +41,7 @@ bcachefs-y := \
opts.o \
quota.o \
rebalance.o \
+ recovery.o \
replicas.o \
siphash.o \
six.o \
diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c
new file mode 100644
index 000000000000..0a87493961c8
--- /dev/null
+++ b/fs/bcachefs/recovery.c
@@ -0,0 +1,191 @@
+
+#include "bcachefs.h"
+#include "alloc.h"
+#include "btree_gc.h"
+#include "btree_update.h"
+#include "btree_update_interior.h"
+#include "btree_io.h"
+#include "error.h"
+#include "fsck.h"
+#include "journal_io.h"
+#include "quota.h"
+#include "recovery.h"
+#include "super-io.h"
+
+int bch2_fs_recovery(struct bch_fs *c)
+{
+ const char *err = "cannot allocate memory";
+ LIST_HEAD(journal);
+ struct jset *j;
+ unsigned i;
+ int ret;
+
+ mutex_lock(&c->sb_lock);
+ if (!bch2_sb_get_replicas(c->disk_sb.sb)) {
+ bch_info(c, "building replicas info");
+ set_bit(BCH_FS_REBUILD_REPLICAS, &c->flags);
+ }
+ mutex_unlock(&c->sb_lock);
+
+ ret = bch2_journal_read(c, &journal);
+ if (ret)
+ goto err;
+
+ j = &list_entry(journal.prev, struct journal_replay, list)->j;
+
+ c->bucket_clock[READ].hand = le16_to_cpu(j->read_clock);
+ c->bucket_clock[WRITE].hand = le16_to_cpu(j->write_clock);
+
+ for (i = 0; i < BTREE_ID_NR; i++) {
+ unsigned level;
+ struct bkey_i *k;
+
+ k = bch2_journal_find_btree_root(c, j, i, &level);
+ if (!k)
+ continue;
+
+ err = "invalid btree root pointer";
+ if (IS_ERR(k))
+ goto err;
+
+ err = "error reading btree root";
+ if (bch2_btree_root_read(c, i, k, level)) {
+ if (i != BTREE_ID_ALLOC)
+ goto err;
+
+ mustfix_fsck_err(c, "error reading btree root");
+ }
+ }
+
+ for (i = 0; i < BTREE_ID_NR; i++)
+ if (!c->btree_roots[i].b)
+ bch2_btree_root_alloc(c, i);
+
+ err = "error reading allocation information";
+ ret = bch2_alloc_read(c, &journal);
+ if (ret)
+ goto err;
+
+ set_bit(BCH_FS_ALLOC_READ_DONE, &c->flags);
+
+ bch_verbose(c, "starting mark and sweep:");
+ err = "error in recovery";
+ ret = bch2_initial_gc(c, &journal);
+ if (ret)
+ goto err;
+ bch_verbose(c, "mark and sweep done");
+
+ if (c->opts.noreplay)
+ goto out;
+
+ /*
+ * bch2_fs_journal_start() can't happen sooner, or btree_gc_finish()
+ * will give spurious errors about oldest_gen > bucket_gen -
+ * this is a hack but oh well.
+ */
+ bch2_fs_journal_start(&c->journal);
+
+ err = "error starting allocator";
+ if (bch2_fs_allocator_start(c))
+ goto err;
+
+ bch_verbose(c, "starting journal replay:");
+ err = "journal replay failed";
+ ret = bch2_journal_replay(c, &journal);
+ if (ret)
+ goto err;
+ bch_verbose(c, "journal replay done");
+
+ if (c->opts.norecovery)
+ goto out;
+
+ bch_verbose(c, "starting fsck:");
+ err = "error in fsck";
+ ret = bch2_fsck(c, !c->opts.nofsck);
+ if (ret)
+ goto err;
+ bch_verbose(c, "fsck done");
+
+ if (enabled_qtypes(c)) {
+ bch_verbose(c, "reading quotas:");
+ ret = bch2_fs_quota_read(c);
+ if (ret)
+ goto err;
+ bch_verbose(c, "quotas done");
+ }
+
+out:
+ bch2_journal_entries_free(&journal);
+ return ret;
+err:
+fsck_err:
+ BUG_ON(!ret);
+ goto out;
+}
+
+int bch2_fs_initialize(struct bch_fs *c)
+{
+ struct bch_inode_unpacked inode;
+ struct bkey_inode_buf packed_inode;
+ const char *err = "cannot allocate memory";
+ struct bch_dev *ca;
+ LIST_HEAD(journal);
+ unsigned i;
+ int ret;
+
+ bch_notice(c, "initializing new filesystem");
+
+ set_bit(BCH_FS_ALLOC_READ_DONE, &c->flags);
+
+ ret = bch2_initial_gc(c, &journal);
+ if (ret)
+ goto err;
+
+ err = "unable to allocate journal buckets";
+ for_each_online_member(ca, c, i)
+ if (bch2_dev_journal_alloc(ca)) {
+ percpu_ref_put(&ca->io_ref);
+ goto err;
+ }
+
+ for (i = 0; i < BTREE_ID_NR; i++)
+ bch2_btree_root_alloc(c, i);
+
+ /*
+ * journal_res_get() will crash if called before this has
+ * set up the journal.pin FIFO and journal.cur pointer:
+ */
+ bch2_fs_journal_start(&c->journal);
+ bch2_journal_set_replay_done(&c->journal);
+
+ err = "error starting allocator";
+ if (bch2_fs_allocator_start(c))
+ goto err;
+
+ bch2_inode_init(c, &inode, 0, 0,
+ S_IFDIR|S_IRWXU|S_IRUGO|S_IXUGO, 0, NULL);
+ inode.bi_inum = BCACHEFS_ROOT_INO;
+
+ bch2_inode_pack(&packed_inode, &inode);
+
+ err = "error creating root directory";
+ if (bch2_btree_insert(c, BTREE_ID_INODES,
+ &packed_inode.inode.k_i,
+ NULL, NULL, NULL, 0))
+ goto err;
+
+ if (enabled_qtypes(c)) {
+ ret = bch2_fs_quota_read(c);
+ if (ret)
+ goto err;
+ }
+
+ err = "error writing first journal entry";
+ if (bch2_journal_meta(&c->journal))
+ goto err;
+
+ return 0;
+err:
+ BUG_ON(!ret);
+ return ret;
+}
diff --git a/fs/bcachefs/recovery.h b/fs/bcachefs/recovery.h
new file mode 100644
index 000000000000..685507e8aa97
--- /dev/null
+++ b/fs/bcachefs/recovery.h
@@ -0,0 +1,7 @@
+#ifndef _BCACHEFS_RECOVERY_H
+#define _BCACHEFS_RECOVERY_H
+
+int bch2_fs_recovery(struct bch_fs *);
+int bch2_fs_initialize(struct bch_fs *);
+
+#endif /* _BCACHEFS_RECOVERY_H */
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index a6604cb95367..bd2e197c020d 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -10,7 +10,6 @@
#include "alloc.h"
#include "btree_cache.h"
#include "btree_gc.h"
-#include "btree_update.h"
#include "btree_update_interior.h"
#include "btree_io.h"
#include "chardev.h"
@@ -26,14 +25,13 @@
#include "inode.h"
#include "io.h"
#include "journal.h"
-#include "journal_io.h"
#include "journal_reclaim.h"
-#include "keylist.h"
#include "move.h"
#include "migrate.h"
#include "movinggc.h"
#include "quota.h"
#include "rebalance.h"
+#include "recovery.h"
#include "replicas.h"
#include "super.h"
#include "super-io.h"
@@ -695,8 +693,6 @@ const char *bch2_fs_start(struct bch_fs *c)
const char *err = "cannot allocate memory";
struct bch_sb_field_members *mi;
struct bch_dev *ca;
- LIST_HEAD(journal);
- struct jset *j;
time64_t now;
unsigned i;
int ret = -EINVAL;
@@ -714,156 +710,12 @@ const char *bch2_fs_start(struct bch_fs *c)
bch2_dev_allocator_add(c, ca);
bch2_recalc_capacity(c);
- if (BCH_SB_INITIALIZED(c->disk_sb.sb)) {
- mutex_lock(&c->sb_lock);
- if (!bch2_sb_get_replicas(c->disk_sb.sb)) {
- bch_info(c, "building replicas info");
- set_bit(BCH_FS_REBUILD_REPLICAS, &c->flags);
- }
- mutex_unlock(&c->sb_lock);
-
- ret = bch2_journal_read(c, &journal);
- if (ret)
- goto err;
-
- j = &list_entry(journal.prev, struct journal_replay, list)->j;
-
- c->bucket_clock[READ].hand = le16_to_cpu(j->read_clock);
- c->bucket_clock[WRITE].hand = le16_to_cpu(j->write_clock);
-
- for (i = 0; i < BTREE_ID_NR; i++) {
- unsigned level;
- struct bkey_i *k;
-
- k = bch2_journal_find_btree_root(c, j, i, &level);
- if (!k)
- continue;
-
- err = "invalid btree root pointer";
- if (IS_ERR(k))
- goto err;
-
- err = "error reading btree root";
- if (bch2_btree_root_read(c, i, k, level)) {
- if (i != BTREE_ID_ALLOC)
- goto err;
-
- mustfix_fsck_err(c, "error reading btree root");
- }
- }
-
- for (i = 0; i < BTREE_ID_NR; i++)
- if (!c->btree_roots[i].b)
- bch2_btree_root_alloc(c, i);
-
- err = "error reading allocation information";
- ret = bch2_alloc_read(c, &journal);
- if (ret)
- goto err;
-
- set_bit(BCH_FS_ALLOC_READ_DONE, &c->flags);
-
- bch_verbose(c, "starting mark and sweep:");
- err = "error in recovery";
- ret = bch2_initial_gc(c, &journal);
- if (ret)
- goto err;
- bch_verbose(c, "mark and sweep done");
-
- if (c->opts.noreplay)
- goto recovery_done;
-
- /*
- * bch2_fs_journal_start() can't happen sooner, or btree_gc_finish()
- * will give spurious errors about oldest_gen > bucket_gen -
- * this is a hack but oh well.
- */
- bch2_fs_journal_start(&c->journal);
-
- err = "error starting allocator";
- if (bch2_fs_allocator_start(c))
- goto err;
-
- bch_verbose(c, "starting journal replay:");
- err = "journal replay failed";
- ret = bch2_journal_replay(c, &journal);
- if (ret)
- goto err;
- bch_verbose(c, "journal replay done");
-
- if (c->opts.norecovery)
- goto recovery_done;
-
- bch_verbose(c, "starting fsck:");
- err = "error in fsck";
- ret = bch2_fsck(c, !c->opts.nofsck);
- if (ret)
- goto err;
- bch_verbose(c, "fsck done");
-
- if (enabled_qtypes(c)) {
- bch_verbose(c, "reading quotas:");
- ret = bch2_fs_quota_read(c);
- if (ret)
- goto err;
- bch_verbose(c, "quotas done");
- }
- } else {
- struct bch_inode_unpacked inode;
- struct bkey_inode_buf packed_inode;
-
- bch_notice(c, "initializing new filesystem");
-
- set_bit(BCH_FS_ALLOC_READ_DONE, &c->flags);
-
- ret = bch2_initial_gc(c, &journal);
- if (ret)
- goto err;
-
- err = "unable to allocate journal buckets";
- for_each_online_member(ca, c, i)
- if (bch2_dev_journal_alloc(ca)) {
- percpu_ref_put(&ca->io_ref);
- goto err;
- }
-
- for (i = 0; i < BTREE_ID_NR; i++)
- bch2_btree_root_alloc(c, i);
-
- /*
- * journal_res_get() will crash if called before this has
- * set up the journal.pin FIFO and journal.cur pointer:
- */
- bch2_fs_journal_start(&c->journal);
- bch2_journal_set_replay_done(&c->journal);
-
- err = "error starting allocator";
- if (bch2_fs_allocator_start(c))
- goto err;
-
- bch2_inode_init(c, &inode, 0, 0,
- S_IFDIR|S_IRWXU|S_IRUGO|S_IXUGO, 0, NULL);
- inode.bi_inum = BCACHEFS_ROOT_INO;
-
- bch2_inode_pack(&packed_inode, &inode);
-
- err = "error creating root directory";
- if (bch2_btree_insert(c, BTREE_ID_INODES,
- &packed_inode.inode.k_i,
- NULL, NULL, NULL, 0))
- goto err;
-
- if (enabled_qtypes(c)) {
- ret = bch2_fs_quota_read(c);
- if (ret)
- goto err;
- }
+ ret = BCH_SB_INITIALIZED(c->disk_sb.sb)
+ ? bch2_fs_recovery(c)
+ : bch2_fs_initialize(c);
+ if (ret)
+ goto err;
- err = "error writing first journal entry";
- if (bch2_journal_meta(&c->journal))
- goto err;
- }
-recovery_done:
err = "dynamic fault";
if (bch2_fs_init_fault("fs_start"))
goto err;
@@ -894,10 +746,8 @@ recovery_done:
err = NULL;
out:
mutex_unlock(&c->state_lock);
- bch2_journal_entries_free(&journal);
return err;
err:
-fsck_err:
switch (ret) {
case BCH_FSCK_ERRORS_NOT_FIXED:
bch_err(c, "filesystem contains errors: please report this to the developers");