summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-06-13 15:12:04 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-06-20 22:55:59 -0400
commitf4df03cff22c4cc4e42b63a3d22d90347673c1ca (patch)
tree343b073534300e6690324f6a964ee2711880499a
parentab02dce84e82fa6eff62780878ffcb41d54055e8 (diff)
bcachefs: bch2_extent_ptr_desired_durability()
This adds a new helper for getting a pointer's durability irrespective of the device state, and uses it in the the data update path. This fixes a bug where we do a data update but request 0 replicas to be allocated, because the replica being rewritten is on a device marked as failed. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/data_update.c2
-rw-r--r--fs/bcachefs/extents.c28
-rw-r--r--fs/bcachefs/extents.h1
3 files changed, 23 insertions, 8 deletions
diff --git a/fs/bcachefs/data_update.c b/fs/bcachefs/data_update.c
index c89ee14f8b6b..9f7a30c7ad36 100644
--- a/fs/bcachefs/data_update.c
+++ b/fs/bcachefs/data_update.c
@@ -474,7 +474,7 @@ int bch2_data_update_init(struct btree_trans *trans,
if (crc_is_compressed(p.crc))
reserve_sectors += k.k->size;
- m->op.nr_replicas += bch2_extent_ptr_durability(c, &p);
+ m->op.nr_replicas += bch2_extent_ptr_desired_durability(c, &p);
} else if (!p.ptr.cached) {
bch2_dev_list_add_dev(&m->op.devs_have, p.ptr.dev);
}
diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c
index e2b126ad2bab..7e00550980de 100644
--- a/fs/bcachefs/extents.c
+++ b/fs/bcachefs/extents.c
@@ -641,9 +641,8 @@ unsigned bch2_bkey_replicas(struct bch_fs *c, struct bkey_s_c k)
return replicas;
}
-unsigned bch2_extent_ptr_durability(struct bch_fs *c, struct extent_ptr_decoded *p)
+unsigned bch2_extent_ptr_desired_durability(struct bch_fs *c, struct extent_ptr_decoded *p)
{
- unsigned durability = 0;
struct bch_dev *ca;
if (p->ptr.cached)
@@ -651,13 +650,28 @@ unsigned bch2_extent_ptr_durability(struct bch_fs *c, struct extent_ptr_decoded
ca = bch_dev_bkey_exists(c, p->ptr.dev);
- if (ca->mi.state != BCH_MEMBER_STATE_failed)
- durability = max_t(unsigned, durability, ca->mi.durability);
+ return ca->mi.durability +
+ (p->has_ec
+ ? p->ec.redundancy
+ : 0);
+}
- if (p->has_ec)
- durability += p->ec.redundancy;
+unsigned bch2_extent_ptr_durability(struct bch_fs *c, struct extent_ptr_decoded *p)
+{
+ struct bch_dev *ca;
- return durability;
+ if (p->ptr.cached)
+ return 0;
+
+ ca = bch_dev_bkey_exists(c, p->ptr.dev);
+
+ if (ca->mi.state == BCH_MEMBER_STATE_failed)
+ return 0;
+
+ return ca->mi.durability +
+ (p->has_ec
+ ? p->ec.redundancy
+ : 0);
}
unsigned bch2_bkey_durability(struct bch_fs *c, struct bkey_s_c k)
diff --git a/fs/bcachefs/extents.h b/fs/bcachefs/extents.h
index 31c8140950e0..3ba41e37d864 100644
--- a/fs/bcachefs/extents.h
+++ b/fs/bcachefs/extents.h
@@ -610,6 +610,7 @@ bool bch2_bkey_is_incompressible(struct bkey_s_c);
unsigned bch2_bkey_sectors_compressed(struct bkey_s_c);
unsigned bch2_bkey_replicas(struct bch_fs *, struct bkey_s_c);
+unsigned bch2_extent_ptr_desired_durability(struct bch_fs *, struct extent_ptr_decoded *);
unsigned bch2_extent_ptr_durability(struct bch_fs *, struct extent_ptr_decoded *);
unsigned bch2_bkey_durability(struct bch_fs *, struct bkey_s_c);