map_write函数分析
image.png ObjectCacher::BufferHead *ObjectCacher::Object::map_write(ObjectExtent &ex, ceph_tid_t tid) { if (oc->m_object_lock) { assert(this->lock.is_wlocked()); } BufferHead *final = 0; ldout(oc->cct, 10) << "map_write oex " << ex.oid << " " << ex.offset << "~" << ex.length << dendl; loff_t cur = ex.offset; loff_t left = ex.length; map<loff_t, BufferHead*>::const_iterator p = data_lower_bound(ex.offset); while (left > 0) { loff_t max = left; // at end ? if (p == data.end()) { if (final == NULL) { final = new BufferHead(this); replace_journal_tid(final, tid); final->set_start( cur ); final->set_length( max ); oc->bh_add(this, final); ldout(oc->cct, 10) << "map_write adding trailing bh " << *final << dendl; } else { oc->bh_stat_sub(final); final->set_length(final->length() + max); oc->bh_stat_add(final); } left -= max; cur += max; continue; } ldout(oc->cct, 10) << "cur is " << cur << ", p is " << *p->second << dendl; //oc->verify_stats(); if (p->first <= cur) { BufferHead *bh = p->second; ldout(oc->cct, 10) << "map_write bh " << *bh << " intersected" << dendl; if (p->first < cur) { assert(final == 0); if (cur + max >= bh->end()) { // we want right bit (one splice) final = split(bh, cur); // just split it, take right half. maybe_rebuild_buffer(bh); replace_journal_tid(final, tid); ++p; assert(p->second == final); } else { // we want middle bit (two splices) final = split(bh, cur); maybe_rebuild_buffer(bh); ++p; assert(p->second == final); auto right = split(final, cur+max); maybe_rebuild_buffer(right); replace_journal_tid(final, tid); } } else { assert(p->first == cur); if (bh->length() <= max) { // whole bufferhead, piece of cake. } else { // we want left bit (one splice) auto right = split(bh, cur + max); // just split maybe_rebuild_buffer(right); } if (final) { oc->mark_dirty(bh); oc->mark_dirty(final); --p; // move iterator back to final assert(p->second == final); replace_journal_tid(bh, tid); merge_left(final, bh); } else { final = bh; replace_journal_tid(final, tid); } } // keep going. loff_t lenfromcur = final->end() - cur; cur += lenfromcur; left -= lenfromcur; ++p; continue; } else { // gap! loff_t next = p->first; loff_t glen = MIN(next - cur, max); ldout(oc->cct, 10) << "map_write gap " << cur << "~" << glen << dendl; if (final) { oc->bh_stat_sub(final); final->set_length(final->length() + glen); oc->bh_stat_add(final); } else { final = new BufferHead(this); replace_journal_tid(final, tid); final->set_start( cur ); final->set_length( glen ); oc->bh_add(this, final); } cur += glen; left -= glen; continue; // more? } } // set version assert(final); assert(final->get_journal_tid() == tid); ldout(oc->cct, 10) << "map_write final is " << *final << dendl; return final; }