diff --git a/src/blockstore/blockstore_flush.cpp b/src/blockstore/blockstore_flush.cpp index f05828ee..2afdfbd9 100644 --- a/src/blockstore/blockstore_flush.cpp +++ b/src/blockstore/blockstore_flush.cpp @@ -342,6 +342,13 @@ resume_24: { return false; } + // Recheck the object because it could be invalidated again + cur_obj = bs->heap->read_entry(cur_oid, &modified_block); + if (!cur_obj) + { + // Abort compaction + goto resume_0; + } } bs->heap->mark_object_compacted(cur_obj, compact_lsn); // Done @@ -370,83 +377,53 @@ resume_15: goto resume_0; } -void journal_flusher_co::iterate_partial_overwrites(std::function cb) +void journal_flusher_co::iterate_checksum_holes(std::function cb) { - int prev = 0; - uint32_t prev_begin = 0, prev_end = 0; - for (int i = 0; i < read_vec.size() && !(read_vec[i].copy_flags & COPY_BUF_CSUM_FILL); i++) + bs->find_holes(read_vec, 0, bs->dsk.data_block_size, [&](int & pos, uint32_t hole_start, uint32_t hole_end) { - if (!(read_vec[i].copy_flags & COPY_BUF_COALESCED)) + if (hole_start % bs->dsk.csum_block_size) { - if (read_vec[i].offset > prev_end) - { - if (prev_end > prev_begin && - ((prev_begin % bs->dsk.csum_block_size) && prev_begin > big_start || - (prev_end % bs->dsk.csum_block_size) && prev_end < big_end)) - { - i += cb(prev, prev_begin, prev_end); - } - prev = i; - prev_begin = read_vec[i].offset; - } - prev_end = read_vec[i].offset + read_vec[i].len; + uint32_t blk_end = hole_start - (hole_start % bs->dsk.csum_block_size) + bs->dsk.csum_block_size; + cb(pos, hole_start, hole_end < blk_end ? hole_end : blk_end); } - } - if (prev_end > prev_begin && - ((prev_begin % bs->dsk.csum_block_size) && prev_begin > big_start || - (prev_end % bs->dsk.csum_block_size) && prev_end < big_end)) - { - cb(prev, prev_begin, prev_end); - } -} - -void journal_flusher_co::iterate_checksum_holes(std::function cb) -{ - iterate_partial_overwrites([&](int pos, uint32_t prev_begin, uint32_t prev_end) - { - int r = 0; - if ((prev_begin % bs->dsk.csum_block_size) && prev_begin > big_start && - (prev_begin / bs->dsk.csum_block_size) != (prev_end / bs->dsk.csum_block_size)) + if ((hole_end % bs->dsk.csum_block_size) && + (!(hole_start % bs->dsk.csum_block_size) || (hole_end / bs->dsk.csum_block_size) != (hole_start / bs->dsk.csum_block_size))) { - uint32_t blk_begin = (prev_begin - prev_begin%bs->dsk.csum_block_size); - if (blk_begin < big_start) - blk_begin = big_start; - cb(pos++, blk_begin, prev_begin); - r++; + cb(pos, hole_end - (hole_end % bs->dsk.csum_block_size), hole_end); } - if ((prev_end % bs->dsk.csum_block_size) && prev_end < big_end) - { - uint32_t blk_end = prev_end - (prev_end % bs->dsk.csum_block_size) + bs->dsk.csum_block_size; - if (blk_end > big_end) - blk_end = big_end; - cb(++pos, prev_end, blk_end); - r++; - } - return r; }); } void journal_flusher_co::fill_partial_checksum_blocks() { - iterate_checksum_holes([&](int vec_pos, uint32_t hole_start, uint32_t hole_end) + iterate_checksum_holes([&](int & vec_pos, uint32_t hole_start, uint32_t hole_end) { read_to_fill_incomplete = true; uint32_t blk_begin = (hole_start - hole_start % bs->dsk.csum_block_size); - bs->prepare_disk_read(read_vec, read_vec.size(), cur_obj, end_wr, - blk_begin < big_start ? big_start : blk_begin, - (blk_begin + bs->dsk.csum_block_size) > big_end ? big_end : (blk_begin + bs->dsk.csum_block_size), - blk_begin < big_start ? big_start : blk_begin, - (blk_begin + bs->dsk.csum_block_size) > big_end ? big_end : (blk_begin + bs->dsk.csum_block_size), - COPY_BUF_CSUM_FILL | (bs->perfect_csum_update ? 0 : COPY_BUF_SKIP_CSUM)); + blk_begin = (blk_begin < big_start ? big_start : blk_begin); + uint32_t blk_end = (blk_begin + bs->dsk.csum_block_size) > big_end ? big_end : (blk_begin + bs->dsk.csum_block_size); + uint32_t copy_flags = COPY_BUF_CSUM_FILL | (bs->perfect_csum_update ? 0 : COPY_BUF_SKIP_CSUM); + if (!read_vec.size() || read_vec.back().copy_flags != copy_flags || + read_vec.back().offset != blk_begin || read_vec.back().len != blk_end-blk_begin) + { + read_vec.push_back((copy_buffer_t){ + .copy_flags = COPY_BUF_DATA | copy_flags, + .offset = blk_begin, + .len = blk_end - blk_begin, + .disk_offset = end_wr->location + blk_begin, + .disk_len = blk_end - blk_begin, + .buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, blk_end - blk_begin), + .wr_lsn = end_wr->lsn, + }); + } auto & vec = read_vec[read_vec.size()-1]; - if (!vec.buf) - vec.buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, vec.disk_len); read_vec.insert(read_vec.begin()+vec_pos, (copy_buffer_t){ .copy_flags = COPY_BUF_JOURNAL|COPY_BUF_COALESCED, .offset = hole_start, - .len = hole_end-hole_start, + .len = hole_end - hole_start, .buf = vec.buf + hole_start - vec.offset, }); + vec_pos++; }); } @@ -525,11 +502,18 @@ int journal_flusher_co::check_and_punch_checksums() uint8_t *bmp = end_wr->get_int_bitmap(bs->heap); uint8_t *csums = end_wr->get_checksums(bs->heap); // Clear bits - iterate_partial_overwrites([&](int pos, uint32_t start, uint32_t end) + for (auto & vec: read_vec) { - bitmap_clear(bmp, start, end-start, bs->dsk.bitmap_granularity); - return 0; - }); + if (vec.copy_flags & COPY_BUF_CSUM_FILL) + { + break; + } + if (!(vec.copy_flags & COPY_BUF_COALESCED) && + ((vec.offset % bs->dsk.csum_block_size) || (vec.len % bs->dsk.csum_block_size))) + { + bitmap_clear(bmp, vec.offset, vec.len, bs->dsk.bitmap_granularity); + } + } // Update partial block checksums for (auto & vec: read_vec) { diff --git a/src/blockstore/blockstore_flush.h b/src/blockstore/blockstore_flush.h index 3464985c..dc332fd4 100644 --- a/src/blockstore/blockstore_flush.h +++ b/src/blockstore/blockstore_flush.h @@ -60,8 +60,7 @@ class journal_flusher_co friend class journal_flusher_t; - void iterate_partial_overwrites(std::function cb); - void iterate_checksum_holes(std::function cb); + void iterate_checksum_holes(std::function cb); void fill_partial_checksum_blocks(); void free_buffers(); int check_and_punch_checksums(); diff --git a/src/blockstore/blockstore_heap.cpp b/src/blockstore/blockstore_heap.cpp index 55b3daa5..ee53b8d5 100644 --- a/src/blockstore/blockstore_heap.cpp +++ b/src/blockstore/blockstore_heap.cpp @@ -661,9 +661,9 @@ bool blockstore_heap_t::calc_block_checksums(uint32_t *block_csums, uint8_t *bit bool isset = false; while (pos < end) { + uint32_t prev = pos; if (bitmap) { - uint32_t prev = pos; while (pos < end && pos < block_end) { while (pos < end && pos < block_end && !(bitmap[pos/dsk->bitmap_granularity/8] & (1 << ((pos/dsk->bitmap_granularity) % 8)))) @@ -696,7 +696,7 @@ bool blockstore_heap_t::calc_block_checksums(uint32_t *block_csums, uint8_t *bit { if (bad_block_cb) { - bad_block_cb(block_end, *block_csums, block_crc); + bad_block_cb(prev, *block_csums, block_crc); res = false; } else