| 719 | |
| 720 | template <typename I> |
| 721 | void AbstractWriteLog<I>::read(Extents&& image_extents, |
| 722 | ceph::bufferlist* bl, |
| 723 | int fadvise_flags, Context *on_finish) { |
| 724 | CephContext *cct = m_image_ctx.cct; |
| 725 | utime_t now = ceph_clock_now(); |
| 726 | |
| 727 | on_finish = new LambdaContext( |
| 728 | [this, on_finish](int r) { |
| 729 | m_async_op_tracker.finish_op(); |
| 730 | on_finish->complete(r); |
| 731 | }); |
| 732 | C_ReadRequest *read_ctx = m_builder->create_read_request( |
| 733 | cct, now, m_perfcounter, bl, on_finish); |
| 734 | ldout(cct, 20) << "name: " << m_image_ctx.name << " id: " << m_image_ctx.id |
| 735 | << "image_extents=" << image_extents |
| 736 | << ", bl=" << bl |
| 737 | << ", on_finish=" << on_finish << dendl; |
| 738 | |
| 739 | ceph_assert(m_initialized); |
| 740 | bl->clear(); |
| 741 | m_perfcounter->inc(l_librbd_pwl_rd_req, 1); |
| 742 | |
| 743 | std::vector<std::shared_ptr<GenericWriteLogEntry>> log_entries_to_read; |
| 744 | std::vector<bufferlist*> bls_to_read; |
| 745 | |
| 746 | m_async_op_tracker.start_op(); |
| 747 | Context *ctx = new LambdaContext( |
| 748 | [this, read_ctx, fadvise_flags](int r) { |
| 749 | if (read_ctx->miss_extents.empty()) { |
| 750 | /* All of this read comes from RWL */ |
| 751 | read_ctx->complete(0); |
| 752 | } else { |
| 753 | /* Pass the read misses on to the layer below RWL */ |
| 754 | m_image_writeback.aio_read( |
| 755 | std::move(read_ctx->miss_extents), &read_ctx->miss_bl, |
| 756 | fadvise_flags, read_ctx); |
| 757 | } |
| 758 | }); |
| 759 | |
| 760 | /* |
| 761 | * The strategy here is to look up all the WriteLogMapEntries that overlap |
| 762 | * this read, and iterate through those to separate this read into hits and |
| 763 | * misses. A new Extents object is produced here with Extents for each miss |
| 764 | * region. The miss Extents is then passed on to the read cache below RWL. We |
| 765 | * also produce an ImageExtentBufs for all the extents (hit or miss) in this |
| 766 | * read. When the read from the lower cache layer completes, we iterate |
| 767 | * through the ImageExtentBufs and insert buffers for each cache hit at the |
| 768 | * appropriate spot in the bufferlist returned from below for the miss |
| 769 | * read. The buffers we insert here refer directly to regions of various |
| 770 | * write log entry data buffers. |
| 771 | * |
| 772 | * Locking: These buffer objects hold a reference on the write log entries |
| 773 | * they refer to. Log entries can't be retired until there are no references. |
| 774 | * The GenericWriteLogEntry references are released by the buffer destructor. |
| 775 | */ |
| 776 | for (auto &extent : image_extents) { |
| 777 | uint64_t extent_offset = 0; |
| 778 | RWLock::RLocker entry_reader_locker(m_entry_reader_lock); |
no test coverage detected