| 1747 | } |
| 1748 | |
| 1749 | int ObjectCacher::writex(OSDWrite *wr, ObjectSet *oset, Context *onfreespace, |
| 1750 | ZTracer::Trace *parent_trace, |
| 1751 | bool block_writes_upfront) |
| 1752 | { |
| 1753 | ceph_assert(ceph_mutex_is_locked(lock)); |
| 1754 | ceph::real_time now = ceph::real_clock::now(); |
| 1755 | uint64_t bytes_written = 0; |
| 1756 | uint64_t bytes_written_in_flush = 0; |
| 1757 | bool dontneed = wr->fadvise_flags & LIBRADOS_OP_FLAG_FADVISE_DONTNEED; |
| 1758 | bool nocache = wr->fadvise_flags & LIBRADOS_OP_FLAG_FADVISE_NOCACHE; |
| 1759 | |
| 1760 | ZTracer::Trace trace; |
| 1761 | if (parent_trace != nullptr) { |
| 1762 | trace.init("write", &trace_endpoint, parent_trace); |
| 1763 | trace.event("start"); |
| 1764 | } |
| 1765 | |
| 1766 | list<Context*> wait_for_reads; |
| 1767 | for (vector<ObjectExtent>::iterator ex_it = wr->extents.begin(); |
| 1768 | ex_it != wr->extents.end(); |
| 1769 | ++ex_it) { |
| 1770 | // get object cache |
| 1771 | sobject_t soid(ex_it->oid, CEPH_NOSNAP); |
| 1772 | Object *o = get_object(soid, ex_it->objectno, oset, ex_it->oloc, |
| 1773 | ex_it->truncate_size, oset->truncate_seq); |
| 1774 | |
| 1775 | // map it all into a single bufferhead. |
| 1776 | BufferHead *bh = o->map_write(*ex_it, wr->journal_tid); |
| 1777 | bool missing = bh->is_missing(); |
| 1778 | bh->snapc = wr->snapc; |
| 1779 | |
| 1780 | // readers that need to be woken up due to an overwrite |
| 1781 | for (auto& [_, wait_for_read] : bh->waitfor_read) { |
| 1782 | wait_for_reads.splice(wait_for_reads.end(), wait_for_read); |
| 1783 | } |
| 1784 | bh->waitfor_read.clear(); |
| 1785 | |
| 1786 | bytes_written += ex_it->length; |
| 1787 | if (bh->is_tx()) { |
| 1788 | bytes_written_in_flush += ex_it->length; |
| 1789 | } |
| 1790 | |
| 1791 | // adjust buffer pointers (ie "copy" data into my cache) |
| 1792 | // this is over a single ObjectExtent, so we know that |
| 1793 | // - there is one contiguous bh |
| 1794 | // - the buffer frags need not be (and almost certainly aren't) |
| 1795 | // note: i assume striping is monotonic... no jumps backwards, ever! |
| 1796 | loff_t opos = ex_it->offset; |
| 1797 | for (vector<pair<uint64_t, uint64_t> >::iterator f_it |
| 1798 | = ex_it->buffer_extents.begin(); |
| 1799 | f_it != ex_it->buffer_extents.end(); |
| 1800 | ++f_it) { |
| 1801 | ldout(cct, 10) << "writex writing " << f_it->first << "~" |
| 1802 | << f_it->second << " into " << *bh << " at " << opos |
| 1803 | << dendl; |
| 1804 | uint64_t bhoff = opos - bh->start(); |
| 1805 | ceph_assert(f_it->second <= bh->length() - bhoff); |
| 1806 | |