summaryrefslogtreecommitdiffstats
path: root/src/test/fs
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/fs')
-rw-r--r--src/test/fs/CMakeLists.txt20
-rw-r--r--src/test/fs/mds_types.cc252
-rw-r--r--src/test/fs/test_ino_release_cb.cc81
-rw-r--r--src/test/fs/test_trim_caps.cc85
4 files changed, 438 insertions, 0 deletions
diff --git a/src/test/fs/CMakeLists.txt b/src/test/fs/CMakeLists.txt
new file mode 100644
index 000000000..70ff64afd
--- /dev/null
+++ b/src/test/fs/CMakeLists.txt
@@ -0,0 +1,20 @@
+if(${WITH_CEPHFS})
+ # unittest_mds_types
+ add_executable(unittest_mds_types
+ mds_types.cc
+ )
+ add_ceph_unittest(unittest_mds_types)
+ target_link_libraries(unittest_mds_types global)
+
+ add_executable(ceph_test_trim_caps
+ test_trim_caps.cc
+ )
+ target_link_libraries(ceph_test_trim_caps ceph-common cephfs)
+ install(TARGETS ceph_test_trim_caps DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+ add_executable(ceph_test_ino_release_cb
+ test_ino_release_cb.cc
+ )
+ target_link_libraries(ceph_test_ino_release_cb ceph-common cephfs)
+ install(TARGETS ceph_test_ino_release_cb DESTINATION ${CMAKE_INSTALL_BINDIR})
+endif(${WITH_CEPHFS})
diff --git a/src/test/fs/mds_types.cc b/src/test/fs/mds_types.cc
new file mode 100644
index 000000000..234d020a6
--- /dev/null
+++ b/src/test/fs/mds_types.cc
@@ -0,0 +1,252 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2014 Red Hat
+ *
+ * Author: Greg Farnum <greg@inktank.com>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include "gtest/gtest.h"
+#include "mds/mdstypes.h"
+#include "mds/inode_backtrace.h"
+
+TEST(inode_t, compare_equal)
+{
+ inode_t foo{};
+ inode_t bar{};
+ int compare_r;
+ bool divergent;
+ compare_r = foo.compare(bar, &divergent);
+ EXPECT_EQ(0, compare_r);
+ EXPECT_FALSE(divergent);
+ compare_r = bar.compare(foo, &divergent);
+ EXPECT_EQ(0, compare_r);
+ EXPECT_FALSE(divergent);
+
+
+ foo.ino = 1234;
+ foo.ctime.set_from_double(10.0);
+ foo.mode = 0777;
+ foo.uid = 42;
+ foo.gid = 43;
+ foo.nlink = 3;
+ foo.version = 3;
+
+ bar = foo;
+ compare_r = foo.compare(bar, &divergent);
+ EXPECT_EQ(0, compare_r);
+ EXPECT_FALSE(divergent);
+ compare_r = bar.compare(foo, &divergent);
+ EXPECT_EQ(0, compare_r);
+ EXPECT_FALSE(divergent);
+}
+
+TEST(inode_t, compare_aged)
+{
+ inode_t foo{};
+ inode_t bar{};
+
+ foo.ino = 1234;
+ foo.ctime.set_from_double(10.0);
+ foo.mode = 0777;
+ foo.uid = 42;
+ foo.gid = 43;
+ foo.nlink = 3;
+ foo.version = 3;
+ foo.rstat.version = 1;
+
+ bar = foo;
+ bar.version = 2;
+
+ int compare_r;
+ bool divergent;
+ compare_r = foo.compare(bar, &divergent);
+ EXPECT_EQ(1, compare_r);
+ EXPECT_FALSE(divergent);
+ compare_r = bar.compare(foo, &divergent);
+ EXPECT_EQ(-1, compare_r);
+ EXPECT_FALSE(divergent);
+}
+
+TEST(inode_t, compare_divergent)
+{
+ inode_t foo{};
+ inode_t bar{};
+
+ foo.ino = 1234;
+ foo.ctime.set_from_double(10.0);
+ foo.mode = 0777;
+ foo.uid = 42;
+ foo.gid = 43;
+ foo.nlink = 3;
+ foo.version = 3;
+ foo.rstat.version = 1;
+
+ bar = foo;
+ bar.version = 2;
+ bar.rstat.version = 2;
+
+ int compare_r;
+ bool divergent;
+ compare_r = foo.compare(bar, &divergent);
+ EXPECT_EQ(1, compare_r);
+ EXPECT_TRUE(divergent);
+ compare_r = bar.compare(foo, &divergent);
+ EXPECT_EQ(-1, compare_r);
+ EXPECT_TRUE(divergent);
+}
+
+TEST(inode_backtrace_t, compare_equal)
+{
+ inode_backtrace_t foo;
+ inode_backtrace_t bar;
+
+ foo.ino = 1234;
+ foo.pool = 12;
+ foo.old_pools.push_back(10);
+ foo.old_pools.push_back(5);
+
+ inode_backpointer_t foop;
+ foop.dirino = 3;
+ foop.dname = "l3";
+ foop.version = 15;
+ foo.ancestors.push_back(foop);
+ foop.dirino = 2;
+ foop.dname = "l2";
+ foop.version = 10;
+ foo.ancestors.push_back(foop);
+ foop.dirino = 1;
+ foop.dname = "l1";
+ foop.version = 25;
+ foo.ancestors.push_back(foop);
+
+ bar = foo;
+
+ int compare_r;
+ bool equivalent;
+ bool divergent;
+
+ compare_r = foo.compare(bar, &equivalent, &divergent);
+ EXPECT_EQ(0, compare_r);
+ EXPECT_TRUE(equivalent);
+ EXPECT_FALSE(divergent);
+}
+
+TEST(inode_backtrace_t, compare_newer)
+{
+ inode_backtrace_t foo;
+ inode_backtrace_t bar;
+
+ foo.ino = 1234;
+ foo.pool = 12;
+ foo.old_pools.push_back(10);
+ foo.old_pools.push_back(5);
+
+ bar.ino = 1234;
+ bar.pool = 12;
+ bar.old_pools.push_back(10);
+
+ inode_backpointer_t foop;
+ foop.dirino = 3;
+ foop.dname = "l3";
+ foop.version = 15;
+ foo.ancestors.push_back(foop);
+ foop.version = 14;
+ bar.ancestors.push_back(foop);
+
+ foop.dirino = 2;
+ foop.dname = "l2";
+ foop.version = 10;
+ foo.ancestors.push_back(foop);
+ foop.version = 9;
+ bar.ancestors.push_back(foop);
+
+ foop.dirino = 1;
+ foop.dname = "l1";
+ foop.version = 25;
+ foo.ancestors.push_back(foop);
+ bar.ancestors.push_back(foop);
+
+ int compare_r;
+ bool equivalent;
+ bool divergent;
+
+ compare_r = foo.compare(bar, &equivalent, &divergent);
+ EXPECT_EQ(1, compare_r);
+ EXPECT_TRUE(equivalent);
+ EXPECT_FALSE(divergent);
+
+ compare_r = bar.compare(foo, &equivalent, &divergent);
+ EXPECT_EQ(-1, compare_r);
+ EXPECT_TRUE(equivalent);
+ EXPECT_FALSE(divergent);
+
+ bar.ancestors.back().dirino = 75;
+ bar.ancestors.back().dname = "l1-old";
+ bar.ancestors.back().version = 70;
+
+ compare_r = foo.compare(bar, &equivalent, &divergent);
+ EXPECT_EQ(1, compare_r);
+ EXPECT_FALSE(equivalent);
+ EXPECT_FALSE(divergent);
+
+ compare_r = bar.compare(foo, &equivalent, &divergent);
+ EXPECT_EQ(-1, compare_r);
+ EXPECT_FALSE(equivalent);
+ EXPECT_FALSE(divergent);
+}
+
+TEST(inode_backtrace_t, compare_divergent)
+{
+ inode_backtrace_t foo;
+ inode_backtrace_t bar;
+
+ foo.ino = 1234;
+ foo.pool = 12;
+ foo.old_pools.push_back(10);
+ foo.old_pools.push_back(5);
+
+ bar.ino = 1234;
+ bar.pool = 12;
+ bar.old_pools.push_back(10);
+
+ inode_backpointer_t foop;
+ foop.dirino = 3;
+ foop.dname = "l3";
+ foop.version = 15;
+ foo.ancestors.push_back(foop);
+ foop.version = 17;
+ bar.ancestors.push_back(foop);
+
+ foop.dirino = 2;
+ foop.dname = "l2";
+ foop.version = 10;
+ foo.ancestors.push_back(foop);
+ foop.version = 9;
+ bar.ancestors.push_back(foop);
+
+ foop.dirino = 1;
+ foop.dname = "l1";
+ foop.version = 25;
+ foo.ancestors.push_back(foop);
+ bar.ancestors.push_back(foop);
+
+ int compare_r;
+ bool equivalent;
+ bool divergent;
+
+ compare_r = foo.compare(bar, &equivalent, &divergent);
+ EXPECT_EQ(1, compare_r);
+ EXPECT_TRUE(divergent);
+ compare_r = bar.compare(foo, &equivalent, &divergent);
+ EXPECT_EQ(-1, compare_r);
+ EXPECT_TRUE(divergent);
+}
diff --git a/src/test/fs/test_ino_release_cb.cc b/src/test/fs/test_ino_release_cb.cc
new file mode 100644
index 000000000..688f9ad7f
--- /dev/null
+++ b/src/test/fs/test_ino_release_cb.cc
@@ -0,0 +1,81 @@
+#include <string>
+#include <unistd.h>
+#include <include/fs_types.h>
+#include <mds/mdstypes.h>
+#include <include/cephfs/libcephfs.h>
+
+#define MAX_CEPH_FILES 1000
+#define DIRNAME "ino_release_cb"
+
+static std::atomic<bool> cb_done = false;
+
+static void cb(void *hdl, vinodeno_t vino)
+{
+ cb_done = true;
+}
+
+int main(int argc, char *argv[])
+{
+ inodeno_t inos[MAX_CEPH_FILES];
+ struct ceph_mount_info *cmount = NULL;
+
+ ceph_create(&cmount, "admin");
+ ceph_conf_read_file(cmount, NULL);
+ ceph_init(cmount);
+
+ [[maybe_unused]] int ret = ceph_mount(cmount, NULL);
+ assert(ret >= 0);
+ ret = ceph_mkdir(cmount, DIRNAME, 0755);
+ assert(ret >= 0);
+ ret = ceph_chdir(cmount, DIRNAME);
+ assert(ret >= 0);
+
+ /* Create a bunch of files, get their inode numbers and close them */
+ int i;
+ for (i = 0; i < MAX_CEPH_FILES; ++i) {
+ int fd;
+ struct ceph_statx stx;
+
+ string name = std::to_string(i);
+
+ fd = ceph_open(cmount, name.c_str(), O_RDWR|O_CREAT, 0644);
+ assert(fd >= 0);
+
+ ret = ceph_fstatx(cmount, fd, &stx, CEPH_STATX_INO, 0);
+ assert(ret >= 0);
+
+ inos[i] = stx.stx_ino;
+ ceph_close(cmount, fd);
+ }
+
+ /* Remount */
+ ceph_unmount(cmount);
+ ceph_release(cmount);
+ ceph_create(&cmount, "admin");
+ ceph_conf_read_file(cmount, NULL);
+ ceph_init(cmount);
+
+ struct ceph_client_callback_args args = { 0 };
+ args.ino_release_cb = cb;
+ ceph_ll_register_callbacks(cmount, &args);
+
+ ret = ceph_mount(cmount, NULL);
+ assert(ret >= 0);
+
+ Inode *inodes[MAX_CEPH_FILES];
+
+ for (i = 0; i < MAX_CEPH_FILES; ++i) {
+ /* We can stop if we got a callback */
+ if (cb_done)
+ break;
+
+ ret = ceph_ll_lookup_inode(cmount, inos[i], &inodes[i]);
+ assert(ret >= 0);
+ }
+ sleep(45);
+
+ assert(cb_done);
+ ceph_unmount(cmount);
+ ceph_release(cmount);
+ return 0;
+}
diff --git a/src/test/fs/test_trim_caps.cc b/src/test/fs/test_trim_caps.cc
new file mode 100644
index 000000000..11acabb0a
--- /dev/null
+++ b/src/test/fs/test_trim_caps.cc
@@ -0,0 +1,85 @@
+#define _FILE_OFFSET_BITS 64
+#if defined(__linux__)
+#include <features.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+#include <unistd.h>
+#include <include/cephfs/libcephfs.h>
+
+int main(int argc, char *argv[])
+{
+ char buf;
+ int pipefd[2];
+ int rc [[maybe_unused]] = pipe(pipefd);
+ assert(rc >= 0);
+
+ pid_t pid = fork();
+ assert(pid >= 0);
+ if (pid == 0)
+ close(pipefd[1]);
+ else
+ close(pipefd[0]);
+
+ struct ceph_mount_info *cmount = NULL;
+
+ ceph_create(&cmount, "admin");
+ ceph_conf_read_file(cmount, NULL);
+
+ int ret [[maybe_unused]] = ceph_mount(cmount, NULL);
+ assert(ret >= 0);
+
+ if (pid == 0) {
+ ret = read(pipefd[0], &buf, 1);
+ assert(ret == 1);
+
+ ret = ceph_rename(cmount, "1", "3");
+ assert(ret >= 0);
+
+ ret = ceph_rename(cmount, "2", "1");
+ assert(ret >= 0);
+
+ ceph_unmount(cmount);
+ printf("child exits\n");
+ } else {
+ ret = ceph_mkdirs(cmount, "1/2", 0755);
+ assert(ret >= 0);
+
+ struct ceph_statx stx;
+ ret = ceph_statx(cmount, "1", &stx, 0, 0);
+ assert(ret >= 0);
+ uint64_t orig_ino [[maybe_unused]] = stx.stx_ino;
+
+
+ ret = ceph_mkdir(cmount, "2", 0755);
+ assert(ret >= 0);
+
+ ret = write(pipefd[1], &buf, 1);
+ assert(ret == 1);
+
+ int wstatus;
+ ret = waitpid(pid, &wstatus, 0);
+ assert(ret >= 0);
+ assert(wstatus == 0);
+
+ // make origin '1' no parent dentry
+ ret = ceph_statx(cmount, "1", &stx, 0, 0);
+ assert(ret >= 0);
+ assert(orig_ino != stx.stx_ino);
+
+ // move root inode's cap_item to tail of session->caps
+ ret = ceph_statx(cmount, ".", &stx, 0, 0);
+ assert(ret >= 0);
+
+ printf("waiting for crash\n");
+ sleep(60);
+ }
+ return 0;
+}