Merge PR #20113 into master

* refs/pull/20113/head:
	osdc/ObjectCacher: don't merge TX buffer heads
	osdc/ObjectCacher: fix off-by-one error in bh_write_commit()

Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
This commit is contained in:
Patrick Donnelly 2018-01-30 15:17:10 -08:00
commit ae0b89c6c9
No known key found for this signature in database
GPG Key ID: 3A2A7E25BEA8AADB
2 changed files with 19 additions and 17 deletions

View File

@ -157,9 +157,6 @@ ObjectCacher::BufferHead *ObjectCacher::Object::split(BufferHead *left,
void ObjectCacher::Object::merge_left(BufferHead *left, BufferHead *right)
{
assert(oc->lock.is_locked());
assert(left->end() == right->start());
assert(left->get_state() == right->get_state());
assert(left->can_merge_journal(right));
ldout(oc->cct, 10) << "merge_left " << *left << " + " << *right << dendl;
if (left->get_journal_tid() == 0) {
@ -196,6 +193,17 @@ void ObjectCacher::Object::merge_left(BufferHead *left, BufferHead *right)
ldout(oc->cct, 10) << "merge_left result " << *left << dendl;
}
bool ObjectCacher::Object::can_merge_bh(BufferHead *left, BufferHead *right)
{
if (left->end() != right->start() ||
left->get_state() != right->get_state() ||
!left->can_merge_journal(right))
return false;
if (left->is_tx() && left->last_write_tid != right->last_write_tid)
return false;
return true;
}
void ObjectCacher::Object::try_merge_bh(BufferHead *bh)
{
assert(oc->lock.is_locked());
@ -210,9 +218,7 @@ void ObjectCacher::Object::try_merge_bh(BufferHead *bh)
assert(p->second == bh);
if (p != data.begin()) {
--p;
if (p->second->end() == bh->start() &&
p->second->get_state() == bh->get_state() &&
p->second->can_merge_journal(bh)) {
if (can_merge_bh(p->second, bh)) {
merge_left(p->second, bh);
bh = p->second;
} else {
@ -222,10 +228,7 @@ void ObjectCacher::Object::try_merge_bh(BufferHead *bh)
// to the right?
assert(p->second == bh);
++p;
if (p != data.end() &&
p->second->start() == bh->end() &&
p->second->get_state() == bh->get_state() &&
p->second->can_merge_journal(bh))
if (p != data.end() && can_merge_bh(bh, p->second))
merge_left(bh, p->second);
}
@ -1149,15 +1152,9 @@ void ObjectCacher::bh_write_commit(int64_t poolid, sobject_t oid,
++p) {
BufferHead *bh = p->second;
if (bh->start() > start+(loff_t)length)
if (bh->start() >= start+(loff_t)length)
break;
if (bh->start() < start &&
bh->end() > start+(loff_t)length) {
ldout(cct, 20) << "bh_write_commit skipping " << *bh << dendl;
continue;
}
// make sure bh is tx
if (!bh->is_tx()) {
ldout(cct, 10) << "bh_write_commit skipping non-tx " << *bh << dendl;
@ -1171,6 +1168,10 @@ void ObjectCacher::bh_write_commit(int64_t poolid, sobject_t oid,
continue;
}
// we don't merge tx buffers. tx buffer should be within the range
assert(bh->start() >= start);
assert(bh->end() <= start+(loff_t)length);
if (r >= 0) {
// ok! mark bh clean and error-free
mark_clean(bh);

View File

@ -341,6 +341,7 @@ class ObjectCacher {
// mid-level
BufferHead *split(BufferHead *bh, loff_t off);
void merge_left(BufferHead *left, BufferHead *right);
bool can_merge_bh(BufferHead *left, BufferHead *right);
void try_merge_bh(BufferHead *bh);
bool is_cached(loff_t off, loff_t len) const;