diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-01-07 22:55:42 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-01-07 22:55:42 -0500 |
commit | 44aba34548e1cc6d0affb2c0af02c33c884b5706 (patch) | |
tree | 96bdf2b0e72fa4b832320c8729bf541a3e14afc0 | |
parent | 0fc4378a90017ccd2476f15617845112dbec8755 (diff) |
bcachefs: Fix rereplicate when we already have a cached pointerbcachefs-data_update_fix
When we need to add more replicas to an extent, it might be the case
that we already have a replica on every device, but some of them are
cached.
This patch fixes a bug where we'd spin on that extent because the write
path fails to find a device we can allocate from: we allow allocating
from devices that already have cached replicas on them, and change
bch2_data_update_index_update() to drop the cached replica if needed.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/data_update.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/fs/bcachefs/data_update.c b/fs/bcachefs/data_update.c index e764597428c7..259bd243fc5b 100644 --- a/fs/bcachefs/data_update.c +++ b/fs/bcachefs/data_update.c @@ -182,7 +182,17 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, /* Add new ptrs: */ extent_for_each_ptr_decode(extent_i_to_s(new), p, entry) { - if (bch2_bkey_has_device(bkey_i_to_s_c(insert), p.ptr.dev)) { + const struct bch_extent_ptr *existing_ptr = + bch2_bkey_has_device(bkey_i_to_s_c(insert), p.ptr.dev); + + if (existing_ptr && existing_ptr->cached) { + /* + * We're replacing a cached pointer with a non + * cached pointer: + */ + bch2_bkey_drop_device_noerror(bkey_i_to_s(insert), + existing_ptr->dev); + } else if (existing_ptr) { /* * raced with another move op? extent already * has a pointer to the device we just wrote @@ -432,7 +442,8 @@ int bch2_data_update_init(struct btree_trans *trans, p.ptr.cached) BUG(); - if (!((1U << i) & m->data_opts.rewrite_ptrs)) + if (!((1U << i) & m->data_opts.rewrite_ptrs) && + !p.ptr.cached) bch2_dev_list_add_dev(&m->op.devs_have, p.ptr.dev); if (((1U << i) & m->data_opts.rewrite_ptrs) && |