return -ENOENT;
}
+ int ImageCtx::get_snap_namespace(snap_t in_snap_id,
+ cls::rbd::SnapshotNamespace *out_snap_namespace) const
+ {
+ assert(snap_lock.is_locked());
+ const SnapInfo *info = get_snap_info(in_snap_id);
+ if (info) {
+ *out_snap_namespace = info->snap_namespace;
+ return 0;
+ }
+ return -ENOENT;
+ }
+
int ImageCtx::get_parent_spec(snap_t in_snap_id,
parent_spec *out_pspec) const
{
return -ENOENT;
}
- void ImageCtx::add_snap(string in_snap_name, snap_t id, uint64_t in_size,
+ void ImageCtx::add_snap(string in_snap_name,
+ cls::rbd::SnapshotNamespace in_snap_namespace,
+ snap_t id, uint64_t in_size,
parent_info parent, uint8_t protection_status,
uint64_t flags)
{
assert(snap_lock.is_wlocked());
snaps.push_back(id);
- SnapInfo info(in_snap_name, in_size, parent, protection_status, flags);
+ SnapInfo info(in_snap_name, in_snap_namespace,
+ in_size, parent, protection_status, flags);
snap_info.insert(pair<snap_t, SnapInfo>(id, info));
snap_ids.insert(pair<string, snap_t>(in_snap_name, id));
}
#include "include/xlist.h"
#include "osdc/ObjectCacher.h"
+#include "cls/rbd/cls_rbd_types.h"
#include "cls/rbd/cls_rbd_client.h"
#include "librbd/AsyncRequest.h"
#include "librbd/SnapInfo.h"
const SnapInfo* get_snap_info(librados::snap_t in_snap_id) const;
int get_snap_name(librados::snap_t in_snap_id,
std::string *out_snap_name) const;
+ int get_snap_namespace(librados::snap_t in_snap_id,
+ cls::rbd::SnapshotNamespace *out_snap_namespace) const;
int get_parent_spec(librados::snap_t in_snap_id,
parent_spec *pspec) const;
int is_snap_protected(librados::snap_t in_snap_id,
uint64_t get_stripe_count() const;
uint64_t get_stripe_period() const;
- void add_snap(std::string in_snap_name, librados::snap_t id,
+ void add_snap(std::string in_snap_name,
+ cls::rbd::SnapshotNamespace in_snap_namespace,
+ librados::snap_t id,
uint64_t in_size, parent_info parent,
uint8_t protection_status, uint64_t flags);
void rm_snap(std::string in_snap_name, librados::snap_t id);
template <typename I>
void ImageWatcher<I>::notify_snap_create(const std::string &snap_name,
+ const cls::rbd::SnapshotNamespace &snap_namespace,
Context *on_finish) {
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.exclusive_lock &&
!m_image_ctx.exclusive_lock->is_lock_owner());
bufferlist bl;
- ::encode(NotifyMessage(SnapCreatePayload(snap_name)), bl);
+ ::encode(NotifyMessage(SnapCreatePayload(snap_name, snap_namespace)), bl);
notify_lock_owner(std::move(bl), on_finish);
}
<< payload.snap_name << dendl;
m_image_ctx.operations->execute_snap_create(payload.snap_name,
+ payload.snap_namespace,
new C_ResponseMessage(ack_ctx),
0, false);
return false;
#ifndef CEPH_LIBRBD_IMAGE_WATCHER_H
#define CEPH_LIBRBD_IMAGE_WATCHER_H
+#include "cls/rbd/cls_rbd_types.h"
#include "common/Mutex.h"
#include "common/RWLock.h"
#include "include/Context.h"
Context *on_finish);
void notify_resize(uint64_t request_id, uint64_t size, bool allow_shrink,
ProgressContext &prog_ctx, Context *on_finish);
- void notify_snap_create(const std::string &snap_name, Context *on_finish);
+ void notify_snap_create(const std::string &snap_name,
+ const cls::rbd::SnapshotNamespace &snap_namespace,
+ Context *on_finish);
void notify_snap_rename(const snapid_t &src_snap_id,
const std::string &dst_snap_name,
Context *on_finish);
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+#include "cls/rbd/cls_rbd_types.h"
#include "librbd/Operations.h"
#include "common/dout.h"
#include "common/errno.h"
}
template <typename I>
-int Operations<I>::snap_create(const char *snap_name) {
+int Operations<I>::snap_create(const char *snap_name,
+ const cls::rbd::SnapshotNamespace &snap_namespace) {
if (m_image_ctx.read_only) {
return -EROFS;
}
}
C_SaferCond ctx;
- snap_create(snap_name, &ctx);
+ snap_create(snap_name, snap_namespace, &ctx);
r = ctx.wait();
if (r < 0) {
}
template <typename I>
-void Operations<I>::snap_create(const char *snap_name, Context *on_finish) {
+void Operations<I>::snap_create(const char *snap_name,
+ const cls::rbd::SnapshotNamespace &snap_namespace,
+ Context *on_finish) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << ": snap_name=" << snap_name
<< dendl;
C_InvokeAsyncRequest<I> *req = new C_InvokeAsyncRequest<I>(
m_image_ctx, "snap_create", true,
- boost::bind(&Operations<I>::execute_snap_create, this, snap_name, _1, 0,
- false),
+ boost::bind(&Operations<I>::execute_snap_create, this, snap_name,
+ snap_namespace, _1, 0, false),
boost::bind(&ImageWatcher<I>::notify_snap_create, m_image_ctx.image_watcher,
- snap_name, _1),
+ snap_name, snap_namespace, _1),
{-EEXIST}, on_finish);
req->send();
}
template <typename I>
void Operations<I>::execute_snap_create(const std::string &snap_name,
+ const cls::rbd::SnapshotNamespace &snap_namespace,
Context *on_finish,
uint64_t journal_op_tid,
bool skip_object_map) {
operation::SnapshotCreateRequest<I> *req =
new operation::SnapshotCreateRequest<I>(
m_image_ctx, new C_NotifyUpdate<I>(m_image_ctx, on_finish), snap_name,
- journal_op_tid, skip_object_map);
+ snap_namespace, journal_op_tid, skip_object_map);
req->send();
}
#ifndef CEPH_LIBRBD_OPERATIONS_H
#define CEPH_LIBRBD_OPERATIONS_H
+#include "cls/rbd/cls_rbd_types.h"
#include "include/int_types.h"
#include "librbd/operation/ObjectMapIterate.h"
#include <atomic>
void execute_resize(uint64_t size, bool allow_shrink, ProgressContext &prog_ctx,
Context *on_finish, uint64_t journal_op_tid);
- int snap_create(const char *snap_name);
- void snap_create(const char *snap_name, Context *on_finish);
- void execute_snap_create(const std::string &snap_name, Context *on_finish,
+ int snap_create(const char *snap_name,
+ const cls::rbd::SnapshotNamespace &snap_namespace);
+ void snap_create(const char *snap_name,
+ const cls::rbd::SnapshotNamespace &snap_namespace,
+ Context *on_finish);
+ void execute_snap_create(const std::string &snap_name,
+ const cls::rbd::SnapshotNamespace &snap_namespace,
+ Context *on_finish,
uint64_t journal_op_tid, bool skip_object_map);
int snap_rollback(const char *snap_name, ProgressContext& prog_ctx);
#ifndef CEPH_LIBRBD_SNAPINFO_H
#define CEPH_LIBRBD_SNAPINFO_H
+#include "cls/rbd/cls_rbd_types.h"
#include "include/int_types.h"
#include "librbd/parent_types.h"
struct SnapInfo {
std::string name;
+ cls::rbd::SnapshotNamespace snap_namespace;
uint64_t size;
parent_info parent;
uint8_t protection_status;
uint64_t flags;
- SnapInfo(std::string _name, uint64_t _size, parent_info _parent,
+ SnapInfo(std::string _name, const cls::rbd::SnapshotNamespace &_snap_namespace,
+ uint64_t _size, parent_info _parent,
uint8_t _protection_status, uint64_t _flags)
- : name(_name), size(_size), parent(_parent),
+ : name(_name), snap_namespace(_snap_namespace), size(_size), parent(_parent),
protection_status(_protection_status), flags(_flags) {}
};
}
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+#include "cls/rbd/cls_rbd_types.h"
#include "librbd/WatchNotifyTypes.h"
#include "include/assert.h"
#include "include/stringify.h"
f->dump_string("snap_name", snap_name);
}
+void SnapCreatePayload::encode(bufferlist &bl) const {
+ SnapPayloadBase::encode(bl);
+ ::encode(cls::rbd::SnapshotNamespaceOnDisk(snap_namespace), bl);
+}
+
+void SnapCreatePayload::decode(__u8 version, bufferlist::iterator &iter) {
+ SnapPayloadBase::decode(version, iter);
+ if (version >= 5) {
+ cls::rbd::SnapshotNamespaceOnDisk sn;
+ ::decode(sn, iter);
+ snap_namespace = sn.snapshot_namespace;
+ }
+}
+
+void SnapCreatePayload::dump(Formatter *f) const {
+ SnapPayloadBase::dump(f);
+ cls::rbd::SnapshotNamespaceOnDisk sn(snap_namespace);
+ sn.dump(f);
+}
+
void SnapRenamePayload::encode(bufferlist &bl) const {
::encode(snap_id, bl);
SnapPayloadBase::encode(bl);
}
void NotifyMessage::encode(bufferlist& bl) const {
- ENCODE_START(4, 1, bl);
+ ENCODE_START(5, 1, bl);
boost::apply_visitor(EncodePayloadVisitor(bl), payload);
ENCODE_FINISH(bl);
}
o.push_back(new NotifyMessage(AsyncCompletePayload(AsyncRequestId(ClientId(0, 1), 2), 3)));
o.push_back(new NotifyMessage(FlattenPayload(AsyncRequestId(ClientId(0, 1), 2))));
o.push_back(new NotifyMessage(ResizePayload(123, true, AsyncRequestId(ClientId(0, 1), 2))));
- o.push_back(new NotifyMessage(SnapCreatePayload("foo")));
+ o.push_back(new NotifyMessage(SnapCreatePayload("foo",
+ cls::rbd::UserSnapshotNamespace())));
o.push_back(new NotifyMessage(SnapRemovePayload("foo")));
o.push_back(new NotifyMessage(SnapProtectPayload("foo")));
o.push_back(new NotifyMessage(SnapUnprotectPayload("foo")));
#ifndef LIBRBD_WATCH_NOTIFY_TYPES_H
#define LIBRBD_WATCH_NOTIFY_TYPES_H
+#include "cls/rbd/cls_rbd_types.h"
#include "include/int_types.h"
#include "include/buffer_fwd.h"
#include "include/encoding.h"
static const NotifyOp NOTIFY_OP = NOTIFY_OP_SNAP_CREATE;
SnapCreatePayload() {}
- SnapCreatePayload(const std::string &name) : SnapPayloadBase(name) {}
+ SnapCreatePayload(const std::string &name,
+ const cls::rbd::SnapshotNamespace &_snap_namespace) : SnapPayloadBase(name), snap_namespace(_snap_namespace) {}
+
+ cls::rbd::SnapshotNamespace snap_namespace;
+
+ void encode(bufferlist &bl) const;
+ void decode(__u8 version, bufferlist::iterator &iter);
+ void dump(Formatter *f) const;
};
struct SnapRenamePayload : public SnapPayloadBase {
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());
+
send_v1_get_locks();
return nullptr;
}
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_parents.clear();
m_snap_protection.clear();
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_names,
+ &m_snap_sizes,
&m_snap_parents,
&m_snap_protection);
}
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::snap_namespace_list_start(&op, m_snapc.snaps);
+
+ using klass = RefreshRequest<I>;
+ librados::AioCompletion *comp = create_rados_ack_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::snap_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;
+ return m_on_finish;
+ }
+
send_v2_refresh_parent();
return nullptr;
}
parent = m_snap_parents[i];
}
- m_image_ctx.add_snap(m_snap_names[i], m_snapc.snaps[i].val,
+ m_image_ctx.add_snap(m_snap_names[i], m_snap_namespaces[i], m_snapc.snaps[i].val,
m_snap_sizes[i], parent, protection_status, flags);
}
m_image_ctx.snapc = m_snapc;
* V2_GET_SNAPSHOTS (skip if no snaps) |
* | |
* v |
+ * V2_GET_SNAP_NAMESPACES |
+ * | |
+ * v |
* V2_REFRESH_PARENT (skip if no parent or |
* | refresh not needed) |
* v |
::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<parent_info> m_snap_parents;
std::vector<uint8_t> m_snap_protection;
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_refresh_parent();
Context *handle_v2_refresh_parent(int *result);
return 0;
}
+ int get_snap_namespace(ImageCtx *ictx,
+ const char *snap_name,
+ cls::rbd::SnapshotNamespace *snap_namespace) {
+ ldout(ictx->cct, 20) << "get_snap_namespace " << ictx << " " << snap_name
+ << dendl;
+
+ int r = ictx->state->refresh_if_required();
+ if (r < 0)
+ return r;
+
+ RWLock::RLocker l(ictx->snap_lock);
+ snap_t snap_id = ictx->get_snap_id(snap_name);
+ if (snap_id == CEPH_NOSNAP)
+ return -ENOENT;
+ r = ictx->get_snap_namespace(snap_id, snap_namespace);
+ return r;
+ }
+
int snap_is_protected(ImageCtx *ictx, const char *snap_name,
bool *is_protected)
{
int r = 0;
+ cls::rbd::SnapshotNamespace snap_namespace;
+ r = get_snap_namespace(ictx, snap_name, &snap_namespace);
+ if (r < 0) {
+ return r;
+ }
+ if (boost::get<cls::rbd::UserSnapshotNamespace>(&snap_namespace) == nullptr) {
+ return -EINVAL;
+ }
+
r = ictx->state->refresh_if_required();
if (r < 0)
return r;
#include "include/rbd/librbd.hpp"
#include "include/rbd_types.h"
#include "librbd/parent_types.h"
+#include "cls/rbd/cls_rbd_types.h"
#include "common/WorkQueue.h"
enum {
int snap_get_limit(ImageCtx *ictx, uint64_t *limit);
int snap_set_limit(ImageCtx *ictx, uint64_t limit);
int snap_remove(ImageCtx *ictx, const char *snap_name, uint32_t flags, ProgressContext& pctx);
+ int get_snap_namespace(ImageCtx *ictx,
+ const char *snap_name,
+ cls::rbd::SnapshotNamespace *snap_namespace);
int snap_is_protected(ImageCtx *ictx, const char *snap_name,
bool *is_protected);
int copy(ImageCtx *ictx, IoCtx& dest_md_ctx, const char *destname,
void execute(const journal::SnapCreateEvent &_) {
image_ctx.operations->execute_snap_create(event.snap_name,
+ event.snap_namespace,
on_op_complete,
event.op_tid, false);
}
f->dump_string("snap_name", snap_name);
}
+void SnapCreateEvent::encode(bufferlist &bl) const {
+ SnapEventBase::encode(bl);
+ ::encode(cls::rbd::SnapshotNamespaceOnDisk(snap_namespace), bl);
+}
+
+void SnapCreateEvent::decode(__u8 version, bufferlist::iterator& it) {
+ SnapEventBase::decode(version, it);
+ if (version >= 3) {
+ cls::rbd::SnapshotNamespaceOnDisk sn;
+ ::decode(sn, it);
+ snap_namespace = sn.snapshot_namespace;
+ }
+}
+
+void SnapCreateEvent::dump(Formatter *f) const {
+ SnapEventBase::dump(f);
+ cls::rbd::SnapshotNamespaceOnDisk(snap_namespace).dump(f);
+}
+
void SnapLimitEvent::encode(bufferlist &bl) const {
OpEventBase::encode(bl);
::encode(limit, bl);
}
void EventEntry::encode(bufferlist& bl) const {
- ENCODE_START(2, 1, bl);
+ ENCODE_START(3, 1, bl);
boost::apply_visitor(EncodeVisitor(bl), event);
ENCODE_FINISH(bl);
}
o.push_back(new EventEntry(OpFinishEvent(123, -1)));
o.push_back(new EventEntry(SnapCreateEvent()));
- o.push_back(new EventEntry(SnapCreateEvent(234, "snap")));
+ o.push_back(new EventEntry(SnapCreateEvent(234, "snap",
+ cls::rbd::UserSnapshotNamespace())));
o.push_back(new EventEntry(SnapRemoveEvent()));
o.push_back(new EventEntry(SnapRemoveEvent(345, "snap")));
#ifndef CEPH_LIBRBD_JOURNAL_TYPES_H
#define CEPH_LIBRBD_JOURNAL_TYPES_H
+#include "cls/rbd/cls_rbd_types.h"
#include "include/int_types.h"
#include "include/buffer.h"
#include "include/encoding.h"
struct SnapCreateEvent : public SnapEventBase {
static const EventType TYPE = EVENT_TYPE_SNAP_CREATE;
+ cls::rbd::SnapshotNamespace snap_namespace;
SnapCreateEvent() {
}
- SnapCreateEvent(uint64_t op_tid, const std::string &snap_name)
- : SnapEventBase(op_tid, snap_name) {
+ SnapCreateEvent(uint64_t op_tid, const std::string &snap_name, const cls::rbd::SnapshotNamespace &_snap_namespace)
+ : SnapEventBase(op_tid, snap_name), snap_namespace(_snap_namespace) {
}
- using SnapEventBase::encode;
- using SnapEventBase::decode;
- using SnapEventBase::dump;
+ void encode(bufferlist& bl) const;
+ void decode(__u8 version, bufferlist::iterator& it);
+ void dump(Formatter *f) const;
};
struct SnapRemoveEvent : public SnapEventBase {
#include <errno.h>
+#include "cls/rbd/cls_rbd_types.h"
#include "common/dout.h"
#include "common/errno.h"
#include "common/TracepointProvider.h"
#include "librbd/AioCompletion.h"
#include "librbd/AioImageRequestWQ.h"
#include "cls/rbd/cls_rbd_client.h"
+#include "cls/rbd/cls_rbd_types.h"
#include "librbd/Group.h"
#include "librbd/ImageCtx.h"
#include "librbd/ImageState.h"
{
ImageCtx *ictx = (ImageCtx *)ctx;
tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
- int r = ictx->operations->snap_create(snap_name);
+ int r = ictx->operations->snap_create(snap_name,
+ cls::rbd::UserSnapshotNamespace());
tracepoint(librbd, snap_create_exit, r);
return r;
}
{
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
tracepoint(librbd, snap_create_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, snap_name);
- int r = ictx->operations->snap_create(snap_name);
+ int r = ictx->operations->snap_create(snap_name,
+ cls::rbd::UserSnapshotNamespace());
tracepoint(librbd, snap_create_exit, r);
return r;
}
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+#include "cls/rbd/cls_rbd_types.h"
#include "librbd/operation/SnapshotCreateRequest.h"
#include "common/dout.h"
#include "common/errno.h"
SnapshotCreateRequest<I>::SnapshotCreateRequest(I &image_ctx,
Context *on_finish,
const std::string &snap_name,
+ const cls::rbd::SnapshotNamespace &snap_namespace,
uint64_t journal_op_tid,
bool skip_object_map)
: Request<I>(image_ctx, on_finish, journal_op_tid), m_snap_name(snap_name),
+ m_snap_namespace(snap_namespace),
m_skip_object_map(skip_object_map), m_ret_val(0), m_snap_id(CEPH_NOSNAP) {
}
if (image_ctx.exclusive_lock != nullptr) {
image_ctx.exclusive_lock->assert_header_locked(&op);
}
- cls_client::snapshot_add(&op, m_snap_id, m_snap_name);
+ cls_client::snapshot_add(&op, m_snap_id, m_snap_name, m_snap_namespace);
}
librados::AioCompletion *rados_completion = create_rados_safe_callback<
image_ctx.exclusive_lock->is_lock_owner());
// immediately add a reference to the new snapshot
- image_ctx.add_snap(m_snap_name, m_snap_id, m_size, m_parent_info,
+ image_ctx.add_snap(m_snap_name, m_snap_namespace, m_snap_id, m_size, m_parent_info,
RBD_PROTECTION_STATUS_UNPROTECTED, 0);
// immediately start using the new snap context if we
#ifndef CEPH_LIBRBD_OPERATION_SNAPSHOT_CREATE_REQUEST_H
#define CEPH_LIBRBD_OPERATION_SNAPSHOT_CREATE_REQUEST_H
+#include "cls/rbd/cls_rbd_types.h"
#include "librbd/operation/Request.h"
#include "librbd/parent_types.h"
#include <string>
* (if enabled) and bubble the originating error code back to the client.
*/
SnapshotCreateRequest(ImageCtxT &image_ctx, Context *on_finish,
- const std::string &snap_name, uint64_t journal_op_tid,
+ const std::string &snap_name,
+ const cls::rbd::SnapshotNamespace &snap_namespace,
+ uint64_t journal_op_tid,
bool skip_object_map);
protected:
return true;
}
virtual journal::Event create_event(uint64_t op_tid) const {
- return journal::SnapCreateEvent(op_tid, m_snap_name);
+ return journal::SnapCreateEvent(op_tid, m_snap_name, m_snap_namespace);
}
private:
std::string m_snap_name;
+ cls::rbd::SnapshotNamespace m_snap_namespace;
bool m_skip_object_map;
int m_ret_val;
}
}
+ 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"), _, _, _));
+ }
+
void expect_add_snap(MockRefreshImageCtx &mock_image_ctx,
const std::string &snap_name, uint64_t snap_id) {
- EXPECT_CALL(mock_image_ctx, add_snap(snap_name, snap_id, _, _, _, _));
+ EXPECT_CALL(mock_image_ctx, add_snap(snap_name, _, snap_id, _, _, _, _));
}
void expect_init_exclusive_lock(MockRefreshImageCtx &mock_image_ctx,
TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV1) {
REQUIRE_FORMAT_V1();
-
librbd::ImageCtx *ictx;
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, snap_create(*ictx, "snap"));
expect_get_flags(mock_image_ctx, 0);
expect_get_flags(mock_image_ctx, 0);
expect_get_snapshots(mock_image_ctx, 0);
+ expect_snap_namespace_list(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
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_flags(mock_image_ctx, 0);
expect_get_snapshots(mock_image_ctx, 0);
+ expect_snap_namespace_list(mock_image_ctx, 0);
expect_refresh_parent_is_required(mock_refresh_parent_request, false);
if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
expect_open_object_map(mock_image_ctx, &mock_object_map, 0);
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+#include "cls/rbd/cls_rbd_types.h"
#include "test/librbd/test_fixture.h"
#include "test/librbd/test_support.h"
+#include "cls/rbd/cls_rbd_types.h"
#include "cls/journal/cls_journal_types.h"
#include "cls/journal/cls_journal_client.h"
#include "journal/Journaler.h"
get_journal_commit_position(ictx, &initial_tag, &initial_entry);
// inject snapshot ops into journal
- inject_into_journal(ictx, librbd::journal::SnapCreateEvent(1, "snap"));
+ inject_into_journal(ictx, librbd::journal::SnapCreateEvent(1, "snap",
+ cls::rbd::UserSnapshotNamespace()));
inject_into_journal(ictx, librbd::journal::OpFinishEvent(1, 0));
close_image(ictx);
}
// verify lock ordering constraints
- ASSERT_EQ(0, ictx->operations->snap_create("snap2"));
+ ASSERT_EQ(0, ictx->operations->snap_create("snap2",
+ cls::rbd::UserSnapshotNamespace()));
}
TEST_F(TestJournalReplay, SnapProtect) {
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- ASSERT_EQ(0, ictx->operations->snap_create("snap"));
+ ASSERT_EQ(0, ictx->operations->snap_create("snap",
+ cls::rbd::UserSnapshotNamespace()));
// get current commit position
int64_t initial_tag;
ASSERT_TRUE(is_protected);
// verify lock ordering constraints
- ASSERT_EQ(0, ictx->operations->snap_create("snap2"));
+ ASSERT_EQ(0, ictx->operations->snap_create("snap2",
+ cls::rbd::UserSnapshotNamespace()));
ASSERT_EQ(0, ictx->operations->snap_protect("snap2"));
}
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- ASSERT_EQ(0, ictx->operations->snap_create("snap"));
+ ASSERT_EQ(0, ictx->operations->snap_create("snap",
+ cls::rbd::UserSnapshotNamespace()));
uint64_t snap_id;
{
RWLock::RLocker snap_locker(ictx->snap_lock);
ASSERT_FALSE(is_protected);
// verify lock ordering constraints
- ASSERT_EQ(0, ictx->operations->snap_create("snap2"));
+ ASSERT_EQ(0, ictx->operations->snap_create("snap2",
+ cls::rbd::UserSnapshotNamespace()));
ASSERT_EQ(0, ictx->operations->snap_protect("snap2"));
ASSERT_EQ(0, ictx->operations->snap_unprotect("snap2"));
}
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- ASSERT_EQ(0, ictx->operations->snap_create("snap"));
+ ASSERT_EQ(0, ictx->operations->snap_create("snap",
+ cls::rbd::UserSnapshotNamespace()));
uint64_t snap_id;
{
RWLock::RLocker snap_locker(ictx->snap_lock);
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- ASSERT_EQ(0, ictx->operations->snap_create("snap"));
+ ASSERT_EQ(0, ictx->operations->snap_create("snap",
+ cls::rbd::UserSnapshotNamespace()));
// get current commit position
int64_t initial_tag;
ASSERT_EQ(0, open_image(m_image_name, &ictx));
ASSERT_EQ(0, when_acquired_lock(ictx));
- ASSERT_EQ(0, ictx->operations->snap_create("snap"));
+ ASSERT_EQ(0, ictx->operations->snap_create("snap",
+ cls::rbd::UserSnapshotNamespace()));
// get current commit position
int64_t initial_tag;
}
// verify lock ordering constraints
- ASSERT_EQ(0, ictx->operations->snap_create("snap"));
+ ASSERT_EQ(0, ictx->operations->snap_create("snap",
+ cls::rbd::UserSnapshotNamespace()));
ASSERT_EQ(0, ictx->operations->snap_remove("snap"));
}
librbd::ImageCtx *ictx;
ASSERT_EQ(0, open_image(m_image_name, &ictx));
- ASSERT_EQ(0, ictx->operations->snap_create("snap"));
+ ASSERT_EQ(0, ictx->operations->snap_create("snap",
+ cls::rbd::UserSnapshotNamespace()));
ASSERT_EQ(0, ictx->operations->snap_protect("snap"));
std::string clone_name = get_temp_image_name();
void expect_snap_create(MockReplayImageCtx &mock_image_ctx,
Context **on_finish, const char *snap_name,
uint64_t op_tid) {
- EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(StrEq(snap_name), _,
+ EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(StrEq(snap_name), _, _,
op_tid, false))
- .WillOnce(DoAll(SaveArg<1>(on_finish),
+ .WillOnce(DoAll(SaveArg<2>(on_finish),
NotifyInvoke(&m_invoke_lock, &m_invoke_cond)));
}
C_SaferCond on_start_ready;
C_SaferCond on_start_safe;
- when_process(mock_journal_replay, EventEntry{SnapCreateEvent(123, "snap")},
+ when_process(mock_journal_replay, EventEntry{SnapCreateEvent(123, "snap",
+ cls::rbd::UserSnapshotNamespace())},
&on_start_ready, &on_start_safe);
C_SaferCond on_resume;
C_SaferCond on_snap_create_ready;
C_SaferCond on_snap_create_safe;
- when_process(mock_journal_replay, EventEntry{SnapCreateEvent(123, "snap")},
+ when_process(mock_journal_replay, EventEntry{SnapCreateEvent(123, "snap",
+ cls::rbd::UserSnapshotNamespace())},
&on_snap_create_ready, &on_snap_create_safe);
C_SaferCond on_shut_down;
C_SaferCond on_snap_create_ready;
C_SaferCond on_snap_create_safe;
- when_process(mock_journal_replay, EventEntry{SnapCreateEvent(123, "snap")},
+ when_process(mock_journal_replay, EventEntry{SnapCreateEvent(123, "snap", cls::rbd::UserSnapshotNamespace())},
&on_snap_create_ready, &on_snap_create_safe);
C_SaferCond on_resume;
C_SaferCond on_start_ready;
C_SaferCond on_start_safe;
- when_process(mock_journal_replay, EventEntry{SnapCreateEvent(123, "snap")},
+ when_process(mock_journal_replay, EventEntry{SnapCreateEvent(123, "snap", cls::rbd::UserSnapshotNamespace())},
&on_start_ready, &on_start_safe);
C_SaferCond on_resume;
C_SaferCond on_start_ready;
C_SaferCond on_start_safe;
- when_process(mock_journal_replay, EventEntry{SnapCreateEvent(123, "snap")},
+ when_process(mock_journal_replay, EventEntry{SnapCreateEvent(123, "snap", cls::rbd::UserSnapshotNamespace())},
&on_start_ready, &on_start_safe);
wait_for_op_invoked(&on_finish, -EEXIST);
MOCK_CONST_METHOD1(get_object_count, uint64_t(librados::snap_t));
MOCK_CONST_METHOD1(get_snap_id, librados::snap_t(std::string in_snap_name));
MOCK_CONST_METHOD1(get_snap_info, const SnapInfo*(librados::snap_t));
+ MOCK_CONST_METHOD2(get_snap_namespace, int(librados::snap_t,
+ cls::rbd::SnapshotNamespace *out_snap_namespace));
MOCK_CONST_METHOD2(get_parent_spec, int(librados::snap_t in_snap_id,
parent_spec *pspec));
MOCK_CONST_METHOD2(is_snap_unprotected, int(librados::snap_t in_snap_id,
bool *is_unprotected));
- MOCK_METHOD6(add_snap, void(std::string in_snap_name, librados::snap_t id,
+ MOCK_METHOD7(add_snap, void(std::string in_snap_name,
+ cls::rbd::SnapshotNamespace in_snap_namespace,
+ librados::snap_t id,
uint64_t in_size, parent_info parent,
uint8_t protection_status, uint64_t flags));
MOCK_METHOD2(rm_snap, void(std::string in_snap_name, librados::snap_t id));
#ifndef CEPH_TEST_LIBRBD_MOCK_OPERATIONS_H
#define CEPH_TEST_LIBRBD_MOCK_OPERATIONS_H
+#include "cls/rbd/cls_rbd_types.h"
#include "include/int_types.h"
#include "include/rbd/librbd.hpp"
#include "gmock/gmock.h"
ProgressContext &prog_ctx,
Context *on_finish,
uint64_t journal_op_tid));
- MOCK_METHOD2(snap_create, void(const std::string &snap_name,
+ MOCK_METHOD3(snap_create, void(const std::string &snap_name,
+ const cls::rbd::SnapshotNamespace &snapshot_namespace,
Context *on_finish));
- MOCK_METHOD4(execute_snap_create, void(const std::string &snap_name,
+ MOCK_METHOD5(execute_snap_create, void(const std::string &snap_name,
+ const cls::rbd::SnapshotNamespace &snapshot_namespace,
Context *on_finish,
uint64_t journal_op_tid,
bool skip_object_map));
#include "test/librbd/test_support.h"
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
#include "common/bit_vector.hpp"
+#include "cls/rbd/cls_rbd_types.h"
#include "librbd/internal.h"
#include "librbd/ObjectMap.h"
#include "librbd/object_map/SnapshotCreateRequest.h"
void inject_snap_info(librbd::ImageCtx *ictx, uint64_t snap_id) {
RWLock::WLocker snap_locker(ictx->snap_lock);
RWLock::RLocker parent_locker(ictx->parent_lock);
- ictx->add_snap("snap name", snap_id, ictx->size, ictx->parent_md,
+ ictx->add_snap("snap name",
+ cls::rbd::UserSnapshotNamespace(), snap_id,
+ ictx->size, ictx->parent_md,
RBD_PROTECTION_STATUS_UNPROTECTED, 0);
}
// state machine checks to ensure a refresh hasn't already added the snap
EXPECT_CALL(mock_image_ctx, get_snap_info(_))
.WillOnce(Return(reinterpret_cast<const librbd::SnapInfo*>(NULL)));
- EXPECT_CALL(mock_image_ctx, add_snap("snap1", _, _, _, _, _));
+ EXPECT_CALL(mock_image_ctx, add_snap("snap1", _, _, _, _, _, _));
}
void expect_unblock_writes(MockImageCtx &mock_image_ctx) {
C_SaferCond cond_ctx;
MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
- mock_image_ctx, &cond_ctx, "snap1", 0, false);
+ mock_image_ctx, &cond_ctx, "snap1",
+ cls::rbd::UserSnapshotNamespace(), 0, false);
{
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
req->send();
C_SaferCond cond_ctx;
MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
- mock_image_ctx, &cond_ctx, "snap1", 0, false);
+ mock_image_ctx, &cond_ctx, "snap1",
+ cls::rbd::UserSnapshotNamespace(), 0, false);
{
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
req->send();
C_SaferCond cond_ctx;
MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
- mock_image_ctx, &cond_ctx, "snap1", 0, false);
+ mock_image_ctx, &cond_ctx, "snap1",
+ cls::rbd::UserSnapshotNamespace(), 0, false);
{
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
req->send();
C_SaferCond cond_ctx;
MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
- mock_image_ctx, &cond_ctx, "snap1", 0, false);
+ mock_image_ctx, &cond_ctx, "snap1",
+ cls::rbd::UserSnapshotNamespace(), 0, false);
{
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
req->send();
C_SaferCond cond_ctx;
MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
- mock_image_ctx, &cond_ctx, "snap1", 0, false);
+ mock_image_ctx, &cond_ctx, "snap1",
+ cls::rbd::UserSnapshotNamespace(), 0, false);
{
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
req->send();
C_SaferCond cond_ctx;
MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
- mock_image_ctx, &cond_ctx, "snap1", 0, true);
+ mock_image_ctx, &cond_ctx, "snap1",
+ cls::rbd::UserSnapshotNamespace(), 0, true);
{
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
req->send();
RWLock::RLocker l(ictx->owner_lock);
C_SaferCond notify_ctx;
- ictx->image_watcher->notify_snap_create("snap", ¬ify_ctx);
+ ictx->image_watcher->notify_snap_create("snap",
+ cls::rbd::UserSnapshotNamespace(), ¬ify_ctx);
ASSERT_EQ(0, notify_ctx.wait());
NotifyOps expected_notify_ops;
RWLock::RLocker l(ictx->owner_lock);
C_SaferCond notify_ctx;
- ictx->image_watcher->notify_snap_create("snap", ¬ify_ctx);
+ ictx->image_watcher->notify_snap_create("snap",
+ cls::rbd::UserSnapshotNamespace(), ¬ify_ctx);
ASSERT_EQ(-EEXIST, notify_ctx.wait());
NotifyOps expected_notify_ops;
#include "librbd/Operations.h"
#include "cls/lock/cls_lock_client.h"
#include "cls/lock/cls_lock_types.h"
+#include "cls/rbd/cls_rbd_types.h"
#include "librbd/internal.h"
#include "test/librados/test.h"
#include <iostream>
int TestFixture::snap_create(librbd::ImageCtx &ictx,
const std::string &snap_name) {
- return ictx.operations->snap_create(snap_name.c_str());
+ return ictx.operations->snap_create(snap_name.c_str(),
+ cls::rbd::UserSnapshotNamespace());
}
int TestFixture::snap_protect(librbd::ImageCtx &ictx,
// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+#include "cls/rbd/cls_rbd_types.h"
#include "test/librbd/test_fixture.h"
#include "test/librbd/test_support.h"
#include "librbd/AioCompletion.h"
} BOOST_SCOPE_EXIT_END;
ASSERT_EQ(0, open_image(clone_name, &ictx2));
- ASSERT_EQ(0, ictx2->operations->snap_create("snap1"));
+ ASSERT_EQ(0, ictx2->operations->snap_create("snap1",
+ cls::rbd::UserSnapshotNamespace()));
bufferlist write_full_bl;
write_full_bl.append(std::string(1 << ictx2->order, '2'));