::encode(snap, parent_bl);
op->exec("rbd", "get_parent", parent_bl);
- op->exec("rbd", "image_get_group", empty_bl);
rados::cls::lock::get_lock_info_start(op, RBD_LOCK_NAME);
}
std::map<rados::cls::lock::locker_id_t,
rados::cls::lock::locker_info_t> *lockers,
bool *exclusive_lock, std::string *lock_tag,
- ::SnapContext *snapc, parent_info *parent,
- cls::rbd::GroupSpec *group_ref) {
+ ::SnapContext *snapc, parent_info *parent) {
assert(size);
assert(features);
assert(incompatible_features);
assert(exclusive_lock);
assert(snapc);
assert(parent);
- assert(group_ref);
try {
uint8_t order;
::decode(parent->spec.image_id, *it);
::decode(parent->spec.snap_id, *it);
::decode(parent->overlap, *it);
- // group_image_get_group
- ::decode(*group_ref, *it);
// get_lock_info
ClsLockType lock_type = LOCK_NONE;
bool *exclusive_lock,
string *lock_tag,
::SnapContext *snapc,
- parent_info *parent,
- cls::rbd::GroupSpec *group_ref)
+ parent_info *parent)
{
librados::ObjectReadOperation op;
get_mutable_metadata_start(&op, read_only);
return get_mutable_metadata_finish(&it, size, features,
incompatible_features, lockers,
exclusive_lock, lock_tag, snapc,
- parent, group_ref);
+ parent);
}
void create_image(librados::ObjectWriteOperation *op, uint64_t size,
}
int group_image_list(librados::IoCtx *ioctx,
- const std::string &oid, const cls::rbd::GroupImageSpec &start,
+ const std::string &oid,
+ const cls::rbd::GroupImageSpec &start,
uint64_t max_return,
- std::vector<cls::rbd::GroupImageStatus>& images)
+ std::vector<cls::rbd::GroupImageStatus> *images)
{
bufferlist bl, bl2;
::encode(start, bl);
bufferlist::iterator iter = bl2.begin();
try {
- ::decode(images, iter);
+ ::decode(*images, iter);
} catch (const buffer::error &err) {
return -EBADMSG;
}
return ioctx->exec(oid, "rbd", "image_remove_group", bl, bl2);
}
- int image_get_group(librados::IoCtx *ioctx, const std::string &oid,
- cls::rbd::GroupSpec &group_spec)
+ void image_get_group_start(librados::ObjectReadOperation *op)
{
- bufferlist in, out;
-
- int r = ioctx->exec(oid, "rbd", "image_get_group", in, out);
- if (r < 0)
- return r;
+ bufferlist in_bl;
+ op->exec("rbd", "image_get_group", in_bl);
+ }
- bufferlist::iterator iter = out.begin();
+ int image_get_group_finish(bufferlist::iterator *iter,
+ cls::rbd::GroupSpec *group_spec)
+ {
try {
- ::decode(group_spec, iter);
+ ::decode(*group_spec, *iter);
} catch (const buffer::error &err) {
return -EBADMSG;
}
-
return 0;
}
+ int image_get_group(librados::IoCtx *ioctx, const std::string &oid,
+ cls::rbd::GroupSpec *group_spec)
+ {
+ librados::ObjectReadOperation op;
+ image_get_group_start(&op);
+
+ bufferlist out_bl;
+ int r = ioctx->operate(oid, &op, &out_bl);
+ if (r < 0) {
+ return r;
+ }
+
+ bufferlist::iterator iter = out_bl.begin();
+ return image_get_group_finish(&iter, group_spec);
+ }
+
} // namespace cls_client
} // namespace librbd
std::map<rados::cls::lock::locker_id_t,
rados::cls::lock::locker_info_t> *lockers,
bool *exclusive_lock, std::string *lock_tag,
- ::SnapContext *snapc, parent_info *parent,
- cls::rbd::GroupSpec *uplink);
+ ::SnapContext *snapc, parent_info *parent);
int get_mutable_metadata(librados::IoCtx *ioctx, const std::string &oid,
bool read_only, uint64_t *size, uint64_t *features,
uint64_t *incompatible_features,
bool *exclusive_lock,
std::string *lock_tag,
::SnapContext *snapc,
- parent_info *parent,
- cls::rbd::GroupSpec *uplink);
+ parent_info *parent);
// low-level interface (mainly for testing)
void create_image(librados::ObjectWriteOperation *op, uint64_t size,
int group_image_list(librados::IoCtx *ioctx, const std::string &oid,
const cls::rbd::GroupImageSpec &start,
uint64_t max_return,
- std::vector<cls::rbd::GroupImageStatus>& images);
+ std::vector<cls::rbd::GroupImageStatus> *images);
int group_image_set(librados::IoCtx *ioctx, const std::string &oid,
const cls::rbd::GroupImageStatus &st);
int image_add_group(librados::IoCtx *ioctx, const std::string &oid,
const cls::rbd::GroupSpec &group_spec);
int image_remove_group(librados::IoCtx *ioctx, const std::string &oid,
const cls::rbd::GroupSpec &group_spec);
+ void image_get_group_start(librados::ObjectReadOperation *op);
+ int image_get_group_finish(bufferlist::iterator *iter,
+ cls::rbd::GroupSpec *group_spec);
int image_get_group(librados::IoCtx *ioctx, const std::string &oid,
- cls::rbd::GroupSpec &s);
+ cls::rbd::GroupSpec *group_spec);
} // namespace cls_client
} // namespace librbd
// RBD consistency groups support functions
int group_create(IoCtx& io_ctx, const char *group_name);
int group_remove(IoCtx& io_ctx, const char *group_name);
- int group_list(IoCtx& io_ctx, std::vector<std::string>& names);
+ int group_list(IoCtx& io_ctx, std::vector<std::string> *names);
int group_image_add(IoCtx& io_ctx, const char *group_name,
IoCtx& image_io_ctx, const char *image_name);
int group_image_remove(IoCtx& io_ctx, const char *group_name,
IoCtx& image_io_ctx, const char *image_name);
int group_image_list(IoCtx& io_ctx, const char *group_name,
- std::vector<group_image_status_t>& images);
+ std::vector<group_image_status_t> *images);
private:
/* We don't allow assignment or copying */
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+
#include "common/errno.h"
#include "librbd/AioCompletion.h"
ldout(cct, 20) << "group_remove " << &io_ctx << " " << group_name << dendl;
std::vector<group_image_status_t> images;
- int r = group_image_list(io_ctx, group_name, images);
+ int r = group_image_list(io_ctx, group_name, &images);
if (r < 0 && r != -ENOENT) {
lderr(cct) << "error listing group images" << dendl;
return r;
return 0;
}
-int group_list(IoCtx& io_ctx, vector<string>& names)
+int group_list(IoCtx& io_ctx, vector<string> *names)
{
CephContext *cct = (CephContext *)io_ctx.cct();
ldout(cct, 20) << "group_list " << &io_ctx << dendl;
int r;
do {
map<string, string> groups;
- r = cls_client::group_dir_list(&io_ctx, RBD_GROUP_DIRECTORY, last_read, max_read, &groups);
+ r = cls_client::group_dir_list(&io_ctx, RBD_GROUP_DIRECTORY, last_read,
+ max_read, &groups);
if (r < 0) {
lderr(cct) << "error listing group in directory: "
<< cpp_strerror(r) << dendl;
return r;
}
for (pair<string, string> group : groups) {
- names.push_back(group.first);
+ names->push_back(group.first);
}
if (!groups.empty()) {
last_read = groups.rbegin()->first;
int group_image_list(librados::IoCtx& group_ioctx,
const char *group_name,
- std::vector<group_image_status_t>& images)
+ std::vector<group_image_status_t> *images)
{
CephContext *cct = (CephContext *)group_ioctx.cct();
ldout(cct, 20) << "group_image_list " << &group_ioctx
cls::rbd::GroupImageSpec start_last;
r = cls_client::group_image_list(&group_ioctx, group_header_oid,
- start_last, max_read, image_ids_page);
+ start_last, max_read, &image_ids_page);
if (r < 0) {
lderr(cct) << "error reading image list from consistency group: "
return r;
}
- images.push_back(
+ images->push_back(
group_image_status_t {
image_name,
i.spec.pool_id,
return 0;
}
+
} // namespace librbd
// Consistency groups functions
int group_create(librados::IoCtx& io_ctx, const char *imgname);
int group_remove(librados::IoCtx& io_ctx, const char *group_name);
-int group_list(librados::IoCtx& io_ctx, std::vector<std::string>& names);
+int group_list(librados::IoCtx& io_ctx, std::vector<std::string> *names);
int group_image_add(librados::IoCtx& group_ioctx, const char *group_name,
librados::IoCtx& image_ioctx, const char *image_name);
int group_image_remove(librados::IoCtx& group_ioctx, const char *group_name,
librados::IoCtx& image_ioctx, const char *image_name);
int group_image_list(librados::IoCtx& group_ioctx, const char *group_name,
- std::vector<group_image_status_t>& images);
+ std::vector<group_image_status_t> *images);
int image_get_group(ImageCtx *ictx, group_spec_t *group_spec);
}
+
#endif // CEPH_LIBRBD_GROUP_H
&m_lockers,
&m_exclusive_locked,
&m_lock_tag, &m_snapc,
- &m_parent_md,
- &m_group_spec);
+ &m_parent_md);
}
if (*result < 0) {
lderr(cct) << "failed to retrieve mutable metadata: "
return m_on_finish;
}
+ send_v2_get_group();
+ return nullptr;
+}
+
+template <typename I>
+void RefreshRequest<I>::send_v2_get_group() {
+ CephContext *cct = m_image_ctx.cct;
+ ldout(cct, 10) << this << " " << __func__ << dendl;
+
+ librados::ObjectReadOperation op;
+ cls_client::image_get_group_start(&op);
+
+ using klass = RefreshRequest<I>;
+ librados::AioCompletion *comp = create_rados_ack_callback<
+ klass, &klass::handle_v2_get_group>(this);
+ m_out_bl.clear();
+ int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, comp, &op,
+ &m_out_bl);
+ assert(r == 0);
+ comp->release();
+}
+
+template <typename I>
+Context *RefreshRequest<I>::handle_v2_get_group(int *result) {
+ CephContext *cct = m_image_ctx.cct;
+ ldout(cct, 10) << this << " " << __func__ << ": "
+ << "r=" << *result << dendl;
+
+ if (*result == 0) {
+ bufferlist::iterator it = m_out_bl.begin();
+ cls_client::image_get_group_finish(&it, &m_group_spec);
+ }
+ if (*result == -EOPNOTSUPP) {
+ // Older OSD doesn't support RBD groups
+ *result = 0;
+ ldout(cct, 10) << "OSD does not support consistency groups" << dendl;
+ } else if (*result < 0) {
+ lderr(cct) << "failed to retrieve group: " << cpp_strerror(*result)
+ << dendl;
+ return m_on_finish;
+ }
+
send_v2_get_snapshots();
return nullptr;
}
} else {
m_image_ctx.features = m_features;
m_image_ctx.flags = m_flags;
+ m_image_ctx.group_spec = m_group_spec;
m_image_ctx.parent_md = m_parent_md;
}
- m_image_ctx.group_spec = m_group_spec;
-
for (size_t i = 0; i < m_snapc.snaps.size(); ++i) {
std::vector<librados::snap_t>::const_iterator it = std::find(
m_image_ctx.snaps.begin(), m_image_ctx.snaps.end(),
* V2_GET_FLAGS |
* | |
* v |
+ * V2_GET_GROUP |
+ * | |
+ * v |
* V2_GET_SNAPSHOTS (skip if no snaps) |
* | |
* v |
void send_v2_get_flags();
Context *handle_v2_get_flags(int *result);
+ void send_v2_get_group();
+ Context *handle_v2_get_group(int *result);
+
void send_v2_get_snapshots();
Context *handle_v2_get_snapshots(int *result);
}
cls::rbd::GroupSpec s;
- r = cls_client::image_get_group(&io_ctx, header_oid, s);
- if (s.is_valid()) {
+ r = cls_client::image_get_group(&io_ctx, header_oid, &s);
+ if (r < 0 && r != -EOPNOTSUPP) {
+ lderr(cct) << "error querying consistency group" << dendl;
+ ictx->owner_lock.put_read();
+ ictx->state->close();
+ return r;
+ } else if (s.is_valid()) {
lderr(cct) << "image is in a consistency group - not removing" << dendl;
ictx->owner_lock.put_read();
ictx->state->close();
return r;
}
- int RBD::group_list(IoCtx& io_ctx, vector<string>& names)
+ int RBD::group_list(IoCtx& io_ctx, vector<string> *names)
{
TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
tracepoint(librbd, group_list_enter, io_ctx.get_pool_name().c_str(),
int r = librbd::group_list(io_ctx, names);
if (r >= 0) {
- for (auto itr : names) {
+ for (auto itr : *names) {
tracepoint(librbd, group_list_entry, itr.c_str());
}
}
}
int RBD::group_image_list(IoCtx& group_ioctx, const char *group_name,
- std::vector<group_image_status_t>& images)
+ std::vector<group_image_status_t> *images)
{
TracepointProvider::initialize<tracepoint_traits>(get_cct(group_ioctx));
tracepoint(librbd, group_image_list_enter, group_ioctx.get_pool_name().c_str(),
group_ioctx.get_id(), group_name);
std::vector<librbd::group_image_status_t> cpp_images;
- int r = librbd::group_image_list(group_ioctx, group_name, cpp_images);
+ int r = librbd::group_image_list(group_ioctx, group_name, &cpp_images);
if (r == -ENOENT) {
tracepoint(librbd, group_image_list_exit, 0);
std::string lock_tag;
::SnapContext snapc;
parent_info parent;
- cls::rbd::GroupSpec group_spec;
ASSERT_EQ(0, get_mutable_metadata(&ioctx, oid, true, &size, &features,
&incompatible_features, &lockers,
&exclusive_lock, &lock_tag, &snapc,
- &parent, &group_spec));
+ &parent));
ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK), features);
ASSERT_EQ(0U, incompatible_features);
ASSERT_EQ(0, get_mutable_metadata(&ioctx, oid, false, &size, &features,
&incompatible_features, &lockers,
&exclusive_lock, &lock_tag, &snapc,
- &parent, &group_spec));
+ &parent));
ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK), features);
ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK),
incompatible_features);
vector<cls::rbd::GroupImageStatus> images;
cls::rbd::GroupImageSpec empty_image_spec = cls::rbd::GroupImageSpec();
- ASSERT_EQ(0, group_image_list(&ioctx, group_id, empty_image_spec, 1024, images));
+ ASSERT_EQ(0, group_image_list(&ioctx, group_id, empty_image_spec, 1024,
+ &images));
ASSERT_EQ(1U, images.size());
ASSERT_EQ(image_id, images[0].spec.image_id);
ASSERT_EQ(pool_id, images[0].spec.pool_id);
ASSERT_EQ(cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE, images[0].state);
cls::rbd::GroupImageStatus last_image = *images.rbegin();
- ASSERT_EQ(0, group_image_list(&ioctx, group_id, last_image.spec, 1024, images));
+ ASSERT_EQ(0, group_image_list(&ioctx, group_id, last_image.spec, 1024,
+ &images));
ASSERT_EQ(0U, images.size());
}
ASSERT_EQ(0, image_add_group(&ioctx, image_id, spec_add));
cls::rbd::GroupSpec spec;
- ASSERT_EQ(0, image_get_group(&ioctx, image_id, spec));
+ ASSERT_EQ(0, image_get_group(&ioctx, image_id, &spec));
ASSERT_EQ(group_id, spec.group_id);
ASSERT_EQ(pool_id, spec.pool_id);
EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_parent"), _, _, _))
.WillOnce(DoDefault());
- EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
- exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("image_get_group"), _, _, _))
- .WillOnce(DoDefault());
EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("get_info"), _, _, _))
.WillOnce(DoDefault());
}
}
+ void expect_get_group(MockRefreshImageCtx &mock_image_ctx, int r) {
+ auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
+ exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
+ StrEq("image_get_group"), _, _, _));
+ if (r < 0) {
+ expect.WillOnce(Return(r));
+ } else {
+ expect.WillOnce(DoDefault());
+ }
+ }
+
+
void expect_get_snapshots(MockRefreshImageCtx &mock_image_ctx, int r) {
auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_name"), _, _, _));
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_get_snapshots(mock_image_ctx, 0);
expect_snap_namespace_list(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_get_snapshots(mock_image_ctx, 0);
expect_snap_namespace_list(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_refresh_parent_is_required(*mock_refresh_parent_request, true);
expect_refresh_parent_send(mock_image_ctx, *mock_refresh_parent_request, 0);
if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
expect_shut_down_exclusive_lock(mock_image_ctx, *mock_exclusive_lock, 0);
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
C_SaferCond ctx;
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
MockJournalPolicy mock_journal_policy;
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
MockJournalPolicy mock_journal_policy;
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
expect_set_require_lock_on_read(mock_image_ctx);
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
expect_block_writes(mock_image_ctx, 0);
expect_clear_require_lock_on_read(mock_image_ctx);
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
expect_open_object_map(mock_image_ctx, &mock_object_map, 0);
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
C_SaferCond ctx;
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
expect_close_object_map(mock_image_ctx, *mock_object_map, 0);
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
+ expect_get_group(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
expect_open_object_map(mock_image_ctx, mock_object_map, -EFBIG);
ASSERT_EQ(0, rbd.group_create(ioctx, "mygroup"));
vector<string> groups;
- ASSERT_EQ(0, rbd.group_list(ioctx, groups));
+ ASSERT_EQ(0, rbd.group_list(ioctx, &groups));
ASSERT_EQ(1U, groups.size());
ASSERT_EQ("mygroup", groups[0]);
ASSERT_EQ(0, rbd.group_remove(ioctx, "mygroup"));
groups.clear();
- ASSERT_EQ(0, rbd.group_list(ioctx, groups));
+ ASSERT_EQ(0, rbd.group_list(ioctx, &groups));
ASSERT_EQ(0U, groups.size());
}
ASSERT_EQ(0, rbd.group_image_add(ioctx, group_name, ioctx, image_name));
vector<librbd::group_image_status_t> images;
- ASSERT_EQ(0, rbd.group_image_list(ioctx, group_name, images));
+ ASSERT_EQ(0, rbd.group_image_list(ioctx, group_name, &images));
ASSERT_EQ(1U, images.size());
ASSERT_EQ("myimage", images[0].name);
ASSERT_EQ(ioctx.get_id(), images[0].pool);
ASSERT_EQ(0, rbd.group_image_remove(ioctx, group_name, ioctx, image_name));
images.clear();
- ASSERT_EQ(0, rbd.group_image_list(ioctx, group_name, images));
+ ASSERT_EQ(0, rbd.group_image_list(ioctx, group_name, &images));
ASSERT_EQ(0U, images.size());
}
librbd::RBD rbd;
std::vector<std::string> names;
- r = rbd.group_list(io_ctx, names);
+ r = rbd.group_list(io_ctx, &names);
if (r == -ENOENT)
r = 0;
librbd::RBD rbd;
std::vector<librbd::group_image_status_t> images;
- r = rbd.group_image_list(io_ctx, group_name.c_str(), images);
+ r = rbd.group_image_list(io_ctx, group_name.c_str(), &images);
if (r == -ENOENT)
r = 0;