return os;
};
+void C_ReadRequest::finish(int r) {
+ ldout(m_cct, 20) << "(" << get_name() << "): r=" << r << dendl;
+ int hits = 0;
+ int misses = 0;
+ int hit_bytes = 0;
+ int miss_bytes = 0;
+ if (r >= 0) {
+ /*
+ * At this point the miss read has completed. We'll iterate through
+ * read_extents and produce *m_out_bl by assembling pieces of miss_bl
+ * and the individual hit extent bufs in the read extents that represent
+ * hits.
+ */
+ uint64_t miss_bl_offset = 0;
+ for (auto &extent : read_extents) {
+ if (extent.m_bl.length()) {
+ /* This was a hit */
+ ceph_assert(extent.second == extent.m_bl.length());
+ ++hits;
+ hit_bytes += extent.second;
+ m_out_bl->claim_append(extent.m_bl);
+ } else {
+ /* This was a miss. */
+ ++misses;
+ miss_bytes += extent.second;
+ bufferlist miss_extent_bl;
+ miss_extent_bl.substr_of(miss_bl, miss_bl_offset, extent.second);
+ /* Add this read miss bufferlist to the output bufferlist */
+ m_out_bl->claim_append(miss_extent_bl);
+ /* Consume these bytes in the read miss bufferlist */
+ miss_bl_offset += extent.second;
+ }
+ }
+ }
+ ldout(m_cct, 20) << "(" << get_name() << "): r=" << r << " bl=" << *m_out_bl << dendl;
+ utime_t now = ceph_clock_now();
+ ceph_assert((int)m_out_bl->length() == hit_bytes + miss_bytes);
+ m_on_finish->complete(r);
+ m_perfcounter->inc(l_librbd_rwl_rd_bytes, hit_bytes + miss_bytes);
+ m_perfcounter->inc(l_librbd_rwl_rd_hit_bytes, hit_bytes);
+ m_perfcounter->tinc(l_librbd_rwl_rd_latency, now - m_arrived_time);
+ if (!misses) {
+ m_perfcounter->inc(l_librbd_rwl_rd_hit_req, 1);
+ m_perfcounter->tinc(l_librbd_rwl_rd_hit_latency, now - m_arrived_time);
+ } else {
+ if (hits) {
+ m_perfcounter->inc(l_librbd_rwl_rd_part_hit_req, 1);
+ }
+ }
+}
+
std::ostream &operator<<(std::ostream &os,
const BlockGuardReqState &r) {
os << "barrier=" << r.barrier << ", "
const C_FlushRequest<U> &req);
};
+class C_ReadRequest : public Context {
+public:
+ io::Extents miss_extents; // move back to caller
+ ImageExtentBufs read_extents;
+ bufferlist miss_bl;
+
+ C_ReadRequest(CephContext *cct, utime_t arrived, PerfCounters *perfcounter, bufferlist *out_bl, Context *on_finish)
+ : m_cct(cct), m_on_finish(on_finish), m_out_bl(out_bl),
+ m_arrived_time(arrived), m_perfcounter(perfcounter) {}
+ ~C_ReadRequest() {}
+
+ void finish(int r) override;
+
+ const char *get_name() const {
+ return "C_ReadRequest";
+ }
+
+private:
+ CephContext *m_cct;
+ Context *m_on_finish;
+ bufferlist *m_out_bl;
+ utime_t m_arrived_time;
+ PerfCounters *m_perfcounter;
+};
+
struct BlockGuardReqState {
bool barrier = false; /* This is a barrier request */
bool current_barrier = false; /* This is the currently active barrier */
namespace cache {
namespace rwl {
+class ImageExtentBuf;
+typedef std::vector<ImageExtentBuf> ImageExtentBufs;
+
const int IN_FLIGHT_FLUSH_WRITE_LIMIT = 64;
const int IN_FLIGHT_FLUSH_BYTES_LIMIT = (1 * 1024 * 1024);
Context * override_ctx(int r, Context *ctx);
+class ImageExtentBuf : public io::Extent {
+public:
+ bufferlist m_bl;
+ ImageExtentBuf(io::Extent extent)
+ : io::Extent(extent) { }
+ ImageExtentBuf(io::Extent extent, bufferlist bl)
+ : io::Extent(extent), m_bl(bl) { }
+};
+
} // namespace rwl
} // namespace cache
} // namespace librbd