summaryrefslogtreecommitdiffstats
path: root/fs/bcachefs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-08-13 19:04:08 +0200
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 23:10:11 +0200
commite9679b4a0618b0b55d22ec555bc9c6b2dab39809 (patch)
tree037488daf9a9ef36a9faf95a72fb5332cdd5cf55 /fs/bcachefs
parentbcachefs: Lower BCH_NAME_MAX to 512 (diff)
downloadlinux-e9679b4a0618b0b55d22ec555bc9c6b2dab39809.tar.xz
linux-e9679b4a0618b0b55d22ec555bc9c6b2dab39809.zip
bcachefs: Fix 'pointer to invalid device' check
This fixes the device removal tests, which have been failing at random due to the fact that when we're running the .key_invalid checks in the write path the key may actually no longer exist - we might be racing with the keys being deleted. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs')
-rw-r--r--fs/bcachefs/extents.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c
index d7f74db4c83e..1b25f84e4b9c 100644
--- a/fs/bcachefs/extents.c
+++ b/fs/bcachefs/extents.c
@@ -1059,6 +1059,7 @@ void bch2_bkey_ptrs_to_text(struct printbuf *out, struct bch_fs *c,
static int extent_ptr_invalid(const struct bch_fs *c,
struct bkey_s_c k,
+ enum bkey_invalid_flags flags,
const struct bch_extent_ptr *ptr,
unsigned size_ondisk,
bool metadata,
@@ -1071,6 +1072,14 @@ static int extent_ptr_invalid(const struct bch_fs *c,
struct bch_dev *ca;
if (!bch2_dev_exists2(c, ptr->dev)) {
+ /*
+ * If we're in the write path this key might have already been
+ * overwritten, and we could be seeing a device that doesn't
+ * exist anymore due to racing with device removal:
+ */
+ if (flags & BKEY_INVALID_WRITE)
+ return 0;
+
prt_printf(err, "pointer to invalid device (%u)", ptr->dev);
return -BCH_ERR_invalid_bkey;
}
@@ -1136,8 +1145,8 @@ int bch2_bkey_ptrs_invalid(const struct bch_fs *c, struct bkey_s_c k,
switch (extent_entry_type(entry)) {
case BCH_EXTENT_ENTRY_ptr:
- ret = extent_ptr_invalid(c, k, &entry->ptr, size_ondisk,
- false, err);
+ ret = extent_ptr_invalid(c, k, flags, &entry->ptr,
+ size_ondisk, false, err);
if (ret)
return ret;