diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-08-13 20:04:08 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:10:11 +0300 |
commit | e9679b4a0618b0b55d22ec555bc9c6b2dab39809 (patch) | |
tree | 037488daf9a9ef36a9faf95a72fb5332cdd5cf55 | |
parent | a125c0742ccb0b5f2bc84f3f1a8bcee173c1130d (diff) | |
download | linux-e9679b4a0618b0b55d22ec555bc9c6b2dab39809.tar.xz |
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>
-rw-r--r-- | fs/bcachefs/extents.c | 13 |
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; |