#include "gtest/gtest.h"
#include <boost/scope_exit.hpp>
+#include <chrono>
#include <vector>
void register_test_groups() {
librbd::RBD rbd;
ASSERT_EQ(0, rbd.group_create(ioctx, "mygroup"));
- vector<string> groups;
+ std::vector<std::string> groups;
ASSERT_EQ(0, rbd.group_list(ioctx, &groups));
ASSERT_EQ(1U, groups.size());
ASSERT_EQ("mygroup", groups[0]);
ASSERT_EQ(0, rbd_get_op_features(image, &op_features));
ASSERT_TRUE((op_features & RBD_OPERATION_FEATURE_GROUP) == 0ULL);
+ rbd_group_info_t group_info;
+ ASSERT_EQ(0, rbd_get_group(image, &group_info, sizeof(group_info)));
+ ASSERT_EQ(0, strcmp("", group_info.name));
+ ASSERT_EQ(RBD_GROUP_INVALID_POOL, group_info.pool);
+ rbd_group_info_cleanup(&group_info, sizeof(group_info));
+
ASSERT_EQ(0, rbd_group_image_add(ioctx, group_name, ioctx,
m_image_name.c_str()));
+ ASSERT_EQ(-ERANGE, rbd_get_group(image, &group_info, 0));
+ ASSERT_EQ(0, rbd_get_group(image, &group_info, sizeof(group_info)));
+ ASSERT_EQ(0, strcmp(group_name, group_info.name));
+ ASSERT_EQ(rados_ioctx_get_id(ioctx), group_info.pool);
+ rbd_group_info_cleanup(&group_info, sizeof(group_info));
+
ASSERT_EQ(0, rbd_get_features(image, &features));
ASSERT_TRUE((features & RBD_FEATURE_OPERATIONS) ==
RBD_FEATURE_OPERATIONS);
ASSERT_EQ(0, image.get_op_features(&op_features));
ASSERT_TRUE((op_features & RBD_OPERATION_FEATURE_GROUP) == 0ULL);
+ librbd::group_info_t group_info;
+ ASSERT_EQ(0, image.get_group(&group_info, sizeof(group_info)));
+ ASSERT_EQ(std::string(""), group_info.name);
+ ASSERT_EQ(RBD_GROUP_INVALID_POOL, group_info.pool);
+
ASSERT_EQ(0, rbd.group_image_add(ioctx, group_name, ioctx,
m_image_name.c_str()));
+ ASSERT_EQ(-ERANGE, image.get_group(&group_info, 0));
+ ASSERT_EQ(0, image.get_group(&group_info, sizeof(group_info)));
+ ASSERT_EQ(std::string(group_name), group_info.name);
+ ASSERT_EQ(ioctx.get_id(), group_info.pool);
+
ASSERT_EQ(0, image.features(&features));
ASSERT_TRUE((features & RBD_FEATURE_OPERATIONS) ==
RBD_FEATURE_OPERATIONS);
ASSERT_TRUE((op_features & RBD_OPERATION_FEATURE_GROUP) ==
RBD_OPERATION_FEATURE_GROUP);
- vector<librbd::group_image_info_t> images;
+ std::vector<librbd::group_image_info_t> images;
ASSERT_EQ(0, rbd.group_image_list(ioctx, group_name, &images,
sizeof(librbd::group_image_info_t)));
ASSERT_EQ(1U, images.size());
ASSERT_EQ(0, rbd_group_image_add(ioctx, group_name, ioctx,
m_image_name.c_str()));
+ struct Watcher {
+ static void quiesce_cb(void *arg) {
+ Watcher *watcher = static_cast<Watcher *>(arg);
+ watcher->handle_quiesce();
+ }
+ static void unquiesce_cb(void *arg) {
+ Watcher *watcher = static_cast<Watcher *>(arg);
+ watcher->handle_unquiesce();
+ }
+
+ rbd_image_t ℑ
+ uint64_t handle = 0;
+ size_t quiesce_count = 0;
+ size_t unquiesce_count = 0;
+ int r = 0;
+
+ ceph::mutex lock = ceph::make_mutex("lock");
+ ceph::condition_variable cv;
+
+ Watcher(rbd_image_t &image) : image(image) {
+ }
+
+ void handle_quiesce() {
+ ASSERT_EQ(quiesce_count, unquiesce_count);
+ quiesce_count++;
+ rbd_quiesce_complete(image, handle, r);
+ }
+ void handle_unquiesce() {
+ std::unique_lock locker(lock);
+ unquiesce_count++;
+ cv.notify_one();
+ }
+ bool wait_for_unquiesce(size_t c) {
+ std::unique_lock locker(lock);
+ return cv.wait_for(locker, std::chrono::seconds(60),
+ [this, c]() { return unquiesce_count >= c; });
+ }
+ } watcher(image);
+
+ ASSERT_EQ(0, rbd_quiesce_watch(image, Watcher::quiesce_cb,
+ Watcher::unquiesce_cb, &watcher,
+ &watcher.handle));
+
ASSERT_EQ(0, rbd_group_snap_create(ioctx, group_name, snap_name));
+ ASSERT_TRUE(watcher.wait_for_unquiesce(1U));
+ ASSERT_EQ(1U, watcher.quiesce_count);
size_t num_snaps = 0;
ASSERT_EQ(-ERANGE, rbd_group_snap_list(ioctx, group_name, NULL,
&num_snaps));
ASSERT_EQ(0U, num_snaps);
+ ASSERT_EQ(-EINVAL, rbd_group_snap_create2(ioctx, group_name, snap_name,
+ RBD_SNAP_CREATE_SKIP_QUIESCE |
+ RBD_SNAP_CREATE_IGNORE_QUIESCE_ERROR));
+ watcher.r = -EINVAL;
+ ASSERT_EQ(-EINVAL, rbd_group_snap_create2(ioctx, group_name, snap_name, 0));
+
+ num_snaps = 1;
+ ASSERT_EQ(0, rbd_group_snap_list(ioctx, group_name, snaps,
+ sizeof(rbd_group_snap_info_t),
+ &num_snaps));
+
+ watcher.quiesce_count = 0;
+ watcher.unquiesce_count = 0;
+ ASSERT_EQ(0, rbd_group_snap_create2(ioctx, group_name, snap_name,
+ RBD_SNAP_CREATE_SKIP_QUIESCE));
+ ASSERT_EQ(0U, watcher.quiesce_count);
+ num_snaps = 1;
+ ASSERT_EQ(1, rbd_group_snap_list(ioctx, group_name, snaps,
+ sizeof(rbd_group_snap_info_t),
+ &num_snaps));
+ ASSERT_EQ(0, rbd_group_snap_list_cleanup(snaps, sizeof(rbd_group_snap_info_t),
+ num_snaps));
+ ASSERT_EQ(0, rbd_group_snap_remove(ioctx, group_name, snap_name));
+
+ ASSERT_EQ(0, rbd_group_snap_create2(ioctx, group_name, snap_name,
+ RBD_SNAP_CREATE_IGNORE_QUIESCE_ERROR));
+ ASSERT_EQ(1, rbd_group_snap_list(ioctx, group_name, snaps,
+ sizeof(rbd_group_snap_info_t),
+ &num_snaps));
+ ASSERT_EQ(0, rbd_group_snap_list_cleanup(snaps, sizeof(rbd_group_snap_info_t),
+ num_snaps));
+ ASSERT_EQ(0, rbd_group_snap_remove(ioctx, group_name, snap_name));
+
+ ASSERT_EQ(0, rbd_quiesce_unwatch(image, watcher.handle));
ASSERT_EQ(0, rbd_group_remove(ioctx, group_name));
}
sizeof(librbd::group_snap_info_t)));
ASSERT_EQ(0U, snaps.size());
+ ASSERT_EQ(0, rbd.group_snap_create(ioctx, group_name, snap_name));
+ ASSERT_EQ(0, rbd.group_snap_list(ioctx, group_name, &snaps,
+ sizeof(librbd::group_snap_info_t)));
+ ASSERT_EQ(1U, snaps.size());
+ ASSERT_EQ(0, rbd.group_snap_remove(ioctx, group_name, snap_name));
+
+ ASSERT_EQ(-EINVAL, rbd.group_snap_create2(ioctx, group_name, snap_name,
+ RBD_SNAP_CREATE_SKIP_QUIESCE |
+ RBD_SNAP_CREATE_IGNORE_QUIESCE_ERROR));
+ snaps.clear();
+ ASSERT_EQ(0, rbd.group_snap_list(ioctx, group_name, &snaps,
+ sizeof(librbd::group_snap_info_t)));
+ ASSERT_EQ(0U, snaps.size());
+
+ ASSERT_EQ(0, rbd.group_snap_create2(ioctx, group_name, snap_name,
+ RBD_SNAP_CREATE_SKIP_QUIESCE));
+ snaps.clear();
+ ASSERT_EQ(0, rbd.group_snap_list(ioctx, group_name, &snaps,
+ sizeof(librbd::group_snap_info_t)));
+ ASSERT_EQ(1U, snaps.size());
+
+ ASSERT_EQ(0, rbd.group_snap_remove(ioctx, group_name, snap_name));
ASSERT_EQ(0, rbd.group_remove(ioctx, group_name));
}