diff options
-rw-r--r-- | fs/bcachefs/errcode.h | 5 | ||||
-rw-r--r-- | fs/bcachefs/movinggc.c | 44 |
2 files changed, 36 insertions, 13 deletions
diff --git a/fs/bcachefs/errcode.h b/fs/bcachefs/errcode.h index c4344a1d6976..cbf1eedddad7 100644 --- a/fs/bcachefs/errcode.h +++ b/fs/bcachefs/errcode.h @@ -188,6 +188,11 @@ x(BCH_ERR_recovery_will_run, recovery_pass_will_run) \ x(0, data_update_done) \ x(0, bkey_was_deleted) \ + x(0, bucket_not_moveable) \ + x(BCH_ERR_bucket_not_moveable, bucket_not_moveable_dev_not_rw) \ + x(BCH_ERR_bucket_not_moveable, bucket_not_moveable_bucket_open) \ + x(BCH_ERR_bucket_not_moveable, bucket_not_moveable_bp_mismatch) \ + x(BCH_ERR_bucket_not_moveable, bucket_not_moveable_lru_race) \ x(BCH_ERR_data_update_done, data_update_done_would_block) \ x(BCH_ERR_data_update_done, data_update_done_unwritten) \ x(BCH_ERR_data_update_done, data_update_done_no_writes_needed) \ diff --git a/fs/bcachefs/movinggc.c b/fs/bcachefs/movinggc.c index f36d60b8fb07..0f7e35684bc8 100644 --- a/fs/bcachefs/movinggc.c +++ b/fs/bcachefs/movinggc.c @@ -62,25 +62,38 @@ static int bch2_bucket_is_movable(struct btree_trans *trans, { struct bch_fs *c = trans->c; - if (bch2_bucket_is_open(c, b->k.bucket.inode, b->k.bucket.offset)) + /* + * Valid bucket? + * + * XXX: we should kill the LRU entry here if it's not + */ + CLASS(bch2_dev_bucket_tryget, ca)(c, b->k.bucket); + if (!ca) return 0; - CLASS(btree_iter, iter)(trans, BTREE_ID_alloc, b->k.bucket, BTREE_ITER_cached); - struct bkey_s_c k = bch2_btree_iter_peek_slot(&iter); - int ret = bkey_err(k); - if (ret) - return ret; - - CLASS(bch2_dev_bucket_tryget, ca)(c, k.k->p); - if (!ca) + if (ca->mi.state != BCH_MEMBER_STATE_rw || + !bch2_dev_is_online(ca)) { + bch_err_throw(c, bucket_not_moveable_dev_not_rw); return 0; + } - if (bch2_bucket_bitmap_test(&ca->bucket_backpointer_mismatch, b->k.bucket.offset)) + /* Bucket still being written? */ + if (bch2_bucket_is_open(c, b->k.bucket.inode, b->k.bucket.offset)) { + bch_err_throw(c, bucket_not_moveable_bucket_open); return 0; + } - if (ca->mi.state != BCH_MEMBER_STATE_rw || - !bch2_dev_is_online(ca)) + /* We won't be able to evacuate it if there's missing backpointers */ + if (bch2_bucket_bitmap_test(&ca->bucket_backpointer_mismatch, b->k.bucket.offset)) { + bch_err_throw(c, bucket_not_moveable_bp_mismatch); return 0; + } + + CLASS(btree_iter, iter)(trans, BTREE_ID_alloc, b->k.bucket, BTREE_ITER_cached); + struct bkey_s_c k = bch2_btree_iter_peek_slot(&iter); + int ret = bkey_err(k); + if (ret) + return ret; struct bch_alloc_v4 _a; const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k, &_a); @@ -88,7 +101,12 @@ static int bch2_bucket_is_movable(struct btree_trans *trans, b->sectors = bch2_bucket_sectors_dirty(*a); u64 lru_idx = alloc_lru_idx_fragmentation(*a, ca); - return lru_idx && lru_idx <= time; + if (!lru_idx || lru_idx > time) { + bch_err_throw(c, bucket_not_moveable_lru_race); + return 0; + } + + return true; } static void move_bucket_free(struct buckets_in_flight *list, |