mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
bcachefs: bcachefs_metadata_version_fast_device_removal
Fast device removal, that uses backpointers to find pointers to the device being removed instead of a full metadata scan. This requires BCH_SB_MEMBER_DELETED_UUID, which is an incompatible change - hence the version number bump. We don't fully trust backpointers, so we don't want to reuse device indexes until after a fsck has verified that there aren't any pointers to removed devices. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
09fa6c3039
commit
a8539ad8fa
|
|
@ -696,7 +696,8 @@ struct bch_sb_field_ext {
|
|||
x(stripe_lru, BCH_VERSION(1, 23)) \
|
||||
x(casefolding, BCH_VERSION(1, 24)) \
|
||||
x(extent_flags, BCH_VERSION(1, 25)) \
|
||||
x(snapshot_deletion_v2, BCH_VERSION(1, 26))
|
||||
x(snapshot_deletion_v2, BCH_VERSION(1, 26)) \
|
||||
x(fast_device_removal, BCH_VERSION(1, 27))
|
||||
|
||||
enum bcachefs_metadata_version {
|
||||
bcachefs_metadata_version_min = 9,
|
||||
|
|
|
|||
|
|
@ -2197,13 +2197,15 @@ static int bch2_invalidate_stripe_to_dev_from_alloc(struct btree_trans *trans, s
|
|||
|
||||
int bch2_dev_remove_stripes(struct bch_fs *c, unsigned dev_idx, unsigned flags)
|
||||
{
|
||||
return bch2_trans_run(c,
|
||||
int ret = bch2_trans_run(c,
|
||||
for_each_btree_key_max_commit(trans, iter,
|
||||
BTREE_ID_alloc, POS(dev_idx, 0), POS(dev_idx, U64_MAX),
|
||||
BTREE_ITER_intent, k,
|
||||
NULL, NULL, 0, ({
|
||||
bch2_invalidate_stripe_to_dev_from_alloc(trans, k, flags);
|
||||
})));
|
||||
bch_err_fn(c, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* startup/shutdown */
|
||||
|
|
|
|||
|
|
@ -1726,6 +1726,8 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
|
|||
{
|
||||
struct bch_member *m;
|
||||
unsigned dev_idx = ca->dev_idx, data;
|
||||
bool fast_device_removal = !bch2_request_incompat_feature(c,
|
||||
bcachefs_metadata_version_fast_device_removal);
|
||||
int ret;
|
||||
|
||||
down_write(&c->state_lock);
|
||||
|
|
@ -1744,12 +1746,25 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
|
|||
|
||||
__bch2_dev_read_only(c, ca);
|
||||
|
||||
ret = bch2_dev_data_drop(c, ca->dev_idx, flags) ?:
|
||||
bch2_dev_remove_stripes(c, ca->dev_idx, flags);
|
||||
bch_err_msg(ca, ret, "bch2_dev_data_drop()");
|
||||
ret = fast_device_removal
|
||||
? bch2_dev_data_drop_by_backpointers(c, ca->dev_idx, flags)
|
||||
: (bch2_dev_data_drop(c, ca->dev_idx, flags) ?:
|
||||
bch2_dev_remove_stripes(c, ca->dev_idx, flags));
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* Check if device still has data before blowing away alloc info */
|
||||
struct bch_dev_usage usage = bch2_dev_usage_read(ca);
|
||||
for (unsigned i = 0; i < BCH_DATA_NR; i++)
|
||||
if (!data_type_is_empty(i) &&
|
||||
!data_type_is_hidden(i) &&
|
||||
usage.buckets[i]) {
|
||||
bch_err(ca, "Remove failed: still has data (%s, %llu buckets)",
|
||||
__bch2_data_types[i], usage.buckets[i]);
|
||||
ret = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = bch2_dev_remove_alloc(c, ca);
|
||||
bch_err_msg(ca, ret, "bch2_dev_remove_alloc()");
|
||||
if (ret)
|
||||
|
|
@ -1813,7 +1828,11 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
|
|||
*/
|
||||
mutex_lock(&c->sb_lock);
|
||||
m = bch2_members_v2_get_mut(c->disk_sb.sb, dev_idx);
|
||||
memset(&m->uuid, 0, sizeof(m->uuid));
|
||||
|
||||
if (fast_device_removal)
|
||||
m->uuid = BCH_SB_MEMBER_DELETED_UUID;
|
||||
else
|
||||
memset(&m->uuid, 0, sizeof(m->uuid));
|
||||
|
||||
bch2_write_super(c);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user