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;
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);
if (snap_id == CEPH_NOSNAP) {
return -EINVAL;
}
-
+
cls_rbd_snap snap;
string snapshot_key;
key_from_snap_id(snap_id, &snapshot_key);
}
/**
- * 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;
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;
}
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;
}
* 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.
}
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;
}
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;
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);
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
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);
}
// 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);
}
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);
-
- int r = ioctx->exec(oid, "rbd", "get_parent", inbl, outbl);
- if (r < 0)
- return r;
+ librados::ObjectReadOperation op;
+ get_parent_start(&op, snap_id);
- 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,
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);
}
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);
}
}
// 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;
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)
{
return ioctx->exec(oid, "rbd", "copyup", data, out);
}
- int get_protection_status(librados::IoCtx *ioctx, const std::string &oid,
- snapid_t snap_id, uint8_t *protection_status)
+ void get_protection_status_start(librados::ObjectReadOperation *op,
+ snapid_t snap_id)
{
- bufferlist in, out;
- encode(snap_id.val, in);
-
- int r = ioctx->exec(oid, "rbd", "get_protection_status", in, out);
- if (r < 0)
- return r;
+ 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 {
- bufferlist::iterator iter = out.begin();
- decode(*protection_status, iter);
- } catch (const buffer::error &err) {
+ 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)
+ {
+ librados::ObjectReadOperation op;
+ get_protection_status_start(&op, snap_id);
+
+ bufferlist out_bl;
+ int r = ioctx->operate(oid, &op, &out_bl);
+ if (r < 0) {
+ return r;
+ }
+
+ 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,
snapid_t snap_id, uint8_t protection_status)
{
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,
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);
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,
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,
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,
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,
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 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 SnapshotNamespaceOnDisk::decode(bufferlist::iterator &p)
+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) {
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 {
-
- SnapshotNamespaceOnDisk() : snapshot_namespace(UnknownSnapshotNamespace()) {}
- SnapshotNamespaceOnDisk(const SnapshotNamespace &sn) : snapshot_namespace(sn) {}
+ SnapshotNamespace() {
+ }
- 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,
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 {
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);
}
}
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) {
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;
<< "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);
}
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;
}
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<
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,
- &m_snap_parents,
- &m_snap_protection);
+ *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_get_snap_timestamps();
+ send_v2_refresh_parent();
return nullptr;
}
template <typename I>
-void RefreshRequest<I>::send_v2_get_snap_timestamps() {
+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_timestamp_list_start(&op, m_snapc.snaps);
+ cls_client::snapshot_list_start(&op, m_snapc.snaps);
using klass = RefreshRequest<I>;
librados::AioCompletion *comp = create_rados_callback<
- klass, &klass::handle_v2_get_snap_timestamps>(this);
+ 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);
+ &m_out_bl);
assert(r == 0);
comp->release();
}
template <typename I>
-Context *RefreshRequest<I>::handle_v2_get_snap_timestamps(int *result) {
+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;
+ 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_timestamp_list_finish(&it, m_snapc.snaps, &m_snap_timestamps);
+ *result = cls_client::snapshot_list_finish(&it, m_snapc.snaps,
+ &snap_names, &snap_sizes,
+ &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) {
- 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();
+ 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_namespaces() {
+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;
librados::ObjectReadOperation op;
- cls_client::snapshot_namespace_list_start(&op, m_snapc.snaps);
+ cls_client::snapshot_timestamp_list_start(&op, m_snapc.snaps);
using klass = RefreshRequest<I>;
librados::AioCompletion *comp = create_rados_callback<
- klass, &klass::handle_v2_get_snap_namespaces>(this);
+ klass, &klass::handle_v2_get_snap_timestamps>(this);
m_out_bl.clear();
int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, comp, &op,
- &m_out_bl);
+ &m_out_bl);
assert(r == 0);
comp->release();
}
template <typename I>
-Context *RefreshRequest<I>::handle_v2_get_snap_namespaces(int *result) {
+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;
+ 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_namespace_list_finish(&it, m_snapc.snaps,
- &m_snap_namespaces);
+ *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_namespaces = std::vector
- <cls::rbd::SnapshotNamespace>(
- m_snap_names.size(),
- cls::rbd::UserSnapshotNamespace());
- // Ignore it means no snap namespaces are available
+ // Ignore it means no snap timestamps 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() {
{
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;
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;
}
}
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;
* | |
* 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 |
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;
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);
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) {
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 {
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);
}
}
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) {
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);
}
}
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 {
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;
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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;
ioctx.close();
}
-
TEST_F(TestClsRbd, snapid_race)
{
librados::IoCtx ioctx;
TYPE(cls::rbd::MirrorImageStatus)
TYPE(cls::rbd::GroupImageSpec)
TYPE(cls::rbd::GroupImageStatus)
+TYPE(cls::rbd::GroupSnapshot)
TYPE(cls::rbd::GroupSpec)
-TYPE(cls::rbd::SnapshotNamespaceOnDisk)
TYPE(cls::rbd::ImageSnapshotSpec)
-TYPE(cls::rbd::GroupSnapshot)
+TYPE(cls::rbd::SnapshotInfo)
+TYPE(cls::rbd::SnapshotNamespace)
#endif
#include "cls/lock/cls_lock_types.h"
// 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);
}
}
-
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"), _, _, _));
+ 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_size"), _, _, _))
- .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());
}
}
- void expect_snap_timestamp_list(MockRefreshImageCtx &mock_image_ctx, int r) {
+ 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_timestamp"), _, _, _));
- if (r < 0) {
+ exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_name"), _, _, _));
+ 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_size"), _, _, _))
+ .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_snap_namespace_list(MockRefreshImageCtx &mock_image_ctx, int r) {
+ void expect_snap_timestamp_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) {
+ exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_timestamp"), _, _, _));
+ if (r < 0) {
expect.WillOnce(Return(r));
} else {
expect.WillOnce(DoDefault());
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);
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);