bcachefs: Fix a cache coherency bug in bch2_subvolume_create()
authorKent Overstreet <kent.overstreet@gmail.com>
Mon, 18 Oct 2021 18:46:57 +0000 (14:46 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:14 +0000 (17:09 -0400)
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>
fs/bcachefs/subvolume.c

index d1c111050c35cdf2601e011f504b46175ef58c2d..9bd8d61c96fef889849aab6d460ef5a41cdb2d47 100644 (file)
@@ -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;
                }