1
0
mirror of https://github.com/ceph/ceph synced 2025-04-01 14:51:13 +00:00

librbd: simplified retrieving snapshots from image header

Added a new cls 'snapshot_get' method that retrieves all snapshot
specific details to avoid the need to add a new cls method to
retrieve each individual snapshot data field.

The cls 'get_snapshot_namespace' method has been dropped since Luminous
clients will treat that as a user-generated snapshot (and that's all
that is supported by Luminous clients). The cls 'get_snapshot_timestamp'
method has been deprecated and can be removed once <=Luminous clients
are no longer supported.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
Jason Dillaman 2018-01-17 13:40:13 -05:00
parent 7cd13f8351
commit 4ad9d565a1
13 changed files with 507 additions and 359 deletions

View File

@ -1562,6 +1562,14 @@ int get_data_pool(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
return 0;
}
/**
* Input:
* @param snap_id which snapshot to query
*
* Output:
* @param name (string) of the snapshot
* @returns 0 on success, negative error code on failure
*/
int get_snapshot_name(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
{
uint64_t snap_id;
@ -1590,10 +1598,20 @@ int get_snapshot_name(cls_method_context_t hctx, bufferlist *in, bufferlist *out
return 0;
}
/**
* Input:
* @param snap_id which snapshot to query
*
* Output:
* @param timestamp (utime_t) of the snapshot
* @returns 0 on success, negative error code on failure
*
* NOTE: deprecated - remove this method after Luminous is unsupported
*/
int get_snapshot_timestamp(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
{
uint64_t snap_id;
bufferlist::iterator iter = in->begin();
try {
decode(snap_id, iter);
@ -1606,7 +1624,7 @@ int get_snapshot_timestamp(cls_method_context_t hctx, bufferlist *in, bufferlist
if (snap_id == CEPH_NOSNAP) {
return -EINVAL;
}
cls_rbd_snap snap;
string snapshot_key;
key_from_snap_id(snap_id, &snapshot_key);
@ -1620,16 +1638,14 @@ int get_snapshot_timestamp(cls_method_context_t hctx, bufferlist *in, bufferlist
}
/**
* Retrieve namespace of a snapshot.
*
* Input:
* @param snap_id id of the snapshot (uint64_t)
* @param snap_id which snapshot to query
*
* Output:
* @param SnapshotNamespace
* @returns 0 on success, negative error code on failure.
* @param snapshot (cls::rbd::SnapshotInfo)
* @returns 0 on success, negative error code on failure
*/
int get_snapshot_namespace(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
int snapshot_get(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
{
uint64_t snap_id;
@ -1640,8 +1656,7 @@ int get_snapshot_namespace(cls_method_context_t hctx, bufferlist *in, bufferlist
return -EINVAL;
}
CLS_LOG(20, "get_snapshot_namespace snap_id=%" PRIu64, snap_id);
CLS_LOG(20, "snapshot_get snap_id=%llu", (unsigned long long)snap_id);
if (snap_id == CEPH_NOSNAP) {
return -EINVAL;
}
@ -1654,8 +1669,10 @@ int get_snapshot_namespace(cls_method_context_t hctx, bufferlist *in, bufferlist
return r;
}
encode(snap.snapshot_namespace, *out);
cls::rbd::SnapshotInfo snapshot_info{snap.id, snap.snapshot_namespace,
snap.name, snap.image_size,
snap.timestamp};
encode(snapshot_info, *out);
return 0;
}
@ -1665,7 +1682,7 @@ int get_snapshot_namespace(cls_method_context_t hctx, bufferlist *in, bufferlist
* Input:
* @param snap_name name of the snapshot (string)
* @param snap_id id of the snapshot (uint64_t)
* @param snap_namespace namespace of the snapshot (cls::rbd::SnapshotNamespaceOnDisk)
* @param snap_namespace namespace of the snapshot (cls::rbd::SnapshotNamespace)
*
* Output:
* @returns 0 on success, negative error code on failure.
@ -1690,7 +1707,7 @@ int snapshot_add(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
}
if (boost::get<cls::rbd::UnknownSnapshotNamespace>(
&snap_meta.snapshot_namespace.snapshot_namespace) != nullptr) {
&snap_meta.snapshot_namespace) != nullptr) {
CLS_ERR("Unknown snapshot namespace provided");
return -EINVAL;
}
@ -5678,8 +5695,8 @@ CLS_INIT(rbd)
cls_method_handle_t h_get_object_prefix;
cls_method_handle_t h_get_data_pool;
cls_method_handle_t h_get_snapshot_name;
cls_method_handle_t h_get_snapshot_namespace;
cls_method_handle_t h_get_snapshot_timestamp;
cls_method_handle_t h_snapshot_get;
cls_method_handle_t h_snapshot_add;
cls_method_handle_t h_snapshot_remove;
cls_method_handle_t h_snapshot_rename;
@ -5780,12 +5797,12 @@ CLS_INIT(rbd)
cls_register_cxx_method(h_class, "get_snapshot_name",
CLS_METHOD_RD,
get_snapshot_name, &h_get_snapshot_name);
cls_register_cxx_method(h_class, "get_snapshot_namespace",
CLS_METHOD_RD,
get_snapshot_namespace, &h_get_snapshot_namespace);
cls_register_cxx_method(h_class, "get_snapshot_timestamp",
CLS_METHOD_RD,
get_snapshot_timestamp, &h_get_snapshot_timestamp);
cls_register_cxx_method(h_class, "snapshot_get",
CLS_METHOD_RD,
snapshot_get, &h_snapshot_get);
cls_register_cxx_method(h_class, "snapshot_add",
CLS_METHOD_RD | CLS_METHOD_WR,
snapshot_add, &h_snapshot_add);

View File

@ -66,7 +66,7 @@ struct cls_rbd_snap {
cls_rbd_parent parent;
uint64_t flags;
utime_t timestamp;
cls::rbd::SnapshotNamespaceOnDisk snapshot_namespace = {
cls::rbd::SnapshotNamespace snapshot_namespace = {
cls::rbd::UserSnapshotNamespace{}};
/// true if we have a parent

View File

@ -78,9 +78,7 @@ namespace librbd {
bufferlist empty_bl;
op->exec("rbd", "get_snapcontext", empty_bl);
bufferlist parent_bl;
encode(snap, parent_bl);
op->exec("rbd", "get_parent", parent_bl);
get_parent_start(op, snap);
rados::cls::lock::get_lock_info_start(op, RBD_LOCK_NAME);
}
@ -111,18 +109,15 @@ namespace librbd {
// get_snapcontext
decode(*snapc, *it);
// get_parent
decode(parent->spec.pool_id, *it);
decode(parent->spec.image_id, *it);
decode(parent->spec.snap_id, *it);
decode(parent->overlap, *it);
int r = get_parent_finish(it, &parent->spec, &parent->overlap);
if (r < 0) {
return r;
}
// get_lock_info
ClsLockType lock_type = LOCK_NONE;
int r = rados::cls::lock::get_lock_info_finish(it, lockers, &lock_type,
lock_tag);
if (r == -EOPNOTSUPP) {
r = 0;
}
r = rados::cls::lock::get_lock_info_finish(it, lockers, &lock_type,
lock_tag);
if (r == 0) {
*exclusive_lock = (lock_type == LOCK_EXCLUSIVE);
}
@ -304,28 +299,42 @@ namespace librbd {
op->exec("rbd", "set_size", bl);
}
void get_parent_start(librados::ObjectReadOperation *op, snapid_t snap_id)
{
bufferlist bl;
encode(snap_id, bl);
op->exec("rbd", "get_parent", bl);
}
int get_parent_finish(bufferlist::iterator *it, ParentSpec *pspec,
uint64_t *parent_overlap)
{
try {
decode(pspec->pool_id, *it);
decode(pspec->image_id, *it);
decode(pspec->snap_id, *it);
decode(*parent_overlap, *it);
} catch (const buffer::error &) {
return -EBADMSG;
}
return 0;
}
int get_parent(librados::IoCtx *ioctx, const std::string &oid,
snapid_t snap_id, ParentSpec *pspec,
uint64_t *parent_overlap)
{
bufferlist inbl, outbl;
encode(snap_id, inbl);
librados::ObjectReadOperation op;
get_parent_start(&op, snap_id);
int r = ioctx->exec(oid, "rbd", "get_parent", inbl, outbl);
if (r < 0)
return r;
try {
bufferlist::iterator iter = outbl.begin();
decode(pspec->pool_id, iter);
decode(pspec->image_id, iter);
decode(pspec->snap_id, iter);
decode(*parent_overlap, iter);
} catch (const buffer::error &err) {
return -EBADMSG;
bufferlist out_bl;
int r = ioctx->operate(oid, &op, &out_bl);
if (r < 0) {
return r;
}
return 0;
bufferlist::iterator it = out_bl.begin();
return get_parent_finish(&it, pspec, parent_overlap);
}
int set_parent(librados::IoCtx *ioctx, const std::string &oid,
@ -540,13 +549,78 @@ namespace librbd {
return get_children_finish(&it, &children);
}
void snapshot_get_start(librados::ObjectReadOperation *op,
const std::vector<snapid_t> &ids)
{
for (auto snap_id : ids) {
bufferlist bl;
encode(snap_id, bl);
op->exec("rbd", "snapshot_get", bl);
get_parent_start(op, snap_id);
get_protection_status_start(op, snap_id);
}
}
int snapshot_get_finish(bufferlist::iterator *it,
const std::vector<snapid_t> &ids,
std::vector<cls::rbd::SnapshotInfo>* snaps,
std::vector<ParentInfo> *parents,
std::vector<uint8_t> *protection_statuses)
{
snaps->resize(ids.size());
parents->resize(ids.size());
protection_statuses->resize(ids.size());
try {
for (size_t i = 0; i < snaps->size(); ++i) {
decode((*snaps)[i], *it);
// get_parent
int r = get_parent_finish(it, &(*parents)[i].spec,
&(*parents)[i].overlap);
if (r < 0) {
return r;
}
// get_protection_status
r = get_protection_status_finish(it, &(*protection_statuses)[i]);
if (r < 0) {
return r;
}
}
} catch (const buffer::error &err) {
return -EBADMSG;
}
return 0;
}
int snapshot_get(librados::IoCtx* ioctx, const std::string& oid,
const std::vector<snapid_t>& ids,
std::vector<cls::rbd::SnapshotInfo>* snaps,
std::vector<ParentInfo> *parents,
std::vector<uint8_t> *protection_statuses)
{
librados::ObjectReadOperation op;
snapshot_get_start(&op, ids);
bufferlist out_bl;
int r = ioctx->operate(oid, &op, &out_bl);
if (r < 0) {
return r;
}
bufferlist::iterator it = out_bl.begin();
return snapshot_get_finish(&it, ids, snaps, parents, protection_statuses);
}
void snapshot_add(librados::ObjectWriteOperation *op, snapid_t snap_id,
const std::string &snap_name, const cls::rbd::SnapshotNamespace &snap_namespace)
const std::string &snap_name,
const cls::rbd::SnapshotNamespace &snap_namespace)
{
bufferlist bl;
encode(snap_name, bl);
encode(snap_id, bl);
encode(cls::rbd::SnapshotNamespaceOnDisk(snap_namespace), bl);
encode(snap_namespace, bl);
op->exec("rbd", "snapshot_add", bl);
}
@ -606,15 +680,13 @@ namespace librbd {
void snapshot_list_start(librados::ObjectReadOperation *op,
const std::vector<snapid_t> &ids) {
for (auto snap_id : ids) {
bufferlist bl1, bl2, bl3, bl4;
bufferlist bl1, bl2;
encode(snap_id, bl1);
op->exec("rbd", "get_snapshot_name", bl1);
encode(snap_id, bl2);
op->exec("rbd", "get_size", bl2);
encode(snap_id, bl3);
op->exec("rbd", "get_parent", bl3);
encode(snap_id, bl4);
op->exec("rbd", "get_protection_status", bl4);
get_parent_start(op, snap_id);
get_protection_status_start(op, snap_id);
}
}
@ -637,13 +709,19 @@ namespace librbd {
// get_size
decode(order, *it);
decode((*sizes)[i], *it);
// get_parent
decode((*parents)[i].spec.pool_id, *it);
decode((*parents)[i].spec.image_id, *it);
decode((*parents)[i].spec.snap_id, *it);
decode((*parents)[i].overlap, *it);
int r = get_parent_finish(it, &(*parents)[i].spec,
&(*parents)[i].overlap);
if (r < 0) {
return r;
}
// get_protection_status
decode((*protection_statuses)[i], *it);
r = get_protection_status_finish(it, &(*protection_statuses)[i]);
if (r < 0) {
return r;
}
}
} catch (const buffer::error &err) {
return -EBADMSG;
@ -716,50 +794,6 @@ namespace librbd {
return snapshot_timestamp_list_finish(&it, ids, timestamps);
}
void snapshot_namespace_list_start(librados::ObjectReadOperation *op,
const std::vector<snapid_t> &ids)
{
for (auto snap_id : ids) {
bufferlist bl;
encode(snap_id, bl);
op->exec("rbd", "get_snapshot_namespace", bl);
}
}
int snapshot_namespace_list_finish(bufferlist::iterator *it,
const std::vector<snapid_t> &ids,
std::vector<cls::rbd::SnapshotNamespace> *namespaces)
{
namespaces->resize(ids.size());
try {
for (size_t i = 0; i < namespaces->size(); ++i) {
cls::rbd::SnapshotNamespaceOnDisk e;
decode(e, *it);
(*namespaces)[i] = e.snapshot_namespace;
}
} catch (const buffer::error &err) {
return -EBADMSG;
}
return 0;
}
int snapshot_namespace_list(librados::IoCtx *ioctx, const std::string &oid,
const std::vector<snapid_t> &ids,
std::vector<cls::rbd::SnapshotNamespace> *namespaces)
{
librados::ObjectReadOperation op;
snapshot_namespace_list_start(&op, ids);
bufferlist out_bl;
int r = ioctx->operate(oid, &op, &out_bl);
if (r < 0) {
return r;
}
bufferlist::iterator it = out_bl.begin();
return snapshot_namespace_list_finish(&it, ids, namespaces);
}
void old_snapshot_add(librados::ObjectWriteOperation *op,
snapid_t snap_id, const std::string &snap_name)
{
@ -868,24 +902,39 @@ namespace librbd {
return ioctx->exec(oid, "rbd", "copyup", data, out);
}
void get_protection_status_start(librados::ObjectReadOperation *op,
snapid_t snap_id)
{
bufferlist bl;
encode(snap_id, bl);
op->exec("rbd", "get_protection_status", bl);
}
int get_protection_status_finish(bufferlist::iterator *it,
uint8_t *protection_status)
{
try {
decode(*protection_status, *it);
} catch (const buffer::error &) {
return -EBADMSG;
}
return 0;
}
int get_protection_status(librados::IoCtx *ioctx, const std::string &oid,
snapid_t snap_id, uint8_t *protection_status)
{
bufferlist in, out;
encode(snap_id.val, in);
librados::ObjectReadOperation op;
get_protection_status_start(&op, snap_id);
int r = ioctx->exec(oid, "rbd", "get_protection_status", in, out);
if (r < 0)
return r;
try {
bufferlist::iterator iter = out.begin();
decode(*protection_status, iter);
} catch (const buffer::error &err) {
return -EBADMSG;
bufferlist out_bl;
int r = ioctx->operate(oid, &op, &out_bl);
if (r < 0) {
return r;
}
return 0;
bufferlist::iterator it = out_bl.begin();
return get_protection_status_finish(&it, protection_status);
}
int set_protection_status(librados::IoCtx *ioctx, const std::string &oid,

View File

@ -72,9 +72,14 @@ namespace librbd {
int set_size(librados::IoCtx *ioctx, const std::string &oid,
uint64_t size);
void set_size(librados::ObjectWriteOperation *op, uint64_t size);
void get_parent_start(librados::ObjectReadOperation *op, snapid_t snap_id);
int get_parent_finish(bufferlist::iterator *it, ParentSpec *pspec,
uint64_t *parent_overlap);
int get_parent(librados::IoCtx *ioctx, const std::string &oid,
snapid_t snap_id, ParentSpec *pspec,
uint64_t *parent_overlap);
int set_parent(librados::IoCtx *ioctx, const std::string &oid,
const ParentSpec &pspec, uint64_t parent_overlap);
void set_parent(librados::ObjectWriteOperation *op,
@ -113,6 +118,20 @@ namespace librbd {
std::set<string> *children);
int get_children(librados::IoCtx *ioctx, const std::string &oid,
const ParentSpec &pspec, set<string>& children);
void snapshot_get_start(librados::ObjectReadOperation *op,
const std::vector<snapid_t> &ids);
int snapshot_get_finish(bufferlist::iterator *it,
const std::vector<snapid_t> &ids,
std::vector<cls::rbd::SnapshotInfo>* snaps,
std::vector<ParentInfo> *parents,
std::vector<uint8_t> *protection_statuses);
int snapshot_get(librados::IoCtx* ioctx, const std::string& oid,
const std::vector<snapid_t>& ids,
std::vector<cls::rbd::SnapshotInfo>* snaps,
std::vector<ParentInfo> *parents,
std::vector<uint8_t> *protection_statuses);
void snapshot_add(librados::ObjectWriteOperation *op, snapid_t snap_id,
const std::string &snap_name,
const cls::rbd::SnapshotNamespace &snap_namespace);
@ -126,6 +145,7 @@ namespace librbd {
int get_snapcontext(librados::IoCtx *ioctx, const std::string &oid,
::SnapContext *snapc);
/// NOTE: remove after Luminous is retired
void snapshot_list_start(librados::ObjectReadOperation *op,
const std::vector<snapid_t> &ids);
int snapshot_list_finish(bufferlist::iterator *it,
@ -134,17 +154,6 @@ namespace librbd {
std::vector<uint64_t> *sizes,
std::vector<ParentInfo> *parents,
std::vector<uint8_t> *protection_statuses);
void snapshot_timestamp_list_start(librados::ObjectReadOperation *op,
const std::vector<snapid_t> &ids);
int snapshot_timestamp_list_finish(bufferlist::iterator *it,
const std::vector<snapid_t> &ids,
std::vector<utime_t> *timestamps);
int snapshot_timestamp_list(librados::IoCtx *ioctx, const std::string &oid,
const std::vector<snapid_t> &ids,
std::vector<utime_t> *timestamps);
int snapshot_list(librados::IoCtx *ioctx, const std::string &oid,
const std::vector<snapid_t> &ids,
std::vector<string> *names,
@ -152,14 +161,15 @@ namespace librbd {
std::vector<ParentInfo> *parents,
std::vector<uint8_t> *protection_statuses);
void snapshot_namespace_list_start(librados::ObjectReadOperation *op,
/// NOTE: remove after Luminous is retired
void snapshot_timestamp_list_start(librados::ObjectReadOperation *op,
const std::vector<snapid_t> &ids);
int snapshot_namespace_list_finish(bufferlist::iterator *it,
int snapshot_timestamp_list_finish(bufferlist::iterator *it,
const std::vector<snapid_t> &ids,
std::vector<cls::rbd::SnapshotNamespace> *namespaces);
int snapshot_namespace_list(librados::IoCtx *ioctx, const std::string &oid,
std::vector<utime_t> *timestamps);
int snapshot_timestamp_list(librados::IoCtx *ioctx, const std::string &oid,
const std::vector<snapid_t> &ids,
std::vector<cls::rbd::SnapshotNamespace> *namespaces);
std::vector<utime_t> *timestamps);
void get_all_features_start(librados::ObjectReadOperation *op);
int get_all_features_finish(bufferlist::iterator *it,
@ -169,8 +179,15 @@ namespace librbd {
int copyup(librados::IoCtx *ioctx, const std::string &oid,
bufferlist data);
/// NOTE: remove protection after clone v1 is retired
void get_protection_status_start(librados::ObjectReadOperation *op,
snapid_t snap_id);
int get_protection_status_finish(bufferlist::iterator *it,
uint8_t *protection_status);
int get_protection_status(librados::IoCtx *ioctx, const std::string &oid,
snapid_t snap_id, uint8_t *protection_status);
int set_protection_status(librados::IoCtx *ioctx, const std::string &oid,
snapid_t snap_id, uint8_t protection_status);
void set_protection_status(librados::ObjectWriteOperation *op,

View File

@ -415,40 +415,79 @@ SnapshotNamespaceType get_snap_namespace_type(
GetTypeVisitor(), snapshot_namespace));
}
void SnapshotNamespaceOnDisk::encode(bufferlist& bl) const {
void SnapshotInfo::encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);
boost::apply_visitor(EncodeSnapshotNamespaceVisitor(bl), snapshot_namespace);
encode(id, bl);
encode(snapshot_namespace, bl);
encode(name, bl);
encode(image_size, bl);
encode(timestamp, bl);
ENCODE_FINISH(bl);
}
void SnapshotNamespaceOnDisk::decode(bufferlist::iterator &p)
void SnapshotInfo::decode(bufferlist::iterator& it) {
DECODE_START(1, it);
decode(id, it);
decode(snapshot_namespace, it);
decode(name, it);
decode(image_size, it);
decode(timestamp, it);
DECODE_FINISH(it);
}
void SnapshotInfo::dump(Formatter *f) const {
f->dump_unsigned("id", id);
f->open_object_section("namespace");
boost::apply_visitor(DumpSnapshotNamespaceVisitor(f, "type"),
snapshot_namespace);
f->close_section();
f->dump_string("name", name);
f->dump_unsigned("image_size", image_size);
f->dump_stream("timestamp") << timestamp;
}
void SnapshotInfo::generate_test_instances(std::list<SnapshotInfo*> &o) {
o.push_back(new SnapshotInfo(1ULL, UserSnapshotNamespace{}, "snap1", 123,
{123456, 0}));
o.push_back(new SnapshotInfo(2ULL,
GroupSnapshotNamespace{567, "group1", "snap1"},
"snap1", 123, {123456, 0}));
}
void SnapshotNamespace::encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);
boost::apply_visitor(EncodeSnapshotNamespaceVisitor(bl), *this);
ENCODE_FINISH(bl);
}
void SnapshotNamespace::decode(bufferlist::iterator &p)
{
DECODE_START(1, p);
uint32_t snap_type;
decode(snap_type, p);
switch (snap_type) {
case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_USER:
snapshot_namespace = UserSnapshotNamespace();
*this = UserSnapshotNamespace();
break;
case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_GROUP:
snapshot_namespace = GroupSnapshotNamespace();
*this = GroupSnapshotNamespace();
break;
default:
snapshot_namespace = UnknownSnapshotNamespace();
*this = UnknownSnapshotNamespace();
break;
}
boost::apply_visitor(DecodeSnapshotNamespaceVisitor(p), snapshot_namespace);
boost::apply_visitor(DecodeSnapshotNamespaceVisitor(p), *this);
DECODE_FINISH(p);
}
void SnapshotNamespaceOnDisk::dump(Formatter *f) const {
boost::apply_visitor(DumpSnapshotNamespaceVisitor(f, "snapshot_namespace_type"), snapshot_namespace);
void SnapshotNamespace::dump(Formatter *f) const {
boost::apply_visitor(DumpSnapshotNamespaceVisitor(f, "snapshot_namespace_type"), *this);
}
void SnapshotNamespaceOnDisk::generate_test_instances(std::list<SnapshotNamespaceOnDisk *> &o) {
o.push_back(new SnapshotNamespaceOnDisk(UserSnapshotNamespace()));
o.push_back(new SnapshotNamespaceOnDisk(GroupSnapshotNamespace(0, "10152ae8944a", "2118643c9732")));
o.push_back(new SnapshotNamespaceOnDisk(GroupSnapshotNamespace(5, "1018643c9869", "33352be8933c")));
void SnapshotNamespace::generate_test_instances(std::list<SnapshotNamespace*> &o) {
o.push_back(new SnapshotNamespace(UserSnapshotNamespace()));
o.push_back(new SnapshotNamespace(GroupSnapshotNamespace(0, "10152ae8944a", "2118643c9732")));
o.push_back(new SnapshotNamespace(GroupSnapshotNamespace(5, "1018643c9869", "33352be8933c")));
}
std::ostream& operator<<(std::ostream& os, const UserSnapshotNamespace& ns) {

View File

@ -319,30 +319,60 @@ struct UnknownSnapshotNamespace {
std::ostream& operator<<(std::ostream& os, const UnknownSnapshotNamespace& ns);
typedef boost::variant<UserSnapshotNamespace,
GroupSnapshotNamespace,
UnknownSnapshotNamespace> SnapshotNamespace;
GroupSnapshotNamespace,
UnknownSnapshotNamespace> SnapshotNamespaceVariant;
struct SnapshotNamespace : public SnapshotNamespaceVariant {
struct SnapshotNamespaceOnDisk {
SnapshotNamespace() {
}
SnapshotNamespaceOnDisk() : snapshot_namespace(UnknownSnapshotNamespace()) {}
SnapshotNamespaceOnDisk(const SnapshotNamespace &sn) : snapshot_namespace(sn) {}
SnapshotNamespace snapshot_namespace;
template <typename T>
SnapshotNamespace(T&& t) : SnapshotNamespaceVariant(std::forward<T>(t)) {
}
void encode(bufferlist& bl) const;
void decode(bufferlist::iterator& it);
void dump(Formatter *f) const;
static void generate_test_instances(std::list<SnapshotNamespaceOnDisk *> &o);
static void generate_test_instances(std::list<SnapshotNamespace*> &o);
inline bool operator==(const SnapshotNamespaceOnDisk& gsn) const {
return snapshot_namespace == gsn.snapshot_namespace;
inline bool operator==(const SnapshotNamespaceVariant& sn) const {
return static_cast<const SnapshotNamespaceVariant&>(*this) == sn;
}
inline bool operator<(const SnapshotNamespaceVariant& sn) const {
return static_cast<const SnapshotNamespaceVariant&>(*this) < sn;
}
};
WRITE_CLASS_ENCODER(SnapshotNamespaceOnDisk);
WRITE_CLASS_ENCODER(SnapshotNamespace);
SnapshotNamespaceType get_snap_namespace_type(const SnapshotNamespace& snapshot_namespace);
SnapshotNamespaceType get_snap_namespace_type(
const SnapshotNamespace& snapshot_namespace);
struct SnapshotInfo {
snapid_t id = CEPH_NOSNAP;
cls::rbd::SnapshotNamespace snapshot_namespace = {UserSnapshotNamespace{}};
std::string name;
uint64_t image_size = 0;
utime_t timestamp;
SnapshotInfo() {
}
SnapshotInfo(snapid_t id,
const cls::rbd::SnapshotNamespace& snapshot_namespace,
const std::string& name, uint64_t image_size,
const utime_t& timestamp)
: id(id), snapshot_namespace(snapshot_namespace),
name(name), image_size(image_size), timestamp(timestamp) {
}
void encode(bufferlist& bl) const;
void decode(bufferlist::iterator& it);
void dump(Formatter *f) const;
static void generate_test_instances(std::list<SnapshotInfo*> &o);
};
WRITE_CLASS_ENCODER(SnapshotInfo);
enum GroupSnapshotState {
GROUP_SNAPSHOT_STATE_INCOMPLETE = 0,

View File

@ -204,23 +204,20 @@ void ResizePayload::dump(Formatter *f) const {
void SnapPayloadBase::encode(bufferlist &bl) const {
using ceph::encode;
encode(snap_name, bl);
encode(cls::rbd::SnapshotNamespaceOnDisk(snap_namespace), bl);
encode(snap_namespace, bl);
}
void SnapPayloadBase::decode(__u8 version, bufferlist::iterator &iter) {
using ceph::decode;
decode(snap_name, iter);
if (version >= 6) {
cls::rbd::SnapshotNamespaceOnDisk sn;
decode(sn, iter);
snap_namespace = sn.snapshot_namespace;
decode(snap_namespace, iter);
}
}
void SnapPayloadBase::dump(Formatter *f) const {
f->dump_string("snap_name", snap_name);
cls::rbd::SnapshotNamespaceOnDisk sn(snap_namespace);
sn.dump(f);
snap_namespace.dump(f);
}
void SnapCreatePayload::encode(bufferlist &bl) const {
@ -231,9 +228,7 @@ void SnapCreatePayload::decode(__u8 version, bufferlist::iterator &iter) {
using ceph::decode;
SnapPayloadBase::decode(version, iter);
if (version == 5) {
cls::rbd::SnapshotNamespaceOnDisk sn;
decode(sn, iter);
snap_namespace = sn.snapshot_namespace;
decode(snap_namespace, iter);
}
}

View File

@ -133,10 +133,12 @@ Context *RefreshRequest<I>::handle_v1_get_snapshots(int *result) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << this << " " << __func__ << ": " << "r=" << *result << dendl;
std::vector<std::string> snap_names;
std::vector<uint64_t> snap_sizes;
if (*result == 0) {
bufferlist::iterator it = m_out_bl.begin();
*result = cls_client::old_snapshot_list_finish(
&it, &m_snap_names, &m_snap_sizes, &m_snapc);
*result = cls_client::old_snapshot_list_finish(&it, &snap_names,
&snap_sizes, &m_snapc);
}
if (*result < 0) {
@ -151,12 +153,12 @@ Context *RefreshRequest<I>::handle_v1_get_snapshots(int *result) {
return m_on_finish;
}
//m_snap_namespaces = {m_snap_names.size(), cls::rbd::UserSnapshotNamespace()};
m_snap_namespaces = std::vector<cls::rbd::SnapshotNamespace>(
m_snap_names.size(),
cls::rbd::UserSnapshotNamespace());
m_snap_timestamps = std::vector<utime_t>(m_snap_names.size(), utime_t());
m_snap_infos.clear();
for (size_t i = 0; i < m_snapc.snaps.size(); ++i) {
m_snap_infos.push_back({m_snapc.snaps[i],
{cls::rbd::UserSnapshotNamespace{}},
snap_names[i], snap_sizes[i], {}});
}
send_v1_get_locks();
return nullptr;
@ -378,6 +380,7 @@ Context *RefreshRequest<I>::handle_v2_get_flags(int *result) {
<< "r=" << *result << dendl;
if (*result == 0) {
/// NOTE: remove support for snap paramter after Luminous is retired
bufferlist::iterator it = m_out_bl.begin();
cls_client::get_flags_finish(&it, &m_flags, m_snapc.snaps, &m_snap_flags);
}
@ -495,12 +498,9 @@ Context *RefreshRequest<I>::handle_v2_get_group(int *result) {
template <typename I>
void RefreshRequest<I>::send_v2_get_snapshots() {
if (m_snapc.snaps.empty()) {
m_snap_names.clear();
m_snap_namespaces.clear();
m_snap_sizes.clear();
m_snap_infos.clear();
m_snap_parents.clear();
m_snap_protection.clear();
m_snap_timestamps.clear();
send_v2_refresh_parent();
return;
}
@ -509,7 +509,7 @@ void RefreshRequest<I>::send_v2_get_snapshots() {
ldout(cct, 10) << this << " " << __func__ << dendl;
librados::ObjectReadOperation op;
cls_client::snapshot_list_start(&op, m_snapc.snaps);
cls_client::snapshot_get_start(&op, m_snapc.snaps);
using klass = RefreshRequest<I>;
librados::AioCompletion *comp = create_rados_callback<
@ -527,11 +527,62 @@ Context *RefreshRequest<I>::handle_v2_get_snapshots(int *result) {
ldout(cct, 10) << this << " " << __func__ << ": "
<< "r=" << *result << dendl;
if (*result == 0) {
bufferlist::iterator it = m_out_bl.begin();
*result = cls_client::snapshot_get_finish(&it, m_snapc.snaps, &m_snap_infos,
&m_snap_parents,
&m_snap_protection);
}
if (*result == -ENOENT) {
ldout(cct, 10) << "out-of-sync snapshot state detected" << dendl;
send_v2_get_mutable_metadata();
return nullptr;
} else if (*result == -EOPNOTSUPP) {
ldout(cct, 10) << "retrying using legacy snapshot methods" << dendl;
send_v2_get_snapshots_legacy();
return nullptr;
} else if (*result < 0) {
lderr(cct) << "failed to retrieve snapshots: " << cpp_strerror(*result)
<< dendl;
return m_on_finish;
}
send_v2_refresh_parent();
return nullptr;
}
template <typename I>
void RefreshRequest<I>::send_v2_get_snapshots_legacy() {
/// NOTE: remove after Luminous is retired
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << this << " " << __func__ << dendl;
librados::ObjectReadOperation op;
cls_client::snapshot_list_start(&op, m_snapc.snaps);
using klass = RefreshRequest<I>;
librados::AioCompletion *comp = create_rados_callback<
klass, &klass::handle_v2_get_snapshots_legacy>(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_snapshots_legacy(int *result) {
/// NOTE: remove after Luminous is retired
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << this << " " << __func__ << ": "
<< "r=" << *result << dendl;
std::vector<std::string> snap_names;
std::vector<uint64_t> snap_sizes;
if (*result == 0) {
bufferlist::iterator it = m_out_bl.begin();
*result = cls_client::snapshot_list_finish(&it, m_snapc.snaps,
&m_snap_names,
&m_snap_sizes,
&snap_names, &snap_sizes,
&m_snap_parents,
&m_snap_protection);
}
@ -545,12 +596,20 @@ Context *RefreshRequest<I>::handle_v2_get_snapshots(int *result) {
return m_on_finish;
}
m_snap_infos.clear();
for (size_t i = 0; i < m_snapc.snaps.size(); ++i) {
m_snap_infos.push_back({m_snapc.snaps[i],
{cls::rbd::UserSnapshotNamespace{}},
snap_names[i], snap_sizes[i], {}});
}
send_v2_get_snap_timestamps();
return nullptr;
}
template <typename I>
void RefreshRequest<I>::send_v2_get_snap_timestamps() {
/// NOTE: remove after Luminous is retired
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << this << " " << __func__ << dendl;
@ -569,79 +628,37 @@ void RefreshRequest<I>::send_v2_get_snap_timestamps() {
template <typename I>
Context *RefreshRequest<I>::handle_v2_get_snap_timestamps(int *result) {
/// NOTE: remove after Luminous is retired
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << this << " " << __func__ << ": " << "r=" << *result << dendl;
std::vector<utime_t> snap_timestamps;
if (*result == 0) {
bufferlist::iterator it = m_out_bl.begin();
*result = cls_client::snapshot_timestamp_list_finish(&it, m_snapc.snaps, &m_snap_timestamps);
*result = cls_client::snapshot_timestamp_list_finish(&it, m_snapc.snaps,
&snap_timestamps);
}
if (*result == -ENOENT) {
ldout(cct, 10) << "out-of-sync snapshot state detected" << dendl;
send_v2_get_mutable_metadata();
return nullptr;
} else if (*result == -EOPNOTSUPP) {
m_snap_timestamps = std::vector<utime_t>(m_snap_names.size(), utime_t());
// Ignore it means no snap timestamps are available
} else if (*result < 0) {
lderr(cct) << "failed to retrieve snapshots: " << cpp_strerror(*result)
<< dendl;
return m_on_finish;
}
send_v2_get_snap_namespaces();
return nullptr;
}
template <typename I>
void RefreshRequest<I>::send_v2_get_snap_namespaces() {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << this << " " << __func__ << dendl;
librados::ObjectReadOperation op;
cls_client::snapshot_namespace_list_start(&op, m_snapc.snaps);
using klass = RefreshRequest<I>;
librados::AioCompletion *comp = create_rados_callback<
klass, &klass::handle_v2_get_snap_namespaces>(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_snap_namespaces(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();
*result = cls_client::snapshot_namespace_list_finish(&it, m_snapc.snaps,
&m_snap_namespaces);
}
if (*result == -ENOENT) {
ldout(cct, 10) << "out-of-sync snapshot state detected" << dendl;
send_v2_get_mutable_metadata();
return nullptr;
} else if (*result == -EOPNOTSUPP) {
m_snap_namespaces = std::vector
<cls::rbd::SnapshotNamespace>(
m_snap_names.size(),
cls::rbd::UserSnapshotNamespace());
// Ignore it means no snap namespaces are available
} else if (*result < 0) {
lderr(cct) << "failed to retrieve snapshots: " << cpp_strerror(*result)
<< dendl;
lderr(cct) << "failed to retrieve snapshot timestamps: "
<< cpp_strerror(*result) << dendl;
return m_on_finish;
} else {
for (size_t i = 0; i < m_snapc.snaps.size(); ++i) {
m_snap_infos[i].timestamp = snap_timestamps[i];
}
}
send_v2_refresh_parent();
return nullptr;
}
template <typename I>
void RefreshRequest<I>::send_v2_refresh_parent() {
{
@ -850,8 +867,8 @@ void RefreshRequest<I>::send_v2_open_object_map() {
if (m_image_ctx.snap_name.empty()) {
m_object_map = m_image_ctx.create_object_map(CEPH_NOSNAP);
} else {
for (size_t snap_idx = 0; snap_idx < m_snap_names.size(); ++snap_idx) {
if (m_snap_names[snap_idx] == m_image_ctx.snap_name) {
for (size_t snap_idx = 0; snap_idx < m_snap_infos.size(); ++snap_idx) {
if (m_snap_infos[snap_idx].name == m_image_ctx.snap_name) {
m_object_map = m_image_ctx.create_object_map(
m_snapc.snaps[snap_idx].val);
break;
@ -1143,8 +1160,8 @@ void RefreshRequest<I>::apply() {
if (it == m_image_ctx.snaps.end()) {
m_flush_aio = true;
ldout(cct, 20) << "new snapshot id=" << m_snapc.snaps[i].val
<< " name=" << m_snap_names[i]
<< " size=" << m_snap_sizes[i]
<< " name=" << m_snap_infos[i].name
<< " size=" << m_snap_infos[i].image_size
<< dendl;
}
}
@ -1162,9 +1179,11 @@ void RefreshRequest<I>::apply() {
parent = m_snap_parents[i];
}
m_image_ctx.add_snap(m_snap_namespaces[i], m_snap_names[i],
m_snapc.snaps[i].val, m_snap_sizes[i], parent,
protection_status, flags, m_snap_timestamps[i]);
m_image_ctx.add_snap(m_snap_infos[i].snapshot_namespace,
m_snap_infos[i].name, m_snapc.snaps[i].val,
m_snap_infos[i].image_size, parent,
protection_status, flags,
m_snap_infos[i].timestamp);
}
m_image_ctx.snapc = m_snapc;

View File

@ -65,14 +65,14 @@ private:
* | |
* v |
* V2_GET_SNAPSHOTS (skip if no snaps) |
* | |
* v |
* V2_GET_SNAP_TIMESTAMPS |
* | |
* v |
* V2_GET_SNAP_NAMESPACES |
* | |
* v |
* | . |
* | v (pre-mimic OSD) |
* | V2_GET_SNAPSHOTS_LEGACY |
* | | |
* | v |
* | V2_GET_SNAP_TIMESTAMPS |
* | | |
* v v |
* V2_REFRESH_PARENT (skip if no parent or |
* | refresh not needed) |
* v |
@ -143,13 +143,10 @@ private:
cls::rbd::GroupSpec m_group_spec;
::SnapContext m_snapc;
std::vector<std::string> m_snap_names;
std::vector<cls::rbd::SnapshotNamespace> m_snap_namespaces;
std::vector<uint64_t> m_snap_sizes;
std::vector<cls::rbd::SnapshotInfo> m_snap_infos;
std::vector<ParentInfo> m_snap_parents;
std::vector<uint8_t> m_snap_protection;
std::vector<uint64_t> m_snap_flags;
std::vector<utime_t> m_snap_timestamps;
std::map<rados::cls::lock::locker_id_t,
rados::cls::lock::locker_info_t> m_lockers;
@ -189,8 +186,8 @@ private:
void send_v2_get_snapshots();
Context *handle_v2_get_snapshots(int *result);
void send_v2_get_snap_namespaces();
Context *handle_v2_get_snap_namespaces(int *result);
void send_v2_get_snapshots_legacy();
Context *handle_v2_get_snapshots_legacy(int *result);
void send_v2_get_snap_timestamps();
Context *handle_v2_get_snap_timestamps(int *result);

View File

@ -207,7 +207,7 @@ void SnapEventBase::encode(bufferlist& bl) const {
using ceph::encode;
OpEventBase::encode(bl);
encode(snap_name, bl);
encode(cls::rbd::SnapshotNamespaceOnDisk(snap_namespace), bl);
encode(snap_namespace, bl);
}
void SnapEventBase::decode(__u8 version, bufferlist::iterator& it) {
@ -216,16 +216,14 @@ void SnapEventBase::decode(__u8 version, bufferlist::iterator& it) {
using ceph::decode;
decode(snap_name, it);
if (version >= 4) {
cls::rbd::SnapshotNamespaceOnDisk sn;
decode(sn, it);
snap_namespace = sn.snapshot_namespace;
decode(snap_namespace, it);
}
}
void SnapEventBase::dump(Formatter *f) const {
OpEventBase::dump(f);
f->dump_string("snap_name", snap_name);
cls::rbd::SnapshotNamespaceOnDisk(snap_namespace).dump(f);
snap_namespace.dump(f);
}
void SnapCreateEvent::encode(bufferlist &bl) const {
@ -236,9 +234,7 @@ void SnapCreateEvent::decode(__u8 version, bufferlist::iterator& it) {
using ceph::decode;
SnapEventBase::decode(version, it);
if (version == 3) {
cls::rbd::SnapshotNamespaceOnDisk sn;
decode(sn, it);
snap_namespace = sn.snapshot_namespace;
decode(snap_namespace, it);
}
}
@ -579,7 +575,7 @@ void MirrorPeerSyncPoint::encode(bufferlist& bl) const {
encode(snap_name, bl);
encode(from_snap_name, bl);
encode(object_number, bl);
encode(cls::rbd::SnapshotNamespaceOnDisk(snap_namespace), bl);
encode(snap_namespace, bl);
}
void MirrorPeerSyncPoint::decode(__u8 version, bufferlist::iterator& it) {
@ -588,9 +584,7 @@ void MirrorPeerSyncPoint::decode(__u8 version, bufferlist::iterator& it) {
decode(from_snap_name, it);
decode(object_number, it);
if (version >= 2) {
cls::rbd::SnapshotNamespaceOnDisk sn;
decode(sn, it);
snap_namespace = sn.snapshot_namespace;
decode(snap_namespace, it);
}
}
@ -600,7 +594,7 @@ void MirrorPeerSyncPoint::dump(Formatter *f) const {
if (object_number) {
f->dump_unsigned("object_number", *object_number);
}
cls::rbd::SnapshotNamespaceOnDisk(snap_namespace).dump(f);
snap_namespace.dump(f);
}
void MirrorPeerClientMeta::encode(bufferlist& bl) const {

View File

@ -796,8 +796,8 @@ TEST_F(TestClsRbd, snapshots)
ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
vector<cls::rbd::SnapshotInfo> snaps;
vector<string> snap_names;
vector<cls::rbd::SnapshotNamespace> snap_namespaces;
vector<uint64_t> snap_sizes;
SnapContext snapc;
vector<ParentInfo> parents;
@ -807,11 +807,14 @@ TEST_F(TestClsRbd, snapshots)
ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
ASSERT_EQ(0u, snapc.snaps.size());
ASSERT_EQ(0u, snapc.seq);
ASSERT_EQ(0, snapshot_get(&ioctx, oid, snapc.snaps, &snaps,
&parents, &protection_status));
ASSERT_EQ(0u, snaps.size());
ASSERT_EQ(0u, parents.size());
ASSERT_EQ(0u, protection_status.size());
ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
&snap_sizes, &parents, &protection_status));
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(0u, snap_names.size());
ASSERT_EQ(0u, snap_namespaces.size());
ASSERT_EQ(0u, snap_sizes.size());
ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
ASSERT_EQ(0u, snap_timestamps.size());
@ -821,13 +824,17 @@ TEST_F(TestClsRbd, snapshots)
ASSERT_EQ(1u, snapc.snaps.size());
ASSERT_EQ(0u, snapc.snaps[0]);
ASSERT_EQ(0u, snapc.seq);
ASSERT_EQ(0, snapshot_get(&ioctx, oid, snapc.snaps, &snaps,
&parents, &protection_status));
ASSERT_EQ(1u, snaps.size());
ASSERT_EQ(1u, parents.size());
ASSERT_EQ(1u, protection_status.size());
ASSERT_EQ("snap1", snaps[0].name);
ASSERT_EQ(userSnapNamespace, snaps[0].snapshot_namespace);
ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
&snap_sizes, &parents, &protection_status));
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(1u, snap_names.size());
ASSERT_EQ("snap1", snap_names[0]);
ASSERT_EQ(1u, snap_namespaces.size());
ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
ASSERT_EQ(10u, snap_sizes[0]);
ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
ASSERT_EQ(1u, snap_timestamps.size());
@ -840,11 +847,8 @@ TEST_F(TestClsRbd, snapshots)
ASSERT_EQ(0u, snapc.seq);
ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
&snap_sizes, &parents, &protection_status));
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(1u, snap_names.size());
ASSERT_EQ("snap1", snap_names[0]);
ASSERT_EQ(1u, snap_namespaces.size());
ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
ASSERT_EQ(10u, snap_sizes[0]);
ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
ASSERT_EQ(1u, snap_timestamps.size());
@ -858,11 +862,8 @@ TEST_F(TestClsRbd, snapshots)
ASSERT_EQ(0u, snapc.seq);
ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
&snap_sizes, &parents, &protection_status));
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(1u, snap_names.size());
ASSERT_EQ("snap1", snap_names[0]);
ASSERT_EQ(1u, snap_namespaces.size());
ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
ASSERT_EQ(10u, snap_sizes[0]);
ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
ASSERT_EQ(1u, snap_timestamps.size());
@ -875,11 +876,8 @@ TEST_F(TestClsRbd, snapshots)
ASSERT_EQ(0u, snapc.seq);
ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
&snap_sizes, &parents, &protection_status));
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(snap_names.size(), 1u);
ASSERT_EQ(snap_names[0], "snap1");
ASSERT_EQ(1u, snap_namespaces.size());
ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
ASSERT_EQ(snap_sizes[0], 10u);
ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
ASSERT_EQ(1u, snap_timestamps.size());
@ -891,16 +889,21 @@ TEST_F(TestClsRbd, snapshots)
ASSERT_EQ(1u, snapc.snaps[0]);
ASSERT_EQ(0u, snapc.snaps[1]);
ASSERT_EQ(1u, snapc.seq);
ASSERT_EQ(0, snapshot_get(&ioctx, oid, snapc.snaps, &snaps,
&parents, &protection_status));
ASSERT_EQ(2u, snaps.size());
ASSERT_EQ(2u, parents.size());
ASSERT_EQ(2u, protection_status.size());
ASSERT_EQ("snap2", snaps[0].name);
ASSERT_EQ("snap1", snaps[1].name);
ASSERT_EQ(userSnapNamespace, snaps[0].snapshot_namespace);
ASSERT_EQ(userSnapNamespace, snaps[1].snapshot_namespace);
ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
&snap_sizes, &parents, &protection_status));
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(2u, snap_names.size());
ASSERT_EQ(2u, snap_namespaces.size());
ASSERT_EQ("snap2", snap_names[0]);
ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
ASSERT_EQ(10u, snap_sizes[0]);
ASSERT_EQ("snap1", snap_names[1]);
ASSERT_EQ(userSnapNamespace, snap_namespaces[1]);
ASSERT_EQ(10u, snap_sizes[1]);
ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
ASSERT_EQ(2u, snap_timestamps.size());
@ -908,14 +911,10 @@ TEST_F(TestClsRbd, snapshots)
ASSERT_EQ(0, snapshot_rename(&ioctx, oid, 0, "snap1-rename"));
ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
&snap_sizes, &parents, &protection_status));
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(2u, snap_names.size());
ASSERT_EQ(2u, snap_namespaces.size());
ASSERT_EQ("snap2", snap_names[0]);
ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
ASSERT_EQ(10u, snap_sizes[0]);
ASSERT_EQ("snap1-rename", snap_names[1]);
ASSERT_EQ(userSnapNamespace, snap_namespaces[1]);
ASSERT_EQ(10u, snap_sizes[1]);
ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
ASSERT_EQ(2u, snap_timestamps.size());
@ -925,13 +924,17 @@ TEST_F(TestClsRbd, snapshots)
ASSERT_EQ(1u, snapc.snaps.size());
ASSERT_EQ(1u, snapc.snaps[0]);
ASSERT_EQ(1u, snapc.seq);
ASSERT_EQ(0, snapshot_get(&ioctx, oid, snapc.snaps, &snaps,
&parents, &protection_status));
ASSERT_EQ(1u, snaps.size());
ASSERT_EQ(1u, parents.size());
ASSERT_EQ(1u, protection_status.size());
ASSERT_EQ("snap2", snaps[0].name);
ASSERT_EQ(userSnapNamespace, snaps[0].snapshot_namespace);
ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
&snap_sizes, &parents, &protection_status));
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(1u, snap_names.size());
ASSERT_EQ(1u, snap_namespaces.size());
ASSERT_EQ("snap2", snap_names[0]);
ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
ASSERT_EQ(10u, snap_sizes[0]);
ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
ASSERT_EQ(1u, snap_timestamps.size());
@ -952,14 +955,10 @@ TEST_F(TestClsRbd, snapshots)
ASSERT_EQ(large_snap_id, snapc.seq);
ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
&snap_sizes, &parents, &protection_status));
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(2u, snap_names.size());
ASSERT_EQ(2u, snap_namespaces.size());
ASSERT_EQ("snap3", snap_names[0]);
ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
ASSERT_EQ(0u, snap_sizes[0]);
ASSERT_EQ("snap2", snap_names[1]);
ASSERT_EQ(userSnapNamespace, snap_namespaces[1]);
ASSERT_EQ(10u, snap_sizes[1]);
ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
ASSERT_EQ(2u, snap_timestamps.size());
@ -979,11 +978,8 @@ TEST_F(TestClsRbd, snapshots)
ASSERT_EQ(large_snap_id, snapc.seq);
ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
&snap_sizes, &parents, &protection_status));
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(1u, snap_names.size());
ASSERT_EQ(1u, snap_namespaces.size());
ASSERT_EQ("snap2", snap_names[0]);
ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
ASSERT_EQ(10u, snap_sizes[0]);
ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
ASSERT_EQ(1u, snap_timestamps.size());
@ -995,9 +991,7 @@ TEST_F(TestClsRbd, snapshots)
ASSERT_EQ(large_snap_id, snapc.seq);
ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
&snap_sizes, &parents, &protection_status));
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(0u, snap_names.size());
ASSERT_EQ(0u, snap_namespaces.size());
ASSERT_EQ(0u, snap_sizes.size());
ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
ASSERT_EQ(0u, snap_timestamps.size());
@ -1005,45 +999,6 @@ TEST_F(TestClsRbd, snapshots)
ioctx.close();
}
TEST_F(TestClsRbd, snapshots_namespaces)
{
cls::rbd::SnapshotNamespace groupSnapNamespace = cls::rbd::GroupSnapshotNamespace(5, "1018643c9869", "3338524f9933");
cls::rbd::SnapshotNamespace userSnapNamespace = cls::rbd::UserSnapshotNamespace();
librados::IoCtx ioctx;
ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
string oid = get_temp_image_name();
ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
vector<cls::rbd::SnapshotNamespace> snap_namespaces;
SnapContext snapc;
ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
ASSERT_EQ(0u, snapc.snaps.size());
ASSERT_EQ(0u, snapc.seq);
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(0u, snap_namespaces.size());
ASSERT_EQ(0, snapshot_add(&ioctx, oid, 0, "snap1"));
librados::ObjectWriteOperation op;
::librbd::cls_client::snapshot_add(&op, 1, "snap1", groupSnapNamespace);
int r = ioctx.operate(oid, &op);
ASSERT_EQ(0, r);
ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
ASSERT_EQ(2u, snapc.snaps.size());
ASSERT_EQ(1u, snapc.snaps[0]);
ASSERT_EQ(0u, snapc.snaps[1]);
ASSERT_EQ(1u, snapc.seq);
ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
ASSERT_EQ(groupSnapNamespace, snap_namespaces[0]);
ASSERT_EQ(userSnapNamespace, snap_namespaces[1]);
ioctx.close();
}
TEST_F(TestClsRbd, snapshots_timestamps)
{
librados::IoCtx ioctx;
@ -1071,7 +1026,6 @@ TEST_F(TestClsRbd, snapshots_timestamps)
ioctx.close();
}
TEST_F(TestClsRbd, snapid_race)
{
librados::IoCtx ioctx;

View File

@ -421,10 +421,11 @@ TYPE(cls::rbd::MirrorImageMap)
TYPE(cls::rbd::MirrorImageStatus)
TYPE(cls::rbd::GroupImageSpec)
TYPE(cls::rbd::GroupImageStatus)
TYPE(cls::rbd::GroupSpec)
TYPE(cls::rbd::SnapshotNamespaceOnDisk)
TYPE(cls::rbd::ImageSnapshotSpec)
TYPE(cls::rbd::GroupSnapshot)
TYPE(cls::rbd::GroupSpec)
TYPE(cls::rbd::ImageSnapshotSpec)
TYPE(cls::rbd::SnapshotInfo)
TYPE(cls::rbd::SnapshotNamespace)
#endif
#include "cls/lock/cls_lock_types.h"

View File

@ -69,7 +69,6 @@ RefreshParentRequest<MockRefreshImageCtx>* RefreshParentRequest<MockRefreshImage
// template definitions
#include "librbd/image/RefreshRequest.cc"
template class librbd::image::RefreshRequest<librbd::MockRefreshImageCtx>;
ACTION_P(TestFeatures, image_ctx) {
return ((image_ctx->features & arg0) != 0);
@ -210,8 +209,23 @@ public:
}
}
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("snapshot_get"), _, _, _));
if (r < 0) {
expect.WillOnce(Return(r));
} else {
expect.WillOnce(DoDefault());
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("get_protection_status"), _, _, _))
.WillOnce(DoDefault());
}
}
void expect_get_snapshots_legacy(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"), _, _, _));
if (r < 0) {
@ -240,16 +254,6 @@ public:
}
}
void expect_snap_namespace_list(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_namespace"), _, _, _));
if (r < 0) {
expect.WillOnce(Return(r));
} else {
expect.WillOnce(DoDefault());
}
}
void expect_apply_metadata(MockRefreshImageCtx &mock_image_ctx,
int r) {
EXPECT_CALL(mock_image_ctx, apply_metadata(_, false))
@ -475,8 +479,42 @@ TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV2) {
expect_get_flags(mock_image_ctx, 0);
expect_get_group(mock_image_ctx, 0);
expect_get_snapshots(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_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
C_SaferCond ctx;
MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
req->send();
ASSERT_EQ(0, ctx.wait());
}
TEST_F(TestMockImageRefreshRequest, SuccessLegacySnapshotV2) {
REQUIRE_FORMAT_V2();
librbd::ImageCtx *ictx;
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, snap_create(*ictx, "snap"));
MockRefreshImageCtx mock_image_ctx(*ictx);
MockRefreshParentRequest mock_refresh_parent_request;
MockExclusiveLock mock_exclusive_lock;
expect_op_work_queue(mock_image_ctx);
expect_test_features(mock_image_ctx);
InSequence seq;
expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
expect_get_metadata(mock_image_ctx, 0);
expect_apply_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, -EOPNOTSUPP);
expect_get_snapshots_legacy(mock_image_ctx, 0);
expect_snap_timestamp_list(mock_image_ctx, 0);
expect_snap_namespace_list(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);
@ -512,8 +550,6 @@ TEST_F(TestMockImageRefreshRequest, SuccessSetSnapshotV2) {
expect_get_flags(mock_image_ctx, 0);
expect_get_group(mock_image_ctx, 0);
expect_get_snapshots(mock_image_ctx, 0);
expect_snap_timestamp_list(mock_image_ctx, 0);
expect_snap_namespace_list(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
expect_open_object_map(mock_image_ctx, &mock_object_map, 0);