handle_detained_aio_update(cell, r, on_finish);
});
aio_update(CEPH_NOSNAP, op.start_object_no, op.end_object_no, op.new_state,
- op.current_state, ctx);
+ op.current_state, op.parent_trace, ctx);
}
template <typename I>
void ObjectMap<I>::aio_update(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,
+ const ZTracer::Trace &parent_trace,
Context *on_finish) {
assert(m_image_ctx.snap_lock.is_locked());
assert((m_image_ctx.features & RBD_FEATURE_OBJECT_MAP) != 0);
auto req = object_map::UpdateRequest<I>::create(
m_image_ctx, &m_object_map, snap_id, start_object_no, end_object_no,
- new_state, current_state, on_finish);
+ new_state, current_state, parent_trace, on_finish);
req->send();
}
class Context;
class RWLock;
-namespace librados {
- class IoCtx;
-}
+namespace librados { class IoCtx; }
+namespace ZTracer { struct Trace; }
namespace librbd {
template <typename T, void(T::*MF)(int) = &T::complete>
bool aio_update(uint64_t snap_id, uint64_t start_object_no, uint8_t new_state,
const boost::optional<uint8_t> ¤t_state,
- T *callback_object) {
+ const ZTracer::Trace &parent_trace, T *callback_object) {
return aio_update<T, MF>(snap_id, start_object_no, start_object_no + 1,
- new_state, current_state, callback_object);
+ new_state, current_state, parent_trace,
+ callback_object);
}
template <typename T, void(T::*MF)(int) = &T::complete>
bool aio_update(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,
- T *callback_object) {
+ const ZTracer::Trace &parent_trace, T *callback_object) {
assert(start_object_no < end_object_no);
if (snap_id == CEPH_NOSNAP) {
uint64_t object_no;
}
UpdateOperation update_operation(start_object_no, end_object_no,
- new_state, current_state,
+ new_state, current_state, parent_trace,
util::create_context_callback<T, MF>(
callback_object));
detained_aio_update(std::move(update_operation));
} else {
aio_update(snap_id, start_object_no, end_object_no, new_state,
- current_state,
+ current_state, parent_trace,
util::create_context_callback<T, MF>(callback_object));
}
return true;
uint64_t end_object_no;
uint8_t new_state;
boost::optional<uint8_t> current_state;
+ ZTracer::Trace parent_trace;
Context *on_finish;
UpdateOperation(uint64_t start_object_no, uint64_t end_object_no,
uint8_t new_state,
const boost::optional<uint8_t> ¤t_state,
- Context *on_finish)
+ const ZTracer::Trace &parent_trace, Context *on_finish)
: start_object_no(start_object_no), end_object_no(end_object_no),
new_state(new_state), current_state(current_state),
- on_finish(on_finish) {
+ parent_trace(parent_trace), on_finish(on_finish) {
}
};
void aio_update(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);
+ const ZTracer::Trace &parent_trace, Context *on_finish);
bool update_required(uint64_t object_no, uint8_t new_state);
};
public:
UpdateObjectMap(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx,
uint64_t object_no, const std::vector<uint64_t> *snap_ids,
- size_t snap_id_idx)
- : C_AsyncObjectThrottle(throttle, *image_ctx),
- m_object_no(object_no), m_snap_ids(*snap_ids), m_snap_id_idx(snap_id_idx)
+ const ZTracer::Trace &trace, size_t snap_id_idx)
+ : C_AsyncObjectThrottle(throttle, *image_ctx), m_object_no(object_no),
+ m_snap_ids(*snap_ids), m_trace(trace), m_snap_id_idx(snap_id_idx)
{
}
assert(m_image_ctx.exclusive_lock->is_lock_owner());
assert(m_image_ctx.object_map != nullptr);
bool sent = m_image_ctx.object_map->aio_update<Context>(
- CEPH_NOSNAP, m_object_no, OBJECT_EXISTS, {}, this);
+ CEPH_NOSNAP, m_object_no, OBJECT_EXISTS, {}, m_trace, this);
return (sent ? 0 : 1);
}
}
bool sent = m_image_ctx.object_map->aio_update<Context>(
- snap_id, m_object_no, state, {}, this);
+ snap_id, m_object_no, state, {}, m_trace, this);
assert(sent);
return 0;
}
private:
uint64_t m_object_no;
const std::vector<uint64_t> &m_snap_ids;
+ const ZTracer::Trace &m_trace;
size_t m_snap_id_idx;
};
if (may_update && (new_state != current_state) &&
m_ictx->object_map->aio_update<CopyupRequest>(
- CEPH_NOSNAP, m_object_no, new_state, current_state, this)) {
+ CEPH_NOSNAP, m_object_no, new_state, current_state, m_trace,
+ this)) {
return false;
}
}
RWLock::RLocker owner_locker(m_ictx->owner_lock);
AsyncObjectThrottle<>::ContextFactory context_factory(
boost::lambda::bind(boost::lambda::new_ptr<UpdateObjectMap>(),
- boost::lambda::_1, m_ictx, m_object_no, &m_snap_ids,
+ boost::lambda::_1, m_ictx, m_object_no, &m_snap_ids, m_trace,
boost::lambda::_2));
AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>(
NULL, *m_ictx, context_factory, util::create_context_callback(this),
m_state = LIBRBD_AIO_WRITE_PRE;
if (m_ictx->object_map->aio_update<ObjectRequest>(
- CEPH_NOSNAP, m_object_no, new_state, {}, this)) {
+ CEPH_NOSNAP, m_object_no, new_state, {}, this->m_trace, this)) {
return;
}
}
m_state = LIBRBD_AIO_WRITE_POST;
if (m_ictx->object_map->aio_update<ObjectRequest>(
- CEPH_NOSNAP, m_object_no, OBJECT_NONEXISTENT, OBJECT_PENDING, this)) {
+ CEPH_NOSNAP, m_object_no, OBJECT_NONEXISTENT, OBJECT_PENDING,
+ this->m_trace, this)) {
return false;
}
m_new_state, m_current_state);
librados::AioCompletion *rados_completion = create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op);
+ std::vector<librados::snap_t> snaps;
+ int r = m_image_ctx.md_ctx.aio_operate(
+ oid, rados_completion, &op, 0, snaps,
+ (m_trace.valid() ? m_trace.get_info() : nullptr));
assert(r == 0);
rados_completion->release();
}
#include "include/int_types.h"
#include "librbd/object_map/Request.h"
#include "common/bit_vector.hpp"
+#include "common/zipkin_trace.h"
+#include "librbd/Utils.h"
#include <boost/optional.hpp>
class Context;
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,
+ const ZTracer::Trace &parent_trace,
Context *on_finish) {
return new UpdateRequest(image_ctx, object_map, snap_id, start_object_no,
end_object_no, new_state, current_state,
- on_finish);
+ parent_trace, on_finish);
}
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)
+ const ZTracer::Trace &parent_trace, 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)
+ m_new_state(new_state), m_current_state(current_state),
+ m_trace(util::create_trace(image_ctx, "update object map", parent_trace))
{
+ m_trace.event("start");
+ }
+ virtual ~UpdateRequest() {
+ m_trace.event("finish");
}
void send() override;
uint64_t m_end_object_no;
uint8_t m_new_state;
boost::optional<uint8_t> m_current_state;
+ ZTracer::Trace m_trace;
};
} // namespace object_map
RWLock::WLocker object_map_locker(image_ctx.object_map_lock);
if (image_ctx.object_map->template aio_update<AsyncRequest<I> >(
CEPH_NOSNAP, m_copyup_start, m_copyup_end, OBJECT_PENDING,
- OBJECT_EXISTS, this)) {
+ OBJECT_EXISTS, {}, this)) {
return;
}
}
RWLock::WLocker object_map_locker(image_ctx.object_map_lock);
if (image_ctx.object_map->template aio_update<AsyncRequest<I> >(
CEPH_NOSNAP, m_delete_start, m_num_objects, OBJECT_PENDING,
- OBJECT_EXISTS, this)) {
+ OBJECT_EXISTS, {}, this)) {
return;
}
}
RWLock::WLocker object_map_locker(image_ctx.object_map_lock);
if (image_ctx.object_map->template aio_update<AsyncRequest<I> >(
CEPH_NOSNAP, m_copyup_start, m_copyup_end, OBJECT_NONEXISTENT,
- OBJECT_PENDING, this)) {
+ OBJECT_PENDING, {}, this)) {
return;
}
}
RWLock::WLocker object_map_locker(image_ctx.object_map_lock);
if (image_ctx.object_map->template aio_update<AsyncRequest<I> >(
CEPH_NOSNAP, m_delete_start, m_num_objects, OBJECT_NONEXISTENT,
- OBJECT_PENDING, this)) {
+ OBJECT_PENDING, {}, this)) {
return;
}
}
template <typename T, void(T::*MF)(int)>
bool aio_update(uint64_t snap_id, uint64_t start_object_no, uint8_t new_state,
const boost::optional<uint8_t> ¤t_state,
- T *callback_object) {
+ const ZTracer::Trace &parent_trace, T *callback_object) {
return aio_update<T, MF>(snap_id, start_object_no, start_object_no + 1,
- new_state, current_state, callback_object);
+ new_state, current_state, parent_trace,
+ callback_object);
}
template <typename T, void(T::*MF)(int)>
bool aio_update(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,
- T *callback_object) {
+ const ZTracer::Trace &parent_trace, T *callback_object) {
return aio_update(snap_id, start_object_no, end_object_no, new_state,
- current_state,
+ current_state, parent_trace,
util::create_context_callback<T, MF>(callback_object));
}
- MOCK_METHOD6(aio_update, bool(uint64_t snap_id, uint64_t start_object_no,
+ MOCK_METHOD7(aio_update, bool(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,
+ const ZTracer::Trace &parent_trace,
Context *on_finish));
MOCK_METHOD2(snapshot_add, void(uint64_t snap_id, Context *on_finish));
MOCK_METHOD2(snapshot_remove, void(uint64_t snap_id, Context *on_finish));
C_SaferCond cond_ctx;
AsyncRequest<> *req = new UpdateRequest<>(
*ictx, &object_map, CEPH_NOSNAP, 0, object_map.size(), OBJECT_NONEXISTENT,
- OBJECT_EXISTS, &cond_ctx);
+ OBJECT_EXISTS, {}, &cond_ctx);
{
RWLock::RLocker snap_locker(ictx->snap_lock);
RWLock::WLocker object_map_locker(ictx->object_map_lock);
C_SaferCond cond_ctx;
AsyncRequest<> *req = new UpdateRequest<>(
*ictx, &object_map, CEPH_NOSNAP, 0, object_map.size(), OBJECT_NONEXISTENT,
- OBJECT_EXISTS, &cond_ctx);
+ OBJECT_EXISTS, {}, &cond_ctx);
{
RWLock::RLocker snap_locker(ictx->snap_lock);
RWLock::WLocker object_map_locker(ictx->object_map_lock);
C_SaferCond cond_ctx;
AsyncRequest<> *req = new UpdateRequest<>(
*ictx, &object_map, snap_id, 0, object_map.size(), OBJECT_NONEXISTENT,
- OBJECT_EXISTS, &cond_ctx);
+ OBJECT_EXISTS, {}, &cond_ctx);
{
RWLock::RLocker snap_locker(ictx->snap_lock);
RWLock::WLocker object_map_locker(ictx->object_map_lock);
C_SaferCond cond_ctx;
AsyncRequest<> *req = new UpdateRequest<>(
*ictx, &object_map, CEPH_NOSNAP, 0, object_map.size(), OBJECT_NONEXISTENT,
- OBJECT_EXISTS, &cond_ctx);
+ OBJECT_EXISTS, {}, &cond_ctx);
{
RWLock::RLocker snap_locker(ictx->snap_lock);
RWLock::WLocker object_map_locker(ictx->object_map_lock);
C_SaferCond cond_ctx;
AsyncRequest<> *req = new UpdateRequest<>(
*ictx, &object_map, snap_id, 0, object_map.size(), OBJECT_EXISTS_CLEAN,
- boost::optional<uint8_t>(), &cond_ctx);
+ boost::optional<uint8_t>(), {}, &cond_ctx);
{
RWLock::RLocker snap_locker(ictx->snap_lock);
RWLock::WLocker object_map_locker(ictx->object_map_lock);
uint64_t start_object_no, uint64_t end_object_no,
uint8_t new_state,
const boost::optional<uint8_t> ¤t_state,
+ const ZTracer::Trace &parent_trace,
Context *on_finish) {
assert(s_instance != nullptr);
s_instance->on_finish = on_finish;
{
RWLock::RLocker snap_locker(mock_image_ctx.snap_lock);
RWLock::WLocker object_map_locker(mock_image_ctx.object_map_lock);
- mock_object_map.aio_update(CEPH_NOSNAP, 0, 1, {}, &update_ctx1);
- mock_object_map.aio_update(CEPH_NOSNAP, 1, 1, {}, &update_ctx2);
+ mock_object_map.aio_update(CEPH_NOSNAP, 0, 1, {}, {}, &update_ctx1);
+ mock_object_map.aio_update(CEPH_NOSNAP, 1, 1, {}, {}, &update_ctx2);
}
finish_update_2->complete(0);
{
RWLock::RLocker snap_locker(mock_image_ctx.snap_lock);
RWLock::WLocker object_map_locker(mock_image_ctx.object_map_lock);
- mock_object_map.aio_update(CEPH_NOSNAP, 1, 4, 1, {}, &update_ctx1);
- mock_object_map.aio_update(CEPH_NOSNAP, 1, 3, 1, {}, &update_ctx2);
- mock_object_map.aio_update(CEPH_NOSNAP, 2, 3, 1, {}, &update_ctx3);
- mock_object_map.aio_update(CEPH_NOSNAP, 0, 2, 1, {}, &update_ctx4);
+ mock_object_map.aio_update(CEPH_NOSNAP, 1, 4, 1, {}, {}, &update_ctx1);
+ mock_object_map.aio_update(CEPH_NOSNAP, 1, 3, 1, {}, {}, &update_ctx2);
+ mock_object_map.aio_update(CEPH_NOSNAP, 2, 3, 1, {}, {}, &update_ctx3);
+ mock_object_map.aio_update(CEPH_NOSNAP, 0, 2, 1, {}, {}, &update_ctx4);
}
// updates 2, 3, and 4 are blocked on update 1
librados::snap_t snap_id, uint8_t state,
int r) {
if (mock_image_ctx.image_ctx->object_map != nullptr) {
- auto &expect = EXPECT_CALL(mock_object_map, aio_update(snap_id, 0, 1, state, _, _));
+ auto &expect = EXPECT_CALL(mock_object_map, aio_update(snap_id, 0, 1, state, _, _, _));
if (r < 0) {
- expect.WillOnce(DoAll(WithArg<5>(Invoke([this, r](Context *ctx) {
+ expect.WillOnce(DoAll(WithArg<6>(Invoke([this, r](Context *ctx) {
m_threads->work_queue->queue(ctx, r);
})),
Return(true)));
} else {
- expect.WillOnce(DoAll(WithArg<5>(Invoke([&mock_image_ctx, snap_id, state, r](Context *ctx) {
+ expect.WillOnce(DoAll(WithArg<6>(Invoke([&mock_image_ctx, snap_id, state, r](Context *ctx) {
assert(mock_image_ctx.image_ctx->snap_lock.is_locked());
assert(mock_image_ctx.image_ctx->object_map_lock.is_wlocked());
mock_image_ctx.image_ctx->object_map->aio_update<Context>(
- snap_id, 0, 1, state, boost::none, ctx);
+ snap_id, 0, 1, state, boost::none, {}, ctx);
})),
Return(true)));
}
bool sent = m_local_image_ctx->object_map->template aio_update<
ObjectCopyRequest<I>, &ObjectCopyRequest<I>::handle_update_object_map>(
snap_object_state.first, m_object_number, snap_object_state.second, {},
- this);
+ {}, this);
assert(sent);
m_local_image_ctx->snap_lock.put_read();
}