--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_ASIO_UTILS_H
+#define CEPH_LIBRBD_ASIO_UTILS_H
+
+#include "include/Context.h"
+#include "include/rados/librados_fwd.hpp"
+#include <boost/system/error_code.hpp>
+
+namespace librbd {
+namespace asio {
+namespace util {
+
+template <typename T>
+auto get_context_adapter(T&& t) {
+ return [t = std::move(t)](boost::system::error_code ec) {
+ t->complete(-ec.value());
+ };
+}
+
+template <typename T>
+auto get_callback_adapter(T&& t) {
+ return [t = std::move(t)](boost::system::error_code ec, auto&& ... args) {
+ t(-ec.value(), std::forward<decltype(args)>(args)...);
+ };
+}
+
+} // namespace util
+} // namespace asio
+} // namespace librbd
+
+#endif // CEPH_LIBRBD_ASIO_UTILS_H
bool ObjectCacherObjectDispatch<I>::read(
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags, const ZTracer::Trace &parent_trace,
- ceph::bufferlist* read_data, io::ExtentMap* extent_map,
+ ceph::bufferlist* read_data, io::Extents* extent_map,
int* object_dispatch_flags, io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) {
// IO chained in reverse order
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags,
const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
- io::ExtentMap* extent_map, int* object_dispatch_flags,
+ io::Extents* extent_map, int* object_dispatch_flags,
io::DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) override;
uint64_t object_no, uint64_t object_off,
uint64_t object_len, librados::snap_t snap_id, int op_flags,
const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
- io::ExtentMap* extent_map, int* object_dispatch_flags,
+ io::Extents* extent_map, int* object_dispatch_flags,
io::DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) {
auto cct = m_image_ctx->cct;
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags,
const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
- io::ExtentMap* extent_map, int* object_dispatch_flags,
+ io::Extents* extent_map, int* object_dispatch_flags,
io::DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) override;
bool WriteAroundObjectDispatch<I>::read(
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags, const ZTracer::Trace &parent_trace,
- ceph::bufferlist* read_data, io::ExtentMap* extent_map,
+ ceph::bufferlist* read_data, io::Extents* extent_map,
int* object_dispatch_flags, io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) {
return dispatch_unoptimized_io(object_no, object_off, object_len,
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags,
const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
- io::ExtentMap* extent_map, int* object_dispatch_flags,
+ io::Extents* extent_map, int* object_dispatch_flags,
io::DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) override;
// vim: ts=8 sw=2 smarttab
#include "librbd/io/CopyupRequest.h"
+#include "include/neorados/RADOS.hpp"
#include "common/ceph_context.h"
#include "common/ceph_mutex.h"
#include "common/dout.h"
#include "librbd/ObjectMap.h"
#include "librbd/Utils.h"
#include "librbd/asio/ContextWQ.h"
+#include "librbd/asio/Utils.h"
#include "librbd/deep_copy/ObjectCopyRequest.h"
#include "librbd/io/AioCompletion.h"
#include "librbd/io/ImageRequest.h"
auto cct = m_image_ctx->cct;
m_image_ctx->image_lock.lock_shared();
auto snapc = m_image_ctx->snapc;
+ auto io_context = m_image_ctx->get_data_io_context();
m_image_ctx->image_lock.unlock_shared();
m_lock.lock();
m_copyup_extent_map.clear();
}
- int r;
- librados::ObjectWriteOperation copyup_op;
+ neorados::WriteOp copyup_op;
if (copy_on_read || deep_copyup) {
if (m_image_ctx->enable_sparse_copyup) {
cls_client::sparse_copyup(©up_op, m_copyup_extent_map, m_copyup_data);
++m_pending_copyups;
}
- librados::ObjectWriteOperation write_op;
+ neorados::WriteOp write_op;
if (!copy_on_read) {
if (!deep_copyup) {
if (m_image_ctx->enable_sparse_copyup) {
m_lock.unlock();
// issue librados ops at the end to simplify test cases
- std::string oid(data_object_name(m_image_ctx, m_object_no));
- std::vector<librados::snap_t> snaps;
+ auto object = neorados::Object{data_object_name(m_image_ctx, m_object_no)};
if (copyup_op.size() > 0) {
// send only the copyup request with a blank snapshot context so that
// all snapshots are detected from the parent for this object. If
// actual modification.
ldout(cct, 20) << "copyup with empty snapshot context" << dendl;
- auto comp = util::create_rados_callback<
- CopyupRequest<I>, &CopyupRequest<I>::handle_copyup>(this);
- r = m_image_ctx->data_ctx.aio_operate(
- oid, comp, ©up_op, 0, snaps,
- (m_trace.valid() ? m_trace.get_info() : nullptr));
- ceph_assert(r == 0);
- comp->release();
+ auto copyup_io_context = *io_context;
+ copyup_io_context.write_snap_context({});
+
+ m_image_ctx->rados_api.execute(
+ object, copyup_io_context, std::move(copyup_op),
+ librbd::asio::util::get_callback_adapter(
+ [this](int r) { handle_copyup(r); }), nullptr,
+ (this->m_trace.valid() ? this->m_trace.get_info() : nullptr));
}
if (write_op.size() > 0) {
"copyup + ops" : !deep_copyup ? "copyup" : "ops")
<< " with current snapshot context" << dendl;
- snaps.insert(snaps.end(), snapc.snaps.begin(), snapc.snaps.end());
- auto comp = util::create_rados_callback<
- CopyupRequest<I>, &CopyupRequest<I>::handle_copyup>(this);
- r = m_image_ctx->data_ctx.aio_operate(
- oid, comp, &write_op, snapc.seq, snaps,
- (m_trace.valid() ? m_trace.get_info() : nullptr));
- ceph_assert(r == 0);
- comp->release();
+ m_image_ctx->rados_api.execute(
+ object, *io_context, std::move(write_op),
+ librbd::asio::util::get_callback_adapter(
+ [this](int r) { handle_copyup(r); }), nullptr,
+ (this->m_trace.valid() ? this->m_trace.get_info() : nullptr));
}
}
#define CEPH_LIBRBD_IO_COPYUP_REQUEST_H
#include "include/int_types.h"
-#include "include/rados/librados.hpp"
#include "include/buffer.h"
#include "common/ceph_mutex.h"
#include "common/zipkin_trace.h"
uint64_t length;
bufferlist read_data;
- io::ExtentMap extent_map;
+ io::Extents extent_map;
C_RBD_Readahead(I *ictx, uint64_t object_no, uint64_t offset, uint64_t length)
: ictx(ictx), object_no(object_no), offset(offset), length(length) {
bool ObjectDispatch<I>::read(
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags, const ZTracer::Trace &parent_trace,
- ceph::bufferlist* read_data, ExtentMap* extent_map,
+ ceph::bufferlist* read_data, Extents* extent_map,
int* object_dispatch_flags, DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) {
auto cct = m_image_ctx->cct;
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags,
const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
- ExtentMap* extent_map, int* object_dispatch_flags,
+ Extents* extent_map, int* object_dispatch_flags,
DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) override;
virtual bool read(
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags,const ZTracer::Trace &parent_trace,
- ceph::bufferlist* read_data, ExtentMap* extent_map,
+ ceph::bufferlist* read_data, Extents* extent_map,
int* object_dispatch_flags, DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) = 0;
uint64_t object_len;
librados::snap_t snap_id;
ceph::bufferlist* read_data;
- ExtentMap* extent_map;
+ Extents* extent_map;
ReadRequest(uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, ceph::bufferlist* read_data,
- ExtentMap* extent_map)
+ Extents* extent_map)
: RequestBase(object_no, object_off),
object_len(object_len), snap_id(snap_id), read_data(read_data),
extent_map(extent_map) {
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags,
const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
- ExtentMap* extent_map, Context* on_finish) {
+ Extents* extent_map, Context* on_finish) {
return new ObjectDispatchSpec(image_ctx->io_object_dispatcher,
object_dispatch_layer,
ReadRequest{object_no, object_off,
#include "common/ceph_mutex.h"
#include "include/Context.h"
#include "include/err.h"
+#include "include/neorados/RADOS.hpp"
#include "osd/osd_types.h"
#include "librbd/AsioEngine.h"
#include "librbd/ImageCtx.h"
#include "librbd/ObjectMap.h"
#include "librbd/Utils.h"
+#include "librbd/asio/Utils.h"
#include "librbd/io/AioCompletion.h"
#include "librbd/io/CopyupRequest.h"
#include "librbd/io/ImageRequest.h"
#include "librbd/io/ReadResult.h"
+#include "librbd/io/Utils.h"
#include <boost/bind.hpp>
#include <boost/optional.hpp>
const ZTracer::Trace &trace, Context *completion)
: m_ictx(ictx), m_object_no(objectno), m_object_off(off),
m_object_len(len), m_snap_id(snap_id), m_completion(completion),
- m_trace(util::create_trace(*ictx, "", trace)) {
+ m_trace(librbd::util::create_trace(*ictx, "", trace)) {
ceph_assert(m_ictx->data_ctx.is_valid());
if (m_trace.valid()) {
m_trace.copy_name(trace_name + std::string(" ") +
}
template <typename I>
-void ObjectRequest<I>::add_write_hint(I& image_ctx,
- librados::ObjectWriteOperation *wr) {
+void ObjectRequest<I>::add_write_hint(I& image_ctx, neorados::WriteOp* wr) {
+ auto alloc_hint_flags = static_cast<neorados::alloc_hint::alloc_hint_t>(
+ image_ctx.alloc_hint_flags);
if (image_ctx.enable_alloc_hint) {
- wr->set_alloc_hint2(image_ctx.get_object_size(),
- image_ctx.get_object_size(),
- image_ctx.alloc_hint_flags);
+ wr->set_alloc_hint(image_ctx.get_object_size(),
+ image_ctx.get_object_size(),
+ alloc_hint_flags);
} else if (image_ctx.alloc_hint_flags != 0U) {
- wr->set_alloc_hint2(0, 0, image_ctx.alloc_hint_flags);
+ wr->set_alloc_hint(0, 0, alloc_hint_flags);
}
}
ObjectReadRequest<I>::ObjectReadRequest(
I *ictx, uint64_t objectno, uint64_t offset, uint64_t len,
librados::snap_t snap_id, int op_flags, const ZTracer::Trace &parent_trace,
- bufferlist* read_data, ExtentMap* extent_map, Context *completion)
+ bufferlist* read_data, Extents* extent_map, Context *completion)
: ObjectRequest<I>(ictx, objectno, offset, len, snap_id, "read",
parent_trace, completion),
m_op_flags(op_flags), m_read_data(read_data), m_extent_map(extent_map) {
ldout(image_ctx->cct, 20) << dendl;
- librados::ObjectReadOperation op;
+ neorados::ReadOp read_op;
if (this->m_object_len >= image_ctx->sparse_read_threshold_bytes) {
- op.sparse_read(this->m_object_off, this->m_object_len, m_extent_map,
- m_read_data, nullptr);
+ read_op.sparse_read(this->m_object_off, this->m_object_len, m_read_data,
+ m_extent_map);
} else {
- op.read(this->m_object_off, this->m_object_len, m_read_data, nullptr);
+ read_op.read(this->m_object_off, this->m_object_len, m_read_data);
}
- op.set_op_flags2(m_op_flags);
+ util::apply_op_flags(m_op_flags, image_ctx->get_read_flags(this->m_snap_id),
+ &read_op);
- librados::AioCompletion *rados_completion = util::create_rados_callback<
- ObjectReadRequest<I>, &ObjectReadRequest<I>::handle_read_object>(this);
- int flags = image_ctx->get_read_flags(this->m_snap_id);
- int r = image_ctx->data_ctx.aio_operate(
- data_object_name(this->m_ictx, this->m_object_no), rados_completion, &op,
- flags, nullptr,
- (this->m_trace.valid() ? this->m_trace.get_info() : nullptr));
- ceph_assert(r == 0);
-
- rados_completion->release();
+ image_ctx->rados_api.execute(
+ {data_object_name(this->m_ictx, this->m_object_no)},
+ *image_ctx->get_data_io_context(), std::move(read_op), nullptr,
+ librbd::asio::util::get_callback_adapter(
+ [this](int r) { handle_read_object(r); }), nullptr,
+ (this->m_trace.valid() ? this->m_trace.get_info() : nullptr));
}
template <typename I>
auto parent_completion = AioCompletion::create_and_start<
ObjectReadRequest<I>, &ObjectReadRequest<I>::handle_read_parent>(
- this, util::get_image_ctx(image_ctx->parent), AIO_TYPE_READ);
+ this, librbd::util::get_image_ctx(image_ctx->parent), AIO_TYPE_READ);
ImageRequest<I>::aio_read(image_ctx->parent, parent_completion,
std::move(parent_extents), ReadResult{m_read_data},
0, this->m_trace);
template <typename I>
void AbstractObjectWriteRequest<I>::add_write_hint(
- librados::ObjectWriteOperation *wr) {
+ neorados::WriteOp *wr) {
I *image_ctx = this->m_ictx;
std::shared_lock image_locker{image_ctx->image_lock};
if (image_ctx->object_map == nullptr || !this->m_object_may_exist) {
I *image_ctx = this->m_ictx;
ldout(image_ctx->cct, 20) << dendl;
- librados::ObjectWriteOperation write;
+ neorados::WriteOp write_op;
if (m_copyup_enabled) {
ldout(image_ctx->cct, 20) << "guarding write" << dendl;
if (m_guarding_migration_write) {
cls_client::assert_snapc_seq(
- &write, m_snap_seq, cls::rbd::ASSERT_SNAPC_SEQ_LE_SNAPSET_SEQ);
+ &write_op, m_snap_seq, cls::rbd::ASSERT_SNAPC_SEQ_LE_SNAPSET_SEQ);
} else {
- write.assert_exists();
+ write_op.assert_exists();
}
}
- add_write_hint(&write);
- add_write_ops(&write);
- ceph_assert(write.size() != 0);
+ add_write_hint(&write_op);
+ add_write_ops(&write_op);
+ ceph_assert(write_op.size() != 0);
- librados::AioCompletion *rados_completion = util::create_rados_callback<
- AbstractObjectWriteRequest<I>,
- &AbstractObjectWriteRequest<I>::handle_write_object>(this);
- int r = image_ctx->data_ctx.aio_operate(
- data_object_name(this->m_ictx, this->m_object_no), rados_completion,
- &write, m_snap_seq, m_snaps,
- (this->m_trace.valid() ? this->m_trace.get_info() : nullptr));
- ceph_assert(r == 0);
- rados_completion->release();
+ image_ctx->rados_api.execute(
+ {data_object_name(this->m_ictx, this->m_object_no)},
+ *image_ctx->get_data_io_context(), std::move(write_op),
+ librbd::asio::util::get_callback_adapter(
+ [this](int r) { handle_write_object(r); }), nullptr,
+ (this->m_trace.valid() ? this->m_trace.get_info() : nullptr));
}
template <typename I>
}
template <typename I>
-void ObjectWriteRequest<I>::add_write_ops(librados::ObjectWriteOperation *wr) {
+void ObjectWriteRequest<I>::add_write_ops(neorados::WriteOp* wr) {
if (this->m_full_object) {
- wr->write_full(m_write_data);
+ wr->write_full(bufferlist{m_write_data});
} else {
- wr->write(this->m_object_off, m_write_data);
+ wr->write(this->m_object_off, bufferlist{m_write_data});
+ }
+ util::apply_op_flags(m_op_flags, 0U, wr);
+}
+
+template <typename I>
+void ObjectDiscardRequest<I>::add_write_ops(neorados::WriteOp* wr) {
+ switch (m_discard_action) {
+ case DISCARD_ACTION_REMOVE:
+ wr->remove();
+ break;
+ case DISCARD_ACTION_REMOVE_TRUNCATE:
+ wr->create(false);
+ // fall through
+ case DISCARD_ACTION_TRUNCATE:
+ wr->truncate(this->m_object_off);
+ break;
+ case DISCARD_ACTION_ZERO:
+ wr->zero(this->m_object_off, this->m_object_len);
+ break;
+ default:
+ ceph_abort();
+ break;
}
- wr->set_op_flags2(m_op_flags);
}
template <typename I>
-void ObjectWriteSameRequest<I>::add_write_ops(
- librados::ObjectWriteOperation *wr) {
- wr->writesame(this->m_object_off, this->m_object_len, m_write_data);
- wr->set_op_flags2(m_op_flags);
+void ObjectWriteSameRequest<I>::add_write_ops(neorados::WriteOp* wr) {
+ wr->writesame(this->m_object_off, this->m_object_len,
+ bufferlist{m_write_data});
+ util::apply_op_flags(m_op_flags, 0U, wr);
}
template <typename I>
-void ObjectCompareAndWriteRequest<I>::add_write_ops(
- librados::ObjectWriteOperation *wr) {
- wr->cmpext(this->m_object_off, m_cmp_bl, nullptr);
+void ObjectCompareAndWriteRequest<I>::add_write_ops(neorados::WriteOp* wr) {
+ wr->cmpext(this->m_object_off, bufferlist{m_cmp_bl}, nullptr);
if (this->m_full_object) {
- wr->write_full(m_write_bl);
+ wr->write_full(bufferlist{m_write_bl});
} else {
- wr->write(this->m_object_off, m_write_bl);
+ wr->write(this->m_object_off, bufferlist{m_write_bl});
}
- wr->set_op_flags2(m_op_flags);
+ util::apply_op_flags(m_op_flags, 0U, wr);
}
template <typename I>
class Context;
class ObjectExtent;
+namespace neorados { struct WriteOp; }
+
namespace librbd {
struct ImageCtx;
}
static void add_write_hint(ImageCtxT& image_ctx,
- librados::ObjectWriteOperation *wr);
+ neorados::WriteOp *wr);
virtual void send() = 0;
template <typename ImageCtxT = ImageCtx>
class ObjectReadRequest : public ObjectRequest<ImageCtxT> {
public:
- typedef std::map<uint64_t, uint64_t> ExtentMap;
-
static ObjectReadRequest* create(
ImageCtxT *ictx, uint64_t objectno, uint64_t offset, uint64_t len,
librados::snap_t snap_id, int op_flags,
const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
- ExtentMap* extent_map, Context *completion) {
+ Extents* extent_map, Context *completion) {
return new ObjectReadRequest(ictx, objectno, offset, len,
snap_id, op_flags, parent_trace, read_data,
extent_map, completion);
ImageCtxT *ictx, uint64_t objectno, uint64_t offset, uint64_t len,
librados::snap_t snap_id, int op_flags,
const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
- ExtentMap* extent_map, Context *completion);
+ Extents* extent_map, Context *completion);
void send() override;
int m_op_flags;
ceph::bufferlist* m_read_data;
- ExtentMap* m_extent_map;
+ Extents* m_extent_map;
void read_object();
void handle_read_object(int r);
return OBJECT_EXISTS;
}
- virtual void add_copyup_ops(librados::ObjectWriteOperation *wr) {
+ virtual void add_copyup_ops(neorados::WriteOp *wr) {
add_write_ops(wr);
}
return false;
}
- virtual void add_write_hint(librados::ObjectWriteOperation *wr);
- virtual void add_write_ops(librados::ObjectWriteOperation *wr) = 0;
+ virtual void add_write_hint(neorados::WriteOp *wr);
+ virtual void add_write_ops(neorados::WriteOp *wr) = 0;
virtual int filter_write_result(int r) const {
return r;
}
protected:
- void add_write_ops(librados::ObjectWriteOperation *wr) override;
+ void add_write_ops(neorados::WriteOp *wr) override;
private:
ceph::bufferlist m_write_data;
return (m_discard_action == DISCARD_ACTION_REMOVE);
}
- void add_write_hint(librados::ObjectWriteOperation *wr) override {
+ void add_write_hint(neorados::WriteOp *wr) override {
// no hint for discard
}
- void add_write_ops(librados::ObjectWriteOperation *wr) override {
- switch (m_discard_action) {
- case DISCARD_ACTION_REMOVE:
- wr->remove();
- break;
- case DISCARD_ACTION_REMOVE_TRUNCATE:
- wr->create(false);
- // fall through
- case DISCARD_ACTION_TRUNCATE:
- wr->truncate(this->m_object_off);
- break;
- case DISCARD_ACTION_ZERO:
- wr->zero(this->m_object_off, this->m_object_len);
- break;
- default:
- ceph_abort();
- break;
- }
- }
+ void add_write_ops(neorados::WriteOp *wr) override;
private:
enum DiscardAction {
}
protected:
- void add_write_ops(librados::ObjectWriteOperation *wr) override;
+ void add_write_ops(neorados::WriteOp *wr) override;
private:
ceph::bufferlist m_write_data;
return "compare_and_write";
}
- void add_copyup_ops(librados::ObjectWriteOperation *wr) override {
+ void add_copyup_ops(neorados::WriteOp *wr) override {
// no-op on copyup
}
return true;
}
- void add_write_ops(librados::ObjectWriteOperation *wr) override;
+ void add_write_ops(neorados::WriteOp *wr) override;
int filter_write_result(int r) const override;
LightweightBufferExtents buffer_extents;
bufferlist bl;
- ExtentMap extent_map;
+ Extents extent_map;
C_ObjectReadRequest(AioCompletion *aio_completion, uint64_t object_off,
uint64_t object_len,
bool SimpleSchedulerObjectDispatch<I>::read(
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags, const ZTracer::Trace &parent_trace,
- ceph::bufferlist* read_data, ExtentMap* extent_map,
+ ceph::bufferlist* read_data, Extents* extent_map,
int* object_dispatch_flags, DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) {
auto cct = m_image_ctx->cct;
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags,
const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
- ExtentMap* extent_map, int* object_dispatch_flags,
+ Extents* extent_map, int* object_dispatch_flags,
DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) override;
#include "librbd/io/Utils.h"
#include "include/buffer.h"
+#include "include/rados/librados.hpp"
+#include "include/neorados/RADOS.hpp"
#include "osd/osd_types.h"
namespace librbd {
namespace io {
namespace util {
+void apply_op_flags(uint32_t op_flags, uint32_t flags, neorados::Op* op) {
+ if (op_flags & LIBRADOS_OP_FLAG_FADVISE_RANDOM)
+ op->set_fadvise_random();
+ if (op_flags & LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL)
+ op->set_fadvise_sequential();
+ if (op_flags & LIBRADOS_OP_FLAG_FADVISE_WILLNEED)
+ op->set_fadvise_willneed();
+ if (op_flags & LIBRADOS_OP_FLAG_FADVISE_DONTNEED)
+ op->set_fadvise_dontneed();
+ if (op_flags & LIBRADOS_OP_FLAG_FADVISE_NOCACHE)
+ op->set_fadvise_nocache();
+
+ if (flags & librados::OPERATION_BALANCE_READS)
+ op->balance_reads();
+ if (flags & librados::OPERATION_LOCALIZE_READS)
+ op->localize_reads();
+}
+
bool assemble_write_same_extent(
const LightweightObjectExtent &object_extent, const ceph::bufferlist& data,
ceph::bufferlist *ws_data, bool force_write) {
class ObjectExtent;
+namespace neorados { struct Op; }
+
namespace librbd {
namespace io {
namespace util {
+void apply_op_flags(uint32_t op_flags, uint32_t flags, neorados::Op* op);
+
bool assemble_write_same_extent(const LightweightObjectExtent &object_extent,
const ceph::bufferlist& data,
ceph::bufferlist *ws_data,
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags,
const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
- io::ExtentMap* extent_map, int* object_dispatch_flags,
+ io::Extents* extent_map, int* object_dispatch_flags,
io::DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) {
return false;
}
};
+template <typename I>
+void add_partial_sparse_result(
+ CephContext *cct,
+ std::map<uint64_t, std::pair<ceph::buffer::list, uint64_t> >* partial,
+ uint64_t* total_intended_len, bufferlist& bl, I* it, const I& end_it,
+ uint64_t* bl_off, uint64_t tofs, uint64_t tlen) {
+ ldout(cct, 30) << " be " << tofs << "~" << tlen << dendl;
+
+ auto& s = *it;
+ while (tlen > 0) {
+ ldout(cct, 20) << " t " << tofs << "~" << tlen
+ << " bl has " << bl.length()
+ << " off " << *bl_off << dendl;
+ if (s == end_it) {
+ ldout(cct, 20) << " s at end" << dendl;
+ auto& r = (*partial)[tofs];
+ r.second = tlen;
+ *total_intended_len += r.second;
+ break;
+ }
+
+ ldout(cct, 30) << " s " << s->first << "~" << s->second << dendl;
+
+ // skip zero-length extent
+ if (s->second == 0) {
+ ldout(cct, 30) << " s len 0, skipping" << dendl;
+ ++s;
+ continue;
+ }
+
+ if (s->first > *bl_off) {
+ // gap in sparse read result
+ pair<bufferlist, uint64_t>& r = (*partial)[tofs];
+ size_t gap = std::min<size_t>(s->first - *bl_off, tlen);
+ ldout(cct, 20) << " s gap " << gap << ", skipping" << dendl;
+ r.second = gap;
+ *total_intended_len += r.second;
+ *bl_off += gap;
+ tofs += gap;
+ tlen -= gap;
+ if (tlen == 0) {
+ continue;
+ }
+ }
+
+ ceph_assert(s->first <= *bl_off);
+ size_t left = (s->first + s->second) - *bl_off;
+ size_t actual = std::min<size_t>(left, tlen);
+
+ if (actual > 0) {
+ ldout(cct, 20) << " s has " << actual << ", copying" << dendl;
+ pair<bufferlist, uint64_t>& r = (*partial)[tofs];
+ bl.splice(0, actual, &r.first);
+ r.second = actual;
+ *total_intended_len += r.second;
+ *bl_off += actual;
+ tofs += actual;
+ tlen -= actual;
+ }
+ if (actual == left) {
+ ldout(cct, 30) << " s advancing" << dendl;
+ ++s;
+ }
+ }
+}
+
} // anonymous namespace
void Striper::file_to_extents(CephContext *cct, const char *object_format,
<< " to " << buffer_extents << dendl;
auto s = bl_map.cbegin();
for (auto& be : buffer_extents) {
- add_partial_sparse_result(cct, bl, &s, bl_map.end(), &bl_off, be.first,
- be.second);
+ ::add_partial_sparse_result(cct, &partial, &total_intended_len, bl, &s,
+ bl_map.end(), &bl_off, be.first, be.second);
}
}
void Striper::StripedReadResult::add_partial_sparse_result(
CephContext *cct, ceph::buffer::list& bl,
- const std::map<uint64_t, uint64_t>& bl_map, uint64_t bl_off,
+ const std::vector<std::pair<uint64_t, uint64_t>>& bl_map, uint64_t bl_off,
const striper::LightweightBufferExtents& buffer_extents) {
ldout(cct, 10) << "add_partial_sparse_result(" << this << ") " << bl.length()
<< " covering " << bl_map << " (offset " << bl_off << ")"
<< " to " << buffer_extents << dendl;
auto s = bl_map.cbegin();
for (auto& be : buffer_extents) {
- add_partial_sparse_result(cct, bl, &s, bl_map.cend(), &bl_off, be.first,
- be.second);
- }
-}
-
-void Striper::StripedReadResult::add_partial_sparse_result(
- CephContext *cct, bufferlist& bl,
- std::map<uint64_t, uint64_t>::const_iterator* it,
- const std::map<uint64_t, uint64_t>::const_iterator& end_it,
- uint64_t* bl_off, uint64_t tofs, uint64_t tlen) {
- ldout(cct, 30) << " be " << tofs << "~" << tlen << dendl;
-
- auto& s = *it;
- while (tlen > 0) {
- ldout(cct, 20) << " t " << tofs << "~" << tlen
- << " bl has " << bl.length()
- << " off " << *bl_off << dendl;
- if (s == end_it) {
- ldout(cct, 20) << " s at end" << dendl;
- auto& r = partial[tofs];
- r.second = tlen;
- total_intended_len += r.second;
- break;
- }
-
- ldout(cct, 30) << " s " << s->first << "~" << s->second << dendl;
-
- // skip zero-length extent
- if (s->second == 0) {
- ldout(cct, 30) << " s len 0, skipping" << dendl;
- ++s;
- continue;
- }
-
- if (s->first > *bl_off) {
- // gap in sparse read result
- pair<bufferlist, uint64_t>& r = partial[tofs];
- size_t gap = std::min<size_t>(s->first - *bl_off, tlen);
- ldout(cct, 20) << " s gap " << gap << ", skipping" << dendl;
- r.second = gap;
- total_intended_len += r.second;
- *bl_off += gap;
- tofs += gap;
- tlen -= gap;
- if (tlen == 0) {
- continue;
- }
- }
-
- ceph_assert(s->first <= *bl_off);
- size_t left = (s->first + s->second) - *bl_off;
- size_t actual = std::min<size_t>(left, tlen);
-
- if (actual > 0) {
- ldout(cct, 20) << " s has " << actual << ", copying" << dendl;
- pair<bufferlist, uint64_t>& r = partial[tofs];
- bl.splice(0, actual, &r.first);
- r.second = actual;
- total_intended_len += r.second;
- *bl_off += actual;
- tofs += actual;
- tlen -= actual;
- }
- if (actual == left) {
- ldout(cct, 30) << " s advancing" << dendl;
- ++s;
- }
+ ::add_partial_sparse_result(cct, &partial, &total_intended_len, bl, &s,
+ bl_map.cend(), &bl_off, be.first, be.second);
}
}
const std::vector<std::pair<uint64_t,uint64_t> >& buffer_extents);
void add_partial_sparse_result(
CephContext *cct, ceph::buffer::list& bl,
- const std::map<uint64_t, uint64_t>& bl_map, uint64_t bl_off,
- const striper::LightweightBufferExtents& buffer_extents);
+ const std::vector<std::pair<uint64_t, uint64_t>>& bl_map,
+ uint64_t bl_off,
+ const striper::LightweightBufferExtents& buffer_extents);
void assemble_result(CephContext *cct, ceph::buffer::list& bl,
bool zero_tail);
void assemble_result(CephContext *cct,
std::map<uint64_t, uint64_t> *extent_map,
ceph::buffer::list *bl);
-
- private:
- void add_partial_sparse_result(
- CephContext *cct, ceph::buffer::list& bl,
- std::map<uint64_t, uint64_t>::const_iterator* it,
- const std::map<uint64_t, uint64_t>::const_iterator& end_it,
- uint64_t* bl_off, uint64_t tofs, uint64_t tlen);
};
};
template <>
struct ObjectRequest<librbd::MockTestImageCtx> {
static void add_write_hint(librbd::MockTestImageCtx&,
- librados::ObjectWriteOperation*) {
+ neorados::WriteOp*) {
}
};
MOCK_CONST_METHOD0(get_pre_write_object_map_state, uint8_t());
MOCK_CONST_METHOD0(is_empty_write_op, bool());
- MOCK_METHOD1(add_copyup_ops, void(librados::ObjectWriteOperation*));
+ MOCK_METHOD1(add_copyup_ops, void(neorados::WriteOp*));
};
template <>
snapc = mock_image_ctx.snapc;
}
- EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ EXPECT_CALL(mock_io_ctx,
exec(oid, _, StrEq("rbd"), StrEq("copyup"),
ContentsEqual(in_bl), _, _, snapc))
.WillOnce(Return(r));
snapc = mock_image_ctx.snapc;
}
- EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ EXPECT_CALL(mock_io_ctx,
exec(oid, _, StrEq("rbd"), StrEq("sparse_copyup"),
ContentsEqual(in_bl), _, _, snapc))
.WillOnce(Return(r));
snapc = mock_image_ctx.snapc;
}
- EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
- write(oid, _, 0, 0, snapc))
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ EXPECT_CALL(mock_io_ctx, write(oid, _, 0, 0, snapc))
.WillOnce(Return(r));
}
void expect_add_copyup_ops(MockAbstractObjectWriteRequest& mock_write_request) {
EXPECT_CALL(mock_write_request, add_copyup_ops(_))
- .WillOnce(Invoke([](librados::ObjectWriteOperation* op) {
+ .WillOnce(Invoke([](neorados::WriteOp* op) {
op->write(0, bufferlist{});
}));
}
{{0, 4096}}, data, 0);
MockAbstractObjectWriteRequest mock_write_request2;
- EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
- write(ictx->get_object_name(0), _, 0, 0, _))
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ EXPECT_CALL(mock_io_ctx, write(ictx->get_object_name(0), _, 0, 0, _))
.WillOnce(WithoutArgs(Invoke([req, &mock_write_request2]() {
req->append_request(&mock_write_request2);
return 0;
bufferlist bl;
bl.append(data);
- auto& expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
- read(oid, len, off, _, _));
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ auto& expect = EXPECT_CALL(mock_io_ctx, read(oid, len, off, _, _));
if (r < 0) {
expect.WillOnce(Return(r));
} else {
bufferlist bl;
bl.append(data);
- auto& expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ auto& expect = EXPECT_CALL(mock_io_ctx,
sparse_read(oid, off, len, _, _, _));
if (r < 0) {
expect.WillOnce(Return(r));
}
void expect_assert_exists(MockTestImageCtx &mock_image_ctx, int r) {
- EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
- assert_exists(_, _))
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ EXPECT_CALL(mock_io_ctx, assert_exists(_, _))
.WillOnce(Return(r));
}
void expect_write(MockTestImageCtx &mock_image_ctx,
uint64_t offset, uint64_t length, int r) {
- auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ auto &expect = EXPECT_CALL(mock_io_ctx,
write(_, _, length, offset, _));
if (r < 0) {
expect.WillOnce(Return(r));
}
void expect_write_full(MockTestImageCtx &mock_image_ctx, int r) {
- auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
- write_full(_, _, _));
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ auto &expect = EXPECT_CALL(mock_io_ctx, write_full(_, _, _));
if (r < 0) {
expect.WillOnce(Return(r));
} else {
void expect_writesame(MockTestImageCtx &mock_image_ctx,
uint64_t offset, uint64_t length, int r) {
- auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
- writesame(_, _, length, offset, _));
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ auto &expect = EXPECT_CALL(mock_io_ctx, writesame(_, _, length, offset, _));
if (r < 0) {
expect.WillOnce(Return(r));
} else {
}
void expect_remove(MockTestImageCtx &mock_image_ctx, int r) {
- auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
- remove(_, _));
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ auto &expect = EXPECT_CALL(mock_io_ctx, remove(_, _));
if (r < 0) {
expect.WillOnce(Return(r));
} else {
}
void expect_create(MockTestImageCtx &mock_image_ctx, bool exclusive) {
- EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx), create(_, exclusive, _))
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ EXPECT_CALL(mock_io_ctx, create(_, exclusive, _))
.Times(1);
}
void expect_truncate(MockTestImageCtx &mock_image_ctx, int offset, int r) {
- auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
- truncate(_, offset, _));
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ auto &expect = EXPECT_CALL(mock_io_ctx, truncate(_, offset, _));
if (r < 0) {
expect.WillOnce(Return(r));
} else {
void expect_zero(MockTestImageCtx &mock_image_ctx, int offset, int length,
int r) {
- auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
- zero(_, offset, length, _));
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ auto &expect = EXPECT_CALL(mock_io_ctx, zero(_, offset, length, _));
if (r < 0) {
expect.WillOnce(Return(r));
} else {
}
void expect_cmpext(MockTestImageCtx &mock_image_ctx, int offset, int r) {
- auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
- cmpext(_, offset, _, _));
+ auto& mock_io_ctx = librados::get_mock_io_ctx(
+ mock_image_ctx.rados_api, *mock_image_ctx.get_data_io_context());
+ auto &expect = EXPECT_CALL(mock_io_ctx, cmpext(_, offset, _, _));
if (r < 0) {
expect.WillOnce(Return(r));
} else {
std::string(4096, '1'), 0);
bufferlist bl;
- ExtentMap extent_map;
+ Extents extent_map;
C_SaferCond ctx;
auto req = MockObjectReadRequest::create(
&mock_image_ctx, 0, 0, 4096, CEPH_NOSNAP, 0, {}, &bl, &extent_map, &ctx);
std::string(ictx->sparse_read_threshold_bytes, '1'), 0);
bufferlist bl;
- ExtentMap extent_map;
+ Extents extent_map;
C_SaferCond ctx;
auto req = MockObjectReadRequest::create(
&mock_image_ctx, 0, 0, ictx->sparse_read_threshold_bytes, CEPH_NOSNAP, 0,
expect_read(mock_image_ctx, ictx->get_object_name(0), 0, 4096, "", -EPERM);
bufferlist bl;
- ExtentMap extent_map;
+ Extents extent_map;
C_SaferCond ctx;
auto req = MockObjectReadRequest::create(
&mock_image_ctx, 0, 0, 4096, CEPH_NOSNAP, 0, {}, &bl, &extent_map, &ctx);
expect_aio_read(mock_image_ctx, mock_image_request, {{0, 4096}}, 0);
bufferlist bl;
- ExtentMap extent_map;
+ Extents extent_map;
C_SaferCond ctx;
auto req = MockObjectReadRequest::create(
&mock_image_ctx, 0, 0, 4096, CEPH_NOSNAP, 0, {}, &bl, &extent_map, &ctx);
expect_aio_read(mock_image_ctx, mock_image_request, {{0, 4096}}, -EPERM);
bufferlist bl;
- ExtentMap extent_map;
+ Extents extent_map;
C_SaferCond ctx;
auto req = MockObjectReadRequest::create(
&mock_image_ctx, 0, 0, 4096, CEPH_NOSNAP, 0, {}, &bl, &extent_map, &ctx);
expect_copyup(mock_copyup_request, 0);
bufferlist bl;
- ExtentMap extent_map;
+ Extents extent_map;
C_SaferCond ctx;
auto req = MockObjectReadRequest::create(
&mock_image_ctx, 0, 0, 4096, CEPH_NOSNAP, 0, {}, &bl, &extent_map, &ctx);
MOCK_METHOD8(execute_read,
bool(uint64_t, uint64_t, uint64_t, librados::snap_t,
- ceph::bufferlist*, ExtentMap*, DispatchResult*, Context*));
+ ceph::bufferlist*, Extents*, DispatchResult*, Context*));
bool read(
uint64_t object_no, uint64_t object_off, uint64_t object_len,
librados::snap_t snap_id, int op_flags,
const ZTracer::Trace& parent_trace, ceph::bufferlist* read_data,
- ExtentMap* extent_map, int* dispatch_flags,
+ Extents* extent_map, int* dispatch_flags,
DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) {
return execute_read(object_no, object_off, object_len, snap_id, read_data,