return r;
}
- auto primary = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ auto mirror_ns = boost::get<cls::rbd::MirrorSnapshotNamespace>(
&snap.snapshot_namespace);
- if (primary == nullptr) {
+ if (mirror_ns == nullptr) {
CLS_LOG(5, "mirror_image_snapshot_unlink_peer " \
"not mirroring snapshot snap_id=%" PRIu64, snap_id);
return -EINVAL;
}
- if (primary->mirror_peer_uuids.count(mirror_peer_uuid) == 0) {
+ if (mirror_ns->mirror_peer_uuids.count(mirror_peer_uuid) == 0) {
return -ENOENT;
}
- if (primary->mirror_peer_uuids.size() == 1) {
+ if (mirror_ns->mirror_peer_uuids.size() == 1) {
// return a special error when trying to unlink the last peer
return -ERESTART;
}
- primary->mirror_peer_uuids.erase(mirror_peer_uuid);
+ mirror_ns->mirror_peer_uuids.erase(mirror_peer_uuid);
r = image::snapshot::write(hctx, snap_key, std::move(snap));
if (r < 0) {
<< original_snapshot_namespace_type;
}
-void MirrorPrimarySnapshotNamespace::encode(bufferlist& bl) const {
+void MirrorSnapshotNamespace::encode(bufferlist& bl) const {
using ceph::encode;
- encode(demoted, bl);
+ encode(state, bl);
+ encode(complete, bl);
encode(mirror_peer_uuids, bl);
+ encode(primary_mirror_uuid, bl);
+ encode(primary_snap_id, bl);
+ encode(last_copied_object_number, bl);
+ encode(snap_seqs, bl);
}
-void MirrorPrimarySnapshotNamespace::decode(bufferlist::const_iterator& it) {
+void MirrorSnapshotNamespace::decode(bufferlist::const_iterator& it) {
using ceph::decode;
- decode(demoted, it);
+ decode(state, it);
+ decode(complete, it);
decode(mirror_peer_uuids, it);
+ decode(primary_mirror_uuid, it);
+ decode(primary_snap_id, it);
+ decode(last_copied_object_number, it);
+ decode(snap_seqs, it);
}
-void MirrorPrimarySnapshotNamespace::dump(Formatter *f) const {
- f->dump_bool("demoted", demoted);
+void MirrorSnapshotNamespace::dump(Formatter *f) const {
+ f->dump_stream("state") << state;
+ f->dump_bool("complete", complete);
f->open_array_section("mirror_peer_uuids");
for (auto &peer : mirror_peer_uuids) {
f->dump_string("mirror_peer_uuid", peer);
}
f->close_section();
+ f->dump_string("primary_mirror_uuid", primary_mirror_uuid);
+ f->dump_unsigned("primary_snap_id", primary_snap_id);
+ f->dump_unsigned("last_copied_object_number", last_copied_object_number);
+ f->dump_stream("snap_seqs") << snap_seqs;
}
void MirrorNonPrimarySnapshotNamespace::encode(bufferlist& bl) const {
SNAPSHOT_NAMESPACE_TYPE_USER, "snap1"},
"12345", 123, {123456, 0}, 429));
o.push_back(new SnapshotInfo(1ULL,
- MirrorPrimarySnapshotNamespace{true, {"1", "2"}},
+ MirrorSnapshotNamespace{MIRROR_SNAPSHOT_STATE_PRIMARY,
+ {"1", "2"}, "", CEPH_NOSNAP},
+ "snap1", 123, {123456, 0}, 12));
+ o.push_back(new SnapshotInfo(1ULL,
+ MirrorSnapshotNamespace{MIRROR_SNAPSHOT_STATE_NON_PRIMARY,
+ {"1", "2"}, "uuid", 123},
"snap1", 123, {123456, 0}, 12));
o.push_back(new SnapshotInfo(1ULL,
MirrorNonPrimarySnapshotNamespace{"uuid", 111},
case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_TRASH:
*this = TrashSnapshotNamespace();
break;
- case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY:
- *this = MirrorPrimarySnapshotNamespace();
+ case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR:
+ *this = MirrorSnapshotNamespace();
break;
case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY:
*this = MirrorNonPrimarySnapshotNamespace();
o.push_back(new SnapshotNamespace(GroupSnapshotNamespace(5, "1018643c9869",
"33352be8933c")));
o.push_back(new SnapshotNamespace(TrashSnapshotNamespace()));
- o.push_back(new SnapshotNamespace(MirrorPrimarySnapshotNamespace(true,
- {"uuid"})));
+ o.push_back(new SnapshotNamespace(MirrorSnapshotNamespace(MIRROR_SNAPSHOT_STATE_PRIMARY,
+ {"peer uuid"},
+ "", CEPH_NOSNAP)));
+ o.push_back(new SnapshotNamespace(MirrorSnapshotNamespace(MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
+ {"peer uuid"},
+ "", CEPH_NOSNAP)));
+ o.push_back(new SnapshotNamespace(MirrorSnapshotNamespace(MIRROR_SNAPSHOT_STATE_NON_PRIMARY,
+ {"peer uuid"},
+ "uuid", 123)));
+ o.push_back(new SnapshotNamespace(MirrorSnapshotNamespace(MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED,
+ {"peer uuid"},
+ "uuid", 123)));
o.push_back(new SnapshotNamespace(MirrorNonPrimarySnapshotNamespace("", 0)));
}
case SNAPSHOT_NAMESPACE_TYPE_TRASH:
os << "trash";
break;
- case SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY:
- os << "mirror_primary";
+ case SNAPSHOT_NAMESPACE_TYPE_MIRROR:
+ os << "mirror";
break;
case SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY:
os << "mirror_non_primary";
return os;
}
-std::ostream& operator<<(std::ostream& os,
- const MirrorPrimarySnapshotNamespace& ns) {
- os << "[" << SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY << " "
- << "demoted=" << ns.demoted << ", "
- << "mirror_peer_uuids=" << ns.mirror_peer_uuids
+std::ostream& operator<<(std::ostream& os, const MirrorSnapshotNamespace& ns) {
+ os << "[" << SNAPSHOT_NAMESPACE_TYPE_MIRROR << " "
+ << "state=" << ns.state << ", "
+ << "complete=" << ns.complete << ", "
+ << "mirror_peer_uuids=" << ns.mirror_peer_uuids << ", "
+ << "primary_mirror_uuid=" << ns.primary_mirror_uuid << ", "
+ << "primary_snap_id=" << ns.primary_snap_id << ", "
+ << "last_copied_object_number=" << ns.last_copied_object_number << ", "
+ << "snap_seqs=" << ns.snap_seqs
<< "]";
return os;
}
return os;
}
+std::ostream& operator<<(std::ostream& os, MirrorSnapshotState type) {
+ switch (type) {
+ case MIRROR_SNAPSHOT_STATE_PRIMARY:
+ os << "primary";
+ break;
+ case MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED:
+ os << "primary (demoted)";
+ break;
+ case MIRROR_SNAPSHOT_STATE_NON_PRIMARY:
+ os << "non-primary";
+ break;
+ case MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED:
+ os << "demoted (demoted)";
+ break;
+ default:
+ os << "unknown";
+ break;
+ }
+ return os;
+
+}
+
void ImageSnapshotSpec::encode(bufferlist& bl) const {
using ceph::encode;
ENCODE_START(1, 1, bl);
SNAPSHOT_NAMESPACE_TYPE_USER = 0,
SNAPSHOT_NAMESPACE_TYPE_GROUP = 1,
SNAPSHOT_NAMESPACE_TYPE_TRASH = 2,
- SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY = 3,
+ SNAPSHOT_NAMESPACE_TYPE_MIRROR = 3,
SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY = 4,
};
}
};
-struct MirrorPrimarySnapshotNamespace {
+enum MirrorSnapshotState {
+ MIRROR_SNAPSHOT_STATE_PRIMARY = 0,
+ MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED = 1,
+ MIRROR_SNAPSHOT_STATE_NON_PRIMARY = 2,
+ MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED = 3,
+};
+
+inline void encode(const MirrorSnapshotState &state, bufferlist& bl,
+ uint64_t features=0) {
+ using ceph::encode;
+ encode(static_cast<uint8_t>(state), bl);
+}
+
+inline void decode(MirrorSnapshotState &state, bufferlist::const_iterator& it) {
+ using ceph::decode;
+ uint8_t int_state;
+ decode(int_state, it);
+ state = static_cast<MirrorSnapshotState>(int_state);
+}
+
+std::ostream& operator<<(std::ostream& os, MirrorSnapshotState type);
+
+typedef std::map<uint64_t, uint64_t> SnapSeqs;
+
+struct MirrorSnapshotNamespace {
static const SnapshotNamespaceType SNAPSHOT_NAMESPACE_TYPE =
- SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY;
+ SNAPSHOT_NAMESPACE_TYPE_MIRROR;
- bool demoted = false;
+ MirrorSnapshotState state = MIRROR_SNAPSHOT_STATE_NON_PRIMARY;
+ bool complete = false;
std::set<std::string> mirror_peer_uuids;
- MirrorPrimarySnapshotNamespace() {
+ std::string primary_mirror_uuid;
+ snapid_t primary_snap_id = CEPH_NOSNAP;
+ uint64_t last_copied_object_number = 0;
+ SnapSeqs snap_seqs;
+
+ MirrorSnapshotNamespace() {
}
- MirrorPrimarySnapshotNamespace(bool demoted,
- const std::set<std::string> &mirror_peer_uuids)
- : demoted(demoted), mirror_peer_uuids(mirror_peer_uuids) {
+ MirrorSnapshotNamespace(MirrorSnapshotState state,
+ const std::set<std::string> &mirror_peer_uuids,
+ const std::string& primary_mirror_uuid,
+ snapid_t primary_snap_id)
+ : state(state), mirror_peer_uuids(mirror_peer_uuids),
+ primary_mirror_uuid(primary_mirror_uuid),
+ primary_snap_id(primary_snap_id) {
+ }
+
+ inline bool is_primary() const {
+ return (state == MIRROR_SNAPSHOT_STATE_PRIMARY ||
+ state == MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED);
+ }
+
+ inline bool is_non_primary() const {
+ return (state == MIRROR_SNAPSHOT_STATE_NON_PRIMARY ||
+ state == MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED);
+ }
+
+ inline bool is_demoted() const {
+ return (state == MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED ||
+ state == MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED);
}
void encode(bufferlist& bl) const;
void dump(Formatter *f) const;
- inline bool operator==(const MirrorPrimarySnapshotNamespace& mpsn) const {
- return demoted == mpsn.demoted &&
- mirror_peer_uuids == mpsn.mirror_peer_uuids;
+ inline bool operator==(const MirrorSnapshotNamespace& rhs) const {
+ return state == rhs.state &&
+ complete == rhs.complete &&
+ mirror_peer_uuids == rhs.mirror_peer_uuids &&
+ primary_mirror_uuid == rhs.primary_mirror_uuid &&
+ primary_snap_id == rhs.primary_snap_id &&
+ last_copied_object_number == rhs.last_copied_object_number &&
+ snap_seqs == rhs.snap_seqs;
}
- inline bool operator<(const MirrorPrimarySnapshotNamespace& mpsn) const {
- if (demoted != mpsn.demoted) {
- return demoted < mpsn.demoted;
+ inline bool operator<(const MirrorSnapshotNamespace& rhs) const {
+ if (state != rhs.state) {
+ return state < rhs.state;
+ } else if (complete != rhs.complete) {
+ return complete < rhs.complete;
+ } else if (mirror_peer_uuids != rhs.mirror_peer_uuids) {
+ return mirror_peer_uuids < rhs.mirror_peer_uuids;
+ } else if (primary_mirror_uuid != rhs.primary_mirror_uuid) {
+ return primary_mirror_uuid < rhs.primary_mirror_uuid;
+ } else if (primary_snap_id != rhs.primary_snap_id) {
+ return primary_snap_id < rhs.primary_snap_id;
+ } else if (last_copied_object_number != rhs.last_copied_object_number) {
+ return last_copied_object_number < rhs.last_copied_object_number;
+ } else {
+ return snap_seqs < rhs.snap_seqs;
}
- return mirror_peer_uuids < mpsn.mirror_peer_uuids;
}
};
-typedef std::map<uint64_t, uint64_t> SnapSeqs;
-
struct MirrorNonPrimarySnapshotNamespace {
static const SnapshotNamespaceType SNAPSHOT_NAMESPACE_TYPE =
SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY;
std::ostream& operator<<(std::ostream& os, const UserSnapshotNamespace& ns);
std::ostream& operator<<(std::ostream& os, const GroupSnapshotNamespace& ns);
std::ostream& operator<<(std::ostream& os, const TrashSnapshotNamespace& ns);
-std::ostream& operator<<(std::ostream& os,
- const MirrorPrimarySnapshotNamespace& ns);
+std::ostream& operator<<(std::ostream& os, const MirrorSnapshotNamespace& ns);
std::ostream& operator<<(std::ostream& os,
const MirrorNonPrimarySnapshotNamespace& ns);
std::ostream& operator<<(std::ostream& os, const UnknownSnapshotNamespace& ns);
typedef boost::variant<UserSnapshotNamespace,
GroupSnapshotNamespace,
TrashSnapshotNamespace,
- MirrorPrimarySnapshotNamespace,
+ MirrorSnapshotNamespace,
MirrorNonPrimarySnapshotNamespace,
UnknownSnapshotNamespace> SnapshotNamespaceVariant;
{
std::shared_lock image_locker{img_ctx->image_lock};
for (auto &it : img_ctx->snap_info) {
- auto info = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ auto info = boost::get<cls::rbd::MirrorSnapshotNamespace>(
&it.second.snap_namespace);
if (info && info->mirror_peer_uuids.count(uuid)) {
snap_ids.push_back(it.first);
#include "librbd/Operations.h"
#include "librbd/Utils.h"
#include "librbd/api/Image.h"
-#include "librbd/api/Mirror.h"
#include <boost/variant.hpp>
#include "include/Context.h"
#include "common/Cond.h"
class GetMirrorVisitor : public boost::static_visitor<int> {
public:
snap_mirror_namespace_t *mirror_snap;
- std::string mirror_uuid;
- explicit GetMirrorVisitor(snap_mirror_namespace_t *mirror_snap,
- const std::string& mirror_uuid)
- : mirror_snap(mirror_snap), mirror_uuid(mirror_uuid) {
+ explicit GetMirrorVisitor(snap_mirror_namespace_t *mirror_snap)
+ : mirror_snap(mirror_snap) {
}
template <typename T>
}
inline int operator()(
- const cls::rbd::MirrorPrimarySnapshotNamespace& snap_namespace) {
- if (snap_namespace.demoted) {
- mirror_snap->state = RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED;
- } else {
- mirror_snap->state = RBD_SNAP_MIRROR_STATE_PRIMARY;
- }
+ const cls::rbd::MirrorSnapshotNamespace& snap_namespace) {
+ mirror_snap->state = static_cast<snap_mirror_state_t>(snap_namespace.state);
+ mirror_snap->complete = snap_namespace.complete;
mirror_snap->mirror_peer_uuids = snap_namespace.mirror_peer_uuids;
- mirror_snap->complete = true;
+ mirror_snap->primary_mirror_uuid = snap_namespace.primary_mirror_uuid;
+ mirror_snap->primary_snap_id = snap_namespace.primary_snap_id;
+ mirror_snap->last_copied_object_number =
+ snap_namespace.last_copied_object_number;
return 0;
}
return -ENOENT;
}
- // TODO temporary
- std::string mirror_uuid;
- r = Mirror<I>::uuid_get(ictx->md_ctx, &mirror_uuid);
- if (r < 0) {
- return r;
- }
-
- auto gmv = GetMirrorVisitor(mirror_snap, mirror_uuid);
+ auto gmv = GetMirrorVisitor(mirror_snap);
r = boost::apply_visitor(gmv, snap_info->snap_namespace);
if (r < 0) {
return r;
break;
} else if (src_snap_id == m_src_snap_id_end) {
// ... map it to destination HEAD since it's not a user snapshot that we
- // will create (e.g. MirrorPrimarySnapshotNamespace)
+ // will create (e.g. MirrorSnapshotNamespace)
m_snap_seqs[src_snap_id] = CEPH_NOSNAP;
}
}
auto snap_namespace_type = cls::rbd::get_snap_namespace_type(
snap_info.snap_namespace);
switch (snap_namespace_type) {
- case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY:
+ case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR:
case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY:
return true;
default:
auto &snap_info = it.second;
auto type = cls::rbd::get_snap_namespace_type(
snap_info.snap_namespace);
- if (type == cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY ||
+ if (type == cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR ||
type == cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY) {
send_remove_snap("", snap_info.snap_namespace, snap_info.name);
removing_snapshots = true;
*m_primary_mirror_uuid = "";
for (auto it = snap_info.rbegin(); it != snap_info.rend(); it++) {
- auto primary = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ auto mirror_ns = boost::get<cls::rbd::MirrorSnapshotNamespace>(
&it->second.snap_namespace);
- if (primary != nullptr) {
- if (primary->demoted) {
- *m_promotion_state = PROMOTION_STATE_ORPHAN;
- } else {
+ if (mirror_ns != nullptr) {
+ switch (mirror_ns->state) {
+ case cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY:
*m_promotion_state = PROMOTION_STATE_PRIMARY;
+ break;
+ case cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY:
+ *m_promotion_state = PROMOTION_STATE_NON_PRIMARY;
+ break;
+ case cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED:
+ case cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED:
+ *m_promotion_state = PROMOTION_STATE_ORPHAN;
+ break;
}
break;
}
+
auto non_primary =
boost::get<cls::rbd::MirrorNonPrimarySnapshotNamespace>(
&it->second.snap_namespace);
}
ldout(m_cct, 10) << "promotion_state=" << *m_promotion_state << ", "
- << "primary_mirror_uuid=" << *m_promotion_state << dendl;
+ << "primary_mirror_uuid=" << *m_primary_mirror_uuid << dendl;
}
} // namespace mirror
CephContext *cct = m_image_ctx->cct;
ldout(cct, 20) << dendl;
- cls::rbd::MirrorPrimarySnapshotNamespace ns{
- ((m_flags & CREATE_PRIMARY_FLAG_DEMOTED) != 0), m_mirror_peer_uuids};
+ cls::rbd::MirrorSnapshotNamespace ns{
+ ((m_flags & CREATE_PRIMARY_FLAG_DEMOTED) != 0 ?
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED :
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY),
+ m_mirror_peer_uuids, "", CEPH_NOSNAP};
+
+ // TODO delay until after image state written
+ ns.complete = true;
+
auto ctx = create_context_callback<
CreatePrimaryRequest<I>,
&CreatePrimaryRequest<I>::handle_create_snapshot>(this);
if (m_snap_id != nullptr) {
std::shared_lock image_locker{m_image_ctx->image_lock};
- cls::rbd::MirrorPrimarySnapshotNamespace ns{
- ((m_flags & CREATE_PRIMARY_FLAG_DEMOTED) != 0), m_mirror_peer_uuids};
+ cls::rbd::MirrorSnapshotNamespace ns{
+ ((m_flags & CREATE_PRIMARY_FLAG_DEMOTED) != 0 ?
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED :
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY),
+ m_mirror_peer_uuids, "", CEPH_NOSNAP};
+
+ // TODO delay until after image state written
+ ns.complete = true;
+
*m_snap_id = m_image_ctx->get_snap_id(ns, m_snap_name);
}
prev_snap_id = 0;
continue;
}
- auto info = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ auto info = boost::get<cls::rbd::MirrorSnapshotNamespace>(
&snap_it.second.snap_namespace);
if (info == nullptr) {
continue;
}
- if (info->demoted) {
+ if (info->state != cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY) {
// reset counters -- we count primary snapshots after the last promotion
count = 0;
prev_snap_id = 0;
for (auto &[snap_id, snap_info] : m_image_ctx->snap_info) {
auto type = cls::rbd::get_snap_namespace_type(snap_info.snap_namespace);
- if (type == cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY ||
+ if (type == cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR ||
type == cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY) {
continue;
}
return;
}
- auto info = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ auto info = boost::get<cls::rbd::MirrorSnapshotNamespace>(
&snap_info->snap_namespace);
if (info == nullptr) {
lderr(cct) << "not mirror primary snapshot (snap_id=" << m_snap_id << ")"
return;
}
- auto info = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ auto info = boost::get<cls::rbd::MirrorSnapshotNamespace>(
&snap_namespace);
ceph_assert(info);
uint64_t *rollback_snap_id) {
for (; it != end; it++) {
- auto primary = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ auto primary = boost::get<cls::rbd::MirrorSnapshotNamespace>(
&it->second.snap_namespace);
if (primary != nullptr) {
break;
}
return true;
}
- auto primary = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+
+ auto mirror_ns = boost::get<cls::rbd::MirrorSnapshotNamespace>(
&it->second.snap_namespace);
- if (primary == nullptr) {
+ if (mirror_ns == nullptr) {
continue;
}
ldout(cct, 20) << "previous snapshot snap_id=" << it->first << " "
- << *primary << dendl;
- if (primary->demoted && !force) {
+ << *mirror_ns << dendl;
+ if ((mirror_ns->state == cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED ||
+ mirror_ns->state ==
+ cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED) &&
+ !force) {
lderr(cct) << "trying to create primary snapshot without force "
<< "when previous primary snapshot is demoted"
<< dendl;
return false;
}
+
+ if (mirror_ns->state == cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY) {
+ if (!force) {
+ lderr(cct) << "trying to create primary snapshot without force "
+ << "when previous snapshot is non-primary"
+ << dendl;
+ return false;
+ }
+ if (demoted) {
+ lderr(cct) << "trying to create primary demoted snapshot "
+ << "when previous snapshot is non-primary"
+ << dendl;
+ return false;
+ }
+ if (!mirror_ns->complete) {
+ ldout(cct, 20) << "needs rollback" << dendl;
+ if (!rollback_snap_id) {
+ lderr(cct) << "trying to create primary snapshot "
+ << "when previous non-primary snapshot is not copied yet"
+ << dendl;
+ return false;
+ }
+ if (!get_rollback_snap_id(++it, image_ctx->snap_info.rend(),
+ rollback_snap_id)) {
+ lderr(cct) << "cannot rollback" << dendl;
+ return false;
+ }
+ ldout(cct, 20) << "rollback_snap_id=" << *rollback_snap_id << dendl;
+ }
+ return true;
+ }
+
return true;
}
for (auto it = image_ctx->snap_info.rbegin();
it != image_ctx->snap_info.rend(); it++) {
- auto primary = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ auto mirror_ns = boost::get<cls::rbd::MirrorSnapshotNamespace>(
&it->second.snap_namespace);
- if (primary != nullptr) {
+ if (mirror_ns != nullptr) {
ldout(cct, 20) << "previous mirror snapshot snap_id=" << it->first << " "
- << *primary << dendl;
- if (!primary->demoted) {
+ << *mirror_ns << dendl;
+
+ if (mirror_ns->state == cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY) {
+ if (!mirror_ns->complete) {
+ lderr(cct) << "trying to create non-primary snapshot "
+ << "when previous non-primary snapshot is not copied yet"
+ << dendl;
+ return false;
+ }
+ return true;
+ }
+
+ if (mirror_ns->state == cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY) {
lderr(cct) << "trying to create non-primary snapshot "
<< "when previous primary snapshot is not in demoted state"
<< dendl;
}
return true;
}
+
auto non_primary = boost::get<cls::rbd::MirrorNonPrimarySnapshotNamespace>(
&it->second.snap_namespace);
if (non_primary == nullptr) {
I &image_ctx = this->m_image_ctx;
auto type = cls::rbd::get_snap_namespace_type(m_snap_namespace);
- if (type != cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY) {
+ if (type != cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR) {
update_snap_context();
image_ctx.io_work_queue->unblock_writes();
return this->create_context_finisher(0);
I &image_ctx = this->m_image_ctx;
auto type = cls::rbd::get_snap_namespace_type(m_snap_namespace);
- if (type != cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY &&
+ if (type != cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR &&
type != cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY) {
release_snap_id();
return;
string oid = get_temp_image_name();
ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
- cls::rbd::MirrorPrimarySnapshotNamespace primary = {false,
- {"peer1", "peer2"}};
+ cls::rbd::MirrorSnapshotNamespace primary = {
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"peer1", "peer2"}, "",
+ CEPH_NOSNAP};
cls::rbd::MirrorNonPrimarySnapshotNamespace non_primary = {"uuid", 123};
librados::ObjectWriteOperation op;
::librbd::cls_client::snapshot_add(&op, 1, "primary", primary);
cls::rbd::SnapshotInfo snap;
ASSERT_EQ(0, snapshot_get(&ioctx, oid, 1, &snap));
- auto sn = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ auto sn = boost::get<cls::rbd::MirrorSnapshotNamespace>(
&snap.snapshot_namespace);
ASSERT_NE(nullptr, sn);
ASSERT_EQ(primary, *sn);
ASSERT_EQ(-ENOENT, mirror_image_snapshot_unlink_peer(&ioctx, oid, 1,
"peer1"));
ASSERT_EQ(0, snapshot_get(&ioctx, oid, 1, &snap));
- sn = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ sn = boost::get<cls::rbd::MirrorSnapshotNamespace>(
&snap.snapshot_namespace);
ASSERT_NE(nullptr, sn);
ASSERT_EQ(1U, sn->mirror_peer_uuids.size());
ASSERT_EQ(-ERESTART,
mirror_image_snapshot_unlink_peer(&ioctx, oid, 1, "peer2"));
ASSERT_EQ(0, snapshot_get(&ioctx, oid, 1, &snap));
- sn = boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ sn = boost::get<cls::rbd::MirrorSnapshotNamespace>(
&snap.snapshot_namespace);
ASSERT_NE(nullptr, sn);
ASSERT_EQ(1U, sn->mirror_peer_uuids.size());
ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap1", false));
ASSERT_EQ(0, create_snap(m_src_image_ctx, "snap2", false));
ASSERT_EQ(0, create_snap(m_src_image_ctx,
- {cls::rbd::MirrorPrimarySnapshotNamespace{
- false, {{"peer uuid1"}}}},
+ {cls::rbd::MirrorSnapshotNamespace{
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY,
+ {"peer uuid1"}, "", CEPH_NOSNAP}},
"snap3", false));
auto src_snap_id1 = m_src_image_ctx->snaps[2];
auto src_snap_id2 = m_src_image_ctx->snaps[1];
auto it = mock_image_ctx.snap_info.find(snap_id);
ASSERT_NE(it, mock_image_ctx.snap_info.end());
auto info =
- boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ boost::get<cls::rbd::MirrorSnapshotNamespace>(
&it->second.snap_namespace);
ASSERT_NE(nullptr, info);
ASSERT_NE(0, info->mirror_peer_uuids.erase(
MockTestImageCtx mock_image_ctx(*ictx);
for (int i = 0; i < 3; i++) {
- cls::rbd::MirrorPrimarySnapshotNamespace ns{false, {"uuid"}};
+ cls::rbd::MirrorSnapshotNamespace ns{
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"uuid"}, "", CEPH_NOSNAP};
snap_create(mock_image_ctx, ns, "mirror_snap");
}
expect_list_watchers(mock_image_ctx, mock_list_watchers_request, {}, 0);
expect_acquire_lock(mock_image_ctx, 0);
- SnapInfo snap_info = {"snap", cls::rbd::MirrorPrimarySnapshotNamespace{}, 0,
+ SnapInfo snap_info = {"snap", cls::rbd::MirrorSnapshotNamespace{}, 0,
{}, 0, 0, {}};
expect_rollback(mock_image_ctx, 123, &snap_info, 0);
MockCreatePrimaryRequest mock_create_primary_request;
auto it = mock_image_ctx.snap_info.find(snap_id);
EXPECT_NE(it, mock_image_ctx.snap_info.end());
auto info =
- boost::get<cls::rbd::MirrorPrimarySnapshotNamespace>(
+ boost::get<cls::rbd::MirrorSnapshotNamespace>(
&it->second.snap_namespace);
EXPECT_NE(nullptr, info);
EXPECT_NE(0, info->mirror_peer_uuids.erase(
ASSERT_EQ(0, open_image(m_image_name, &ictx));
MockTestImageCtx mock_image_ctx(*ictx);
- cls::rbd::MirrorPrimarySnapshotNamespace ns{false, {"peer1_uuid", "peer2_uuid"}};
+ cls::rbd::MirrorSnapshotNamespace ns{
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"peer1_uuid", "peer2_uuid"},
+ "", CEPH_NOSNAP};
auto snap_id = snap_create(mock_image_ctx, ns, "mirror_snap");
expect_get_snap_info(mock_image_ctx, snap_id);
ASSERT_EQ(0, open_image(m_image_name, &ictx));
MockTestImageCtx mock_image_ctx(*ictx);
- cls::rbd::MirrorPrimarySnapshotNamespace ns{false, {"peer_uuid"}};
+ cls::rbd::MirrorSnapshotNamespace ns{
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"peer_uuid"},
+ "", CEPH_NOSNAP};
auto snap_id = snap_create(mock_image_ctx, ns, "mirror_snap");
expect_get_snap_info(mock_image_ctx, snap_id);
ASSERT_EQ(0, open_image(m_image_name, &ictx));
MockTestImageCtx mock_image_ctx(*ictx);
- cls::rbd::MirrorPrimarySnapshotNamespace ns{false, {"peer_uuid"}};
+ cls::rbd::MirrorSnapshotNamespace ns{
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"peer_uuid"},
+ "", CEPH_NOSNAP};
auto snap_id = snap_create(mock_image_ctx, ns, "mirror_snap");
expect_get_snap_info(mock_image_ctx, snap_id);
ASSERT_EQ(0, open_image(m_image_name, &ictx));
MockTestImageCtx mock_image_ctx(*ictx);
- cls::rbd::MirrorPrimarySnapshotNamespace ns{false,
- {"peer1_uuid", "peer2_uuid"}};
+ cls::rbd::MirrorSnapshotNamespace ns{
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"peer1_uuid", "peer2_uuid"},
+ "", CEPH_NOSNAP};
auto snap_id = snap_create(mock_image_ctx, ns, "mirror_snap");
expect_get_snap_info(mock_image_ctx, snap_id);
ASSERT_EQ(0, open_image(m_image_name, &ictx));
MockTestImageCtx mock_image_ctx(*ictx);
- cls::rbd::MirrorPrimarySnapshotNamespace ns{false,
- {"peer1_uuid", "peer2_uuid"}};
+ cls::rbd::MirrorSnapshotNamespace ns{
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"peer1_uuid", "peer2_uuid"},
+ "", CEPH_NOSNAP};
auto snap_id = snap_create(mock_image_ctx, ns, "mirror_snap");
expect_get_snap_info(mock_image_ctx, snap_id);
ASSERT_EQ(0, open_image(m_image_name, &ictx));
MockTestImageCtx mock_image_ctx(*ictx);
- cls::rbd::MirrorPrimarySnapshotNamespace ns{false, {"peer_uuid"}};
+ cls::rbd::MirrorSnapshotNamespace ns{
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"peer_uuid"},
+ "", CEPH_NOSNAP};
auto snap_id = snap_create(mock_image_ctx, ns, "mirror_snap");
expect_get_snap_info(mock_image_ctx, snap_id);
ASSERT_TRUE(util::can_create_primary_snapshot(&mock_image_ctx, false, true,
&rollback_snap_id));
ASSERT_EQ(rollback_snap_id, CEPH_NOSNAP);
-
nns.copied = false;
snap_create(mock_image_ctx, nns, "NPS2");
ASSERT_TRUE(util::can_create_primary_snapshot(&mock_image_ctx, false, true,
nullptr));
- cls::rbd::MirrorPrimarySnapshotNamespace pns{true, {"uuid"}};
+ cls::rbd::MirrorSnapshotNamespace pns{
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED, {"uuid"}, "", CEPH_NOSNAP};
snap_create(mock_image_ctx, pns, "PS1");
// previous primary snapshot is demoted, no force
ASSERT_TRUE(util::can_create_primary_snapshot(&mock_image_ctx, false, true,
nullptr));
- pns.demoted = false;
+ pns.state = cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY;
snap_create(mock_image_ctx, pns, "PS2");
// previous snapshot is not demoted primary
// previous non-primary snapshot is copied
ASSERT_TRUE(util::can_create_non_primary_snapshot(&mock_image_ctx));
- cls::rbd::MirrorPrimarySnapshotNamespace pns{false, {"uuid"}};
+ cls::rbd::MirrorSnapshotNamespace pns{
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"uuid"}, "", CEPH_NOSNAP};
snap_create(mock_image_ctx, pns, "PS1");
// previous primary snapshot is not in demoted state
ASSERT_FALSE(util::can_create_non_primary_snapshot(&mock_image_ctx));
- pns.demoted = true;
+ pns.state = cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED;
snap_create(mock_image_ctx, pns, "PS2");
// previous primary snapshot is in demoted state
C_SaferCond cond_ctx;
MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
- mock_image_ctx, &cond_ctx, cls::rbd::MirrorPrimarySnapshotNamespace(),
+ mock_image_ctx, &cond_ctx, cls::rbd::MirrorSnapshotNamespace(),
"snap1", 0, false);
{
std::shared_lock owner_locker{mock_image_ctx.owner_lock};
uint64_t snap_id = ictx->snap_info.rbegin()->first;
expect_snapshot_get(mock_image_ctx,
- {snap_id, {cls::rbd::MirrorPrimarySnapshotNamespace{}},
+ {snap_id, {cls::rbd::MirrorSnapshotNamespace{}},
"mirror", 123, {}, 0}, 0);
expect_get_parent_spec(mock_image_ctx, 0);
C_SaferCond cond_ctx;
MockSnapshotRemoveRequest *req = new MockSnapshotRemoveRequest(
- mock_image_ctx, &cond_ctx, cls::rbd::MirrorPrimarySnapshotNamespace(),
+ mock_image_ctx, &cond_ctx, cls::rbd::MirrorSnapshotNamespace(),
"mirror", snap_id);
{
std::shared_lock owner_locker{mock_image_ctx.owner_lock};