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) {
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());
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 {
// 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);
}
++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;
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);