summaryrefslogtreecommitdiff
path: root/fs/bcachefs/super.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2020-01-03 22:38:14 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2020-11-05 12:45:00 -0500
commit230706ae6f3575da39c2630abde79eb0b718c1fa (patch)
tree89b0626c6f5eaf7bfde5e070093ed66b6eded8e8 /fs/bcachefs/super.c
parent542be2759d8456ad0649038db0e673337a04a8b8 (diff)
bcachefs: Hacky fixes for device removal
The device remove test was sporadically failing, because we hadn't finished dropping btree sector counts for the device when bch2_replicas_gc2() was called - mainly due to in flight journal writes. We don't yet have a good mechanism for flushing the counts that correspend to open journal entries yet. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Diffstat (limited to 'fs/bcachefs/super.c')
-rw-r--r--fs/bcachefs/super.c43
1 files changed, 26 insertions, 17 deletions
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index 51728c21c59f..eaae12d8b3e2 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -1377,7 +1377,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");
@@ -1386,11 +1390,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);
@@ -1403,17 +1402,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),
@@ -1428,12 +1416,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);