diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-10-18 14:46:57 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2021-10-19 12:39:27 -0400 |
commit | 56bc61587d7b8491f3449b9dd85009e90baa2cda (patch) | |
tree | 1f9057b4d139a92dfe111a4f6f395c79c9c88e81 | |
parent | 1e8ccfd9c1687a3ce501ffaabaad26593063deb9 (diff) |
bcachefs: Fix a cache coherency bug in bch2_subvolume_create()
Subvolume deletion doesn't flush & evict the btree key cache - ideally
it would, but that's tricky, so instead bch2_subvolume_create() needs to
make sure the slot doesn't exist in the key cache to avoid triggering
assertions.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/subvolume.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/bcachefs/subvolume.c b/fs/bcachefs/subvolume.c index d1c111050c35..9bd8d61c96fe 100644 --- a/fs/bcachefs/subvolume.c +++ b/fs/bcachefs/subvolume.c @@ -886,6 +886,7 @@ int bch2_subvolume_create(struct btree_trans *trans, u64 inode, u32 *new_snapshotid, bool ro) { + struct bch_fs *c = trans->c; struct btree_iter dst_iter, src_iter = (struct btree_iter) { NULL }; struct bkey_i_subvolume *new_subvol = NULL; struct bkey_i_subvolume *src_subvol = NULL; @@ -897,7 +898,13 @@ int bch2_subvolume_create(struct btree_trans *trans, u64 inode, BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) { if (bkey_cmp(k.k->p, SUBVOL_POS_MAX) > 0) break; - if (bkey_deleted(k.k)) + + /* + * bch2_subvolume_delete() doesn't flush the btree key cache - + * ideally it would but that's tricky + */ + if (bkey_deleted(k.k) && + !bch2_btree_key_cache_find(c, BTREE_ID_subvolumes, dst_iter.pos)) goto found_slot; } @@ -925,7 +932,7 @@ found_slot: goto err; if (k.k->type != KEY_TYPE_subvolume) { - bch_err(trans->c, "subvolume %u not found", src_subvolid); + bch_err(c, "subvolume %u not found", src_subvolid); ret = -ENOENT; goto err; } |