state = OBJECT_EXISTS_CLEAN;
}
+ RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
RWLock::RLocker object_map_locker(m_image_ctx.object_map_lock);
m_image_ctx.object_map.aio_update(snap_id, m_object_no, m_object_no + 1,
state, boost::optional<uint8_t>(), this);
#include "osdc/ObjectCacher.h"
#include "cls/rbd/cls_rbd_client.h"
+#include "librbd/AsyncRequest.h"
#include "librbd/LibrbdWriteback.h"
#include "librbd/ObjectMap.h"
#include "librbd/SnapInfo.h"
namespace librbd {
+ struct ImageCtx;
class AioImageRequestWQ;
class AsyncOperation;
- template <typename ImageCtxT> class AsyncRequest;
class CopyupRequest;
class LibrbdAdminSocketHook;
class ImageWatcher;
librbd/LibrbdAdminSocketHook.cc \
librbd/LibrbdWriteback.cc \
librbd/ObjectMap.cc \
+ librbd/object_map/Request.cc \
+ librbd/object_map/ResizeRequest.cc \
+ librbd/object_map/UpdateRequest.cc \
librbd/operation/FlattenRequest.cc \
librbd/operation/RebuildObjectMapRequest.cc \
librbd/operation/Request.cc \
librbd/SnapInfo.h \
librbd/TaskFinisher.h \
librbd/WatchNotifyTypes.h \
+ librbd/object_map/Request.h \
+ librbd/object_map/ResizeRequest.h \
+ librbd/object_map/UpdateRequest.h \
librbd/operation/FlattenRequest.h \
librbd/operation/RebuildObjectMapRequest.h \
librbd/operation/Request.h \
#include "librbd/ImageCtx.h"
#include "librbd/ImageWatcher.h"
#include "librbd/internal.h"
+#include "librbd/object_map/ResizeRequest.h"
+#include "librbd/object_map/UpdateRequest.h"
#include "common/dout.h"
#include "common/errno.h"
#include "include/stringify.h"
r = m_image_ctx.md_ctx.operate(oid, &op);
if (r == 0) {
m_object_map.clear();
- resize(num_objs, OBJECT_NONEXISTENT);
+ object_map::ResizeRequest::resize(&m_object_map, num_objs,
+ OBJECT_NONEXISTENT);
}
}
if (r < 0) {
r = m_image_ctx.md_ctx.operate(oid, &op);
if (r == 0) {
- resize(num_objs, OBJECT_NONEXISTENT);
+ object_map::ResizeRequest::resize(&m_object_map, num_objs,
+ OBJECT_NONEXISTENT);
}
} else if (m_object_map.size() > num_objs) {
// resize op might have been interrupted
assert(!m_image_ctx.image_watcher->is_lock_supported() ||
m_image_ctx.image_watcher->is_lock_owner());
- ResizeRequest *req = new ResizeRequest(
- m_image_ctx, m_snap_id, new_size, default_object_state, on_finish);
+ object_map::ResizeRequest *req = new object_map::ResizeRequest(
+ m_image_ctx, &m_object_map, m_snap_id, new_size, default_object_state,
+ on_finish);
req->send();
}
uint64_t end_object_no, uint8_t new_state,
const boost::optional<uint8_t> ¤t_state,
Context *on_finish) {
- UpdateRequest *req = new UpdateRequest(m_image_ctx, snap_id,
- start_object_no, end_object_no,
- new_state, current_state,
- on_finish);
+ object_map::UpdateRequest *req = new object_map::UpdateRequest(
+ m_image_ctx, &m_object_map, snap_id, start_object_no, end_object_no,
+ new_state, current_state, on_finish);
req->send();
}
}
}
-void ObjectMap::resize(uint64_t num_objs, uint8_t defualt_state) {
- size_t orig_object_map_size = m_object_map.size();
- m_object_map.resize(num_objs);
- for (uint64_t i = orig_object_map_size;
- i < m_object_map.size(); ++i) {
- m_object_map[i] = defualt_state;
- }
-}
-
-bool ObjectMap::Request::should_complete(int r) {
- CephContext *cct = m_image_ctx.cct;
- ldout(cct, 20) << &m_image_ctx << " should_complete: r=" << r << dendl;
-
- switch (m_state)
- {
- case STATE_REQUEST:
- if (r == -EBUSY) {
- lderr(cct) << "object map lock not owned by client" << dendl;
- return invalidate();
- } else if (r < 0) {
- lderr(cct) << "failed to update object map: " << cpp_strerror(r)
- << dendl;
- return invalidate();
- }
-
- {
- RWLock::WLocker l2(m_image_ctx.object_map_lock);
- finish(&m_image_ctx.object_map);
- }
- return true;
-
- case STATE_INVALIDATE:
- ldout(cct, 20) << "INVALIDATE" << dendl;
- if (r < 0) {
- lderr(cct) << "failed to invalidate object map: " << cpp_strerror(r)
- << dendl;
- }
- return true;
-
- default:
- lderr(cct) << "invalid state: " << m_state << dendl;
- assert(false);
- break;
- }
- return false;
-}
-
-bool ObjectMap::Request::invalidate() {
- if (m_image_ctx.test_flags(RBD_FLAG_OBJECT_MAP_INVALID)) {
- return true;
- }
-
- CephContext *cct = m_image_ctx.cct;
- RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
-
- // requests shouldn't be running while using snapshots
- assert(m_image_ctx.snap_id == CEPH_NOSNAP);
-
- uint64_t flags = RBD_FLAG_OBJECT_MAP_INVALID;
- if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0) {
- flags |= RBD_FLAG_FAST_DIFF_INVALID;
- }
-
- lderr(cct) << &m_image_ctx << " invalidating object map" << dendl;
- m_state = STATE_INVALIDATE;
- m_image_ctx.flags |= flags;
-
- librados::ObjectWriteOperation op;
- cls_client::set_flags(&op, CEPH_NOSNAP, flags, flags);
-
- librados::AioCompletion *rados_completion = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
- rados_completion, &op);
- assert(r == 0);
- rados_completion->release();
- return false;
-}
-
-void ObjectMap::ResizeRequest::send() {
- CephContext *cct = m_image_ctx.cct;
-
- RWLock::WLocker l(m_image_ctx.object_map_lock);
- m_num_objs = Striper::get_num_objects(m_image_ctx.layout, m_new_size);
-
- ldout(cct, 5) << &m_image_ctx << " resizing on-disk object map: "
- << m_num_objs << dendl;
-
- librados::ObjectWriteOperation op;
- if (m_snap_id == CEPH_NOSNAP) {
- rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", "");
- }
- cls_client::object_map_resize(&op, m_num_objs, m_default_object_state);
-
- librados::AioCompletion *rados_completion = create_callback_completion();
- std::string oid(object_map_name(m_image_ctx.id, m_snap_id));
- int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op);
- assert(r == 0);
- rados_completion->release();
-}
-
-void ObjectMap::ResizeRequest::finish(ObjectMap *object_map) {
- CephContext *cct = m_image_ctx.cct;
-
- ldout(cct, 5) << &m_image_ctx << " resizing in-memory object map: "
- << m_num_objs << dendl;
- object_map->resize(m_num_objs, m_default_object_state);
-}
-
-void ObjectMap::UpdateRequest::send() {
- assert(m_image_ctx.object_map_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
-
- // safe to update in-memory state first without handling rollback since any
- // failures will invalidate the object map
- ldout(cct, 20) << &m_image_ctx << " updating object map"
- << (m_snap_id != CEPH_NOSNAP ?
- " snap " + stringify(m_snap_id) : std::string())
- << ": ["
- << m_start_object_no << "," << m_end_object_no << ") = "
- << (m_current_state ?
- stringify(static_cast<uint32_t>(*m_current_state)) : "")
- << "->" << static_cast<uint32_t>(m_new_state)
- << dendl;
-
- ObjectMap& object_map = m_image_ctx.object_map;
- if (m_snap_id == object_map.m_snap_id) {
- assert(m_image_ctx.object_map_lock.is_wlocked());
- for (uint64_t object_no = m_start_object_no;
- object_no < MIN(m_end_object_no, object_map.m_object_map.size());
- ++object_no) {
- uint8_t state = object_map.m_object_map[object_no];
- if (!m_current_state || state == *m_current_state ||
- (*m_current_state == OBJECT_EXISTS && state == OBJECT_EXISTS_CLEAN)) {
- object_map.m_object_map[object_no] = m_new_state;
- }
- }
- }
-
- librados::ObjectWriteOperation op;
- if (m_snap_id == CEPH_NOSNAP) {
- rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", "");
- }
- cls_client::object_map_update(&op, m_start_object_no, m_end_object_no,
- m_new_state, m_current_state);
-
- librados::AioCompletion *rados_completion = create_callback_completion();
- std::string oid(object_map_name(m_image_ctx.id, m_snap_id));
- int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op);
- assert(r == 0);
- rados_completion->release();
-}
-
-void ObjectMap::UpdateRequest::finish(ObjectMap *object_map) {
- ldout(m_image_ctx.cct, 20) << &m_image_ctx << " on-disk object map updated"
- << dendl;
-}
-
} // namespace librbd
#include "include/rados/librados.hpp"
#include "include/rbd/object_map_types.h"
#include "common/bit_vector.hpp"
-#include "librbd/AsyncRequest.h"
#include <boost/optional.hpp>
class Context;
bool enabled() const;
private:
-
- class Request : public AsyncRequest<> {
- public:
- Request(ImageCtx &image_ctx, uint64_t snap_id, Context *on_finish)
- : AsyncRequest(image_ctx, on_finish), m_snap_id(snap_id),
- m_state(STATE_REQUEST)
- {
- }
-
- protected:
- const uint64_t m_snap_id;
-
- virtual bool should_complete(int r);
- virtual int filter_return_code(int r) const {
- // never propagate an error back to the caller
- return 0;
- }
- virtual void finish(ObjectMap *object_map) = 0;
- private:
- /**
- * <start> ---> STATE_REQUEST ---> <finish>
- * | ^
- * v |
- * STATE_INVALIDATE -------/
- */
- enum State {
- STATE_REQUEST,
- STATE_INVALIDATE
- };
-
- State m_state;
-
- bool invalidate();
- };
-
- class ResizeRequest : public Request {
- public:
- ResizeRequest(ImageCtx &image_ctx, uint64_t snap_id, uint64_t new_size,
- uint8_t default_object_state, Context *on_finish)
- : Request(image_ctx, snap_id, on_finish), m_num_objs(0),
- m_new_size(new_size), m_default_object_state(default_object_state)
- {
- }
-
- virtual void send();
- protected:
- virtual void finish(ObjectMap *object_map);
- private:
- uint64_t m_num_objs;
- uint64_t m_new_size;
- uint8_t m_default_object_state;
- };
-
- class UpdateRequest : public Request {
- public:
- UpdateRequest(ImageCtx &image_ctx, uint64_t snap_id,
- uint64_t start_object_no, uint64_t end_object_no,
- uint8_t new_state,
- const boost::optional<uint8_t> ¤t_state,
- Context *on_finish)
- : Request(image_ctx, snap_id, on_finish),
- m_start_object_no(start_object_no), m_end_object_no(end_object_no),
- m_new_state(new_state), m_current_state(current_state)
- {
- }
-
- virtual void send();
- protected:
- virtual void finish(ObjectMap *object_map);
- private:
- uint64_t m_start_object_no;
- uint64_t m_end_object_no;
- uint8_t m_new_state;
- boost::optional<uint8_t> m_current_state;
- };
-
ImageCtx &m_image_ctx;
ceph::BitVector<2> m_object_map;
uint64_t m_snap_id;
bool m_enabled;
void invalidate(uint64_t snap_id, bool force);
- void resize(uint64_t num_objs, uint8_t default_state);
};
} // namespace librbd
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/object_map/Request.h"
+#include "include/rados/librados.hpp"
+#include "include/rbd/librbd.hpp"
+#include "common/dout.h"
+#include "common/errno.h"
+#include "common/RWLock.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/ImageWatcher.h"
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::object_map::Request: "
+
+namespace librbd {
+namespace object_map {
+
+bool Request::should_complete(int r) {
+ CephContext *cct = m_image_ctx.cct;
+ ldout(cct, 20) << &m_image_ctx << " should_complete: r=" << r << dendl;
+
+ switch (m_state)
+ {
+ case STATE_REQUEST:
+ if (r == -EBUSY) {
+ lderr(cct) << "object map lock not owned by client" << dendl;
+ return invalidate();
+ } else if (r < 0) {
+ lderr(cct) << "failed to update object map: " << cpp_strerror(r)
+ << dendl;
+ return invalidate();
+ }
+
+ {
+ RWLock::WLocker l2(m_image_ctx.object_map_lock);
+ finish();
+ }
+ return true;
+
+ case STATE_INVALIDATE:
+ ldout(cct, 20) << "INVALIDATE" << dendl;
+ if (r < 0) {
+ lderr(cct) << "failed to invalidate object map: " << cpp_strerror(r)
+ << dendl;
+ }
+ return true;
+
+ default:
+ lderr(cct) << "invalid state: " << m_state << dendl;
+ assert(false);
+ break;
+ }
+ return false;
+}
+
+bool Request::invalidate() {
+ if (m_image_ctx.test_flags(RBD_FLAG_OBJECT_MAP_INVALID)) {
+ return true;
+ }
+
+ CephContext *cct = m_image_ctx.cct;
+ RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
+
+ // requests shouldn't be running while using snapshots
+ assert(m_image_ctx.snap_id == CEPH_NOSNAP);
+
+ uint64_t flags = RBD_FLAG_OBJECT_MAP_INVALID;
+ if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0) {
+ flags |= RBD_FLAG_FAST_DIFF_INVALID;
+ }
+
+ lderr(cct) << &m_image_ctx << " invalidating object map" << dendl;
+ m_state = STATE_INVALIDATE;
+ m_image_ctx.flags |= flags;
+
+ librados::ObjectWriteOperation op;
+ cls_client::set_flags(&op, CEPH_NOSNAP, flags, flags);
+
+ librados::AioCompletion *rados_completion = create_callback_completion();
+ int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
+ rados_completion, &op);
+ assert(r == 0);
+ rados_completion->release();
+ return false;
+}
+
+} // namespace object_map
+} // namespace librbd
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_OBJECT_MAP_REQUEST_H
+#define CEPH_LIBRBD_OBJECT_MAP_REQUEST_H
+
+#include "include/int_types.h"
+#include "librbd/AsyncRequest.h"
+
+class Context;
+
+namespace librbd {
+
+class ImageCtx;
+
+namespace object_map {
+
+class Request : public AsyncRequest<> {
+public:
+ Request(ImageCtx &image_ctx, uint64_t snap_id, Context *on_finish)
+ : AsyncRequest(image_ctx, on_finish), m_snap_id(snap_id),
+ m_state(STATE_REQUEST)
+ {
+ }
+
+ virtual void send() = 0;
+
+protected:
+ const uint64_t m_snap_id;
+
+ virtual bool should_complete(int r);
+ virtual int filter_return_code(int r) const {
+ // never propagate an error back to the caller
+ return 0;
+ }
+ virtual void finish() = 0;
+
+private:
+ /**
+ * <start> ---> STATE_REQUEST ---> <finish>
+ * | ^
+ * v |
+ * STATE_INVALIDATE -------/
+ */
+ enum State {
+ STATE_REQUEST,
+ STATE_INVALIDATE
+ };
+
+ State m_state;
+
+ bool invalidate();
+};
+
+} // namespace object_map
+} // namespace librbd
+
+#endif // CEPH_LIBRBD_OBJECT_MAP_REQUEST_H
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/object_map/ResizeRequest.h"
+#include "common/dout.h"
+#include "common/errno.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/ObjectMap.h"
+#include "cls/lock/cls_lock_client.h"
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::object_map::ResizeRequest: "
+
+namespace librbd {
+namespace object_map {
+
+void ResizeRequest::resize(ceph::BitVector<2> *object_map, uint64_t num_objs,
+ uint8_t default_state) {
+ size_t orig_object_map_size = object_map->size();
+ object_map->resize(num_objs);
+ for (uint64_t i = orig_object_map_size; i < object_map->size(); ++i) {
+ (*object_map)[i] = default_state;
+ }
+}
+
+void ResizeRequest::send() {
+ CephContext *cct = m_image_ctx.cct;
+
+ RWLock::WLocker l(m_image_ctx.object_map_lock);
+ m_num_objs = Striper::get_num_objects(m_image_ctx.layout, m_new_size);
+
+ ldout(cct, 5) << &m_image_ctx << " resizing on-disk object map: "
+ << m_num_objs << dendl;
+
+ librados::ObjectWriteOperation op;
+ if (m_snap_id == CEPH_NOSNAP) {
+ rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", "");
+ }
+ cls_client::object_map_resize(&op, m_num_objs, m_default_object_state);
+
+ librados::AioCompletion *rados_completion = create_callback_completion();
+ std::string oid(ObjectMap::object_map_name(m_image_ctx.id, m_snap_id));
+ int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op);
+ assert(r == 0);
+ rados_completion->release();
+}
+
+void ResizeRequest::finish() {
+ CephContext *cct = m_image_ctx.cct;
+
+ ldout(cct, 5) << &m_image_ctx << " resizing in-memory object map: "
+ << m_num_objs << dendl;
+ resize(m_object_map, m_num_objs, m_default_object_state);
+}
+
+} // namespace object_map
+} // namespace librbd
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_OBJECT_MAP_RESIZE_REQUEST_H
+#define CEPH_LIBRBD_OBJECT_MAP_RESIZE_REQUEST_H
+
+#include "include/int_types.h"
+#include "librbd/object_map/Request.h"
+#include "common/bit_vector.hpp"
+
+class Context;
+
+namespace librbd {
+
+class ImageCtx;
+
+namespace object_map {
+
+class ResizeRequest : public Request {
+public:
+ ResizeRequest(ImageCtx &image_ctx, ceph::BitVector<2> *object_map,
+ uint64_t snap_id, uint64_t new_size,
+ uint8_t default_object_state, Context *on_finish)
+ : Request(image_ctx, snap_id, on_finish), m_object_map(object_map),
+ m_num_objs(0), m_new_size(new_size),
+ m_default_object_state(default_object_state)
+ {
+ }
+
+ static void resize(ceph::BitVector<2> *object_map, uint64_t num_objs,
+ uint8_t default_state);
+
+ virtual void send();
+
+protected:
+ virtual void finish();
+
+private:
+ ceph::BitVector<2> *m_object_map;
+ uint64_t m_num_objs;
+ uint64_t m_new_size;
+ uint8_t m_default_object_state;
+};
+
+} // namespace object_map
+} // namespace librbd
+
+#endif // CEPH_LIBRBD_OBJECT_MAP_RESIZE_REQUEST_H
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/object_map/UpdateRequest.h"
+#include "include/rbd/object_map_types.h"
+#include "include/stringify.h"
+#include "common/dout.h"
+#include "common/errno.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/ObjectMap.h"
+#include "cls/lock/cls_lock_client.h"
+#include <string>
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::object_map::UpdateRequest: "
+
+namespace librbd {
+namespace object_map {
+
+void UpdateRequest::send() {
+ assert(m_image_ctx.snap_lock.is_locked());
+ assert(m_image_ctx.object_map_lock.is_locked());
+ CephContext *cct = m_image_ctx.cct;
+
+ // safe to update in-memory state first without handling rollback since any
+ // failures will invalidate the object map
+ ldout(cct, 20) << &m_image_ctx << " updating object map"
+ << (m_snap_id != CEPH_NOSNAP ?
+ " snap " + stringify(m_snap_id) : std::string())
+ << ": ["
+ << m_start_object_no << "," << m_end_object_no << ") = "
+ << (m_current_state ?
+ stringify(static_cast<uint32_t>(*m_current_state)) : "")
+ << "->" << static_cast<uint32_t>(m_new_state)
+ << dendl;
+
+ // rebuilding the object map might update on-disk only
+ if (m_snap_id == m_image_ctx.snap_id) {
+ assert(m_image_ctx.object_map_lock.is_wlocked());
+ for (uint64_t object_no = m_start_object_no;
+ object_no < MIN(m_end_object_no, m_object_map.size());
+ ++object_no) {
+ uint8_t state = m_object_map[object_no];
+ if (!m_current_state || state == *m_current_state ||
+ (*m_current_state == OBJECT_EXISTS && state == OBJECT_EXISTS_CLEAN)) {
+ m_object_map[object_no] = m_new_state;
+ }
+ }
+ }
+
+ librados::ObjectWriteOperation op;
+ if (m_snap_id == CEPH_NOSNAP) {
+ rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", "");
+ }
+ cls_client::object_map_update(&op, m_start_object_no, m_end_object_no,
+ m_new_state, m_current_state);
+
+ librados::AioCompletion *rados_completion = create_callback_completion();
+ std::string oid(ObjectMap::object_map_name(m_image_ctx.id, m_snap_id));
+ int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op);
+ assert(r == 0);
+ rados_completion->release();
+}
+
+void UpdateRequest::finish() {
+ ldout(m_image_ctx.cct, 20) << &m_image_ctx << " on-disk object map updated"
+ << dendl;
+}
+
+} // namespace object_map
+} // namespace librbd
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_OBJECT_MAP_UPDATE_REQUEST_H
+#define CEPH_LIBRBD_OBJECT_MAP_UPDATE_REQUEST_H
+
+#include "include/int_types.h"
+#include "librbd/object_map/Request.h"
+#include "common/bit_vector.hpp"
+#include <boost/optional.hpp>
+
+class Context;
+
+namespace librbd {
+
+class ImageCtx;
+
+namespace object_map {
+
+class UpdateRequest : public Request {
+public:
+ UpdateRequest(ImageCtx &image_ctx, ceph::BitVector<2> *object_map,
+ uint64_t snap_id, uint64_t start_object_no,
+ uint64_t end_object_no, uint8_t new_state,
+ const boost::optional<uint8_t> ¤t_state,
+ Context *on_finish)
+ : Request(image_ctx, snap_id, on_finish), m_object_map(*object_map),
+ m_start_object_no(start_object_no), m_end_object_no(end_object_no),
+ m_new_state(new_state), m_current_state(current_state)
+ {
+ }
+
+ virtual void send();
+
+protected:
+ virtual void finish();
+
+private:
+ ceph::BitVector<2> &m_object_map;
+ uint64_t m_start_object_no;
+ uint64_t m_end_object_no;
+ uint8_t m_new_state;
+ boost::optional<uint8_t> m_current_state;
+};
+
+} // namespace object_map
+} // namespace librbd
+
+#endif // CEPH_LIBRBD_OBJECT_MAP_UPDATE_REQUEST_H