The next series of commits will work to remove ImageRequestWQ from librbd.
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
*ictx, io::IMAGE_DISPATCH_LAYER_INTERNAL_START,
aio_comp, io::FLUSH_SOURCE_INTERNAL, {});
req->send();
- delete req;
}
int r = flush_ctx.wait();
if (r < 0) {
*m_image_ctx, io::IMAGE_DISPATCH_LAYER_INTERNAL_START, aio_comp,
io::FLUSH_SOURCE_INTERNAL, {});
req->send();
- delete req;
}
template <typename I>
m_image_ctx, io::IMAGE_DISPATCH_LAYER_INTERNAL_START, aio_comp,
io::FLUSH_SOURCE_INTERNAL, {});
req->send();
- delete req;
return nullptr;
} else if (m_error_result < 0) {
// propagate saved error back to caller
image_dispatch_spec->finish(r);
}
-template <typename I>
-struct ImageDispatchSpec<I>::SendVisitor
- : public boost::static_visitor<void> {
- ImageDispatchSpec* spec;
-
- explicit SendVisitor(ImageDispatchSpec* spec)
- : spec(spec) {
- }
-
- void operator()(Read& read) const {
- ImageRequest<I>::aio_read(
- &spec->m_image_ctx, spec->aio_comp, std::move(spec->image_extents),
- std::move(read.read_result), spec->op_flags, spec->parent_trace);
- }
-
- void operator()(Discard& discard) const {
- ImageRequest<I>::aio_discard(
- &spec->m_image_ctx, spec->aio_comp, std::move(spec->image_extents),
- discard.discard_granularity_bytes, spec->parent_trace);
- }
-
- void operator()(Write& write) const {
- ImageRequest<I>::aio_write(
- &spec->m_image_ctx, spec->aio_comp, std::move(spec->image_extents),
- std::move(write.bl), spec->op_flags, spec->parent_trace);
- }
-
- void operator()(WriteSame& write_same) const {
- ImageRequest<I>::aio_writesame(
- &spec->m_image_ctx, spec->aio_comp, std::move(spec->image_extents),
- std::move(write_same.bl), spec->op_flags, spec->parent_trace);
- }
-
- void operator()(CompareAndWrite& compare_and_write) const {
- ImageRequest<I>::aio_compare_and_write(
- &spec->m_image_ctx, spec->aio_comp, std::move(spec->image_extents),
- std::move(compare_and_write.cmp_bl), std::move(compare_and_write.bl),
- compare_and_write.mismatch_offset, spec->op_flags,
- spec->parent_trace);
- }
-
- void operator()(Flush& flush) const {
- ImageRequest<I>::aio_flush(
- &spec->m_image_ctx, spec->aio_comp, flush.flush_source,
- spec->parent_trace);
- }
-};
-
template <typename I>
struct ImageDispatchSpec<I>::IsWriteOpVisitor
: public boost::static_visitor<bool> {
template <typename I>
void ImageDispatchSpec<I>::send() {
- boost::apply_visitor(SendVisitor{this}, request);
+ image_dispatcher->send(this);
}
template <typename I>
template <typename I>
void ImageDispatchSpec<I>::start_op() {
+ tid = 0;
aio_comp->start_op();
}
: dispatcher_ctx(this), image_dispatcher(image_ctx.io_image_dispatcher),
dispatch_layer(image_dispatch_layer), aio_comp(aio_comp),
image_extents(std::move(image_extents)), request(std::move(request)),
- op_flags(op_flags), parent_trace(parent_trace), tid(tid),
- m_image_ctx(image_ctx) {
+ op_flags(op_flags), parent_trace(parent_trace), tid(tid) {
+ aio_comp->image_dispatcher_ctx = &dispatcher_ctx;
aio_comp->get();
}
- ImageCtxT& m_image_ctx;
-
void finish(int r);
uint64_t extents_length();
void ImageDispatcher<I>::finish(int r, ImageDispatchLayer image_dispatch_layer,
uint64_t tid) {
auto cct = this->m_image_ctx->cct;
- ldout(cct, 20) << "tid=" << tid << dendl;
+ ldout(cct, 20) << "r=" << r << ", tid=" << tid << dendl;
// loop in reverse order from last invoked dispatch layer calling its
// handle_finished method
bool ImageDispatcher<I>::send_dispatch(
ImageDispatchInterface* image_dispatch,
ImageDispatchSpec<I>* image_dispatch_spec) {
+ if (image_dispatch_spec->tid == 0) {
+ image_dispatch_spec->tid = ++m_next_tid;
+ }
+
return boost::apply_visitor(
SendVisitor{image_dispatch, image_dispatch_spec},
image_dispatch_spec->request);
#include "librbd/io/ImageDispatchSpec.h"
#include "librbd/io/ImageDispatcherInterface.h"
#include "librbd/io/Types.h"
+#include <atomic>
#include <map>
struct Context;
private:
struct SendVisitor;
+ std::atomic<uint64_t> m_next_tid{0};
+
QueueImageDispatch<ImageCtxT>* m_queue_image_dispatch = nullptr;
QosImageDispatch<ImageCtxT>* m_qos_image_dispatch = nullptr;
namespace io {
-namespace {
-
-template <typename I>
-void flush_image(I& image_ctx, Context* on_finish) {
- auto aio_comp = librbd::io::AioCompletion::create_and_start(
- on_finish, util::get_image_ctx(&image_ctx), librbd::io::AIO_TYPE_FLUSH);
- auto req = librbd::io::ImageDispatchSpec<I>::create_flush_request(
- image_ctx, IMAGE_DISPATCH_LAYER_API_START, aio_comp, FLUSH_SOURCE_INTERNAL,
- {});
- req->send();
- delete req;
-}
-
-} // anonymous namespace
-
template <typename I>
struct ImageRequestWQ<I>::C_AcquireLock : public Context {
ImageRequestWQ *work_queue;
op_flags, trace, tid);
std::shared_lock owner_locker{m_image_ctx.owner_lock};
- if (m_image_ctx.non_blocking_aio || writes_blocked()) {
- queue(req);
- } else {
- process_io(req, false);
- finish_in_flight_io();
- }
+ queue(req);
trace.event("finish");
}
discard_granularity_bytes, trace, tid);
std::shared_lock owner_locker{m_image_ctx.owner_lock};
- if (m_image_ctx.non_blocking_aio || writes_blocked()) {
- queue(req);
- } else {
- process_io(req, false);
- finish_in_flight_io();
- }
+ queue(req);
trace.event("finish");
}
}
std::shared_lock owner_locker{m_image_ctx.owner_lock};
- if (m_image_ctx.non_blocking_aio || writes_blocked() || !writes_empty()) {
- queue(req);
- } else {
- process_io(req, false);
- finish_in_flight_io();
- }
+ queue(req);
trace.event("finish");
}
op_flags, trace, tid);
std::shared_lock owner_locker{m_image_ctx.owner_lock};
- if (m_image_ctx.non_blocking_aio || writes_blocked()) {
- queue(req);
- } else {
- process_io(req, false);
- finish_in_flight_io();
- }
+ queue(req);
trace.event("finish");
}
std::move(cmp_bl), std::move(bl), mismatch_off, op_flags, trace, tid);
std::shared_lock owner_locker{m_image_ctx.owner_lock};
- if (m_image_ctx.non_blocking_aio || writes_blocked()) {
- queue(req);
- } else {
- process_io(req, false);
- finish_in_flight_io();
- }
+ queue(req);
trace.event("finish");
}
}
}
- // ensure that all in-flight IO is flushed
- flush_image(m_image_ctx, on_shutdown);
+ m_image_ctx.op_work_queue->queue(on_shutdown, 0);
}
template <typename I>
}
}
- // ensure that all in-flight IO is flushed
- flush_image(m_image_ctx, on_blocked);
+ m_image_ctx.op_work_queue->queue(on_blocked, 0);
}
template <typename I>
unblock_overlapping_io(offset, length, tid);
unblock_flushes();
}
- delete req;
}
template <typename I>
writes_blocked = true;
}
}
+
if (writes_blocked) {
- flush_image(m_image_ctx, new C_BlockedWrites(this));
+ m_image_ctx.op_work_queue->queue(create_context_callback<
+ ImageRequestWQ<I>, &ImageRequestWQ<I>::handle_blocked_writes>(this), 0);
}
}
CephContext *cct = m_image_ctx.cct;
ldout(cct, 5) << "completing shut down" << dendl;
- ceph_assert(on_shutdown != nullptr);
- flush_image(m_image_ctx, on_shutdown);
+ on_shutdown->complete(0);
}
template <typename I>
finish_queued_io(write_op);
remove_in_flight_write_ios(offset, length, write_op, tid);
- delete req;
finish_in_flight_io();
}
image_ctx, io::IMAGE_DISPATCH_LAYER_INTERNAL_START, aio_comp,
io::FLUSH_SOURCE_INTERNAL, {});
req->send();
- delete req;
}
template <typename I>
}
void expect_front(MockImageRequestWQ &image_request_wq,
- MockImageDispatchSpec *image_request) {
- EXPECT_CALL(image_request_wq, front()).WillOnce(Return(image_request));
+ MockImageDispatchSpec& image_request) {
+ EXPECT_CALL(image_request_wq, front()).WillOnce(Return(&image_request));
}
void expect_is_refresh_request(MockTestImageCtx &mock_image_ctx,
}
void expect_dequeue(MockImageRequestWQ &image_request_wq,
- MockImageDispatchSpec *image_request) {
- EXPECT_CALL(image_request_wq, dequeue()).WillOnce(Return(image_request));
+ MockImageDispatchSpec &image_request) {
+ EXPECT_CALL(image_request_wq, dequeue()).WillOnce(Return(&image_request));
}
void expect_get_exclusive_lock_policy(MockTestImageCtx &mock_image_ctx,
MockExclusiveLock mock_exclusive_lock;
mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
- auto mock_queued_image_request = new MockImageDispatchSpec();
- expect_get_image_extents(*mock_queued_image_request, {});
- expect_get_tid(*mock_queued_image_request, 0);
+ MockImageDispatchSpec mock_queued_image_request;
+ expect_get_image_extents(mock_queued_image_request, {});
+ expect_get_tid(mock_queued_image_request, 0);
InSequence seq;
MockImageRequestWQ mock_image_request_wq(&mock_image_ctx, "io", 60, nullptr);
expect_signal(mock_image_request_wq);
mock_image_request_wq.set_require_lock(DIRECTION_WRITE, true);
- expect_is_write_op(*mock_queued_image_request, true);
+ expect_is_write_op(mock_queued_image_request, true);
expect_queue(mock_image_request_wq);
auto *aio_comp = new librbd::io::AioCompletion();
mock_image_request_wq.aio_write(aio_comp, 0, 0, {}, 0);
librbd::exclusive_lock::MockPolicy mock_exclusive_lock_policy;
expect_front(mock_image_request_wq, mock_queued_image_request);
expect_is_refresh_request(mock_image_ctx, false);
- expect_is_write_op(*mock_queued_image_request, true);
+ expect_is_write_op(mock_queued_image_request, true);
expect_dequeue(mock_image_request_wq, mock_queued_image_request);
expect_get_exclusive_lock_policy(mock_image_ctx, mock_exclusive_lock_policy);
expect_may_auto_request_lock(mock_exclusive_lock_policy, true);
ASSERT_TRUE(on_acquire != nullptr);
expect_process_finish(mock_image_request_wq);
- expect_fail(*mock_queued_image_request, -EPERM);
- expect_is_write_op(*mock_queued_image_request, true);
+ expect_fail(mock_queued_image_request, -EPERM);
+ expect_is_write_op(mock_queued_image_request, true);
expect_signal(mock_image_request_wq);
on_acquire->complete(-EPERM);
MockExclusiveLock mock_exclusive_lock;
mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
- auto mock_queued_image_request = new MockImageDispatchSpec();
- expect_get_image_extents(*mock_queued_image_request, {});
- expect_get_tid(*mock_queued_image_request, 0);
+ MockImageDispatchSpec mock_queued_image_request;
+ expect_get_image_extents(mock_queued_image_request, {});
+ expect_get_tid(mock_queued_image_request, 0);
InSequence seq;
MockImageRequestWQ mock_image_request_wq(&mock_image_ctx, "io", 60, nullptr);
expect_signal(mock_image_request_wq);
mock_image_request_wq.set_require_lock(DIRECTION_WRITE, true);
- expect_is_write_op(*mock_queued_image_request, true);
+ expect_is_write_op(mock_queued_image_request, true);
expect_queue(mock_image_request_wq);
auto *aio_comp = new librbd::io::AioCompletion();
mock_image_request_wq.aio_write(aio_comp, 0, 0, {}, 0);
librbd::exclusive_lock::MockPolicy mock_exclusive_lock_policy;
expect_front(mock_image_request_wq, mock_queued_image_request);
expect_is_refresh_request(mock_image_ctx, false);
- expect_is_write_op(*mock_queued_image_request, true);
+ expect_is_write_op(mock_queued_image_request, true);
expect_dequeue(mock_image_request_wq, mock_queued_image_request);
expect_get_exclusive_lock_policy(mock_image_ctx, mock_exclusive_lock_policy);
expect_may_auto_request_lock(mock_exclusive_lock_policy, false);
EXPECT_CALL(*mock_image_ctx.exclusive_lock, get_unlocked_op_error())
.WillOnce(Return(-EBLACKLISTED));
expect_process_finish(mock_image_request_wq);
- expect_fail(*mock_queued_image_request, -EBLACKLISTED);
- expect_is_write_op(*mock_queued_image_request, true);
+ expect_fail(mock_queued_image_request, -EBLACKLISTED);
+ expect_is_write_op(mock_queued_image_request, true);
expect_signal(mock_image_request_wq);
ASSERT_TRUE(mock_image_request_wq.invoke_dequeue() == nullptr);
MockTestImageCtx mock_image_ctx(*ictx);
- auto mock_queued_image_request = new MockImageDispatchSpec();
- expect_get_image_extents(*mock_queued_image_request, {});
- expect_get_tid(*mock_queued_image_request, 0);
+ MockImageDispatchSpec mock_queued_image_request;
+ expect_get_image_extents(mock_queued_image_request, {});
+ expect_get_tid(mock_queued_image_request, 0);
InSequence seq;
MockImageRequestWQ mock_image_request_wq(&mock_image_ctx, "io", 60, nullptr);
- expect_is_write_op(*mock_queued_image_request, true);
+ expect_is_write_op(mock_queued_image_request, true);
expect_queue(mock_image_request_wq);
auto *aio_comp = new librbd::io::AioCompletion();
mock_image_request_wq.aio_write(aio_comp, 0, 0, {}, 0);
expect_front(mock_image_request_wq, mock_queued_image_request);
expect_is_refresh_request(mock_image_ctx, true);
- expect_is_write_op(*mock_queued_image_request, true);
+ expect_is_write_op(mock_queued_image_request, true);
expect_dequeue(mock_image_request_wq, mock_queued_image_request);
Context *on_refresh = nullptr;
expect_refresh(mock_image_ctx, &on_refresh);
ASSERT_TRUE(on_refresh != nullptr);
expect_process_finish(mock_image_request_wq);
- expect_fail(*mock_queued_image_request, -EPERM);
- expect_is_write_op(*mock_queued_image_request, true);
+ expect_fail(mock_queued_image_request, -EPERM);
+ expect_is_write_op(mock_queued_image_request, true);
expect_signal(mock_image_request_wq);
on_refresh->complete(-EPERM);
*ictx, librbd::io::IMAGE_DISPATCH_LAYER_INTERNAL_START, aio_comp,
librbd::io::FLUSH_SOURCE_INTERNAL, {});
req->send();
- delete req;
ASSERT_EQ(0, flush_ctx.wait());
// check the commit position updated
expect_unblock_writes(mock_image_ctx);
MockTrimRequest mock_trim_request;
- auto mock_io_image_dispatch_spec = new MockIoImageDispatchSpec();
- expect_flush_cache(mock_image_ctx, *mock_io_image_dispatch_spec, 0);
+ MockIoImageDispatchSpec mock_io_image_dispatch_spec;
+ expect_flush_cache(mock_image_ctx, mock_io_image_dispatch_spec, 0);
expect_invalidate_cache(mock_image_ctx, 0);
expect_trim(mock_image_ctx, mock_trim_request, 0);
expect_block_writes(mock_image_ctx, 0);
expect_unblock_writes(mock_image_ctx);
MockTrimRequest mock_trim_request;
- auto mock_io_image_dispatch_spec = new MockIoImageDispatchSpec();
- expect_flush_cache(mock_image_ctx, *mock_io_image_dispatch_spec, 0);
+ MockIoImageDispatchSpec mock_io_image_dispatch_spec;
+ expect_flush_cache(mock_image_ctx, mock_io_image_dispatch_spec, 0);
expect_invalidate_cache(mock_image_ctx, -EBUSY);
expect_trim(mock_image_ctx, mock_trim_request, -EINVAL);
expect_commit_op_event(mock_image_ctx, -EINVAL);
expect_unblock_writes(mock_image_ctx);
MockTrimRequest mock_trim_request;
- auto mock_io_image_dispatch_spec = new MockIoImageDispatchSpec();
- expect_flush_cache(mock_image_ctx, *mock_io_image_dispatch_spec, -EINVAL);
+ MockIoImageDispatchSpec mock_io_image_dispatch_spec;
+ expect_flush_cache(mock_image_ctx, mock_io_image_dispatch_spec, -EINVAL);
expect_commit_op_event(mock_image_ctx, -EINVAL);
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size / 2, true, 0, false));
}
expect_unblock_writes(mock_image_ctx);
MockTrimRequest mock_trim_request;
- auto mock_io_image_dispatch_spec = new MockIoImageDispatchSpec();
- expect_flush_cache(mock_image_ctx, *mock_io_image_dispatch_spec, 0);
+ MockIoImageDispatchSpec mock_io_image_dispatch_spec;
+ expect_flush_cache(mock_image_ctx, mock_io_image_dispatch_spec, 0);
expect_invalidate_cache(mock_image_ctx, -EINVAL);
expect_commit_op_event(mock_image_ctx, -EINVAL);
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size / 2, true, 0, false));
expect_unblock_writes(mock_image_ctx);
MockTrimRequest mock_trim_request;
- auto mock_io_image_dispatch_spec = new MockIoImageDispatchSpec();
- expect_flush_cache(mock_image_ctx, *mock_io_image_dispatch_spec, 0);
+ MockIoImageDispatchSpec mock_io_image_dispatch_spec;
+ expect_flush_cache(mock_image_ctx, mock_io_image_dispatch_spec, 0);
expect_invalidate_cache(mock_image_ctx, 0);
expect_trim(mock_image_ctx, mock_trim_request, 0);
expect_block_writes(mock_image_ctx, -EINVAL);
*image_ctx, librbd::io::IMAGE_DISPATCH_LAYER_INTERNAL_START, aio_comp,
librbd::io::FLUSH_SOURCE_INTERNAL, {});
req->send();
- delete req;
return ctx.wait();
}