diff options
-rw-r--r-- | fs/bcachefs/data_update.c | 6 | ||||
-rw-r--r-- | fs/bcachefs/extents.c | 32 | ||||
-rw-r--r-- | fs/bcachefs/extents.h | 2 |
3 files changed, 37 insertions, 3 deletions
diff --git a/fs/bcachefs/data_update.c b/fs/bcachefs/data_update.c index c3adc7b32e19..c98a393f4916 100644 --- a/fs/bcachefs/data_update.c +++ b/fs/bcachefs/data_update.c @@ -97,8 +97,10 @@ static void bch2_bkey_mark_dev_cached(struct bkey_s k, unsigned dev) struct bch_extent_ptr *ptr; bkey_for_each_ptr(ptrs, ptr) - if (ptr->dev == dev) - ptr->cached = true; + if (ptr->dev == dev) { + bch2_extent_ptr_set_cached(k, ptr); + return; + } } static int __bch2_data_update_index_update(struct btree_trans *trans, diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c index 4b865949768f..2e41545dc1e9 100644 --- a/fs/bcachefs/extents.c +++ b/fs/bcachefs/extents.c @@ -950,6 +950,29 @@ bool bch2_extent_has_ptr(struct bkey_s_c k1, struct extent_ptr_decoded p1, return false; } +void bch2_extent_ptr_set_cached(struct bkey_s k, struct bch_extent_ptr *ptr) +{ + struct bkey_ptrs ptrs = bch2_bkey_ptrs(k); + union bch_extent_entry *entry; + union bch_extent_entry *ec = NULL; + + bkey_extent_entry_for_each(ptrs, entry) { + if (&entry->ptr == ptr) { + ptr->cached = true; + if (ec) + extent_entry_drop(k, ec); + return; + } + + if (extent_entry_is_stripe_ptr(entry)) + ec = entry; + else if (extent_entry_is_ptr(entry)) + ec = NULL; + } + + BUG(); +} + /* * bch_extent_normalize - clean up an extent, dropping stale pointers etc. * @@ -1093,7 +1116,7 @@ int bch2_bkey_ptrs_invalid(const struct bch_fs *c, struct bkey_s_c k, unsigned size_ondisk = k.k->size; unsigned nonce = UINT_MAX; unsigned nr_ptrs = 0; - bool unwritten = false; + bool unwritten = false, have_ec = false; int ret; if (bkey_is_btree_ptr(k.k)) @@ -1129,7 +1152,13 @@ int bch2_bkey_ptrs_invalid(const struct bch_fs *c, struct bkey_s_c k, return -BCH_ERR_invalid_bkey; } + if (entry->ptr.cached && have_ec) { + prt_printf(err, "cached, erasure coded ptr"); + return -BCH_ERR_invalid_bkey; + } + unwritten = entry->ptr.unwritten; + have_ec = false; nr_ptrs++; break; case BCH_EXTENT_ENTRY_crc32: @@ -1165,6 +1194,7 @@ int bch2_bkey_ptrs_invalid(const struct bch_fs *c, struct bkey_s_c k, } break; case BCH_EXTENT_ENTRY_stripe_ptr: + have_ec = true; break; } } diff --git a/fs/bcachefs/extents.h b/fs/bcachefs/extents.h index 1d8f3b309b07..c52a09832857 100644 --- a/fs/bcachefs/extents.h +++ b/fs/bcachefs/extents.h @@ -655,6 +655,8 @@ bool bch2_bkey_matches_ptr(struct bch_fs *, struct bkey_s_c, bool bch2_extents_match(struct bkey_s_c, struct bkey_s_c); bool bch2_extent_has_ptr(struct bkey_s_c, struct extent_ptr_decoded, struct bkey_s_c); +void bch2_extent_ptr_set_cached(struct bkey_s, struct bch_extent_ptr *); + bool bch2_extent_normalize(struct bch_fs *, struct bkey_s); void bch2_bkey_ptrs_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); |