size -= g_conf.client_bcache_alloc_maxsize;
bc->increase_size(g_conf.client_bcache_alloc_maxsize);
}
- dout(7) << "bc: allocated " << bl.buffers().size() << " buffers (" << bl.length() << " bytes) " << endl;
+ dout(6) << "bc: allocated " << bl.buffers().size() << " buffers (" << bl.length() << " bytes) " << endl;
+ assert(bl.length() == size);
}
void Bufferhead::miss_start(size_t miss_len)
if (bl.length() == 0) {
alloc_buffers(miss_len);
bl.zero();
+ dout(6) << "bc: miss_finish: allocated zeroed buffer len: " << bl.length() << endl;
} else {
bc->increase_size(bl.length());
}
{
// returns iterator to buffer overlapping specified extent or end() if no overlap exists
dout(7) << "bc: overlap " << len << " " << off << endl;
+
+ if (buffer_map.empty()) return buffer_map.end();
+
+ // find first buffer with offset >= off
map<off_t, Bufferhead*>::iterator it = buffer_map.lower_bound(off);
- if (it == buffer_map.end() || it->first < off + len) {
- dout(10) << "bc: overlap -- either no lower bound or overlap found" << endl;
+
+ // Found buffer with exact offset
+ if (it != buffer_map.end() && it->first == off) {
+ dout(6) << "bc: overlap -- found buffer with exact offset" << endl;
return it;
- } else if (it == buffer_map.begin()) {
- dout(10) << "bc: overlap -- extent is below where buffer_map begins" << endl;
- return buffer_map.end();
- } else {
- dout(10) << "bc: overlap -- examining previous buffer" << endl;
+ }
+
+ // examine previous buffer (< off) first in case of two overlaps
+ if (it != buffer_map.begin()) {
it--;
if (it->first + it->second->length() > off) {
- dout(10) << "bc: overlap -- found overlap with previous buffer" << endl;
+ dout(6) << "bc: overlap -- found overlap with previous buffer" << endl;
return it;
} else {
- dout(10) << "bc: overlap -- no overlap with previous buffer" << endl;
- return buffer_map.end();
+ dout(6) << "bc: overlap -- no overlap with previous buffer" << endl;
+ it++;
}
}
+
+ // then examine current buffer (> off)
+ if (it != buffer_map.end() && it->first < off + len) {
+ dout(6) << "bc: overlap -- overlap found" << endl;
+ return it;
+ }
+
+ // give up
+ dout(6) << "bc: overlap -- no overlap found" << endl;
+ return buffer_map.end();
}
map<off_t, Bufferhead*>::iterator
//assert(offset + size <= length()); doesn't hold after trim_bcache
int rvalue = size;
- map<off_t, Bufferhead*>::iterator curbuf = overlap(size, offset);
+ map<off_t, Bufferhead*>::iterator curbuf = buffer_map.lower_bound(offset);
if (curbuf == buffer_map.end() || curbuf->first > offset) {
return -1;
}
Filecache *fc = get_fc(ino);
assert(offset >= 0);
- map<off_t, Bufferhead*>::iterator curbuf = fc->overlap(size, offset);
+ map<off_t, Bufferhead*>::iterator curbuf = fc->buffer_map.lower_bound(offset);
+ if (curbuf == fc->buffer_map.end() || curbuf->first > offset) {
+ assert(curbuf != fc->buffer_map.begin());
+ curbuf--;
+ }
offset -= curbuf->first;
assert(offset >= 0);
if (hits.count(offset)) {
// sweet -- we can return stuff immediately: find out how much
- dout(7) << "read bc hit" << endl;
+ dout(6) << "read bc hit" << endl;
rvalue = (int)bc.touch_continuous(hits, size, offset);
assert(rvalue > 0);
rvalue = fc->copy_out((size_t)rvalue, offset, buf);
// issue reads for holes
int hole_rvalue = 0; //FIXME: don't really need to track rvalue in MissFinish context
for (hole = holes.begin(); hole != holes.end(); hole++) {
- dout(7) << "read bc miss" << endl;
+ dout(6) << "read bc miss" << endl;
off_t hole_offset = hole->first;
size_t hole_size = hole->second;
assert(fc->buffer_map.count(hole_offset) == 0);
bh->miss_start(hole_size);
C_Client_MissFinish *onfinish = new C_Client_MissFinish(bh, &client_lock, &hole_rvalue);
filer->read(in->inode.ino, g_OSD_FileLayout, hole_size, hole_offset, &(bh->bl), onfinish);
- dout(7) << "read bc miss: issued osd read len: " << hole_size << " off: " << hole_offset << endl;
+ dout(6) << "read bc miss: issued osd read len: " << hole_size << " off: " << hole_offset << endl;
}
if (rvalue == 0) {
// we need to wait for the first buffer
dout(7) << "read bc miss: waiting for first buffer" << endl;
- Bufferhead *bh = fc->buffer_map[offset];
+ map<off_t, Bufferhead*>::iterator it = fc->buffer_map.lower_bound(offset);
+ if (it == fc->buffer_map.end() || it->first > offset) {
+ assert(it != fc->buffer_map.begin());
+ it--;
+ }
+ Bufferhead *bh = it->second;
+ assert(bh->offset + bh->length() > offset);
#if 0
Bufferhead *bh;
if (curbuf == fc->buffer_map.end() && fc->buffer_map.count(offset)) {
// buffer is filled -- see how much we can return
hits.clear(); rx.clear(); tx.clear(); holes.clear();
fc->map_existing(size, offset, hits, rx, tx, holes); // FIXME: overkill
- assert(hits.count(offset));
+ //assert(hits.count(offset));
rvalue = (int)bc.touch_continuous(hits, size, offset);
fc->copy_out(rvalue, offset, buf);
dout(7) << "read bc no hit: returned first " << rvalue << " bytes" << endl;