aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorGravatar Kent Overstreet <kent.overstreet@linux.dev> 2023-02-21 19:22:44 -0500
committerGravatar Kent Overstreet <kent.overstreet@linux.dev> 2023-10-22 17:09:54 -0400
commitc9163bb03b81e465019cf56d2edf47b70798e3ee (patch)
treefa4e29fa781b97bc47f7038c9d192f210f3b72bb /fs
parentbcachefs: Kill bch2_keylist_add_in_order() (diff)
downloadlinux-c9163bb03b81e465019cf56d2edf47b70798e3ee.tar.gz
linux-c9163bb03b81e465019cf56d2edf47b70798e3ee.tar.bz2
linux-c9163bb03b81e465019cf56d2edf47b70798e3ee.zip
bcachefs: Cached pointers should not be erasure coded
There's no reason to erasure code cached pointers: we'll always have another copy, and it'll be cheaper to read the other copy than do a reconstruct read. And erasure coded cached pointers would add complications that we'd rather not have to deal with, so let's make sure to disallow them. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r--fs/bcachefs/data_update.c6
-rw-r--r--fs/bcachefs/extents.c32
-rw-r--r--fs/bcachefs/extents.h2
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);