bcachefs: New snapshot unit test
authorKent Overstreet <kent.overstreet@gmail.com>
Wed, 29 Dec 2021 18:50:50 +0000 (13:50 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:22 +0000 (17:09 -0400)
This still needs to be expanded more, but this adds a basic test for
BTREE_ITER_FILTER_SNAPSHOTS.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/subvolume.c
fs/bcachefs/subvolume.h
fs/bcachefs/tests.c

index 012d8e8c52c4bfc42e7ab895b7c3572a125fd9ea..69603327d93df6587f4e8713d249c240c8bc1fde 100644 (file)
@@ -456,10 +456,10 @@ err:
        return ret;
 }
 
-static int bch2_snapshot_node_create(struct btree_trans *trans, u32 parent,
-                                    u32 *new_snapids,
-                                    u32 *snapshot_subvols,
-                                    unsigned nr_snapids)
+int bch2_snapshot_node_create(struct btree_trans *trans, u32 parent,
+                             u32 *new_snapids,
+                             u32 *snapshot_subvols,
+                             unsigned nr_snapids)
 {
        struct btree_iter iter;
        struct bkey_i_snapshot *n;
index e4c3fdcdf22f959e61c96180f9822b1d6564ddfe..4abe53df2788466f58fe347f4611a2370fcf1f60 100644 (file)
@@ -122,6 +122,10 @@ int bch2_snapshot_get_subvol(struct btree_trans *, u32,
                             struct bch_subvolume *);
 int bch2_subvolume_get_snapshot(struct btree_trans *, u32, u32 *);
 
+/* only exported for tests: */
+int bch2_snapshot_node_create(struct btree_trans *, u32,
+                             u32 *, u32 *, unsigned);
+
 int bch2_subvolume_delete(struct btree_trans *, u32);
 int bch2_subvolume_unlink(struct btree_trans *, u32);
 int bch2_subvolume_create(struct btree_trans *, u64, u32,
index 0247309a25e6278375dc3ca16be30889199d522d..1f7f2533e544073265ba063889921c8d01cdfff1 100644 (file)
@@ -4,6 +4,7 @@
 #include "bcachefs.h"
 #include "btree_update.h"
 #include "journal_reclaim.h"
+#include "subvolume.h"
 #include "tests.h"
 
 #include "linux/kthread.h"
@@ -461,6 +462,70 @@ static int test_extent_overwrite_all(struct bch_fs *c, u64 nr)
                __test_extent_overwrite(c, 32, 64, 32, 128);
 }
 
+/* snapshot unit tests */
+
+/* Test skipping over keys in unrelated snapshots: */
+static int test_snapshot_filter(struct bch_fs *c, u32 snapid_lo, u32 snapid_hi)
+{
+       struct btree_trans trans;
+       struct btree_iter iter;
+       struct bkey_s_c k;
+       struct bkey_i_cookie cookie;
+       int ret;
+
+       bkey_cookie_init(&cookie.k_i);
+       cookie.k.p.snapshot = snapid_hi;
+       ret = bch2_btree_insert(c, BTREE_ID_xattrs, &cookie.k_i,
+                               NULL, NULL, 0);
+       if (ret)
+               return ret;
+
+       bch2_trans_init(&trans, c, 0, 0);
+       bch2_trans_iter_init(&trans, &iter, BTREE_ID_xattrs,
+                            SPOS(0, 0, snapid_lo), 0);
+       k = bch2_btree_iter_peek(&iter);
+
+       BUG_ON(k.k->p.snapshot != U32_MAX);
+
+       bch2_trans_iter_exit(&trans, &iter);
+       bch2_trans_exit(&trans);
+       return ret;
+}
+
+static int test_snapshots(struct bch_fs *c, u64 nr)
+{
+       struct bkey_i_cookie cookie;
+       u32 snapids[2];
+       u32 snapid_subvols[2] = { 1, 1 };
+       int ret;
+
+       bkey_cookie_init(&cookie.k_i);
+       cookie.k.p.snapshot = U32_MAX;
+       ret = bch2_btree_insert(c, BTREE_ID_xattrs, &cookie.k_i,
+                               NULL, NULL, 0);
+       if (ret)
+               return ret;
+
+       ret = bch2_trans_do(c, NULL, NULL, 0,
+                     bch2_snapshot_node_create(&trans, U32_MAX,
+                                               snapids,
+                                               snapid_subvols,
+                                               2));
+       if (ret)
+               return ret;
+
+       if (snapids[0] > snapids[1])
+               swap(snapids[0], snapids[1]);
+
+       ret = test_snapshot_filter(c, snapids[0], snapids[1]);
+       if (ret) {
+               bch_err(c, "err %i from test_snapshot_filter", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 /* perf tests */
 
 static u64 test_rand(void)
@@ -789,8 +854,10 @@ static int btree_perf_test_thread(void *data)
        }
 
        ret = j->fn(j->c, div64_u64(j->nr, j->nr_threads));
-       if (ret)
+       if (ret) {
+               bch_err(j->c, "%ps: error %i", j->fn, ret);
                j->ret = ret;
+       }
 
        if (atomic_dec_and_test(&j->done)) {
                j->finish = sched_clock();
@@ -843,6 +910,8 @@ int bch2_btree_perf_test(struct bch_fs *c, const char *testname,
        perf_test(test_extent_overwrite_middle);
        perf_test(test_extent_overwrite_all);
 
+       perf_test(test_snapshots);
+
        if (!j.fn) {
                pr_err("unknown test %s", testname);
                return -EINVAL;