diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-01-08 06:55:42 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:09:49 +0300 |
commit | d7dd3fb84f05a0d221be3979929706a4828fb252 (patch) | |
tree | bc7b4e773bebdd65fe51f2fe1a36579cc5ead714 /fs/bcachefs/data_update.c | |
parent | 7c909f654bae57083a0965f105e52ac8737a0785 (diff) | |
download | linux-d7dd3fb84f05a0d221be3979929706a4828fb252.tar.xz |
bcachefs: Fix rereplicate when we already have a cached pointer
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>
Diffstat (limited to 'fs/bcachefs/data_update.c')
-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 b4480852e935..acb634b3480b 100644 --- a/fs/bcachefs/data_update.c +++ b/fs/bcachefs/data_update.c @@ -183,7 +183,17 @@ int bch2_data_update_index_update(struct bch_write_op *op) /* 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 @@ -334,7 +344,8 @@ int bch2_data_update_init(struct bch_fs *c, struct data_update *m, 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) && |