class AioCompletion;
namespace operation {
- class ResizeRequest;
+ template <typename> class ResizeRequest;
}
struct ImageCtx {
atomic_t async_request_seq;
- xlist<operation::ResizeRequest*> resize_reqs;
+ xlist<operation::ResizeRequest<ImageCtx>*> resize_reqs;
AioImageRequestWQ *aio_work_queue;
xlist<AioCompletion*> completed_reqs;
C_SaferCond ctx;
ictx->snap_lock.get_read();
- operation::TrimRequest *req = new operation::TrimRequest(
+ operation::TrimRequest<> *req = new operation::TrimRequest<>(
*ictx, &ctx, ictx->size, newsize, prog_ctx);
ictx->snap_lock.put_read();
req->send();
return;
}
- operation::SnapshotCreateRequest *req =
- new operation::SnapshotCreateRequest(*ictx, ctx, snap_name);
+ operation::SnapshotCreateRequest<> *req =
+ new operation::SnapshotCreateRequest<>(*ictx, ctx, snap_name);
req->send();
}
}
}
- operation::SnapshotRemoveRequest *req =
- new operation::SnapshotRemoveRequest(*ictx, ctx, snap_name, snap_id);
+ operation::SnapshotRemoveRequest<> *req =
+ new operation::SnapshotRemoveRequest<>(*ictx, ctx, snap_name, snap_id);
req->send();
}
return;
}
- operation::SnapshotRenameRequest *req =
- new operation::SnapshotRenameRequest(*ictx, ctx, src_snap_id, dst_name);
+ operation::SnapshotRenameRequest<> *req =
+ new operation::SnapshotRenameRequest<>(*ictx, ctx, src_snap_id, dst_name);
req->send();
}
return;
}
- operation::SnapshotProtectRequest *request =
- new operation::SnapshotProtectRequest(*ictx, ctx, snap_name);
+ operation::SnapshotProtectRequest<> *request =
+ new operation::SnapshotProtectRequest<>(*ictx, ctx, snap_name);
request->send();
}
return;
}
- operation::SnapshotUnprotectRequest *request =
- new operation::SnapshotUnprotectRequest(*ictx, ctx, snap_name);
+ operation::SnapshotUnprotectRequest<> *request =
+ new operation::SnapshotUnprotectRequest<>(*ictx, ctx, snap_name);
request->send();
}
return;
}
- operation::RenameRequest *req =
- new operation::RenameRequest(*ictx, ctx, dstname);
+ operation::RenameRequest<> *req =
+ new operation::RenameRequest<>(*ictx, ctx, dstname);
req->send();
}
}
}
- operation::ResizeRequest *req = new operation::ResizeRequest(
+ operation::ResizeRequest<> *req = new operation::ResizeRequest<>(
*ictx, ctx, size, prog_ctx);
req->send();
}
// TODO need to wait for journal replay to complete (if enabled)
C_SaferCond cond_ctx;
- operation::SnapshotRollbackRequest *request =
- new operation::SnapshotRollbackRequest(*ictx, &cond_ctx, snap_name,
- snap_id, new_size, prog_ctx);
+ operation::SnapshotRollbackRequest<> *request =
+ new operation::SnapshotRollbackRequest<>(*ictx, &cond_ctx, snap_name,
+ snap_id, new_size, prog_ctx);
request->send();
r = cond_ctx.wait();
if (r < 0) {
overlap_objects = Striper::get_num_objects(ictx->layout, overlap);
}
- operation::FlattenRequest *req = new operation::FlattenRequest(
+ operation::FlattenRequest<> *req = new operation::FlattenRequest<>(
*ictx, ctx, object_size, overlap_objects, snapc, prog_ctx);
req->send();
}
return;
}
- operation::RebuildObjectMapRequest *req =
- new operation::RebuildObjectMapRequest(*ictx, ctx, prog_ctx);
+ operation::RebuildObjectMapRequest<> *req =
+ new operation::RebuildObjectMapRequest<>(*ictx, ctx, prog_ctx);
req->send();
}
namespace librbd {
namespace operation {
-class C_FlattenObject : public C_AsyncObjectThrottle<> {
+template <typename I>
+class C_FlattenObject : public C_AsyncObjectThrottle<I> {
public:
- C_FlattenObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx,
+ C_FlattenObject(AsyncObjectThrottle<I> &throttle, I *image_ctx,
uint64_t object_size, ::SnapContext snapc, uint64_t object_no)
- : C_AsyncObjectThrottle(throttle, *image_ctx), m_object_size(object_size),
+ : C_AsyncObjectThrottle<I>(throttle, *image_ctx), m_object_size(object_size),
m_snapc(snapc), m_object_no(object_no)
{
}
virtual int send() {
- assert(m_image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ CephContext *cct = image_ctx.cct;
- if (m_image_ctx.image_watcher->is_lock_supported() &&
- !m_image_ctx.image_watcher->is_lock_owner()) {
+ if (image_ctx.image_watcher->is_lock_supported() &&
+ !image_ctx.image_watcher->is_lock_owner()) {
ldout(cct, 1) << "lost exclusive lock during flatten" << dendl;
return -ERESTART;
}
bufferlist bl;
- string oid = m_image_ctx.get_object_name(m_object_no);
- AioObjectWrite *req = new AioObjectWrite(&m_image_ctx, oid, m_object_no, 0,
+ string oid = image_ctx.get_object_name(m_object_no);
+ AioObjectWrite *req = new AioObjectWrite(&image_ctx, oid, m_object_no, 0,
bl, m_snapc, this);
if (!req->has_parent()) {
// stop early if the parent went away - it just means
uint64_t m_object_no;
};
-bool FlattenRequest::should_complete(int r) {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool FlattenRequest<I>::should_complete(int r) {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " should_complete: " << " r=" << r << dendl;
if (r < 0 && !(r == -ENOENT && m_ignore_enoent) ) {
lderr(cct) << "flatten encountered an error: " << cpp_strerror(r) << dendl;
return true;
}
- RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
+ RWLock::RLocker owner_locker(image_ctx.owner_lock);
switch (m_state) {
case STATE_FLATTEN_OBJECTS:
ldout(cct, 5) << "FLATTEN_OBJECTS" << dendl;
return false;
}
-void FlattenRequest::send_op() {
- assert(m_image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+void FlattenRequest<I>::send_op() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " send" << dendl;
m_state = STATE_FLATTEN_OBJECTS;
- AsyncObjectThrottle<>::ContextFactory context_factory(
- boost::lambda::bind(boost::lambda::new_ptr<C_FlattenObject>(),
- boost::lambda::_1, &m_image_ctx, m_object_size, m_snapc,
+ typename AsyncObjectThrottle<I>::ContextFactory context_factory(
+ boost::lambda::bind(boost::lambda::new_ptr<C_FlattenObject<I> >(),
+ boost::lambda::_1, &image_ctx, m_object_size, m_snapc,
boost::lambda::_2));
- AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>(
- this, m_image_ctx, context_factory, create_callback_context(), &m_prog_ctx,
+ AsyncObjectThrottle<I> *throttle = new AsyncObjectThrottle<I>(
+ this, image_ctx, context_factory, this->create_callback_context(), &m_prog_ctx,
0, m_overlap_objects);
- throttle->start_ops(m_image_ctx.concurrent_management_ops);
+ throttle->start_ops(image_ctx.concurrent_management_ops);
}
-bool FlattenRequest::send_update_header() {
- assert(m_image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool FlattenRequest<I>::send_update_header() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " send_update_header" << dendl;
m_state = STATE_UPDATE_HEADER;
// should have been canceled prior to releasing lock
- assert(!m_image_ctx.image_watcher->is_lock_supported() ||
- m_image_ctx.image_watcher->is_lock_owner());
+ assert(!image_ctx.image_watcher->is_lock_supported() ||
+ image_ctx.image_watcher->is_lock_owner());
{
- RWLock::RLocker parent_locker(m_image_ctx.parent_lock);
+ RWLock::RLocker parent_locker(image_ctx.parent_lock);
// stop early if the parent went away - it just means
// another flatten finished first, so this one is useless.
- if (!m_image_ctx.parent) {
+ if (!image_ctx.parent) {
ldout(cct, 5) << "image already flattened" << dendl;
return true;
}
- m_parent_spec = m_image_ctx.parent_md.spec;
+ m_parent_spec = image_ctx.parent_md.spec;
}
m_ignore_enoent = true;
// remove parent from this (base) image
librados::ObjectWriteOperation op;
- if (m_image_ctx.image_watcher->is_lock_supported()) {
- m_image_ctx.image_watcher->assert_header_locked(&op);
+ if (image_ctx.image_watcher->is_lock_supported()) {
+ image_ctx.image_watcher->assert_header_locked(&op);
}
cls_client::remove_parent(&op);
- librados::AioCompletion *rados_completion = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
+ librados::AioCompletion *rados_completion = this->create_callback_completion();
+ int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid,
rados_completion, &op);
assert(r == 0);
rados_completion->release();
return false;
}
-bool FlattenRequest::send_update_children() {
- assert(m_image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool FlattenRequest<I>::send_update_children() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ CephContext *cct = image_ctx.cct;
// should have been canceled prior to releasing lock
- assert(!m_image_ctx.image_watcher->is_lock_supported() ||
- m_image_ctx.image_watcher->is_lock_owner());
+ assert(!image_ctx.image_watcher->is_lock_supported() ||
+ image_ctx.image_watcher->is_lock_owner());
// if there are no snaps, remove from the children object as well
// (if snapshots remain, they have their own parent info, and the child
// will be removed when the last snap goes away)
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- if ((m_image_ctx.features & RBD_FEATURE_DEEP_FLATTEN) == 0 &&
- !m_image_ctx.snaps.empty()) {
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ if ((image_ctx.features & RBD_FEATURE_DEEP_FLATTEN) == 0 &&
+ !image_ctx.snaps.empty()) {
return true;
}
m_state = STATE_UPDATE_CHILDREN;
librados::ObjectWriteOperation op;
- cls_client::remove_child(&op, m_parent_spec, m_image_ctx.id);
+ cls_client::remove_child(&op, m_parent_spec, image_ctx.id);
- librados::AioCompletion *rados_completion = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(RBD_CHILDREN, rados_completion,
+ librados::AioCompletion *rados_completion = this->create_callback_completion();
+ int r = image_ctx.md_ctx.aio_operate(RBD_CHILDREN, rados_completion,
&op);
assert(r == 0);
rados_completion->release();
} // namespace operation
} // namespace librbd
+
+template class librbd::operation::FlattenRequest<librbd::ImageCtx>;
namespace operation {
-class FlattenRequest : public Request
+template <typename ImageCtxT = ImageCtx>
+class FlattenRequest : public Request<ImageCtxT>
{
public:
- FlattenRequest(ImageCtx &image_ctx, Context *on_finish,
- uint64_t object_size, uint64_t overlap_objects,
- const ::SnapContext &snapc, ProgressContext &prog_ctx)
- : Request(image_ctx, on_finish), m_object_size(object_size),
+ FlattenRequest(ImageCtxT &image_ctx, Context *on_finish,
+ uint64_t object_size, uint64_t overlap_objects,
+ const ::SnapContext &snapc, ProgressContext &prog_ctx)
+ : Request<ImageCtxT>(image_ctx, on_finish), m_object_size(object_size),
m_overlap_objects(overlap_objects), m_snapc(snapc), m_prog_ctx(prog_ctx),
m_ignore_enoent(false)
{
} // namespace operation
} // namespace librbd
+extern template class librbd::operation::FlattenRequest<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_OPERATION_FLATTEN_REQUEST_H
namespace {
-class C_VerifyObject : public C_AsyncObjectThrottle<> {
+template <typename I>
+class C_VerifyObject : public C_AsyncObjectThrottle<I> {
public:
- C_VerifyObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx,
+ C_VerifyObject(AsyncObjectThrottle<I> &throttle, I *image_ctx,
uint64_t snap_id, uint64_t object_no)
- : C_AsyncObjectThrottle(throttle, *image_ctx), m_snap_id(snap_id),
- m_object_no(object_no), m_oid(m_image_ctx.get_object_name(m_object_no))
+ : C_AsyncObjectThrottle<I>(throttle, *image_ctx), m_snap_id(snap_id),
+ m_object_no(object_no),
+ m_oid(image_ctx->get_object_name(m_object_no))
{
- m_io_ctx.dup(m_image_ctx.md_ctx);
+ m_io_ctx.dup(image_ctx->md_ctx);
m_io_ctx.snap_set_read(CEPH_SNAPDIR);
}
virtual void complete(int r) {
+ I &image_ctx = this->m_image_ctx;
if (should_complete(r)) {
- ldout(m_image_ctx.cct, 20) << m_oid << " C_VerifyObject completed "
+ ldout(image_ctx.cct, 20) << m_oid << " C_VerifyObject completed "
<< dendl;
- finish(r);
+ this->finish(r);
delete this;
}
}
int m_snap_list_ret;
bool should_complete(int r) {
- CephContext *cct = m_image_ctx.cct;
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
if (r == 0) {
r = m_snap_list_ret;
}
}
void send_list_snaps() {
- assert(m_image_ctx.owner_lock.is_locked());
- ldout(m_image_ctx.cct, 5) << m_oid << " C_VerifyObject::send_list_snaps"
- << dendl;
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ ldout(image_ctx.cct, 5) << m_oid << " C_VerifyObject::send_list_snaps"
+ << dendl;
librados::AioCompletion *comp = librados::Rados::aio_create_completion(
this, NULL, rados_ctx_cb);
}
uint8_t get_object_state() {
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
+ I &image_ctx = this->m_image_ctx;
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
for (std::vector<librados::clone_info_t>::const_iterator r =
m_snap_set.clones.begin(); r != m_snap_set.clones.end(); ++r) {
librados::snap_t from_snap_id;
break;
}
- if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0 &&
+ if ((image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0 &&
from_snap_id != m_snap_id) {
return OBJECT_EXISTS_CLEAN;
}
}
uint64_t next_valid_snap_id(uint64_t snap_id) {
- assert(m_image_ctx.snap_lock.is_locked());
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.snap_lock.is_locked());
std::map<librados::snap_t, SnapInfo>::iterator it =
- m_image_ctx.snap_info.lower_bound(snap_id);
- if (it == m_image_ctx.snap_info.end()) {
+ image_ctx.snap_info.lower_bound(snap_id);
+ if (it == image_ctx.snap_info.end()) {
return CEPH_NOSNAP;
}
return it->first;
}
bool update_object_map(uint8_t new_state) {
- RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
- CephContext *cct = m_image_ctx.cct;
+ I &image_ctx = this->m_image_ctx;
+ RWLock::RLocker owner_locker(image_ctx.owner_lock);
+ CephContext *cct = image_ctx.cct;
// should have been canceled prior to releasing lock
- assert(!m_image_ctx.image_watcher->is_lock_supported() ||
- m_image_ctx.image_watcher->is_lock_owner());
+ assert(!image_ctx.image_watcher->is_lock_supported() ||
+ image_ctx.image_watcher->is_lock_owner());
- RWLock::WLocker l(m_image_ctx.object_map_lock);
- uint8_t state = m_image_ctx.object_map[m_object_no];
+ RWLock::WLocker l(image_ctx.object_map_lock);
+ uint8_t state = image_ctx.object_map[m_object_no];
if (state == OBJECT_EXISTS && new_state == OBJECT_NONEXISTENT &&
m_snap_id == CEPH_NOSNAP) {
// might be writing object to OSD concurrently
ldout(cct, 15) << m_oid << " C_VerifyObject::update_object_map "
<< static_cast<uint32_t>(state) << "->"
<< static_cast<uint32_t>(new_state) << dendl;
- m_image_ctx.object_map[m_object_no] = new_state;
+ image_ctx.object_map[m_object_no] = new_state;
}
return true;
}
} // anonymous namespace
-
-void RebuildObjectMapRequest::send() {
+template <typename I>
+void RebuildObjectMapRequest<I>::send() {
send_resize_object_map();
}
-bool RebuildObjectMapRequest::should_complete(int r) {
+template <typename I>
+bool RebuildObjectMapRequest<I>::should_complete(int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 5) << this << " should_complete: " << " r=" << r << dendl;
return false;
}
-void RebuildObjectMapRequest::send_resize_object_map() {
+template <typename I>
+void RebuildObjectMapRequest<I>::send_resize_object_map() {
assert(m_image_ctx.owner_lock.is_locked());
CephContext *cct = m_image_ctx.cct;
assert(!m_image_ctx.image_watcher->is_lock_supported() ||
m_image_ctx.image_watcher->is_lock_owner());
m_image_ctx.object_map.aio_resize(size, OBJECT_NONEXISTENT,
- create_callback_context());
+ this->create_callback_context());
}
-void RebuildObjectMapRequest::send_trim_image() {
+template <typename I>
+void RebuildObjectMapRequest<I>::send_trim_image() {
CephContext *cct = m_image_ctx.cct;
RWLock::RLocker l(m_image_ctx.owner_lock);
orig_size = m_image_ctx.get_object_size() *
m_image_ctx.object_map.size();
}
- TrimRequest *req = new TrimRequest(m_image_ctx, create_callback_context(),
- orig_size, new_size, m_prog_ctx);
+ TrimRequest<I> *req = new TrimRequest<I>(m_image_ctx,
+ this->create_callback_context(),
+ orig_size, new_size, m_prog_ctx);
req->send();
}
-void RebuildObjectMapRequest::send_verify_objects() {
+template <typename I>
+void RebuildObjectMapRequest<I>::send_verify_objects() {
assert(m_image_ctx.owner_lock.is_locked());
CephContext *cct = m_image_ctx.cct;
m_state = STATE_VERIFY_OBJECTS;
ldout(cct, 5) << this << " send_verify_objects" << dendl;
- AsyncObjectThrottle<>::ContextFactory context_factory(
- boost::lambda::bind(boost::lambda::new_ptr<C_VerifyObject>(),
+ typename AsyncObjectThrottle<I>::ContextFactory context_factory(
+ boost::lambda::bind(boost::lambda::new_ptr<C_VerifyObject<I> >(),
boost::lambda::_1, &m_image_ctx, snap_id, boost::lambda::_2));
- AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>(
- this, m_image_ctx, context_factory, create_callback_context(), &m_prog_ctx,
- 0, num_objects);
+ AsyncObjectThrottle<I> *throttle = new AsyncObjectThrottle<I>(
+ this, m_image_ctx, context_factory, this->create_callback_context(),
+ &m_prog_ctx, 0, num_objects);
throttle->start_ops(cct->_conf->rbd_concurrent_management_ops);
}
-void RebuildObjectMapRequest::send_save_object_map() {
+template <typename I>
+void RebuildObjectMapRequest<I>::send_save_object_map() {
assert(m_image_ctx.owner_lock.is_locked());
CephContext *cct = m_image_ctx.cct;
// should have been canceled prior to releasing lock
assert(!m_image_ctx.image_watcher->is_lock_supported() ||
m_image_ctx.image_watcher->is_lock_owner());
- m_image_ctx.object_map.aio_save(create_callback_context());
+ m_image_ctx.object_map.aio_save(this->create_callback_context());
}
-void RebuildObjectMapRequest::send_update_header() {
+template <typename I>
+void RebuildObjectMapRequest<I>::send_update_header() {
assert(m_image_ctx.owner_lock.is_locked());
// should have been canceled prior to releasing lock
uint64_t flags = RBD_FLAG_OBJECT_MAP_INVALID | RBD_FLAG_FAST_DIFF_INVALID;
cls_client::set_flags(&op, m_image_ctx.snap_id, 0, flags);
- librados::AioCompletion *comp = create_callback_completion();
+ librados::AioCompletion *comp = this->create_callback_completion();
int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, comp, &op);
assert(r == 0);
comp->release();
m_image_ctx.update_flags(m_image_ctx.snap_id, flags, false);
}
-uint64_t RebuildObjectMapRequest::get_image_size() const {
+template <typename I>
+uint64_t RebuildObjectMapRequest<I>::get_image_size() const {
assert(m_image_ctx.snap_lock.is_locked());
if (m_image_ctx.snap_id == CEPH_NOSNAP) {
if (!m_image_ctx.resize_reqs.empty()) {
} // namespace operation
} // namespace librbd
+
+template class librbd::operation::RebuildObjectMapRequest<librbd::ImageCtx>;
namespace operation {
-class RebuildObjectMapRequest : public AsyncRequest<> {
+template <typename ImageCtxT = ImageCtx>
+class RebuildObjectMapRequest : public AsyncRequest<ImageCtxT> {
public:
- RebuildObjectMapRequest(ImageCtx &image_ctx, Context *on_finish,
+ RebuildObjectMapRequest(ImageCtxT &image_ctx, Context *on_finish,
ProgressContext &prog_ctx)
- : AsyncRequest(image_ctx, on_finish), m_image_ctx(image_ctx),
+ : AsyncRequest<ImageCtxT>(image_ctx, on_finish), m_image_ctx(image_ctx),
m_prog_ctx(prog_ctx), m_attempted_trim(false)
{
}
STATE_UPDATE_HEADER
};
- ImageCtx &m_image_ctx;
+ ImageCtxT &m_image_ctx;
ProgressContext &m_prog_ctx;
State m_state;
bool m_attempted_trim;
} // namespace operation
} // namespace librbd
+extern template class librbd::operation::RebuildObjectMapRequest<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_OPERATION_REBUILD_OBJECT_MAP_REQUEST_H
namespace {
+template <typename I>
std::ostream& operator<<(std::ostream& os,
- const RenameRequest::State& state) {
+ const typename RenameRequest<I>::State& state) {
switch(state) {
- case RenameRequest::STATE_READ_SOURCE_HEADER:
+ case RenameRequest<I>::STATE_READ_SOURCE_HEADER:
os << "READ_SOURCE_HEADER";
break;
- case RenameRequest::STATE_WRITE_DEST_HEADER:
+ case RenameRequest<I>::STATE_WRITE_DEST_HEADER:
os << "WRITE_DEST_HEADER";
break;
- case RenameRequest::STATE_UPDATE_DIRECTORY:
+ case RenameRequest<I>::STATE_UPDATE_DIRECTORY:
os << "UPDATE_DIRECTORY";
break;
- case RenameRequest::STATE_REMOVE_SOURCE_HEADER:
+ case RenameRequest<I>::STATE_REMOVE_SOURCE_HEADER:
os << "REMOVE_SOURCE_HEADER";
break;
default:
} // anonymous namespace
-RenameRequest::RenameRequest(ImageCtx &image_ctx, Context *on_finish,
- const std::string &dest_name)
- : Request(image_ctx, on_finish), m_dest_name(dest_name),
+template <typename I>
+RenameRequest<I>::RenameRequest(I &image_ctx, Context *on_finish,
+ const std::string &dest_name)
+ : Request<I>(image_ctx, on_finish), m_dest_name(dest_name),
m_source_oid(image_ctx.old_format ? old_header_name(image_ctx.name) :
id_obj_name(image_ctx.name)),
m_dest_oid(image_ctx.old_format ? old_header_name(dest_name) :
id_obj_name(dest_name)) {
}
-void RenameRequest::send_op() {
+template <typename I>
+void RenameRequest<I>::send_op() {
send_read_source_header();
}
-bool RenameRequest::should_complete(int r) {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool RenameRequest<I>::should_complete(int r) {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", "
<< "r=" << r << dendl;
r = filter_state_return_code(r);
return true;
}
- RWLock::RLocker owner_lock(m_image_ctx.owner_lock);
+ RWLock::RLocker owner_lock(image_ctx.owner_lock);
bool finished = false;
switch (m_state) {
case STATE_READ_SOURCE_HEADER:
return finished;
}
-int RenameRequest::filter_state_return_code(int r) {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+int RenameRequest<I>::filter_state_return_code(int r) {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
if (m_state == STATE_REMOVE_SOURCE_HEADER && r < 0) {
if (r != -ENOENT) {
return r;
}
-void RenameRequest::send_read_source_header() {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+void RenameRequest<I>::send_read_source_header() {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_READ_SOURCE_HEADER;
// TODO: old code read omap values but there are no omap values on the
// old format header nor the new format id object
- librados::AioCompletion *rados_completion = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(m_source_oid, rados_completion, &op,
- &m_header_bl);
+ librados::AioCompletion *rados_completion = this->create_callback_completion();
+ int r = image_ctx.md_ctx.aio_operate(m_source_oid, rados_completion, &op,
+ &m_header_bl);
assert(r == 0);
rados_completion->release();
}
-void RenameRequest::send_write_destination_header() {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+void RenameRequest<I>::send_write_destination_header() {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_WRITE_DEST_HEADER;
op.create(true);
op.write_full(m_header_bl);
- librados::AioCompletion *rados_completion = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(m_dest_oid, rados_completion, &op);
+ librados::AioCompletion *rados_completion = this->create_callback_completion();
+ int r = image_ctx.md_ctx.aio_operate(m_dest_oid, rados_completion, &op);
assert(r == 0);
rados_completion->release();
}
-void RenameRequest::send_update_directory() {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+void RenameRequest<I>::send_update_directory() {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_UPDATE_DIRECTORY;
librados::ObjectWriteOperation op;
- if (m_image_ctx.old_format) {
+ if (image_ctx.old_format) {
bufferlist cmd_bl;
bufferlist empty_bl;
::encode(static_cast<__u8>(CEPH_OSD_TMAP_SET), cmd_bl);
::encode(m_dest_name, cmd_bl);
::encode(empty_bl, cmd_bl);
::encode(static_cast<__u8>(CEPH_OSD_TMAP_RM), cmd_bl);
- ::encode(m_image_ctx.name, cmd_bl);
+ ::encode(image_ctx.name, cmd_bl);
op.tmap_update(cmd_bl);
} else {
- cls_client::dir_rename_image(&op, m_image_ctx.name, m_dest_name,
- m_image_ctx.id);
+ cls_client::dir_rename_image(&op, image_ctx.name, m_dest_name,
+ image_ctx.id);
}
- librados::AioCompletion *rados_completion = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(RBD_DIRECTORY, rados_completion, &op);
+ librados::AioCompletion *rados_completion = this->create_callback_completion();
+ int r = image_ctx.md_ctx.aio_operate(RBD_DIRECTORY, rados_completion, &op);
assert(r == 0);
rados_completion->release();
}
-void RenameRequest::send_remove_source_header() {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+void RenameRequest<I>::send_remove_source_header() {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_REMOVE_SOURCE_HEADER;
librados::ObjectWriteOperation op;
op.remove();
- librados::AioCompletion *rados_completion = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(m_source_oid, rados_completion, &op);
+ librados::AioCompletion *rados_completion = this->create_callback_completion();
+ int r = image_ctx.md_ctx.aio_operate(m_source_oid, rados_completion, &op);
assert(r == 0);
rados_completion->release();
}
} // namespace operation
} // namespace librbd
+
+template class librbd::operation::RenameRequest<librbd::ImageCtx>;
namespace operation {
-class RenameRequest : public Request
+template <typename ImageCtxT = ImageCtx>
+class RenameRequest : public Request<ImageCtxT>
{
public:
/**
STATE_REMOVE_SOURCE_HEADER
};
- RenameRequest(ImageCtx &image_ctx, Context *on_finish,
+ RenameRequest(ImageCtxT &image_ctx, Context *on_finish,
const std::string &dest_name);
protected:
} // namespace operation
} // namespace librbd
+extern template class librbd::operation::RenameRequest<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_RENAME_REQUEST_H
namespace librbd {
namespace operation {
-Request::Request(ImageCtx &image_ctx, Context *on_finish)
- : AsyncRequest(image_ctx, on_finish), m_tid(0) {
+template <typename I>
+Request<I>::Request(I &image_ctx, Context *on_finish)
+ : AsyncRequest<I>(image_ctx, on_finish), m_tid(0) {
}
-void Request::send() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void Request<I>::send() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
{
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- if (m_image_ctx.journal != NULL &&
- !m_image_ctx.journal->is_journal_replaying()) {
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ if (image_ctx.journal != NULL &&
+ !image_ctx.journal->is_journal_replaying()) {
// journal might be replaying -- wait for it to complete
- if (!m_image_ctx.journal->is_journal_ready()) {
- m_image_ctx.journal->wait_for_journal_ready(
+ if (!image_ctx.journal->is_journal_ready()) {
+ image_ctx.journal->wait_for_journal_ready(
new C_WaitForJournalReady(this));
return;
}
journal::EventEntry event_entry(create_event());
- m_tid = m_image_ctx.journal->append_op_event(event_entry);
+ m_tid = image_ctx.journal->append_op_event(event_entry);
}
}
send_op();
}
-void Request::finish(int r) {
- AsyncRequest::finish(r);
+template <typename I>
+void Request<I>::finish(int r) {
+ AsyncRequest<I>::finish(r);
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
+ I &image_ctx = this->m_image_ctx;
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
if (m_tid != 0 &&
- m_image_ctx.journal != NULL &&
- !m_image_ctx.journal->is_journal_replaying()) {
+ image_ctx.journal != NULL &&
+ !image_ctx.journal->is_journal_replaying()) {
// ops will be canceled / completed before closing journal
- assert(m_image_ctx.journal->is_journal_ready());
+ assert(image_ctx.journal->is_journal_ready());
- m_image_ctx.journal->commit_op_event(m_tid, r);
+ image_ctx.journal->commit_op_event(m_tid, r);
}
}
-void Request::handle_journal_ready() {
- RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
+template <typename I>
+void Request<I>::handle_journal_ready() {
+ I &image_ctx = this->m_image_ctx;
+ RWLock::RLocker owner_locker(image_ctx.owner_lock);
send();
}
} // namespace operation
} // namespace librbd
+
+template class librbd::operation::Request<librbd::ImageCtx>;
#include "librbd/JournalTypes.h"
namespace librbd {
+
+class ImageCtx;
+
namespace operation {
-class Request : public AsyncRequest<> {
+template <typename ImageCtxT = ImageCtx>
+class Request : public AsyncRequest<ImageCtxT> {
public:
- Request(ImageCtx &image_ctx, Context *on_finish);
+ Request(ImageCtxT &image_ctx, Context *on_finish);
virtual void send();
} // namespace operation
} // namespace librbd
+extern template class librbd::operation::Request<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_OPERATION_REQUEST_H
namespace librbd {
namespace operation {
-ResizeRequest::ResizeRequest(ImageCtx &image_ctx, Context *on_finish,
- uint64_t new_size,
- ProgressContext &prog_ctx)
- : Request(image_ctx, on_finish),
- m_original_size(0), m_new_size(new_size),
- m_prog_ctx(prog_ctx), m_new_parent_overlap(0),
- m_xlist_item(this)
+template <typename I>
+ResizeRequest<I>::ResizeRequest(I &image_ctx, Context *on_finish,
+ uint64_t new_size, ProgressContext &prog_ctx)
+ : Request<I>(image_ctx, on_finish),
+ m_original_size(0), m_new_size(new_size), m_prog_ctx(prog_ctx),
+ m_new_parent_overlap(0), m_xlist_item(this)
{
}
-ResizeRequest::~ResizeRequest() {
+template <typename I>
+ResizeRequest<I>::~ResizeRequest() {
+ I &image_ctx = this->m_image_ctx;
ResizeRequest *next_req = NULL;
{
- RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
+ RWLock::WLocker snap_locker(image_ctx.snap_lock);
assert(m_xlist_item.remove_myself());
- if (!m_image_ctx.resize_reqs.empty()) {
- next_req = m_image_ctx.resize_reqs.front();
+ if (!image_ctx.resize_reqs.empty()) {
+ next_req = image_ctx.resize_reqs.front();
}
}
if (next_req != NULL) {
- RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
+ RWLock::RLocker owner_locker(image_ctx.owner_lock);
next_req->send();
}
}
-bool ResizeRequest::should_complete(int r) {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool ResizeRequest<I>::should_complete(int r) {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " should_complete: " << " r=" << r << dendl;
if (r < 0) {
return true;
}
- RWLock::RLocker owner_lock(m_image_ctx.owner_lock);
+ RWLock::RLocker owner_lock(image_ctx.owner_lock);
switch (m_state) {
case STATE_FLUSH:
ldout(cct, 5) << "FLUSH" << dendl;
return false;
}
-void ResizeRequest::send() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void ResizeRequest<I>::send() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
{
- RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
+ RWLock::WLocker snap_locker(image_ctx.snap_lock);
if (!m_xlist_item.is_on_list()) {
- m_image_ctx.resize_reqs.push_back(&m_xlist_item);
- if (m_image_ctx.resize_reqs.front() != this) {
+ image_ctx.resize_reqs.push_back(&m_xlist_item);
+ if (image_ctx.resize_reqs.front() != this) {
return;
}
}
- assert(m_image_ctx.resize_reqs.front() == this);
- m_original_size = m_image_ctx.size;
+ assert(image_ctx.resize_reqs.front() == this);
+ m_original_size = image_ctx.size;
compute_parent_overlap();
}
- Request::send();
+ Request<I>::send();
}
-void ResizeRequest::send_op() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void ResizeRequest<I>::send_op() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
- if (is_canceled()) {
- async_complete(-ERESTART);
+ CephContext *cct = image_ctx.cct;
+ if (this->is_canceled()) {
+ this->async_complete(-ERESTART);
} else if (m_original_size == m_new_size) {
ldout(cct, 2) << this << " no change in size (" << m_original_size
<< " -> " << m_new_size << ")" << dendl;
m_state = STATE_FINISHED;
- async_complete(0);
+ this->async_complete(0);
} else if (m_new_size > m_original_size) {
ldout(cct, 2) << this << " expanding image (" << m_original_size
<< " -> " << m_new_size << ")" << dendl;
}
}
-void ResizeRequest::send_flush() {
- ldout(m_image_ctx.cct, 5) << this << " send_flush: "
- << " original_size=" << m_original_size
- << " new_size=" << m_new_size << dendl;
+template <typename I>
+void ResizeRequest<I>::send_flush() {
+ I &image_ctx = this->m_image_ctx;
+ ldout(image_ctx.cct, 5) << this << " send_flush: "
+ << " original_size=" << m_original_size
+ << " new_size=" << m_new_size << dendl;
m_state = STATE_FLUSH;
// with clipping adjusted, ensure that write / copy-on-read operations won't
// (re-)create objects that we just removed. need async callback to ensure
// we don't have cache_lock already held
- m_image_ctx.flush_async_operations(create_async_callback_context());
+ image_ctx.flush_async_operations(this->create_async_callback_context());
}
-void ResizeRequest::send_invalidate_cache() {
- assert(m_image_ctx.owner_lock.is_locked());
- ldout(m_image_ctx.cct, 5) << this << " send_invalidate_cache: "
- << " original_size=" << m_original_size
- << " new_size=" << m_new_size << dendl;
+template <typename I>
+void ResizeRequest<I>::send_invalidate_cache() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ ldout(image_ctx.cct, 5) << this << " send_invalidate_cache: "
+ << " original_size=" << m_original_size
+ << " new_size=" << m_new_size << dendl;
m_state = STATE_INVALIDATE_CACHE;
// need to invalidate since we're deleting objects, and
// ObjectCacher doesn't track non-existent objects
- m_image_ctx.invalidate_cache(create_callback_context());
+ image_ctx.invalidate_cache(this->create_callback_context());
}
-void ResizeRequest::send_trim_image() {
- assert(m_image_ctx.owner_lock.is_locked());
- ldout(m_image_ctx.cct, 5) << this << " send_trim_image: "
- << " original_size=" << m_original_size
- << " new_size=" << m_new_size << dendl;
+template <typename I>
+void ResizeRequest<I>::send_trim_image() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ ldout(image_ctx.cct, 5) << this << " send_trim_image: "
+ << " original_size=" << m_original_size
+ << " new_size=" << m_new_size << dendl;
m_state = STATE_TRIM_IMAGE;
- TrimRequest *req = new TrimRequest(m_image_ctx, create_callback_context(),
- m_original_size, m_new_size, m_prog_ctx);
+ TrimRequest<I> *req = new TrimRequest<I>(image_ctx,
+ this->create_callback_context(),
+ m_original_size, m_new_size,
+ m_prog_ctx);
req->send();
}
-void ResizeRequest::send_grow_object_map() {
- assert(m_image_ctx.owner_lock.is_locked());
- if (!m_image_ctx.object_map.enabled()) {
+template <typename I>
+void ResizeRequest<I>::send_grow_object_map() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ if (!image_ctx.object_map.enabled()) {
send_update_header();
return;
}
- ldout(m_image_ctx.cct, 5) << this << " send_grow_object_map: "
- << " original_size=" << m_original_size
- << " new_size=" << m_new_size << dendl;
+ ldout(image_ctx.cct, 5) << this << " send_grow_object_map: "
+ << " original_size=" << m_original_size
+ << " new_size=" << m_new_size << dendl;
m_state = STATE_GROW_OBJECT_MAP;
// should have been canceled prior to releasing lock
- assert(!m_image_ctx.image_watcher->is_lock_supported() ||
- m_image_ctx.image_watcher->is_lock_owner());
+ assert(!image_ctx.image_watcher->is_lock_supported() ||
+ image_ctx.image_watcher->is_lock_owner());
- m_image_ctx.object_map.aio_resize(m_new_size, OBJECT_NONEXISTENT,
- create_callback_context());
+ image_ctx.object_map.aio_resize(m_new_size, OBJECT_NONEXISTENT,
+ this->create_callback_context());
}
-bool ResizeRequest::send_shrink_object_map() {
- assert(m_image_ctx.owner_lock.is_locked());
- if (!m_image_ctx.object_map.enabled() || m_new_size > m_original_size) {
+template <typename I>
+bool ResizeRequest<I>::send_shrink_object_map() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ if (!image_ctx.object_map.enabled() || m_new_size > m_original_size) {
return true;
}
- ldout(m_image_ctx.cct, 5) << this << " send_shrink_object_map: "
+ ldout(image_ctx.cct, 5) << this << " send_shrink_object_map: "
<< " original_size=" << m_original_size
<< " new_size=" << m_new_size << dendl;
m_state = STATE_SHRINK_OBJECT_MAP;
// should have been canceled prior to releasing lock
- assert(!m_image_ctx.image_watcher->is_lock_supported() ||
- m_image_ctx.image_watcher->is_lock_owner());
+ assert(!image_ctx.image_watcher->is_lock_supported() ||
+ image_ctx.image_watcher->is_lock_owner());
- m_image_ctx.object_map.aio_resize(m_new_size, OBJECT_NONEXISTENT,
- create_callback_context());
+ image_ctx.object_map.aio_resize(m_new_size, OBJECT_NONEXISTENT,
+ this->create_callback_context());
return false;
}
-void ResizeRequest::send_update_header() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void ResizeRequest<I>::send_update_header() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- ldout(m_image_ctx.cct, 5) << this << " send_update_header: "
+ ldout(image_ctx.cct, 5) << this << " send_update_header: "
<< " original_size=" << m_original_size
<< " new_size=" << m_new_size << dendl;
m_state = STATE_UPDATE_HEADER;
// should have been canceled prior to releasing lock
- assert(!m_image_ctx.image_watcher->is_lock_supported() ||
- m_image_ctx.image_watcher->is_lock_owner());
+ assert(!image_ctx.image_watcher->is_lock_supported() ||
+ image_ctx.image_watcher->is_lock_owner());
librados::ObjectWriteOperation op;
- if (m_image_ctx.old_format) {
+ if (image_ctx.old_format) {
// rewrite only the size field of the header
// NOTE: format 1 image headers are not stored in fixed endian format
bufferlist bl;
bl.append(reinterpret_cast<const char*>(&m_new_size), sizeof(m_new_size));
op.write(offsetof(rbd_obj_header_ondisk, image_size), bl);
} else {
- if (m_image_ctx.image_watcher->is_lock_supported()) {
- m_image_ctx.image_watcher->assert_header_locked(&op);
+ if (image_ctx.image_watcher->is_lock_supported()) {
+ image_ctx.image_watcher->assert_header_locked(&op);
}
cls_client::set_size(&op, m_new_size);
}
- librados::AioCompletion *rados_completion = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
- rados_completion, &op);
+ librados::AioCompletion *rados_completion =
+ this->create_callback_completion();
+ int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid,
+ rados_completion, &op);
assert(r == 0);
rados_completion->release();
}
-void ResizeRequest::compute_parent_overlap() {
- RWLock::RLocker l2(m_image_ctx.parent_lock);
- if (m_image_ctx.parent == NULL) {
+template <typename I>
+void ResizeRequest<I>::compute_parent_overlap() {
+ I &image_ctx = this->m_image_ctx;
+ RWLock::RLocker l2(image_ctx.parent_lock);
+ if (image_ctx.parent == NULL) {
m_new_parent_overlap = 0;
} else {
- m_new_parent_overlap = MIN(m_new_size, m_image_ctx.parent_md.overlap);
+ m_new_parent_overlap = MIN(m_new_size, image_ctx.parent_md.overlap);
}
}
-void ResizeRequest::update_size_and_overlap() {
- RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
- m_image_ctx.size = m_new_size;
+template <typename I>
+void ResizeRequest<I>::update_size_and_overlap() {
+ I &image_ctx = this->m_image_ctx;
+ RWLock::WLocker snap_locker(image_ctx.snap_lock);
+ image_ctx.size = m_new_size;
- RWLock::WLocker parent_locker(m_image_ctx.parent_lock);
- if (m_image_ctx.parent != NULL && m_new_size < m_original_size) {
- m_image_ctx.parent_md.overlap = m_new_parent_overlap;
+ RWLock::WLocker parent_locker(image_ctx.parent_lock);
+ if (image_ctx.parent != NULL && m_new_size < m_original_size) {
+ image_ctx.parent_md.overlap = m_new_parent_overlap;
}
}
} // namespace operation
} // namespace librbd
+
+template class librbd::operation::ResizeRequest<librbd::ImageCtx>;
namespace operation {
-class ResizeRequest : public Request
-{
+template <typename ImageCtxT = ImageCtx>
+class ResizeRequest : public Request<ImageCtxT> {
public:
- ResizeRequest(ImageCtx &image_ctx, Context *on_finish, uint64_t new_size,
- ProgressContext &prog_ctx);
+ ResizeRequest(ImageCtxT &image_ctx, Context *on_finish, uint64_t new_size,
+ ProgressContext &prog_ctx);
virtual ~ResizeRequest();
inline bool shrinking() const {
ProgressContext &m_prog_ctx;
uint64_t m_new_parent_overlap;
- xlist<ResizeRequest *>::item m_xlist_item;
+ typename xlist<ResizeRequest<ImageCtxT>*>::item m_xlist_item;
void send_flush();
void send_invalidate_cache();
} // namespace operation
} // namespace librbd
+extern template class librbd::operation::ResizeRequest<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_OPERATION_RESIZE_REQUEST_H
namespace {
+template <typename I>
std::ostream& operator<<(std::ostream& os,
- const SnapshotCreateRequest::State& state) {
+ const typename SnapshotCreateRequest<I>::State& state) {
switch(state) {
- case SnapshotCreateRequest::STATE_SUSPEND_REQUESTS:
+ case SnapshotCreateRequest<I>::STATE_SUSPEND_REQUESTS:
os << "SUSPEND_REQUESTS";
break;
- case SnapshotCreateRequest::STATE_SUSPEND_AIO:
+ case SnapshotCreateRequest<I>::STATE_SUSPEND_AIO:
os << "SUSPEND_AIO";
break;
- case SnapshotCreateRequest::STATE_ALLOCATE_SNAP_ID:
+ case SnapshotCreateRequest<I>::STATE_ALLOCATE_SNAP_ID:
os << "ALLOCATE_SNAP_ID";
break;
- case SnapshotCreateRequest::STATE_CREATE_SNAP:
+ case SnapshotCreateRequest<I>::STATE_CREATE_SNAP:
os << "CREATE_SNAP";
break;
- case SnapshotCreateRequest::STATE_CREATE_OBJECT_MAP:
+ case SnapshotCreateRequest<I>::STATE_CREATE_OBJECT_MAP:
os << "CREATE_OBJECT_MAP";
break;
- case SnapshotCreateRequest::STATE_RELEASE_SNAP_ID:
+ case SnapshotCreateRequest<I>::STATE_RELEASE_SNAP_ID:
os << "RELEASE_SNAP_ID";
break;
default:
} // anonymous namespace
-SnapshotCreateRequest::SnapshotCreateRequest(ImageCtx &image_ctx,
- Context *on_finish,
- const std::string &snap_name)
- : Request(image_ctx, on_finish), m_snap_name(snap_name), m_ret_val(0),
+template <typename I>
+SnapshotCreateRequest<I>::SnapshotCreateRequest(I &image_ctx,
+ Context *on_finish,
+ const std::string &snap_name)
+ : Request<I>(image_ctx, on_finish), m_snap_name(snap_name), m_ret_val(0),
m_aio_suspended(false), m_requests_suspended(false),
m_snap_id(CEPH_NOSNAP), m_snap_created(false) {
}
-void SnapshotCreateRequest::send_op() {
+template <typename I>
+void SnapshotCreateRequest<I>::send_op() {
send_suspend_requests();
}
-bool SnapshotCreateRequest::should_complete(int r) {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool SnapshotCreateRequest<I>::should_complete(int r) {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", "
<< "r=" << r << dendl;
r = filter_state_return_code(r);
return should_complete_error();
}
- RWLock::RLocker owner_lock(m_image_ctx.owner_lock);
+ RWLock::RLocker owner_lock(image_ctx.owner_lock);
bool finished = false;
switch (m_state) {
case STATE_SUSPEND_REQUESTS:
return finished;
}
-bool SnapshotCreateRequest::should_complete_error() {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool SnapshotCreateRequest<I>::should_complete_error() {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
lderr(cct) << this << " " << __func__ << ": "
<< "ret_val=" << m_ret_val << dendl;
return finished;
}
-void SnapshotCreateRequest::send_suspend_requests() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotCreateRequest<I>::send_suspend_requests() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
// TODO suspend (shrink) resize to ensure consistent RBD mirror
send_suspend_aio();
}
-void SnapshotCreateRequest::send_suspend_aio() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotCreateRequest<I>::send_suspend_aio() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_SUSPEND_AIO;
m_aio_suspended = true;
// can issue a re-entrant callback if no IO in-progress
- m_image_ctx.aio_work_queue->block_writes(create_async_callback_context());
+ image_ctx.aio_work_queue->block_writes(this->create_async_callback_context());
}
-void SnapshotCreateRequest::send_allocate_snap_id() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotCreateRequest<I>::send_allocate_snap_id() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_ALLOCATE_SNAP_ID;
// TODO create an async version of selfmanaged_snap_create
- int r = m_image_ctx.md_ctx.selfmanaged_snap_create(&m_snap_id);
- async_complete(r);
+ int r = image_ctx.md_ctx.selfmanaged_snap_create(&m_snap_id);
+ this->async_complete(r);
}
-void SnapshotCreateRequest::send_create_snap() {
- assert(m_image_ctx.owner_lock.is_locked());
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- RWLock::RLocker parent_locker(m_image_ctx.parent_lock);
+template <typename I>
+void SnapshotCreateRequest<I>::send_create_snap() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ RWLock::RLocker parent_locker(image_ctx.parent_lock);
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_CREATE_SNAP;
// should have been canceled prior to releasing lock
- assert(!m_image_ctx.image_watcher->is_lock_supported(m_image_ctx.snap_lock) ||
- m_image_ctx.image_watcher->is_lock_owner());
+ assert(!image_ctx.image_watcher->is_lock_supported(image_ctx.snap_lock) ||
+ image_ctx.image_watcher->is_lock_owner());
// save current size / parent info for creating snapshot record in ImageCtx
- m_size = m_image_ctx.size;
- m_parent_info = m_image_ctx.parent_md;
+ m_size = image_ctx.size;
+ m_parent_info = image_ctx.parent_md;
librados::ObjectWriteOperation op;
- if (m_image_ctx.old_format) {
+ if (image_ctx.old_format) {
cls_client::old_snapshot_add(&op, m_snap_id, m_snap_name);
} else {
- if (m_image_ctx.image_watcher->is_lock_owner()) {
- m_image_ctx.image_watcher->assert_header_locked(&op);
+ if (image_ctx.image_watcher->is_lock_owner()) {
+ image_ctx.image_watcher->assert_header_locked(&op);
}
cls_client::snapshot_add(&op, m_snap_id, m_snap_name);
}
- librados::AioCompletion *rados_completion = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
+ librados::AioCompletion *rados_completion =
+ this->create_callback_completion();
+ int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid,
rados_completion, &op);
assert(r == 0);
rados_completion->release();
}
-bool SnapshotCreateRequest::send_create_object_map() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+bool SnapshotCreateRequest<I>::send_create_object_map() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
{
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- RWLock::RLocker object_map_lock(m_image_ctx.object_map_lock);
- if (m_image_ctx.object_map.enabled(m_image_ctx.object_map_lock)) {
- CephContext *cct = m_image_ctx.cct;
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ RWLock::RLocker object_map_lock(image_ctx.object_map_lock);
+ if (image_ctx.object_map.enabled(image_ctx.object_map_lock)) {
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_CREATE_OBJECT_MAP;
- m_image_ctx.object_map.snapshot_add(m_snap_id, create_callback_context());
+ image_ctx.object_map.snapshot_add(m_snap_id,
+ this->create_callback_context());
return false;
}
}
return true;
}
-bool SnapshotCreateRequest::send_release_snap_id() {
+template <typename I>
+bool SnapshotCreateRequest<I>::send_release_snap_id() {
+ I &image_ctx = this->m_image_ctx;
if (m_snap_id != CEPH_NOSNAP && !m_snap_created) {
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << ": snap_id=" << m_snap_id
<< dendl;
m_state = STATE_RELEASE_SNAP_ID;
// TODO add async version of selfmanaged_snap_remove
- int r = m_image_ctx.data_ctx.selfmanaged_snap_remove(m_snap_id);
+ int r = image_ctx.data_ctx.selfmanaged_snap_remove(m_snap_id);
m_snap_id = CEPH_NOSNAP;
- async_complete(r);
+ this->async_complete(r);
return false;
}
return true;
}
-void SnapshotCreateRequest::resume_aio() {
+template <typename I>
+void SnapshotCreateRequest<I>::resume_aio() {
+ I &image_ctx = this->m_image_ctx;
if (m_aio_suspended) {
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
- m_image_ctx.aio_work_queue->unblock_writes();
+ image_ctx.aio_work_queue->unblock_writes();
m_aio_suspended = false;
}
}
-void SnapshotCreateRequest::resume_requests() {
+template <typename I>
+void SnapshotCreateRequest<I>::resume_requests() {
+ I &image_ctx = this->m_image_ctx;
if (m_requests_suspended) {
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
// TODO
}
}
-void SnapshotCreateRequest::update_snap_context() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotCreateRequest<I>::update_snap_context() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
m_snap_created = true;
- RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
- if (m_image_ctx.old_format) {
+ RWLock::WLocker snap_locker(image_ctx.snap_lock);
+ if (image_ctx.old_format) {
return;
}
- if (m_image_ctx.get_snap_info(m_snap_id) != NULL) {
+ if (image_ctx.get_snap_info(m_snap_id) != NULL) {
return;
}
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
// should have been canceled prior to releasing lock
- assert(!m_image_ctx.image_watcher->is_lock_supported(m_image_ctx.snap_lock) ||
- m_image_ctx.image_watcher->is_lock_owner());
+ assert(!image_ctx.image_watcher->is_lock_supported(image_ctx.snap_lock) ||
+ image_ctx.image_watcher->is_lock_owner());
// immediately add a reference to the new snapshot
- m_image_ctx.add_snap(m_snap_name, m_snap_id, m_size, m_parent_info,
- RBD_PROTECTION_STATUS_UNPROTECTED, 0);
+ image_ctx.add_snap(m_snap_name, m_snap_id, m_size, m_parent_info,
+ RBD_PROTECTION_STATUS_UNPROTECTED, 0);
// immediately start using the new snap context if we
// own the exclusive lock
std::vector<snapid_t> snaps;
snaps.push_back(m_snap_id);
- snaps.insert(snaps.end(), m_image_ctx.snapc.snaps.begin(),
- m_image_ctx.snapc.snaps.end());
+ snaps.insert(snaps.end(), image_ctx.snapc.snaps.begin(),
+ image_ctx.snapc.snaps.end());
- m_image_ctx.snapc.seq = m_snap_id;
- m_image_ctx.snapc.snaps.swap(snaps);
- m_image_ctx.data_ctx.selfmanaged_snap_set_write_ctx(
- m_image_ctx.snapc.seq, m_image_ctx.snaps);
+ image_ctx.snapc.seq = m_snap_id;
+ image_ctx.snapc.snaps.swap(snaps);
+ image_ctx.data_ctx.selfmanaged_snap_set_write_ctx(
+ image_ctx.snapc.seq, image_ctx.snaps);
}
} // namespace operation
} // namespace librbd
+
+template class librbd::operation::SnapshotCreateRequest<librbd::ImageCtx>;
namespace operation {
-class SnapshotCreateRequest : public Request {
+template <typename ImageCtxT = ImageCtx>
+class SnapshotCreateRequest : public Request<ImageCtxT> {
public:
/**
* Snap Create goes through the following state machine:
STATE_RELEASE_SNAP_ID
};
- SnapshotCreateRequest(ImageCtx &image_ctx, Context *on_finish,
+ SnapshotCreateRequest(ImageCtxT &image_ctx, Context *on_finish,
const std::string &snap_name);
protected:
} // namespace operation
} // namespace librbd
+extern template class librbd::operation::SnapshotCreateRequest<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_CREATE_REQUEST_H
namespace {
+template <typename I>
std::ostream& operator<<(std::ostream& os,
- const SnapshotProtectRequest::State& state) {
+ const typename SnapshotProtectRequest<I>::State& state) {
switch(state) {
- case SnapshotProtectRequest::STATE_PROTECT_SNAP:
+ case SnapshotProtectRequest<I>::STATE_PROTECT_SNAP:
os << "PROTECT_SNAP";
break;
}
} // anonymous namespace
-SnapshotProtectRequest::SnapshotProtectRequest(ImageCtx &image_ctx,
- Context *on_finish,
- const std::string &snap_name)
- : Request(image_ctx, on_finish), m_snap_name(snap_name) {
+template <typename I>
+SnapshotProtectRequest<I>::SnapshotProtectRequest(I &image_ctx,
+ Context *on_finish,
+ const std::string &snap_name)
+ : Request<I>(image_ctx, on_finish), m_snap_name(snap_name) {
}
-void SnapshotProtectRequest::send_op() {
+template <typename I>
+void SnapshotProtectRequest<I>::send_op() {
send_protect_snap();
}
-bool SnapshotProtectRequest::should_complete(int r) {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool SnapshotProtectRequest<I>::should_complete(int r) {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", "
<< "r=" << r << dendl;
if (r < 0) {
return true;
}
-void SnapshotProtectRequest::send_protect_snap() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotProtectRequest<I>::send_protect_snap() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_PROTECT_SNAP;
int r = verify_and_send_protect_snap();
if (r < 0) {
- async_complete(r);
+ this->async_complete(r);
return;
}
}
-int SnapshotProtectRequest::verify_and_send_protect_snap() {
- RWLock::RLocker md_locker(m_image_ctx.md_lock);
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
+template <typename I>
+int SnapshotProtectRequest<I>::verify_and_send_protect_snap() {
+ I &image_ctx = this->m_image_ctx;
+ RWLock::RLocker md_locker(image_ctx.md_lock);
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
- CephContext *cct = m_image_ctx.cct;
- if ((m_image_ctx.features & RBD_FEATURE_LAYERING) == 0) {
+ CephContext *cct = image_ctx.cct;
+ if ((image_ctx.features & RBD_FEATURE_LAYERING) == 0) {
lderr(cct) << "image must support layering" << dendl;
return -ENOSYS;
}
- uint64_t snap_id = m_image_ctx.get_snap_id(m_snap_name);
+ uint64_t snap_id = image_ctx.get_snap_id(m_snap_name);
if (snap_id == CEPH_NOSNAP) {
return -ENOENT;
}
bool is_protected;
- int r = m_image_ctx.is_snap_protected(snap_id, &is_protected);
+ int r = image_ctx.is_snap_protected(snap_id, &is_protected);
if (r < 0) {
return r;
}
cls_client::set_protection_status(&op, snap_id,
RBD_PROTECTION_STATUS_PROTECTED);
- librados::AioCompletion *rados_completion = create_callback_completion();
- r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, rados_completion,
+ librados::AioCompletion *rados_completion =
+ this->create_callback_completion();
+ r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, rados_completion,
&op);
assert(r == 0);
rados_completion->release();
} // namespace operation
} // namespace librbd
+template class librbd::operation::SnapshotProtectRequest<librbd::ImageCtx>;
namespace operation {
-class SnapshotProtectRequest : public Request {
+template <typename ImageCtxT = ImageCtx>
+class SnapshotProtectRequest : public Request<ImageCtxT> {
public:
/**
* Snap Protect goes through the following state machine:
STATE_PROTECT_SNAP
};
- SnapshotProtectRequest(ImageCtx &image_ctx, Context *on_finish,
+ SnapshotProtectRequest(ImageCtxT &image_ctx, Context *on_finish,
const std::string &snap_name);
protected:
} // namespace operation
} // namespace librbd
+extern template class librbd::operation::SnapshotProtectRequest<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_PROTECT_REQUEST_H
namespace {
+template <typename I>
std::ostream& operator<<(std::ostream& os,
- const SnapshotRemoveRequest::State& state) {
+ const typename SnapshotRemoveRequest<I>::State& state) {
switch(state) {
- case SnapshotRemoveRequest::STATE_REMOVE_OBJECT_MAP:
+ case SnapshotRemoveRequest<I>::STATE_REMOVE_OBJECT_MAP:
os << "REMOVE_OBJECT_MAP";
break;
- case SnapshotRemoveRequest::STATE_REMOVE_CHILD:
+ case SnapshotRemoveRequest<I>::STATE_REMOVE_CHILD:
os << "REMOVE_CHILD";
break;
- case SnapshotRemoveRequest::STATE_REMOVE_SNAP:
+ case SnapshotRemoveRequest<I>::STATE_REMOVE_SNAP:
os << "REMOVE_SNAP";
break;
- case SnapshotRemoveRequest::STATE_RELEASE_SNAP_ID:
+ case SnapshotRemoveRequest<I>::STATE_RELEASE_SNAP_ID:
os << "RELEASE_SNAP_ID";
break;
default:
} // anonymous namespace
-SnapshotRemoveRequest::SnapshotRemoveRequest(ImageCtx &image_ctx,
- Context *on_finish,
- const std::string &snap_name,
- uint64_t snap_id)
- : Request(image_ctx, on_finish), m_snap_name(snap_name),
+template <typename I>
+SnapshotRemoveRequest<I>::SnapshotRemoveRequest(I &image_ctx,
+ Context *on_finish,
+ const std::string &snap_name,
+ uint64_t snap_id)
+ : Request<I>(image_ctx, on_finish), m_snap_name(snap_name),
m_snap_id(snap_id) {
}
-void SnapshotRemoveRequest::send_op() {
+template <typename I>
+void SnapshotRemoveRequest<I>::send_op() {
send_remove_object_map();
}
-bool SnapshotRemoveRequest::should_complete(int r) {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool SnapshotRemoveRequest<I>::should_complete(int r) {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", "
<< "r=" << r << dendl;
r = filter_state_return_code(r);
return true;
}
- RWLock::RLocker owner_lock(m_image_ctx.owner_lock);
+ RWLock::RLocker owner_lock(image_ctx.owner_lock);
bool finished = false;
switch (m_state) {
case STATE_REMOVE_OBJECT_MAP:
return finished;
}
-void SnapshotRemoveRequest::send_remove_object_map() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotRemoveRequest<I>::send_remove_object_map() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
{
- RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
- RWLock::RLocker object_map_locker(m_image_ctx.object_map_lock);
- if (m_image_ctx.object_map.enabled(m_image_ctx.object_map_lock)) {
- CephContext *cct = m_image_ctx.cct;
+ RWLock::WLocker snap_locker(image_ctx.snap_lock);
+ RWLock::RLocker object_map_locker(image_ctx.object_map_lock);
+ if (image_ctx.object_map.enabled(image_ctx.object_map_lock)) {
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_REMOVE_OBJECT_MAP;
- m_image_ctx.object_map.snapshot_remove(
- m_snap_id, create_callback_context());
+ image_ctx.object_map.snapshot_remove(
+ m_snap_id, this->create_callback_context());
return;
}
}
send_remove_child();
}
-void SnapshotRemoveRequest::send_remove_child() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotRemoveRequest<I>::send_remove_child() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
{
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- RWLock::RLocker parent_locker(m_image_ctx.parent_lock);
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ RWLock::RLocker parent_locker(image_ctx.parent_lock);
parent_spec our_pspec;
- int r = m_image_ctx.get_parent_spec(m_snap_id, &our_pspec);
+ int r = image_ctx.get_parent_spec(m_snap_id, &our_pspec);
if (r < 0) {
lderr(cct) << "failed to retrieve parent spec" << dendl;
- async_complete(r);
+ this->async_complete(r);
return;
}
- if (m_image_ctx.parent_md.spec != our_pspec &&
+ if (image_ctx.parent_md.spec != our_pspec &&
(scan_for_parents(our_pspec) == -ENOENT)) {
// no other references to the parent image
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_REMOVE_CHILD;
librados::ObjectWriteOperation op;
- cls_client::remove_child(&op, our_pspec, m_image_ctx.id);
+ cls_client::remove_child(&op, our_pspec, image_ctx.id);
- librados::AioCompletion *rados_completion = create_callback_completion();
- r = m_image_ctx.md_ctx.aio_operate(RBD_CHILDREN, rados_completion, &op);
+ librados::AioCompletion *rados_completion = this->create_callback_completion();
+ r = image_ctx.md_ctx.aio_operate(RBD_CHILDREN, rados_completion, &op);
assert(r == 0);
rados_completion->release();
return;
send_remove_snap();
}
-void SnapshotRemoveRequest::send_remove_snap() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotRemoveRequest<I>::send_remove_snap() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_REMOVE_SNAP;
librados::ObjectWriteOperation op;
- if (m_image_ctx.old_format) {
+ if (image_ctx.old_format) {
cls_client::old_snapshot_remove(&op, m_snap_name);
} else {
- if (m_image_ctx.image_watcher->is_lock_owner()) {
- m_image_ctx.image_watcher->assert_header_locked(&op);
+ if (image_ctx.image_watcher->is_lock_owner()) {
+ image_ctx.image_watcher->assert_header_locked(&op);
}
cls_client::snapshot_remove(&op, m_snap_id);
}
- librados::AioCompletion *rados_completion = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
- rados_completion, &op);
+ librados::AioCompletion *rados_completion = this->create_callback_completion();
+ int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid,
+ rados_completion, &op);
assert(r == 0);
rados_completion->release();
}
-void SnapshotRemoveRequest::send_release_snap_id() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotRemoveRequest<I>::send_release_snap_id() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << ": "
<< "snap_name=" << m_snap_name << ", "
<< "snap_id=" << m_snap_id << dendl;
m_state = STATE_RELEASE_SNAP_ID;
// TODO add async version of selfmanaged_snap_remove
- m_image_ctx.data_ctx.selfmanaged_snap_remove(m_snap_id);
- async_complete(0);
+ image_ctx.data_ctx.selfmanaged_snap_remove(m_snap_id);
+ this->async_complete(0);
}
-void SnapshotRemoveRequest::remove_snap_context() {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+void SnapshotRemoveRequest<I>::remove_snap_context() {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
- RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
- m_image_ctx.rm_snap(m_snap_name, m_snap_id);
+ RWLock::WLocker snap_locker(image_ctx.snap_lock);
+ image_ctx.rm_snap(m_snap_name, m_snap_id);
}
-int SnapshotRemoveRequest::scan_for_parents(parent_spec &pspec) {
- assert(m_image_ctx.snap_lock.is_locked());
- assert(m_image_ctx.parent_lock.is_locked());
+template <typename I>
+int SnapshotRemoveRequest<I>::scan_for_parents(parent_spec &pspec) {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.snap_lock.is_locked());
+ assert(image_ctx.parent_lock.is_locked());
if (pspec.pool_id != -1) {
map<uint64_t, SnapInfo>::iterator it;
- for (it = m_image_ctx.snap_info.begin();
- it != m_image_ctx.snap_info.end(); ++it) {
+ for (it = image_ctx.snap_info.begin();
+ it != image_ctx.snap_info.end(); ++it) {
// skip our snap id (if checking base image, CEPH_NOSNAP won't match)
if (it->first == m_snap_id) {
continue;
break;
}
}
- if (it == m_image_ctx.snap_info.end()) {
+ if (it == image_ctx.snap_info.end()) {
return -ENOENT;
}
}
} // namespace operation
} // namespace librbd
+
+template class librbd::operation::SnapshotRemoveRequest<librbd::ImageCtx>;
namespace operation {
-class SnapshotRemoveRequest : public Request {
+template <typename ImageCtxT = ImageCtx>
+class SnapshotRemoveRequest : public Request<ImageCtxT> {
public:
/**
* Snap Remove goes through the following state machine:
STATE_RELEASE_SNAP_ID
};
- SnapshotRemoveRequest(ImageCtx &image_ctx, Context *on_finish,
+ SnapshotRemoveRequest(ImageCtxT &image_ctx, Context *on_finish,
const std::string &snap_name, uint64_t snap_id);
protected:
} // namespace operation
} // namespace librbd
+extern template class librbd::operation::SnapshotRemoveRequest<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_REMOVE_REQUEST_H
namespace {
+template <typename I>
std::ostream& operator<<(std::ostream& os,
- const SnapshotRenameRequest::State& state) {
+ const typename SnapshotRenameRequest<I>::State& state) {
switch(state) {
- case SnapshotRenameRequest::STATE_RENAME_SNAP:
+ case SnapshotRenameRequest<I>::STATE_RENAME_SNAP:
os << "RENAME_SNAP";
break;
}
} // anonymous namespace
-SnapshotRenameRequest::SnapshotRenameRequest(ImageCtx &image_ctx,
- Context *on_finish,
- uint64_t snap_id,
- const std::string &snap_name)
- : Request(image_ctx, on_finish), m_snap_id(snap_id), m_snap_name(snap_name) {
+template <typename I>
+SnapshotRenameRequest<I>::SnapshotRenameRequest(I &image_ctx,
+ Context *on_finish,
+ uint64_t snap_id,
+ const std::string &snap_name)
+ : Request<I>(image_ctx, on_finish), m_snap_id(snap_id), m_snap_name(snap_name) {
}
-void SnapshotRenameRequest::send_op() {
+template <typename I>
+void SnapshotRenameRequest<I>::send_op() {
send_rename_snap();
}
-bool SnapshotRenameRequest::should_complete(int r) {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool SnapshotRenameRequest<I>::should_complete(int r) {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", "
<< "r=" << r << dendl;
if (r < 0) {
return true;
}
-void SnapshotRenameRequest::send_rename_snap() {
- assert(m_image_ctx.owner_lock.is_locked());
- RWLock::RLocker md_locker(m_image_ctx.md_lock);
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
+template <typename I>
+void SnapshotRenameRequest<I>::send_rename_snap() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ RWLock::RLocker md_locker(image_ctx.md_lock);
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_RENAME_SNAP;
librados::ObjectWriteOperation op;
- if (m_image_ctx.old_format) {
+ if (image_ctx.old_format) {
cls_client::old_snapshot_rename(&op, m_snap_id, m_snap_name);
} else {
- if (m_image_ctx.image_watcher->is_lock_owner()) {
- m_image_ctx.image_watcher->assert_header_locked(&op);
+ if (image_ctx.image_watcher->is_lock_owner()) {
+ image_ctx.image_watcher->assert_header_locked(&op);
}
cls_client::snapshot_rename(&op, m_snap_id, m_snap_name);
}
- librados::AioCompletion *rados_completion = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
- rados_completion, &op);
+ librados::AioCompletion *rados_completion = this->create_callback_completion();
+ int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid,
+ rados_completion, &op);
assert(r == 0);
rados_completion->release();
}
} // namespace operation
} // namespace librbd
+template class librbd::operation::SnapshotRenameRequest<librbd::ImageCtx>;
namespace operation {
-class SnapshotRenameRequest : public Request {
+template <typename ImageCtxT = ImageCtx>
+class SnapshotRenameRequest : public Request<ImageCtxT> {
public:
/**
* Snap Rename goes through the following state machine:
STATE_RENAME_SNAP
};
- SnapshotRenameRequest(ImageCtx &image_ctx, Context *on_finish,
+ SnapshotRenameRequest(ImageCtxT &image_ctx, Context *on_finish,
uint64_t snap_id, const std::string &snap_name);
virtual journal::Event create_event() const {
} // namespace operation
} // namespace librbd
+extern template class librbd::operation::SnapshotRenameRequest<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_RENAME_REQUEST_H
namespace {
+template <typename I>
std::ostream& operator<<(std::ostream& os,
- const SnapshotRollbackRequest::State& state) {
+ const typename SnapshotRollbackRequest<I>::State& state) {
switch(state) {
- case SnapshotRollbackRequest::STATE_RESIZE_IMAGE:
+ case SnapshotRollbackRequest<I>::STATE_RESIZE_IMAGE:
os << "RESIZE_IMAGE";
break;
- case SnapshotRollbackRequest::STATE_ROLLBACK_OBJECT_MAP:
+ case SnapshotRollbackRequest<I>::STATE_ROLLBACK_OBJECT_MAP:
os << "ROLLBACK_OBJECT_MAP";
break;
- case SnapshotRollbackRequest::STATE_ROLLBACK_OBJECTS:
+ case SnapshotRollbackRequest<I>::STATE_ROLLBACK_OBJECTS:
os << "ROLLBACK_OBJECTS";
break;
- case SnapshotRollbackRequest::STATE_INVALIDATE_CACHE:
+ case SnapshotRollbackRequest<I>::STATE_INVALIDATE_CACHE:
os << "INVALIDATE_CACHE";
break;
default:
return os;
}
+template <typename I>
class C_RollbackObject : public C_AsyncObjectThrottle<> {
public:
- C_RollbackObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx,
+ C_RollbackObject(AsyncObjectThrottle<> &throttle, I *image_ctx,
uint64_t snap_id, uint64_t object_num)
: C_AsyncObjectThrottle(throttle, *image_ctx), m_snap_id(snap_id),
m_object_num(object_num) {
}
virtual int send() {
- CephContext *cct = m_image_ctx.cct;
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 20) << "C_RollbackObject: " << __func__ << ": object_num="
<< m_object_num << dendl;
- std::string oid = m_image_ctx.get_object_name(m_object_num);
+ std::string oid = image_ctx.get_object_name(m_object_num);
librados::AioCompletion *rados_completion =
librados::Rados::aio_create_completion(this, NULL, rados_ctx_cb);
librados::ObjectWriteOperation op;
op.selfmanaged_snap_rollback(m_snap_id);
- m_image_ctx.data_ctx.aio_operate(oid, rados_completion, &op);
+ image_ctx.data_ctx.aio_operate(oid, rados_completion, &op);
rados_completion->release();
return 0;
}
} // anonymous namespace
-SnapshotRollbackRequest::SnapshotRollbackRequest(ImageCtx &image_ctx,
- Context *on_finish,
- const std::string &snap_name,
- uint64_t snap_id,
- uint64_t snap_size,
- ProgressContext &prog_ctx)
- : Request(image_ctx, on_finish), m_snap_name(snap_name), m_snap_id(snap_id),
- m_snap_size(snap_size), m_prog_ctx(prog_ctx) {
+template <typename I>
+SnapshotRollbackRequest<I>::SnapshotRollbackRequest(I &image_ctx,
+ Context *on_finish,
+ const std::string &snap_name,
+ uint64_t snap_id,
+ uint64_t snap_size,
+ ProgressContext &prog_ctx)
+ : Request<I>(image_ctx, on_finish), m_snap_name(snap_name),
+ m_snap_id(snap_id), m_snap_size(snap_size), m_prog_ctx(prog_ctx) {
}
-void SnapshotRollbackRequest::send_op() {
+template <typename I>
+void SnapshotRollbackRequest<I>::send_op() {
send_resize_image();
}
-bool SnapshotRollbackRequest::should_complete(int r) {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool SnapshotRollbackRequest<I>::should_complete(int r) {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", "
<< "r=" << r << dendl;
if (r < 0) {
return true;
}
- RWLock::RLocker owner_lock(m_image_ctx.owner_lock);
+ RWLock::RLocker owner_lock(image_ctx.owner_lock);
bool finished = false;
switch (m_state) {
case STATE_RESIZE_IMAGE:
return finished;
}
-void SnapshotRollbackRequest::send_resize_image() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotRollbackRequest<I>::send_resize_image() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
uint64_t current_size;
{
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- current_size = m_image_ctx.get_image_size(CEPH_NOSNAP);
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ current_size = image_ctx.get_image_size(CEPH_NOSNAP);
}
if (current_size == m_snap_size) {
return;
}
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_RESIZE_IMAGE;
- ResizeRequest *req = new ResizeRequest(m_image_ctx, create_callback_context(),
- m_snap_size, m_no_op_prog_ctx);
+ ResizeRequest<I> *req = new ResizeRequest<I>(image_ctx,
+ this->create_callback_context(),
+ m_snap_size, m_no_op_prog_ctx);
req->send();
}
-void SnapshotRollbackRequest::send_rollback_object_map() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotRollbackRequest<I>::send_rollback_object_map() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
{
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- RWLock::WLocker object_map_lock(m_image_ctx.object_map_lock);
- if (m_image_ctx.object_map.enabled(m_image_ctx.object_map_lock)) {
- CephContext *cct = m_image_ctx.cct;
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ RWLock::WLocker object_map_lock(image_ctx.object_map_lock);
+ if (image_ctx.object_map.enabled(image_ctx.object_map_lock)) {
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_ROLLBACK_OBJECT_MAP;
- m_image_ctx.object_map.rollback(m_snap_id, create_callback_context());
+ image_ctx.object_map.rollback(m_snap_id, this->create_callback_context());
return;
}
}
send_rollback_objects();
}
-void SnapshotRollbackRequest::send_rollback_objects() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotRollbackRequest<I>::send_rollback_objects() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_ROLLBACK_OBJECTS;
uint64_t num_objects;
{
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- num_objects = Striper::get_num_objects(m_image_ctx.layout,
- m_image_ctx.get_current_size());
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ num_objects = Striper::get_num_objects(image_ctx.layout,
+ image_ctx.get_current_size());
}
- Context *ctx = create_callback_context();
- AsyncObjectThrottle<>::ContextFactory context_factory(
- boost::lambda::bind(boost::lambda::new_ptr<C_RollbackObject>(),
- boost::lambda::_1, &m_image_ctx, m_snap_id, boost::lambda::_2));
- AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>(
- this, m_image_ctx, context_factory, ctx, &m_prog_ctx, 0, num_objects);
- throttle->start_ops(m_image_ctx.concurrent_management_ops);
+ Context *ctx = this->create_callback_context();
+ typename AsyncObjectThrottle<I>::ContextFactory context_factory(
+ boost::lambda::bind(boost::lambda::new_ptr<C_RollbackObject<I> >(),
+ boost::lambda::_1, &image_ctx, m_snap_id, boost::lambda::_2));
+ AsyncObjectThrottle<I> *throttle = new AsyncObjectThrottle<>(
+ this, image_ctx, context_factory, ctx, &m_prog_ctx, 0, num_objects);
+ throttle->start_ops(image_ctx.concurrent_management_ops);
}
-bool SnapshotRollbackRequest::send_invalidate_cache() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+bool SnapshotRollbackRequest<I>::send_invalidate_cache() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- if (m_image_ctx.object_cacher == NULL) {
+ if (image_ctx.object_cacher == NULL) {
return true;
}
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_INVALIDATE_CACHE;
- m_image_ctx.invalidate_cache(create_callback_context());
+ image_ctx.invalidate_cache(this->create_callback_context());
return false;
}
} // namespace operation
} // namespace librbd
+
+template class librbd::operation::SnapshotRollbackRequest<librbd::ImageCtx>;
namespace operation {
-class SnapshotRollbackRequest : public Request {
+template <typename ImageCtxT = ImageCtx>
+class SnapshotRollbackRequest : public Request<ImageCtxT> {
public:
/**
* Snap Rollback goes through the following state machine:
STATE_INVALIDATE_CACHE
};
- SnapshotRollbackRequest(ImageCtx &image_ctx, Context *on_finish,
+ SnapshotRollbackRequest(ImageCtxT &image_ctx, Context *on_finish,
const std::string &snap_name, uint64_t snap_id,
uint64_t snap_size, ProgressContext &prog_ctx);
} // namespace operation
} // namespace librbd
+extern template class librbd::operation::SnapshotRollbackRequest<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_ROLLBACK_REQUEST_H
typedef std::pair<int64_t, std::string> Pool;
typedef std::vector<Pool> Pools;
+template <typename I>
std::ostream& operator<<(std::ostream& os,
- const SnapshotUnprotectRequest::State& state) {
+ const typename SnapshotUnprotectRequest<I>::State& state) {
switch(state) {
- case SnapshotUnprotectRequest::STATE_UNPROTECT_SNAP_START:
+ case SnapshotUnprotectRequest<I>::STATE_UNPROTECT_SNAP_START:
os << "UNPROTECT_SNAP_START";
break;
- case SnapshotUnprotectRequest::STATE_SCAN_POOL_CHILDREN:
+ case SnapshotUnprotectRequest<I>::STATE_SCAN_POOL_CHILDREN:
os << "SCAN_POOL_CHILDREN";
break;
- case SnapshotUnprotectRequest::STATE_UNPROTECT_SNAP_FINISH:
+ case SnapshotUnprotectRequest<I>::STATE_UNPROTECT_SNAP_FINISH:
os << "UNPROTECT_SNAP_FINISH";
break;
- case SnapshotUnprotectRequest::STATE_UNPROTECT_SNAP_ROLLBACK:
+ case SnapshotUnprotectRequest<I>::STATE_UNPROTECT_SNAP_ROLLBACK:
os << "UNPROTECT_SNAP_ROLLBACK";
break;
default:
return os;
}
-class C_ScanPoolChildren : public C_AsyncObjectThrottle<> {
+template <typename I>
+class C_ScanPoolChildren : public C_AsyncObjectThrottle<I> {
public:
- C_ScanPoolChildren(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx,
+ C_ScanPoolChildren(AsyncObjectThrottle<I> &throttle, I *image_ctx,
const parent_spec &pspec, const Pools &pools,
size_t pool_idx)
- : C_AsyncObjectThrottle(throttle, *image_ctx), m_pspec(pspec),
+ : C_AsyncObjectThrottle<I>(throttle, *image_ctx), m_pspec(pspec),
m_pool(pools[pool_idx]) {
}
virtual int send() {
- assert(m_image_ctx.owner_lock.is_locked());
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 10) << this << " scanning pool '" << m_pool.second << "'"
<< dendl;
- librados::Rados rados(m_image_ctx.md_ctx);
+ librados::Rados rados(image_ctx.md_ctx);
int64_t base_tier;
int r = rados.pool_get_base_tier(m_pool.first, &base_tier);
if (r == -ENOENT) {
protected:
virtual void finish(int r) {
- CephContext *cct = m_image_ctx.cct;
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 10) << this << " retrieved children: r=" << r << dendl;
if (r == -ENOENT) {
<< "in pool '" << m_pool.second << "'" << dendl;
r = -EBUSY;
}
- C_AsyncObjectThrottle::finish(r);
+ C_AsyncObjectThrottle<I>::finish(r);
}
private:
} // anonymous namespace
-SnapshotUnprotectRequest::SnapshotUnprotectRequest(ImageCtx &image_ctx,
- Context *on_finish,
- const std::string &snap_name)
- : Request(image_ctx, on_finish), m_snap_name(snap_name), m_ret_val(0),
+template <typename I>
+SnapshotUnprotectRequest<I>::SnapshotUnprotectRequest(I &image_ctx,
+ Context *on_finish,
+ const std::string &snap_name)
+ : Request<I>(image_ctx, on_finish), m_snap_name(snap_name), m_ret_val(0),
m_snap_id(CEPH_NOSNAP) {
}
-void SnapshotUnprotectRequest::send_op() {
+template <typename I>
+void SnapshotUnprotectRequest<I>::send_op() {
send_unprotect_snap_start();
}
-bool SnapshotUnprotectRequest::should_complete(int r) {
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool SnapshotUnprotectRequest<I>::should_complete(int r) {
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", "
<< "r=" << r << dendl;
if (r < 0) {
return should_complete_error();
}
- RWLock::RLocker owner_lock(m_image_ctx.owner_lock);
+ RWLock::RLocker owner_lock(image_ctx.owner_lock);
bool finished = false;
switch (m_state) {
case STATE_UNPROTECT_SNAP_START:
return finished;
}
-bool SnapshotUnprotectRequest::should_complete_error() {
- RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+bool SnapshotUnprotectRequest<I>::should_complete_error() {
+ I &image_ctx = this->m_image_ctx;
+ RWLock::RLocker owner_locker(image_ctx.owner_lock);
+ CephContext *cct = image_ctx.cct;
lderr(cct) << this << " " << __func__ << ": "
<< "ret_val=" << m_ret_val << dendl;
return finished;
}
-void SnapshotUnprotectRequest::send_unprotect_snap_start() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotUnprotectRequest<I>::send_unprotect_snap_start() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_UNPROTECT_SNAP_START;
int r = verify_and_send_unprotect_snap_start();
if (r < 0) {
- async_complete(r);
+ this->async_complete(r);
return;
}
}
-void SnapshotUnprotectRequest::send_scan_pool_children() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotUnprotectRequest<I>::send_scan_pool_children() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_SCAN_POOL_CHILDREN;
// search all pools for children depending on this snapshot
// TODO add async version of wait_for_latest_osdmap
- librados::Rados rados(m_image_ctx.md_ctx);
+ librados::Rados rados(image_ctx.md_ctx);
rados.wait_for_latest_osdmap();
// protect against pools being renamed/deleted
std::list<Pool> pool_list;
rados.pool_list2(pool_list);
- parent_spec pspec(m_image_ctx.md_ctx.get_id(), m_image_ctx.id, m_snap_id);
+ parent_spec pspec(image_ctx.md_ctx.get_id(), image_ctx.id, m_snap_id);
Pools pools(pool_list.begin(), pool_list.end());
- Context *ctx = create_callback_context();
- AsyncObjectThrottle<>::ContextFactory context_factory(
- boost::lambda::bind(boost::lambda::new_ptr<C_ScanPoolChildren>(),
- boost::lambda::_1, &m_image_ctx, pspec, pools, boost::lambda::_2));
- AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>(
- this, m_image_ctx, context_factory, ctx, NULL, 0,
- pools.size());
- throttle->start_ops(m_image_ctx.concurrent_management_ops);
+ Context *ctx = this->create_callback_context();
+ typename AsyncObjectThrottle<I>::ContextFactory context_factory(
+ boost::lambda::bind(boost::lambda::new_ptr<C_ScanPoolChildren<I> >(),
+ boost::lambda::_1, &image_ctx, pspec, pools, boost::lambda::_2));
+ AsyncObjectThrottle<I> *throttle = new AsyncObjectThrottle<I>(
+ this, image_ctx, context_factory, ctx, NULL, 0, pools.size());
+ throttle->start_ops(image_ctx.concurrent_management_ops);
}
-void SnapshotUnprotectRequest::send_unprotect_snap_finish() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotUnprotectRequest<I>::send_unprotect_snap_finish() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_UNPROTECT_SNAP_FINISH;
cls_client::set_protection_status(&op, m_snap_id,
RBD_PROTECTION_STATUS_UNPROTECTED);
- librados::AioCompletion *comp = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, comp, &op);
+ librados::AioCompletion *comp = this->create_callback_completion();
+ int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, comp, &op);
assert(r == 0);
comp->release();
}
-void SnapshotUnprotectRequest::send_unprotect_snap_rollback() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void SnapshotUnprotectRequest<I>::send_unprotect_snap_rollback() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
m_state = STATE_UNPROTECT_SNAP_ROLLBACK;
cls_client::set_protection_status(&op, m_snap_id,
RBD_PROTECTION_STATUS_PROTECTED);
- librados::AioCompletion *comp = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, comp, &op);
+ librados::AioCompletion *comp = this->create_callback_completion();
+ int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, comp, &op);
assert(r == 0);
comp->release();
}
-int SnapshotUnprotectRequest::verify_and_send_unprotect_snap_start() {
- RWLock::RLocker md_locker(m_image_ctx.md_lock);
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
+template <typename I>
+int SnapshotUnprotectRequest<I>::verify_and_send_unprotect_snap_start() {
+ I &image_ctx = this->m_image_ctx;
+ RWLock::RLocker md_locker(image_ctx.md_lock);
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
- CephContext *cct = m_image_ctx.cct;
- if ((m_image_ctx.features & RBD_FEATURE_LAYERING) == 0) {
+ CephContext *cct = image_ctx.cct;
+ if ((image_ctx.features & RBD_FEATURE_LAYERING) == 0) {
lderr(cct) << "image must support layering" << dendl;
return -ENOSYS;
}
- m_snap_id = m_image_ctx.get_snap_id(m_snap_name);
+ m_snap_id = image_ctx.get_snap_id(m_snap_name);
if (m_snap_id == CEPH_NOSNAP) {
return -ENOENT;
}
bool is_unprotected;
- int r = m_image_ctx.is_snap_unprotected(m_snap_id, &is_unprotected);
+ int r = image_ctx.is_snap_unprotected(m_snap_id, &is_unprotected);
if (r < 0) {
return r;
}
cls_client::set_protection_status(&op, m_snap_id,
RBD_PROTECTION_STATUS_UNPROTECTING);
- librados::AioCompletion *comp = create_callback_completion();
- r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, comp, &op);
+ librados::AioCompletion *comp = this->create_callback_completion();
+ r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, comp, &op);
assert(r == 0);
comp->release();
} // namespace operation
} // namespace librbd
+template class librbd::operation::SnapshotUnprotectRequest<librbd::ImageCtx>;
namespace operation {
-class SnapshotUnprotectRequest : public Request {
+template <typename ImageCtxT = ImageCtx>
+class SnapshotUnprotectRequest : public Request<ImageCtxT> {
public:
/**
* Snap Unprotect goes through the following state machine:
STATE_UNPROTECT_SNAP_ROLLBACK
};
- SnapshotUnprotectRequest(ImageCtx &image_ctx, Context *on_finish,
+ SnapshotUnprotectRequest(ImageCtxT &image_ctx, Context *on_finish,
const std::string &snap_name);
protected:
} // namespace operation
} // namespace librbd
+extern template class librbd::operation::SnapshotUnprotectRequest<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_UNPROTECT_REQUEST_H
namespace librbd {
namespace operation {
-class C_CopyupObject : public C_AsyncObjectThrottle<> {
+template <typename I>
+class C_CopyupObject : public C_AsyncObjectThrottle<I> {
public:
- C_CopyupObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx,
+ C_CopyupObject(AsyncObjectThrottle<I> &throttle, I *image_ctx,
::SnapContext snapc, uint64_t object_no)
- : C_AsyncObjectThrottle(throttle, *image_ctx), m_snapc(snapc),
+ : C_AsyncObjectThrottle<I>(throttle, *image_ctx), m_snapc(snapc),
m_object_no(object_no)
{
}
virtual int send() {
- assert(m_image_ctx.owner_lock.is_locked());
- assert(!m_image_ctx.image_watcher->is_lock_supported() ||
- m_image_ctx.image_watcher->is_lock_owner());
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ assert(!image_ctx.image_watcher->is_lock_supported() ||
+ image_ctx.image_watcher->is_lock_owner());
- string oid = m_image_ctx.get_object_name(m_object_no);
- ldout(m_image_ctx.cct, 10) << "removing (with copyup) " << oid << dendl;
+ string oid = image_ctx.get_object_name(m_object_no);
+ ldout(image_ctx.cct, 10) << "removing (with copyup) " << oid << dendl;
- AioObjectRequest *req = new AioObjectTrim(&m_image_ctx, oid, m_object_no,
+ AioObjectRequest *req = new AioObjectTrim(&image_ctx, oid, m_object_no,
m_snapc, this);
req->send();
return 0;
uint64_t m_object_no;
};
-class C_RemoveObject : public C_AsyncObjectThrottle<> {
+template <typename I>
+class C_RemoveObject : public C_AsyncObjectThrottle<I> {
public:
- C_RemoveObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx,
+ C_RemoveObject(AsyncObjectThrottle<I> &throttle, ImageCtx *image_ctx,
uint64_t object_no)
- : C_AsyncObjectThrottle(throttle, *image_ctx), m_object_no(object_no)
+ : C_AsyncObjectThrottle<I>(throttle, *image_ctx), m_object_no(object_no)
{
}
virtual int send() {
- assert(m_image_ctx.owner_lock.is_locked());
- assert(!m_image_ctx.image_watcher->is_lock_supported() ||
- m_image_ctx.image_watcher->is_lock_owner());
- if (!m_image_ctx.object_map.object_may_exist(m_object_no)) {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ assert(!image_ctx.image_watcher->is_lock_supported() ||
+ image_ctx.image_watcher->is_lock_owner());
+ if (!image_ctx.object_map.object_may_exist(m_object_no)) {
return 1;
}
- string oid = m_image_ctx.get_object_name(m_object_no);
- ldout(m_image_ctx.cct, 10) << "removing " << oid << dendl;
+ string oid = image_ctx.get_object_name(m_object_no);
+ ldout(image_ctx.cct, 10) << "removing " << oid << dendl;
librados::AioCompletion *rados_completion =
librados::Rados::aio_create_completion(this, NULL, rados_ctx_cb);
- int r = m_image_ctx.data_ctx.aio_remove(oid, rados_completion);
+ int r = image_ctx.data_ctx.aio_remove(oid, rados_completion);
assert(r == 0);
rados_completion->release();
return 0;
uint64_t m_object_no;
};
-TrimRequest::TrimRequest(ImageCtx &image_ctx, Context *on_finish,
- uint64_t original_size, uint64_t new_size,
- ProgressContext &prog_ctx)
- : AsyncRequest(image_ctx, on_finish), m_new_size(new_size),
+template <typename I>
+TrimRequest<I>::TrimRequest(I &image_ctx, Context *on_finish,
+ uint64_t original_size, uint64_t new_size,
+ ProgressContext &prog_ctx)
+ : AsyncRequest<I>(image_ctx, on_finish), m_new_size(new_size),
m_prog_ctx(prog_ctx)
{
- uint64_t period = m_image_ctx.get_stripe_period();
+ uint64_t period = image_ctx.get_stripe_period();
uint64_t new_num_periods = ((m_new_size + period - 1) / period);
m_delete_off = MIN(new_num_periods * period, original_size);
// first object we can delete free and clear
- m_delete_start = new_num_periods * m_image_ctx.get_stripe_count();
- m_num_objects = Striper::get_num_objects(m_image_ctx.layout, original_size);
+ m_delete_start = new_num_periods * image_ctx.get_stripe_count();
+ m_num_objects = Striper::get_num_objects(image_ctx.layout, original_size);
- CephContext *cct = m_image_ctx.cct;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 10) << this << " trim image " << original_size << " -> "
<< m_new_size << " periods " << new_num_periods
<< " discard to offset " << m_delete_off
<< " to " << m_num_objects << dendl;
}
-
-bool TrimRequest::should_complete(int r)
+template <typename I>
+bool TrimRequest<I>::should_complete(int r)
{
- CephContext *cct = m_image_ctx.cct;
+ I &image_ctx = this->m_image_ctx;
+ CephContext *cct = image_ctx.cct;
ldout(cct, 5) << this << " should_complete: r=" << r << dendl;
if (r < 0) {
lderr(cct) << "trim encountered an error: " << cpp_strerror(r) << dendl;
return true;
}
- RWLock::RLocker owner_lock(m_image_ctx.owner_lock);
+ RWLock::RLocker owner_lock(image_ctx.owner_lock);
switch (m_state) {
case STATE_COPYUP_OBJECTS:
ldout(cct, 5) << " COPYUP_OBJECTS" << dendl;
return false;
}
-void TrimRequest::send() {
+template <typename I>
+void TrimRequest<I>::send() {
send_copyup_objects();
}
-void TrimRequest::send_copyup_objects() {
- assert(m_image_ctx.owner_lock.is_locked());
- assert(!m_image_ctx.image_watcher->is_lock_supported() ||
- m_image_ctx.image_watcher->is_lock_owner());
+template <typename I>
+void TrimRequest<I>::send_copyup_objects() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ assert(!image_ctx.image_watcher->is_lock_supported() ||
+ image_ctx.image_watcher->is_lock_owner());
if (m_delete_start >= m_num_objects) {
send_clean_boundary();
bool has_snapshots;
uint64_t parent_overlap;
{
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- RWLock::RLocker parent_locker(m_image_ctx.parent_lock);
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ RWLock::RLocker parent_locker(image_ctx.parent_lock);
- snapc = m_image_ctx.snapc;
- has_snapshots = !m_image_ctx.snaps.empty();
- int r = m_image_ctx.get_parent_overlap(m_image_ctx.get_copyup_snap_id(),
+ snapc = image_ctx.snapc;
+ has_snapshots = !image_ctx.snaps.empty();
+ int r = image_ctx.get_parent_overlap(image_ctx.get_copyup_snap_id(),
&parent_overlap);
assert(r == 0);
}
// copyup is only required for portion of image that overlaps parent
- uint64_t copyup_end = Striper::get_num_objects(m_image_ctx.layout,
+ uint64_t copyup_end = Striper::get_num_objects(image_ctx.layout,
parent_overlap);
// TODO: protect against concurrent shrink and snap create?
if (copyup_end <= m_delete_start || !has_snapshots) {
uint64_t copyup_start = m_delete_start;
m_delete_start = copyup_end;
- ldout(m_image_ctx.cct, 5) << this << " send_copyup_objects: "
+ ldout(image_ctx.cct, 5) << this << " send_copyup_objects: "
<< " start object=" << copyup_start << ", "
<< " end object=" << copyup_end << dendl;
m_state = STATE_COPYUP_OBJECTS;
- Context *ctx = create_callback_context();
- AsyncObjectThrottle<>::ContextFactory context_factory(
- boost::lambda::bind(boost::lambda::new_ptr<C_CopyupObject>(),
- boost::lambda::_1, &m_image_ctx, snapc, boost::lambda::_2));
- AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>(
- this, m_image_ctx, context_factory, ctx, &m_prog_ctx, copyup_start,
+ Context *ctx = this->create_callback_context();
+ typename AsyncObjectThrottle<I>::ContextFactory context_factory(
+ boost::lambda::bind(boost::lambda::new_ptr<C_CopyupObject<I> >(),
+ boost::lambda::_1, &image_ctx, snapc, boost::lambda::_2));
+ AsyncObjectThrottle<I> *throttle = new AsyncObjectThrottle<I>(
+ this, image_ctx, context_factory, ctx, &m_prog_ctx, copyup_start,
copyup_end);
- throttle->start_ops(m_image_ctx.concurrent_management_ops);
+ throttle->start_ops(image_ctx.concurrent_management_ops);
}
-void TrimRequest::send_remove_objects() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void TrimRequest<I>::send_remove_objects() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
- ldout(m_image_ctx.cct, 5) << this << " send_remove_objects: "
+ ldout(image_ctx.cct, 5) << this << " send_remove_objects: "
<< " delete_start=" << m_delete_start
<< " num_objects=" << m_num_objects << dendl;
m_state = STATE_REMOVE_OBJECTS;
- Context *ctx = create_callback_context();
- AsyncObjectThrottle<>::ContextFactory context_factory(
- boost::lambda::bind(boost::lambda::new_ptr<C_RemoveObject>(),
- boost::lambda::_1, &m_image_ctx, boost::lambda::_2));
- AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>(
- this, m_image_ctx, context_factory, ctx, &m_prog_ctx, m_delete_start,
+ Context *ctx = this->create_callback_context();
+ typename AsyncObjectThrottle<I>::ContextFactory context_factory(
+ boost::lambda::bind(boost::lambda::new_ptr<C_RemoveObject<I> >(),
+ boost::lambda::_1, &image_ctx, boost::lambda::_2));
+ AsyncObjectThrottle<I> *throttle = new AsyncObjectThrottle<I>(
+ this, image_ctx, context_factory, ctx, &m_prog_ctx, m_delete_start,
m_num_objects);
- throttle->start_ops(m_image_ctx.concurrent_management_ops);
+ throttle->start_ops(image_ctx.concurrent_management_ops);
}
-void TrimRequest::send_pre_remove() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void TrimRequest<I>::send_pre_remove() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
if (m_delete_start >= m_num_objects) {
send_clean_boundary();
return;
bool remove_objects = false;
{
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- if (!m_image_ctx.object_map.enabled()) {
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ if (!image_ctx.object_map.enabled()) {
remove_objects = true;
} else {
- ldout(m_image_ctx.cct, 5) << this << " send_pre_remove: "
+ ldout(image_ctx.cct, 5) << this << " send_pre_remove: "
<< " delete_start=" << m_delete_start
<< " num_objects=" << m_num_objects << dendl;
m_state = STATE_PRE_REMOVE;
- assert(m_image_ctx.image_watcher->is_lock_owner());
+ assert(image_ctx.image_watcher->is_lock_owner());
// flag the objects as pending deletion
- Context *ctx = create_callback_context();
- RWLock::WLocker object_map_locker(m_image_ctx.object_map_lock);
- if (!m_image_ctx.object_map.aio_update(m_delete_start, m_num_objects,
+ Context *ctx = this->create_callback_context();
+ RWLock::WLocker object_map_locker(image_ctx.object_map_lock);
+ if (!image_ctx.object_map.aio_update(m_delete_start, m_num_objects,
OBJECT_PENDING, OBJECT_EXISTS,
ctx)) {
delete ctx;
}
}
-void TrimRequest::send_post_remove() {
- assert(m_image_ctx.owner_lock.is_locked());
+template <typename I>
+void TrimRequest<I>::send_post_remove() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
bool clean_boundary = false;
{
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- if (!m_image_ctx.object_map.enabled()) {
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ if (!image_ctx.object_map.enabled()) {
clean_boundary = true;
} else {
- ldout(m_image_ctx.cct, 5) << this << " send_post_remove: "
+ ldout(image_ctx.cct, 5) << this << " send_post_remove: "
<< " delete_start=" << m_delete_start
<< " num_objects=" << m_num_objects << dendl;
m_state = STATE_POST_REMOVE;
- assert(m_image_ctx.image_watcher->is_lock_owner());
+ assert(image_ctx.image_watcher->is_lock_owner());
// flag the pending objects as removed
- Context *ctx = create_callback_context();
- RWLock::WLocker object_map_locker(m_image_ctx.object_map_lock);
- if (!m_image_ctx.object_map.aio_update(m_delete_start, m_num_objects,
+ Context *ctx = this->create_callback_context();
+ RWLock::WLocker object_map_locker(image_ctx.object_map_lock);
+ if (!image_ctx.object_map.aio_update(m_delete_start, m_num_objects,
OBJECT_NONEXISTENT,
OBJECT_PENDING, ctx)) {
delete ctx;
}
}
-void TrimRequest::send_clean_boundary() {
- assert(m_image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
+template <typename I>
+void TrimRequest<I>::send_clean_boundary() {
+ I &image_ctx = this->m_image_ctx;
+ assert(image_ctx.owner_lock.is_locked());
+ CephContext *cct = image_ctx.cct;
if (m_delete_off <= m_new_size) {
send_finish(0);
return;
}
// should have been canceled prior to releasing lock
- assert(!m_image_ctx.image_watcher->is_lock_supported() ||
- m_image_ctx.image_watcher->is_lock_owner());
+ assert(!image_ctx.image_watcher->is_lock_supported() ||
+ image_ctx.image_watcher->is_lock_owner());
uint64_t delete_len = m_delete_off - m_new_size;
- ldout(m_image_ctx.cct, 5) << this << " send_clean_boundary: "
+ ldout(image_ctx.cct, 5) << this << " send_clean_boundary: "
<< " delete_off=" << m_delete_off
<< " length=" << delete_len << dendl;
m_state = STATE_CLEAN_BOUNDARY;
::SnapContext snapc;
{
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- snapc = m_image_ctx.snapc;
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ snapc = image_ctx.snapc;
}
// discard the weird boundary
std::vector<ObjectExtent> extents;
- Striper::file_to_extents(cct, m_image_ctx.format_string,
- &m_image_ctx.layout, m_new_size, delete_len, 0,
+ Striper::file_to_extents(cct, image_ctx.format_string,
+ &image_ctx.layout, m_new_size, delete_len, 0,
extents);
ContextCompletion *completion =
- new ContextCompletion(create_async_callback_context(), true);
+ new ContextCompletion(this->create_async_callback_context(), true);
for (vector<ObjectExtent>::iterator p = extents.begin();
p != extents.end(); ++p) {
ldout(cct, 20) << " ex " << *p << dendl;
AioObjectRequest *req;
if (p->offset == 0) {
- req = new AioObjectTrim(&m_image_ctx, p->oid.name, p->objectno, snapc,
+ req = new AioObjectTrim(&image_ctx, p->oid.name, p->objectno, snapc,
req_comp);
} else {
- req = new AioObjectTruncate(&m_image_ctx, p->oid.name, p->objectno,
+ req = new AioObjectTruncate(&image_ctx, p->oid.name, p->objectno,
p->offset, snapc, req_comp);
}
req->send();
completion->finish_adding_requests();
}
-void TrimRequest::send_finish(int r) {
+template <typename I>
+void TrimRequest<I>::send_finish(int r) {
m_state = STATE_FINISHED;
- async_complete(r);
+ this->async_complete(r);
}
} // namespace operation
} // namespace librbd
+
+template class librbd::operation::TrimRequest<librbd::ImageCtx>;
namespace operation {
-class TrimRequest : public AsyncRequest<>
+template <typename ImageCtxT = ImageCtx>
+class TrimRequest : public AsyncRequest<ImageCtxT>
{
public:
- TrimRequest(ImageCtx &image_ctx, Context *on_finish,
- uint64_t original_size, uint64_t new_size,
- ProgressContext &prog_ctx);
+ TrimRequest(ImageCtxT &image_ctx, Context *on_finish,
+ uint64_t original_size, uint64_t new_size,
+ ProgressContext &prog_ctx);
virtual void send();
} // namespace operation
} // namespace librbd
+extern template class librbd::operation::TrimRequest<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_OPERATION_TRIM_REQUEST_H