#include "common/perf_counters.h"
#include "common/WorkQueue.h"
-#include "librbd/AioObjectRequest.h"
#include "librbd/ImageCtx.h"
#include "librbd/internal.h"
return r;
}
-void C_AioRead::finish(int r)
-{
- m_completion->lock.Lock();
- CephContext *cct = m_completion->ictx->cct;
- ldout(cct, 10) << "C_AioRead::finish() " << this << " r = " << r << dendl;
-
- if (r >= 0 || r == -ENOENT) { // this was a sparse_read operation
- ldout(cct, 10) << " got " << m_req->m_ext_map
- << " for " << m_req->m_buffer_extents
- << " bl " << m_req->data().length() << dendl;
- // reads from the parent don't populate the m_ext_map and the overlap
- // may not be the full buffer. compensate here by filling in m_ext_map
- // with the read extent when it is empty.
- if (m_req->m_ext_map.empty())
- m_req->m_ext_map[m_req->m_object_off] = m_req->data().length();
-
- m_completion->destriper.add_partial_sparse_result(
- cct, m_req->data(), m_req->m_ext_map, m_req->m_object_off,
- m_req->m_buffer_extents);
- r = m_req->m_object_len;
- }
- m_completion->lock.Unlock();
-
- C_AioRequest::finish(r);
-}
-
-void C_CacheRead::complete(int r) {
- if (!m_enqueued) {
- // cache_lock creates a lock ordering issue -- so re-execute this context
- // outside the cache_lock
- m_enqueued = true;
- m_image_ctx.op_work_queue->queue(this, r);
- return;
- }
- Context::complete(r);
-}
-
-void C_CacheRead::finish(int r)
-{
- m_req->complete(r);
-}
-
} // namespace librbd
namespace librbd {
-class AioObjectRead;
-
typedef enum {
AIO_TYPE_NONE = 0,
AIO_TYPE_OPEN,
AioCompletion *m_completion;
};
-class C_AioRead : public C_AioRequest {
-public:
- C_AioRead(AioCompletion *completion)
- : C_AioRequest(completion), m_req(nullptr) {
- }
- virtual ~C_AioRead() {}
- virtual void finish(int r);
- void set_req(AioObjectRead *req) {
- m_req = req;
- }
-private:
- AioObjectRead *m_req;
-};
-
-class C_CacheRead : public Context {
-public:
- explicit C_CacheRead(ImageCtx *ictx, AioObjectRead *req)
- : m_image_ctx(*ictx), m_req(req), m_enqueued(false) {}
- virtual void complete(int r);
-protected:
- virtual void finish(int r);
-private:
- ImageCtx &m_image_ctx;
- AioObjectRead *m_req;
- bool m_enqueued;
-};
-
} // namespace librbd
#endif // CEPH_LIBRBD_AIO_COMPLETION_H
#include "librbd/Utils.h"
#include "librbd/journal/Types.h"
#include "include/rados/librados.hpp"
+#include "common/WorkQueue.h"
#include "osdc/Striper.h"
#define dout_subsys ceph_subsys_rbd
}
};
+class C_AioRead : public C_AioRequest {
+public:
+ C_AioRead(AioCompletion *completion)
+ : C_AioRequest(completion), m_req(nullptr) {
+ }
+
+ virtual void finish(int r) {
+ m_completion->lock.Lock();
+ CephContext *cct = m_completion->ictx->cct;
+ ldout(cct, 10) << "C_AioRead::finish() " << this << " r = " << r << dendl;
+
+ if (r >= 0 || r == -ENOENT) { // this was a sparse_read operation
+ ldout(cct, 10) << " got " << m_req->get_extent_map()
+ << " for " << m_req->get_buffer_extents()
+ << " bl " << m_req->data().length() << dendl;
+ // reads from the parent don't populate the m_ext_map and the overlap
+ // may not be the full buffer. compensate here by filling in m_ext_map
+ // with the read extent when it is empty.
+ if (m_req->get_extent_map().empty()) {
+ m_req->get_extent_map()[m_req->get_offset()] = m_req->data().length();
+ }
+
+ m_completion->destriper.add_partial_sparse_result(
+ cct, m_req->data(), m_req->get_extent_map(), m_req->get_offset(),
+ m_req->get_buffer_extents());
+ r = m_req->get_length();
+ }
+ m_completion->lock.Unlock();
+
+ C_AioRequest::finish(r);
+ }
+
+ void set_req(AioObjectRead *req) {
+ m_req = req;
+ }
+private:
+ AioObjectRead *m_req;
+};
+
+class C_CacheRead : public Context {
+public:
+ explicit C_CacheRead(ImageCtx *ictx, AioObjectRead *req)
+ : m_image_ctx(*ictx), m_req(req), m_enqueued(false) {}
+
+ virtual void complete(int r) {
+ if (!m_enqueued) {
+ // cache_lock creates a lock ordering issue -- so re-execute this context
+ // outside the cache_lock
+ m_enqueued = true;
+ m_image_ctx.op_work_queue->queue(this, r);
+ return;
+ }
+ Context::complete(r);
+ }
+
+protected:
+ virtual void finish(int r) {
+ m_req->complete(r);
+ }
+
+private:
+ ImageCtx &m_image_ctx;
+ AioObjectRead *m_req;
+ bool m_enqueued;
+};
+
} // anonymous namespace
template <typename I>
}
}
-void AioObjectRead::read_from_parent(const vector<pair<uint64_t,uint64_t> >& parent_extents)
+void AioObjectRead::read_from_parent(const Extents& parent_extents)
{
assert(!m_parent_completion);
m_parent_completion = AioCompletion::create_and_start<AioObjectRequest>(
class AioObjectRead : public AioObjectRequest {
public:
+ typedef std::vector<std::pair<uint64_t, uint64_t> > Extents;
+ typedef std::map<uint64_t, uint64_t> ExtentMap;
+
AioObjectRead(ImageCtx *ictx, const std::string &oid,
uint64_t objectno, uint64_t offset, uint64_t len,
- vector<pair<uint64_t,uint64_t> >& be,
- librados::snap_t snap_id, bool sparse,
+ Extents& buffer_extents, librados::snap_t snap_id, bool sparse,
Context *completion, int op_flags);
virtual bool should_complete(int r);
virtual void send();
void guard_read();
+ inline uint64_t get_offset() const {
+ return m_object_off;
+ }
+ inline uint64_t get_length() const {
+ return m_object_len;
+ }
ceph::bufferlist &data() {
return m_read_data;
}
-
- std::map<uint64_t, uint64_t> m_ext_map;
-
- friend class C_AioRead;
-
+ const Extents &get_buffer_extents() const {
+ return m_buffer_extents;
+ }
+ ExtentMap &get_extent_map() {
+ return m_ext_map;
+ }
private:
- vector<pair<uint64_t,uint64_t> > m_buffer_extents;
+ Extents m_buffer_extents;
bool m_tried_parent;
bool m_sparse;
int m_op_flags;
ceph::bufferlist m_read_data;
AioCompletion *m_parent_completion;
+ ExtentMap m_ext_map;
/**
* Reads go through the following state machine to deal with
void send_copyup();
- void read_from_parent(const vector<pair<uint64_t,uint64_t> >& image_extents);
+ void read_from_parent(const Extents& image_extents);
};
class AbstractAioObjectWrite : public AioObjectRequest {