summaryrefslogtreecommitdiff
path: root/fs/bcachefs/data_update.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-01-08 06:55:42 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:09:49 +0300
commitd7dd3fb84f05a0d221be3979929706a4828fb252 (patch)
treebc7b4e773bebdd65fe51f2fe1a36579cc5ead714 /fs/bcachefs/data_update.c
parent7c909f654bae57083a0965f105e52ac8737a0785 (diff)
downloadlinux-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.c15
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) &&