void BufferHead::apply_partial()
{
- assert(!partial.empty());
dout(10) << "apply_partial on " << partial.size() << " substrings" << dendl;
- csum_t *expect = oc->on->get_extent_csum_ptr(start(), 1);
- csum_t oldc = calc_csum(data.c_str(), EBOFS_BLOCK_SIZE);
+ assert(!partial.empty());
+ csum_t *p = oc->on->get_extent_csum_ptr(start(), 1);
do_apply_partial(data, partial);
csum_t newc = calc_csum(data.c_str(), EBOFS_BLOCK_SIZE);
- dout(10) << "apply_partial onode expected " << hex << *expect
- << " bl was " << oldc
- << " now " << newc << dec << dendl;
- assert(*expect == oldc);
- *expect = newc;
- oc->on->data_csum += newc - oldc;
+ oc->on->data_csum += newc - *p;
+ *p = newc;
}
assert(exv[0].start != 0);
block_t cur_block = exv[0].start;
+ off_t off_in_bl = (bh->start() - start) * EBOFS_BLOCK_SIZE;
+ assert(off_in_bl >= 0);
+ off_t len_in_bl = bh->length() * EBOFS_BLOCK_SIZE;
+
// verify csum
- assert(bl.length() == (unsigned)EBOFS_BLOCK_SIZE);
csum_t want = *bh->oc->on->get_extent_csum_ptr(bh->start(), 1);
- csum_t got = calc_csum(bl.c_str(), bl.length());
+ csum_t got = calc_csum(bl.c_str() + off_in_bl, len_in_bl);
if (want != got) {
derr(0) << "rx_finish bad csum on partial readback, want " << hex << want
<< " got " << got << dec << dendl;
assert(bh->data.length() == 0);
bufferptr bp = buffer::create_page_aligned(EBOFS_BLOCK_SIZE);
bh->data.push_back( bp );
- bh->data.copy_in(0, EBOFS_BLOCK_SIZE, bl);
+ bufferlist sub;
+ sub.substr_of(bl, off_in_bl, len_in_bl);
+ bh->data.copy_in(0, EBOFS_BLOCK_SIZE, sub);
bh->apply_partial();
// write "normally"
map<block_t, BufferHead*>& hits,
map<block_t, BufferHead*>& missing,
map<block_t, BufferHead*>& rx,
- map<block_t, BufferHead*>& partial,
- map<block_t, BufferHead*>& corrupt) {
+ map<block_t, BufferHead*>& partial) {
map<block_t, BufferHead*>::iterator p = find_bh(start, len);
block_t cur = start;
if (e->is_clean() ||
e->is_dirty() ||
- e->is_tx()) {
+ e->is_tx() ||
+ e->is_corrupt()) {
hits[cur] = e; // readable!
dout(20) << "map_read hit " << *e << dendl;
bc->touch(e);
}
- else if (e->is_corrupt()) {
- corrupt[cur] = e;
- dout(20) << "map_read corrupt " << *e << dendl;
- }
else if (e->is_rx()) {
rx[cur] = e; // missing, not readable.
dout(20) << "map_read rx " << *e << dendl;
map<block_t, BufferHead*>& hits, // hits
map<block_t, BufferHead*>& missing, // read these from disk
map<block_t, BufferHead*>& rx, // wait for these to finish reading from disk
- map<block_t, BufferHead*>& partial, // (maybe) wait for these to read from disk
- map<block_t, BufferHead*>& corrupt); // bad checksums
+ map<block_t, BufferHead*>& partial); // (maybe) wait for these to read from disk
int try_map_read(block_t start, block_t len); // just tell us how many extents we're missing.
int map_write(block_t start, block_t len,
blpos += len_in_bh;
opos += len_in_bh;
- if (bh->partial_is_complete(on->object_size - bh->start()*EBOFS_BLOCK_SIZE)) {
+ if (bh->is_partial() &&
+ bh->partial_is_complete(on->object_size - bh->start()*EBOFS_BLOCK_SIZE)) {
dout(10) << "apply_write completed partial " << *bh << dendl;
+ bc.bh_cancel_read(bh); // cancel old rx op, if we can.
bh->data.clear();
- bh->data.push_back( buffer::create_page_aligned(EBOFS_BLOCK_SIZE*bh->length()) );
- bh->data.zero();
+ bh->data.push_back(buffer::create_page_aligned(EBOFS_BLOCK_SIZE));
bh->apply_partial();
bc.mark_dirty(bh);
bc.bh_write(on, bh);
map<block_t, BufferHead*> missing; // read these
map<block_t, BufferHead*> rx; // wait for these
map<block_t, BufferHead*> partials; // ??
- map<block_t, BufferHead*> corrupt;
- oc->map_read(bstart, blen, hits, missing, rx, partials, corrupt);
+ oc->map_read(bstart, blen, hits, missing, rx, partials);
// missing buffers?
if (!missing.empty()) {
return 0;
}
+ // wait on rx?
+ if (!rx.empty()) {
+ BufferHead *wait_on = rx.begin()->second;
+ Context *c = new C_Cond(will_wait_on, will_wait_on_bool);
+ dout(20) << "attempt_read waiting for read to finish on " << *wait_on << " c " << c << dendl;
+ block_t b = MAX(wait_on->start(), bstart);
+ wait_on->waitfor_read[b].push_back(c);
+ return 0;
+ }
+
// are partials sufficient?
- bool partials_ok = true;
for (map<block_t,BufferHead*>::iterator i = partials.begin();
i != partials.end();
i++) {
off_t start = MAX( off, bhstart );
off_t end = MIN( off+(off_t)len, bhend );
- if (!i->second->have_partial_range(start-bhstart, end-bhend)) {
- if (partials_ok) {
- // wait on this one
- Context *c = new C_Cond(will_wait_on, will_wait_on_bool);
- dout(10) << "attempt_read insufficient partial buffer " << *(i->second) << " c " << c << dendl;
- i->second->waitfor_read[i->second->start()].push_back(c);
- }
- partials_ok = false;
+ if (!i->second->have_partial_range(start-bhstart, end-bhstart)) {
+ // wait on this one
+ Context *c = new C_Cond(will_wait_on, will_wait_on_bool);
+ dout(10) << "attempt_read insufficient partial buffer " << *(i->second) << " c " << c << dendl;
+ i->second->waitfor_read[i->second->start()].push_back(c);
+ return 0;
}
- }
- if (!partials_ok) return 0;
-
- // wait on rx?
- if (!rx.empty()) {
- BufferHead *wait_on = rx.begin()->second;
- Context *c = new C_Cond(will_wait_on, will_wait_on_bool);
- dout(20) << "attempt_read waiting for read to finish on " << *wait_on << " c " << c << dendl;
- block_t b = MAX(wait_on->start(), bstart);
- wait_on->waitfor_read[b].push_back(c);
- return 0;
+ dout(10) << "attempt_read have partial range " << (start-bhstart) << "~" << (end-bhstart) << " on " << *bh << dendl;
}
// yay, we have it all!
- // concurrently walk thru hits, partials.
+ // concurrently walk thru hits, partials, corrupt.
map<block_t,BufferHead*>::iterator h = hits.begin();
map<block_t,BufferHead*>::iterator p = partials.begin();
- map<block_t,BufferHead*>::iterator c = corrupt.begin();
bl.clear();
off_t pos = off;
} else if (p != partials.end() && p->first == curblock) {
bh = p->second;
p++;
- } else if (c != corrupt.end() && c->first == curblock) {
- bh = c->second;
- c++;
} else assert(0);
off_t bhstart = (off_t)(bh->start()*EBOFS_BLOCK_SIZE);
} else if (bh->is_partial()) {
// copy from a partial block. yuck!
bufferlist frag;
+ dout(10) << "attempt_read copying partial range " << (start-bhstart) << "~" << (end-bhstart) << " on " << *bh << dendl;
bh->copy_partial_substr( start-bhstart, end-bhstart, frag );
bl.claim_append( frag );
pos += frag.length();