summaryrefslogtreecommitdiff
path: root/fs/bcachefs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/super.c')
-rw-r--r--fs/bcachefs/super.c49
1 files changed, 29 insertions, 20 deletions
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index 17bdf985559c..38920fff4500 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -404,7 +404,7 @@ static int bch2_fs_read_write_late(struct bch_fs *c)
return 0;
}
-int __bch2_fs_read_write(struct bch_fs *c, bool early)
+static int __bch2_fs_read_write(struct bch_fs *c, bool early)
{
struct bch_dev *ca;
unsigned i;
@@ -735,9 +735,9 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
if (bch2_fs_init_fault("fs_alloc"))
goto err;
- iter_size = sizeof(struct btree_node_iter_large) +
+ iter_size = sizeof(struct sort_iter) +
(btree_blocks(c) + 1) * 2 *
- sizeof(struct btree_node_iter_set);
+ sizeof(struct sort_iter_set);
if (!(c->wq = alloc_workqueue("bcachefs",
WQ_FREEZABLE|WQ_MEM_RECLAIM|WQ_CPU_INTENSIVE, 1)) ||
@@ -1416,7 +1416,11 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
mutex_lock(&c->state_lock);
- percpu_ref_put(&ca->ref); /* XXX */
+ /*
+ * We consume a reference to ca->ref, regardless of whether we succeed
+ * or fail:
+ */
+ percpu_ref_put(&ca->ref);
if (!bch2_dev_state_allowed(c, ca, BCH_MEMBER_STATE_FAILED, flags)) {
bch_err(ca, "Cannot remove without losing data");
@@ -1425,11 +1429,6 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
__bch2_dev_read_only(c, ca);
- /*
- * XXX: verify that dev_idx is really not in use anymore, anywhere
- *
- * flag_data_bad() does not check btree pointers
- */
ret = bch2_dev_data_drop(c, ca->dev_idx, flags);
if (ret) {
bch_err(ca, "Remove failed: error %i dropping data", ret);
@@ -1442,17 +1441,6 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
goto err;
}
- data = bch2_dev_has_data(c, ca);
- if (data) {
- char data_has_str[100];
-
- bch2_flags_to_text(&PBUF(data_has_str),
- bch2_data_types, data);
- bch_err(ca, "Remove failed, still has data (%s)", data_has_str);
- ret = -EBUSY;
- goto err;
- }
-
ret = bch2_btree_delete_range(c, BTREE_ID_ALLOC,
POS(ca->dev_idx, 0),
POS(ca->dev_idx + 1, 0),
@@ -1467,12 +1455,33 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
* (overwritten) keys that point to the device we're removing:
*/
bch2_journal_flush_all_pins(&c->journal);
+ /*
+ * hack to ensure bch2_replicas_gc2() clears out entries to this device
+ */
+ bch2_journal_meta(&c->journal);
ret = bch2_journal_error(&c->journal);
if (ret) {
bch_err(ca, "Remove failed, journal error");
goto err;
}
+ ret = bch2_replicas_gc2(c);
+ if (ret) {
+ bch_err(ca, "Remove failed: error %i from replicas gc", ret);
+ goto err;
+ }
+
+ data = bch2_dev_has_data(c, ca);
+ if (data) {
+ char data_has_str[100];
+
+ bch2_flags_to_text(&PBUF(data_has_str),
+ bch2_data_types, data);
+ bch_err(ca, "Remove failed, still has data (%s)", data_has_str);
+ ret = -EBUSY;
+ goto err;
+ }
+
__bch2_dev_offline(c, ca);
mutex_lock(&c->sb_lock);