Skip to content

Commit

Permalink
bcachefs: bch2_dev_remove_stripes()
Browse files Browse the repository at this point in the history
We can now correctly force-remove a device that has stripes on it; this
uses the new BCH_SB_MEMBER_INVALID sentinal value.

Signed-off-by: Kent Overstreet <[email protected]>
  • Loading branch information
Kent Overstreet committed Sep 7, 2024
1 parent 92dc188 commit 5509e47
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 3 deletions.
7 changes: 4 additions & 3 deletions fs/bcachefs/alloc_background.c
Original file line number Diff line number Diff line change
Expand Up @@ -2310,18 +2310,19 @@ int bch2_dev_remove_alloc(struct bch_fs *c, struct bch_dev *ca)
* We clear the LRU and need_discard btrees first so that we don't race
* with bch2_do_invalidates() and bch2_do_discards()
*/
ret = bch2_btree_delete_range(c, BTREE_ID_lru, start, end,
ret = bch2_dev_remove_stripes(c, ca) ?:
bch2_btree_delete_range(c, BTREE_ID_lru, start, end,
BTREE_TRIGGER_norun, NULL) ?:
bch2_btree_delete_range(c, BTREE_ID_need_discard, start, end,
BTREE_TRIGGER_norun, NULL) ?:
bch2_btree_delete_range(c, BTREE_ID_freespace, start, end,
BTREE_TRIGGER_norun, NULL) ?:
bch2_btree_delete_range(c, BTREE_ID_backpointers, start, end,
BTREE_TRIGGER_norun, NULL) ?:
bch2_btree_delete_range(c, BTREE_ID_alloc, start, end,
BTREE_TRIGGER_norun, NULL) ?:
bch2_btree_delete_range(c, BTREE_ID_bucket_gens, start, end,
BTREE_TRIGGER_norun, NULL) ?:
bch2_btree_delete_range(c, BTREE_ID_alloc, start, end,
BTREE_TRIGGER_norun, NULL) ?:
bch2_dev_usage_remove(c, ca->dev_idx);
bch_err_msg(c, ret, "removing dev alloc info");
return ret;
Expand Down
73 changes: 73 additions & 0 deletions fs/bcachefs/ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -2169,6 +2169,79 @@ struct ec_stripe_head *bch2_ec_stripe_head_get(struct btree_trans *trans,
return ERR_PTR(ret);
}

/* device removal */

static int bch2_invalidate_stripe_to_dev(struct btree_trans *trans, struct bkey_s_c k_a)
{
struct bch_alloc_v4 a_convert;
const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k_a, &a_convert);

if (!a->stripe)
return 0;

if (a->stripe_sectors) {
bch_err(trans->c, "trying to invalidate device in stripe when bucket has stripe data");
return -BCH_ERR_invalidate_stripe_to_dev;
}

struct btree_iter iter;
struct bkey_i_stripe *s =
bch2_bkey_get_mut_typed(trans, &iter, BTREE_ID_stripes, POS(0, a->stripe),
BTREE_ITER_slots, stripe);
int ret = PTR_ERR_OR_ZERO(s);
if (ret)
return ret;

struct disk_accounting_pos acc = {
.type = BCH_DISK_ACCOUNTING_replicas,
};

s64 sectors = 0;
for (unsigned i = 0; i < s->v.nr_blocks; i++)
sectors -= stripe_blockcount_get(&s->v, i);

bch2_bkey_to_replicas(&acc.replicas, bkey_i_to_s_c(&s->k_i));
acc.replicas.data_type = BCH_DATA_user;
ret = bch2_disk_accounting_mod(trans, &acc, &sectors, 1, false);
if (ret)
goto err;

struct bkey_ptrs ptrs = bch2_bkey_ptrs(bkey_i_to_s(&s->k_i));
bkey_for_each_ptr(ptrs, ptr)
if (ptr->dev == k_a.k->p.inode) {
if (stripe_blockcount_get(&s->v, ptr - &ptrs.start->ptr)) {
bch_err(trans->c, "trying to invalidate device in stripe when stripe block not empty");
ret = -BCH_ERR_invalidate_stripe_to_dev;
goto err;
}
ptr->dev = BCH_SB_MEMBER_INVALID;
}

sectors = -sectors;

bch2_bkey_to_replicas(&acc.replicas, bkey_i_to_s_c(&s->k_i));
acc.replicas.data_type = BCH_DATA_user;
ret = bch2_disk_accounting_mod(trans, &acc, &sectors, 1, false);
if (ret)
goto err;
err:
bch2_trans_iter_exit(trans, &iter);
return ret;
}

int bch2_dev_remove_stripes(struct bch_fs *c, struct bch_dev *ca)
{
return bch2_trans_run(c,
for_each_btree_key_upto_commit(trans, iter,
BTREE_ID_alloc, POS(ca->dev_idx, 0), POS(ca->dev_idx, U64_MAX),
BTREE_ITER_intent, k,
NULL, NULL, 0, ({
bch2_invalidate_stripe_to_dev(trans, k);
})));
}

/* startup/shutdown */

static void __bch2_ec_stop(struct bch_fs *c, struct bch_dev *ca)
{
struct ec_stripe_head *h;
Expand Down
2 changes: 2 additions & 0 deletions fs/bcachefs/ec.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ static inline void ec_stripe_new_put(struct bch_fs *c, struct ec_stripe_new *s,
}
}

int bch2_dev_remove_stripes(struct bch_fs *, struct bch_dev *);

void bch2_ec_stop_dev(struct bch_fs *, struct bch_dev *);
void bch2_fs_ec_stop(struct bch_fs *);
void bch2_fs_ec_flush(struct bch_fs *);
Expand Down
1 change: 1 addition & 0 deletions fs/bcachefs/errcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@
x(EIO, key_type_error) \
x(EIO, no_device_to_read_from) \
x(EIO, missing_indirect_extent) \
x(EIO, invalidate_stripe_to_dev) \
x(BCH_ERR_btree_node_read_err, btree_node_read_err_fixable) \
x(BCH_ERR_btree_node_read_err, btree_node_read_err_want_retry) \
x(BCH_ERR_btree_node_read_err, btree_node_read_err_must_retry) \
Expand Down

0 comments on commit 5509e47

Please sign in to comment.