diff --git a/src/blockstore/blockstore_flush.cpp b/src/blockstore/blockstore_flush.cpp index a83699ef..6b4d3a97 100644 --- a/src/blockstore/blockstore_flush.cpp +++ b/src/blockstore/blockstore_flush.cpp @@ -224,7 +224,7 @@ resume_1: goto resume_0; } assert(!end_wr->next() && end_wr->entry_type == (BS_HEAP_BIG_WRITE|BS_HEAP_STABLE)); - clean_loc = end_wr->location; + clean_loc = end_wr->big().location; if (bs->log_level > 10) printf("Compacting %jx:%jx l%ju .. l%ju (last l%ju)\n", cur_oid.inode, cur_oid.stripe, end_wr->lsn, begin_wr->lsn, compact_lsn); flusher->active_flushers++; @@ -241,8 +241,6 @@ resume_1: { overwrite_start = read_vec[0].offset; overwrite_end = read_vec[read_vec.size()-1].offset + read_vec[read_vec.size()-1].len; - big_start = overwrite_start < end_wr->offset ? overwrite_start : end_wr->offset; - big_end = overwrite_end > end_wr->offset+end_wr->len ? overwrite_end : end_wr->offset+end_wr->len; } read_to_fill_incomplete = false; if (bs->dsk.csum_block_size > bs->dsk.bitmap_granularity) @@ -402,8 +400,7 @@ void journal_flusher_co::fill_partial_checksum_blocks() { read_to_fill_incomplete = true; uint32_t blk_begin = (hole_start - hole_start % bs->dsk.csum_block_size); - 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 blk_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) @@ -412,7 +409,7 @@ void journal_flusher_co::fill_partial_checksum_blocks() .copy_flags = COPY_BUF_DATA | copy_flags, .offset = blk_begin, .len = blk_end - blk_begin, - .disk_loc = end_wr->location, + .disk_loc = end_wr->big().location, .disk_offset = blk_begin, .disk_len = blk_end - blk_begin, .buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, blk_end - blk_begin), @@ -467,7 +464,7 @@ int journal_flusher_co::check_and_punch_checksums() assert(wr); uint32_t *csums = (uint32_t*)(wr->get_checksums(bs->heap) + (vec.disk_offset/bs->dsk.csum_block_size)*(bs->dsk.data_csum_type & 0xFF) - - ((wr->type() == BS_HEAP_BIG_WRITE) ? 0 : (wr->offset/bs->dsk.csum_block_size)*(bs->dsk.data_csum_type & 0xFF))); + - ((wr->type() == BS_HEAP_BIG_WRITE) ? 0 : (wr->small().offset/bs->dsk.csum_block_size)*(bs->dsk.data_csum_type & 0xFF))); bs->heap->calc_block_checksums( csums, vec.buf, wr->get_int_bitmap(bs->heap), vec.disk_offset, vec.disk_offset+vec.disk_len, false, [&](uint32_t mismatch_pos, uint32_t expected_csum, uint32_t real_csum) @@ -524,7 +521,7 @@ int journal_flusher_co::check_and_punch_checksums() { if (vec.copy_flags & COPY_BUF_CSUM_FILL) { - uint32_t csum_off = (vec.offset/bs->dsk.csum_block_size - end_wr->offset/bs->dsk.csum_block_size) * (bs->dsk.data_csum_type & 0xFF); + uint32_t csum_off = vec.offset/bs->dsk.csum_block_size * (bs->dsk.data_csum_type & 0xFF); bs->heap->calc_block_checksums((uint32_t*)(csums+csum_off), vec.buf, bmp, vec.offset, vec.offset+vec.len, true, NULL); } } @@ -561,8 +558,6 @@ bool journal_flusher_co::calc_block_checksums() bitmap_set(bmp, vec.offset, vec.len, bs->dsk.bitmap_granularity); } } - end_wr->offset = big_start; - end_wr->len = big_end-big_start; // Update block checksums size_t i = 0; while (i < read_vec.size() && !(read_vec[i].copy_flags & COPY_BUF_CSUM_FILL)) @@ -576,10 +571,10 @@ bool journal_flusher_co::calc_block_checksums() end = read_vec[i].offset+read_vec[i].len; i++; } - // `read_vec` should contain aligned items (with respect to big_start/big_end), possibly split into pieces - assert(!(start % bs->dsk.csum_block_size) || start == big_start); - assert(!(end % bs->dsk.csum_block_size) || end == big_end); - uint32_t csum_off = (start/bs->dsk.csum_block_size - big_start/bs->dsk.csum_block_size) * (bs->dsk.data_csum_type & 0xFF); + // `read_vec` should contain aligned items, possibly split into pieces + assert(!(start % bs->dsk.csum_block_size)); + assert(!(end % bs->dsk.csum_block_size)); + uint32_t csum_off = start/bs->dsk.csum_block_size * (bs->dsk.data_csum_type & 0xFF); bs->heap->calc_block_checksums( (uint32_t*)(csums+csum_off), bmp, start, end, [&](uint32_t start, uint32_t & len) diff --git a/src/blockstore/blockstore_heap.cpp b/src/blockstore/blockstore_heap.cpp index 66e3189e..4258216a 100644 --- a/src/blockstore/blockstore_heap.cpp +++ b/src/blockstore/blockstore_heap.cpp @@ -20,7 +20,7 @@ #define HEAP_INFLIGHT_DONE 1 #define HEAP_INFLIGHT_COMPACTABLE 2 -#define MIN_ALLOC (sizeof(heap_object_t)+sizeof(heap_write_t)) +#define MIN_ALLOC (sizeof(heap_object_t)+sizeof(heap_tombstone_t)) static constexpr uint32_t heap_entry_type_pos = 4; @@ -31,14 +31,15 @@ heap_write_t *heap_write_t::next() uint32_t heap_write_t::get_size(blockstore_heap_t *heap) { - return (sizeof(heap_write_t) + - (type() != BS_HEAP_TOMBSTONE - ? heap->dsk->clean_entry_bitmap_size - : 0) + - (type() == BS_HEAP_BIG_WRITE - ? heap->dsk->clean_entry_bitmap_size - : 0) + - get_csum_size(heap)); + if (type() == BS_HEAP_BIG_WRITE) + { + return sizeof(heap_big_write_t) + heap->dsk->clean_entry_bitmap_size*2 + get_csum_size(heap); + } + if (type() == BS_HEAP_TOMBSTONE) + { + return sizeof(heap_tombstone_t); + } + return sizeof(heap_small_write_t) + heap->dsk->clean_entry_bitmap_size + get_csum_size(heap); } uint32_t heap_write_t::get_csum_size(blockstore_heap_t *heap) @@ -58,21 +59,30 @@ uint32_t heap_write_t::get_csum_size(blockstore_heap_t *heap) // However, we only use part of it related to offset..offset+len return heap->dsk->data_block_size/heap->dsk->csum_block_size * (heap->dsk->data_csum_type & 0xFF); } - return ((offset+len+heap->dsk->csum_block_size-1)/heap->dsk->csum_block_size - offset/heap->dsk->csum_block_size) + return ((small().offset+small().len+heap->dsk->csum_block_size-1)/heap->dsk->csum_block_size - small().offset/heap->dsk->csum_block_size) * (heap->dsk->data_csum_type & 0xFF); } bool heap_write_t::needs_recheck(blockstore_heap_t *heap) { - return len > 0 && lsn > heap->compacted_lsn && - (type() == BS_HEAP_SMALL_WRITE || type() == BS_HEAP_INTENT_WRITE); + if (type() != BS_HEAP_SMALL_WRITE && type() != BS_HEAP_INTENT_WRITE) + { + return false; + } + return small().len > 0 && lsn > heap->compacted_lsn; } bool heap_write_t::needs_compact(blockstore_heap_t *heap) { - return (entry_type == (BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE) || - entry_type == (BS_HEAP_INTENT_WRITE|BS_HEAP_STABLE) && heap->dsk->csum_block_size > heap->dsk->bitmap_granularity && - ((offset % heap->dsk->csum_block_size) || (len % heap->dsk->csum_block_size))); + if (entry_type == (BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE)) + { + return true; + } + else if (entry_type == (BS_HEAP_INTENT_WRITE|BS_HEAP_STABLE) && heap->dsk->csum_block_size > heap->dsk->bitmap_granularity) + { + return ((small().offset % heap->dsk->csum_block_size) || (small().len % heap->dsk->csum_block_size)); + } + return false; } bool heap_write_t::is_compacted(uint64_t compacted_lsn) @@ -82,8 +92,15 @@ bool heap_write_t::is_compacted(uint64_t compacted_lsn) bool heap_write_t::can_be_collapsed(blockstore_heap_t *heap) { - return !heap->dsk->csum_block_size || heap->dsk->csum_block_size == heap->dsk->bitmap_granularity || - !(offset % heap->dsk->csum_block_size) && !(len % heap->dsk->csum_block_size); + if (type() == BS_HEAP_BIG_WRITE || type() == BS_HEAP_TOMBSTONE) + { + return false; + } + if (!heap->dsk->csum_block_size || heap->dsk->csum_block_size == heap->dsk->bitmap_granularity) + { + return true; + } + return !(small().offset % heap->dsk->csum_block_size) && !(small().len % heap->dsk->csum_block_size); } bool heap_write_t::is_allowed_before_compacted(uint64_t compacted_lsn, bool is_last_entry) @@ -97,34 +114,36 @@ uint8_t *heap_write_t::get_ext_bitmap(blockstore_heap_t *heap) { if (type() == BS_HEAP_TOMBSTONE) return NULL; - return ((uint8_t*)this + sizeof(heap_write_t)); + return ((uint8_t*)this + (type() == BS_HEAP_BIG_WRITE ? sizeof(heap_big_write_t) : sizeof(heap_small_write_t))); } uint8_t *heap_write_t::get_int_bitmap(blockstore_heap_t *heap) { if (type() != BS_HEAP_BIG_WRITE) return NULL; - return ((uint8_t*)this + sizeof(heap_write_t) + heap->dsk->clean_entry_bitmap_size); + return ((uint8_t*)this + (type() == BS_HEAP_BIG_WRITE ? sizeof(heap_big_write_t) : sizeof(heap_small_write_t)) + heap->dsk->clean_entry_bitmap_size); } uint8_t *heap_write_t::get_checksums(blockstore_heap_t *heap) { if (!heap->dsk->csum_block_size) return NULL; - if (len && (type() == BS_HEAP_SMALL_WRITE || - type() == BS_HEAP_INTENT_WRITE)) - return ((uint8_t*)this + sizeof(heap_write_t) + heap->dsk->clean_entry_bitmap_size); + if ((type() == BS_HEAP_SMALL_WRITE || type() == BS_HEAP_INTENT_WRITE) && small().len > 0) + return ((uint8_t*)this + sizeof(heap_small_write_t) + heap->dsk->clean_entry_bitmap_size); if (type() != BS_HEAP_BIG_WRITE) return NULL; - return ((uint8_t*)this + sizeof(heap_write_t) + 2*heap->dsk->clean_entry_bitmap_size); + return ((uint8_t*)this + sizeof(heap_big_write_t) + 2*heap->dsk->clean_entry_bitmap_size); } uint32_t *heap_write_t::get_checksum(blockstore_heap_t *heap) { - if (heap->dsk->csum_block_size || !len || - type() != BS_HEAP_SMALL_WRITE && type() != BS_HEAP_INTENT_WRITE) + if (heap->dsk->csum_block_size || + type() != BS_HEAP_SMALL_WRITE && type() != BS_HEAP_INTENT_WRITE || + small().len == 0) + { return NULL; - return (uint32_t*)((uint8_t*)this + sizeof(heap_write_t) + heap->dsk->clean_entry_bitmap_size); + } + return (uint32_t*)((uint8_t*)this + sizeof(heap_small_write_t) + heap->dsk->clean_entry_bitmap_size); } heap_write_t *heap_object_t::get_writes() @@ -164,7 +183,7 @@ blockstore_heap_t::blockstore_heap_t(blockstore_disk_t *dsk, uint8_t *buffer_are log_level(log_level), meta_block_count(dsk->meta_area_size/dsk->meta_block_size-1), // first block is the superblock target_block_free_space(dsk->meta_block_target_free_space), - max_write_entry_size(sizeof(heap_write_t) + 2*dsk->clean_entry_bitmap_size + + max_write_entry_size(sizeof(heap_small_write_t) + 2*dsk->clean_entry_bitmap_size + (dsk->csum_block_size ? dsk->data_block_size/dsk->csum_block_size*(dsk->data_csum_type & 0xFF) : 4 /*sizeof crc32c*/)) { assert(target_block_free_space < dsk->meta_block_size); @@ -343,13 +362,13 @@ skip_unseen: goto skip_unseen; } // Verify write chain - if (obj->write_pos < -(int16_t)block_offset || obj->write_pos > (int16_t)(dsk->meta_block_size-block_offset-sizeof(heap_write_t))) + if (obj->write_pos < -(int16_t)block_offset || obj->write_pos > (int16_t)(dsk->meta_block_size-block_offset-sizeof(heap_small_write_t))) { fprintf(stderr, "Warning: Object %jx:%jx in metadata block %u at %u write offset (%d) exceeds block boundaries, skipping object\n", obj->inode, obj->stripe, block_num, block_offset, obj->write_pos); goto skip_corrupted; } - if (obj->write_pos < 0 && obj->write_pos > -sizeof(heap_write_t) || + if (obj->write_pos < 0 && obj->write_pos > -sizeof(heap_small_write_t) || obj->write_pos > 0 && obj->write_pos < sizeof(heap_object_t)) { fprintf(stderr, "Warning: Object %jx:%jx in metadata block %u at %u write offset (%d) intersects the object itself, skipping object\n", @@ -441,7 +460,7 @@ skip_unseen: continue; } if (wr->type() == BS_HEAP_SMALL_WRITE && - !is_buffer_area_free(wr->location, wr->len)) + !is_buffer_area_free(wr->small().location, wr->small().len)) { fprintf(stderr, "Error: write %jx:%jx v%lu (l%lu) buffered data overlaps with other writes, skipping object\n", obj->inode, obj->stripe, wr->version, wr->lsn); @@ -449,8 +468,7 @@ skip_unseen: abort(); goto skip_object; } - if (wr->type() == BS_HEAP_BIG_WRITE && - is_data_used(wr->location)) + if (wr->type() == BS_HEAP_BIG_WRITE && is_data_used(wr->big().location)) { fprintf(stderr, "Error: write %jx:%jx v%lu (l%lu) data overlaps with other writes, skipping object\n", obj->inode, obj->stripe, wr->version, wr->lsn); @@ -465,7 +483,7 @@ skip_unseen: to_recheck = true; } // recheck small write data immediately - else if (!calc_checksums(wr, buffer_area + wr->location, false)) + else if (!calc_checksums(wr, buffer_area + wr->small().location, false)) { // entry is invalid (not fully written before OSD crash) - remove it and all newer (previous) entries too if (wr->type() == BS_HEAP_INTENT_WRITE && @@ -537,12 +555,12 @@ uint64_t blockstore_heap_t::load_blocks(uint64_t disk_offset, uint64_t size, uin used_space += wr->size; if (wr->type() == BS_HEAP_SMALL_WRITE) { - use_buffer_area(obj->inode, wr->location, wr->len); + use_buffer_area(obj->inode, wr->small().location, wr->small().len); } else if (wr->type() == BS_HEAP_BIG_WRITE) { // Mark data block as used - use_data(obj->inode, wr->location); + use_data(obj->inode, wr->big().location); } if (wr->lsn > this->compacted_lsn) { @@ -618,17 +636,21 @@ void blockstore_heap_t::finish_load() tmp_compact_queue.clear(); } -bool blockstore_heap_t::calc_checksums(heap_write_t *wr, uint8_t *data, bool set) +bool blockstore_heap_t::calc_checksums(heap_write_t *wr, uint8_t *data, bool set, uint32_t offset, uint32_t len) { if (!dsk->csum_block_size) { + if (wr->type() == BS_HEAP_BIG_WRITE) + { + return true; + } // Single checksum uint32_t *wr_csum = wr->get_checksum(this); if (!wr_csum) { return true; } - uint32_t real_csum = crc32c(0, data, wr->len); + uint32_t real_csum = crc32c(0, data, wr->small().len); if (set) { *wr_csum = real_csum; @@ -636,10 +658,13 @@ bool blockstore_heap_t::calc_checksums(heap_write_t *wr, uint8_t *data, bool set } return ((*wr_csum) == real_csum); } - uint32_t offset = (wr->type() == BS_HEAP_BIG_WRITE - ? (wr->offset / dsk->csum_block_size) * (dsk->data_csum_type & 0xFF) : 0); - return calc_block_checksums((uint32_t*)(wr->get_checksums(this) + offset), data, wr->get_int_bitmap(this), - wr->offset, wr->offset+wr->len, set, NULL); + if (wr->type() == BS_HEAP_BIG_WRITE) + { + return calc_block_checksums((uint32_t*)(wr->get_checksums(this) + offset/dsk->csum_block_size * (dsk->data_csum_type & 0xFF)), + data, wr->get_int_bitmap(this), offset, offset+len, set, NULL); + } + return calc_block_checksums((uint32_t*)wr->get_checksums(this), data, NULL, + wr->small().offset, wr->small().offset+wr->small().len, set, NULL); } bool blockstore_heap_t::calc_block_checksums(uint32_t *block_csums, uint8_t *data, uint8_t *bitmap, uint32_t start, uint32_t end, @@ -751,20 +776,21 @@ bool blockstore_heap_t::recheck_small_writes(std::functionneeds_recheck(this)) { bool is_intent = wr->type() == BS_HEAP_INTENT_WRITE; - uint64_t loc = wr->location; + uint64_t loc = wr->small().location; if (is_intent) { auto next_wr = wr->next(); assert(next_wr && next_wr->entry_type == (BS_HEAP_BIG_WRITE | (wr->entry_type & BS_HEAP_STABLE))); - loc = wr->offset + next_wr->location; + loc = wr->small().offset + next_wr->big().location; } recheck_in_progress++; - uint8_t *buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, wr->len); + uint8_t *buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, wr->small().len); if (log_level > 5) { - fprintf(stderr, "Notice: rechecking %u bytes at %ju in %s area (lsn %lu)\n", wr->len, loc, is_intent ? "data" : "buffer", wr->lsn); + fprintf(stderr, "Notice: rechecking %u bytes at %ju in %s area (lsn %lu)\n", + wr->small().len, loc, is_intent ? "data" : "buffer", wr->lsn); } - recheck_cb(is_intent, loc, wr->len, buf, [this, oid, lsn = wr->lsn, buf]() + recheck_cb(is_intent, loc, wr->small().len, buf, [this, oid, lsn = wr->lsn, buf]() { uint32_t block_num = 0; heap_object_t *obj = read_entry(oid, &block_num); @@ -1053,13 +1079,13 @@ uint32_t blockstore_heap_t::compact_object_to(heap_object_t *obj, uint64_t compa if (compacted_wr_count) { bool is_last = !wr->next(); + // all subsequent small write entries must also be compacted + assert(compacted_wr_count == 1 || wr->is_allowed_before_compacted(compact_lsn, is_last)); if (wr->type() == BS_HEAP_BIG_WRITE) { big_wr = wr; } - // all subsequent small write entries must also be compacted - assert(compacted_wr_count == 1 || wr->is_allowed_before_compacted(compact_lsn, is_last)); - if (!new_csums && !wr->can_be_collapsed(this)) + else if (!new_csums && !wr->can_be_collapsed(this)) { skip_csums = true; } @@ -1080,32 +1106,23 @@ uint32_t blockstore_heap_t::compact_object_to(heap_object_t *obj, uint64_t compa // Collapse compacted_wrs[] into big_wr big_wr->lsn = compacted_wrs[0]->lsn; big_wr->version = compacted_wrs[0]->version; - big_wr->len += big_wr->offset; memcpy(big_wr->get_ext_bitmap(this), compacted_wrs[0]->get_ext_bitmap(this), dsk->clean_entry_bitmap_size); - for (int i = 0; i < compacted_wr_count; i++) - { - auto cur_wr = compacted_wrs[i]; - if (big_wr->offset > cur_wr->offset) - big_wr->offset = cur_wr->offset; - if (big_wr->len < cur_wr->offset+cur_wr->len) - big_wr->len = cur_wr->offset+cur_wr->len; - } - big_wr->len -= big_wr->offset; uint8_t *int_bmp = big_wr->get_int_bitmap(this); uint8_t *csums = big_wr->get_checksums(this); const uint32_t csum_size = (dsk->data_csum_type & 0xFF); for (int i = compacted_wr_count-1; i >= 0; i--) { auto cur_wr = compacted_wrs[i]; - bitmap_set(int_bmp, cur_wr->offset, cur_wr->len, dsk->bitmap_granularity); + assert(cur_wr->type() == BS_HEAP_SMALL_WRITE || cur_wr->type() == BS_HEAP_INTENT_WRITE); + bitmap_set(int_bmp, cur_wr->small().offset, cur_wr->small().len, dsk->bitmap_granularity); // copy checksums if (csums && !skip_csums && !new_csums) { assert(i == compacted_wr_count-1 || - (cur_wr->offset % dsk->csum_block_size) == 0 && - (cur_wr->len % dsk->csum_block_size) == 0); - memcpy(csums + cur_wr->offset/dsk->csum_block_size*csum_size, - cur_wr->get_checksums(this), cur_wr->len/dsk->csum_block_size*csum_size); + (cur_wr->small().offset % dsk->csum_block_size) == 0 && + (cur_wr->small().len % dsk->csum_block_size) == 0); + memcpy(csums + cur_wr->small().offset/dsk->csum_block_size*csum_size, + cur_wr->get_checksums(this), cur_wr->small().len/dsk->csum_block_size*csum_size); } } if (csums && new_csums) @@ -1465,7 +1482,7 @@ bool blockstore_heap_t::mvcc_save_copy(heap_object_t *obj) { if (wr->type() == BS_HEAP_BIG_WRITE) { - mvcc_data_refs[wr->location] += add_ref; + mvcc_data_refs[wr->big().location] += add_ref; if (wr->entry_type & BS_HEAP_STABLE) { if (!for_obj) @@ -1475,9 +1492,9 @@ bool blockstore_heap_t::mvcc_save_copy(heap_object_t *obj) add_ref = 1; } } - else if (wr->type() == BS_HEAP_SMALL_WRITE && wr->len > 0) + else if (wr->type() == BS_HEAP_SMALL_WRITE && wr->small().len > 0) { - mvcc_buffer_refs[wr->location] += add_ref; + mvcc_buffer_refs[wr->small().location] += add_ref; } } // copied :-) @@ -1494,13 +1511,13 @@ void blockstore_heap_t::mark_overwritten(uint64_t over_lsn, uint64_t inode, heap } if (wr->type() == BS_HEAP_BIG_WRITE) { - overwrite_ref_queue.push_back((heap_refqi_t){ .lsn = over_lsn, .inode = inode, .location = wr->location, .len = 0, .is_data = true }); - mvcc_data_refs[wr->location] += !tracking_active; + overwrite_ref_queue.push_back((heap_refqi_t){ .lsn = over_lsn, .inode = inode, .location = wr->big().location, .len = 0, .is_data = true }); + mvcc_data_refs[wr->big().location] += !tracking_active; } - else if (wr->type() == BS_HEAP_SMALL_WRITE && wr->len > 0) + else if (wr->type() == BS_HEAP_SMALL_WRITE && wr->small().len > 0) { - overwrite_ref_queue.push_back((heap_refqi_t){ .lsn = over_lsn, .inode = inode, .location = wr->location, .len = wr->len, .is_data = false }); - mvcc_buffer_refs[wr->location] += !tracking_active; + overwrite_ref_queue.push_back((heap_refqi_t){ .lsn = over_lsn, .inode = inode, .location = wr->small().location, .len = wr->small().len, .is_data = false }); + mvcc_buffer_refs[wr->small().location] += !tracking_active; } wr = wr->next(); } @@ -1592,11 +1609,11 @@ int blockstore_heap_t::update_object(uint32_t block_num, heap_object_t *obj, hea // MVCC reference tracking is in action for the object, increase the refcount if (wr->type() == BS_HEAP_BIG_WRITE) { - mvcc_data_refs[wr->location]++; + mvcc_data_refs[wr->big().location]++; } - else if (wr->type() == BS_HEAP_SMALL_WRITE && wr->len > 0) + else if (wr->type() == BS_HEAP_SMALL_WRITE && wr->small().len > 0) { - mvcc_buffer_refs[wr->location]++; + mvcc_buffer_refs[wr->small().location]++; } } const uint8_t *old_data = inf->data; @@ -1623,16 +1640,16 @@ int blockstore_heap_t::update_object(uint32_t block_num, heap_object_t *obj, hea first_wr->can_be_collapsed(this)) { auto second_wr = first_wr->next(); + assert(second_wr->type() == BS_HEAP_BIG_WRITE); + auto first_offset = first_wr->small().offset; + auto first_len = first_wr->small().len; second_wr->version = first_wr->version; - second_wr->len = (first_wr->offset+first_wr->len > second_wr->offset+second_wr->len ? first_wr->offset+first_wr->len : second_wr->offset+second_wr->len); - second_wr->offset = first_wr->offset < second_wr->offset ? first_wr->offset : second_wr->offset; - second_wr->len -= second_wr->offset; - bitmap_set(second_wr->get_int_bitmap(this), first_wr->offset, first_wr->len, dsk->bitmap_granularity); + bitmap_set(second_wr->get_int_bitmap(this), first_offset, first_len, dsk->bitmap_granularity); if (dsk->csum_block_size) { const uint32_t csum_size = (dsk->data_csum_type & 0xFF); - memcpy(second_wr->get_checksums(this) + first_wr->offset/dsk->csum_block_size*csum_size, - first_wr->get_checksums(this), first_wr->len/dsk->csum_block_size*csum_size); + memcpy(second_wr->get_checksums(this) + first_offset/dsk->csum_block_size*csum_size, + first_wr->get_checksums(this), first_len/dsk->csum_block_size*csum_size); } used_delta -= free_writes(first_wr, second_wr); new_wr->next_pos = (uint8_t*)second_wr - (uint8_t*)new_wr; @@ -1957,16 +1974,16 @@ void blockstore_heap_t::free_object_space(inode_t inode, heap_write_t *from, hea { if (wr->type() == BS_HEAP_BIG_WRITE) { - deref_data(inode, wr->location, mode != BS_HEAP_FREE_MAIN); + deref_data(inode, wr->big().location, mode != BS_HEAP_FREE_MAIN); if (mode == BS_HEAP_FREE_MVCC && (wr->entry_type & BS_HEAP_STABLE)) { // Stop at the last visible version break; } } - else if (wr->type() == BS_HEAP_SMALL_WRITE && wr->len > 0) + else if (wr->type() == BS_HEAP_SMALL_WRITE && wr->small().len > 0) { - deref_buffer(inode, wr->location, wr->len, mode != BS_HEAP_FREE_MAIN); + deref_buffer(inode, wr->small().location, wr->small().len, mode != BS_HEAP_FREE_MAIN); } } } @@ -2010,7 +2027,7 @@ void blockstore_heap_t::add_used_space(uint32_t block_num, int32_t used_delta) { auto & inf = block_info.at(block_num); meta_used_space += used_delta; - auto thresh = dsk->meta_block_size-target_block_free_space; + auto thresh = (dsk->meta_block_size-target_block_free_space) - (dsk->meta_block_size-target_block_free_space)%MIN_ALLOC; auto old_used_space = inf.used_space; inf.used_space += used_delta; meta_alloc->change(block_num, diff --git a/src/blockstore/blockstore_heap.h b/src/blockstore/blockstore_heap.h index 7b35d78b..3fcdd95a 100644 --- a/src/blockstore/blockstore_heap.h +++ b/src/blockstore/blockstore_heap.h @@ -31,6 +31,37 @@ struct pool_shard_settings_t class blockstore_heap_t; +struct __attribute__((__packed__)) heap_small_write_t +{ + uint16_t size; + int16_t next_pos; + uint8_t flags; + uint64_t lsn; + uint64_t version; + uint64_t location; + uint32_t offset; + uint32_t len; +}; + +struct __attribute__((__packed__)) heap_big_write_t +{ + uint16_t size; + int16_t next_pos; + uint8_t flags; + uint64_t lsn; + uint64_t version; + uint64_t location; +}; + +struct __attribute__((__packed__)) heap_tombstone_t +{ + uint16_t size; + int16_t next_pos; + uint8_t flags; + uint64_t lsn; + uint64_t version; +}; + struct __attribute__((__packed__)) heap_write_t { // size should have top bit cleared @@ -39,9 +70,6 @@ struct __attribute__((__packed__)) heap_write_t uint8_t entry_type = 0; // BS_HEAP_* uint64_t lsn = 0; uint64_t version = 0; - uint32_t offset = 0; - uint32_t len = 0; - uint64_t location = 0; // uint8_t[] external_bitmap // uint8_t[] internal_bitmap @@ -49,6 +77,8 @@ struct __attribute__((__packed__)) heap_write_t heap_write_t *next(); inline uint8_t type() const { return (entry_type & BS_HEAP_TYPE); } + inline heap_small_write_t& small() { return *(heap_small_write_t*)this; } + inline heap_big_write_t& big() { return *(heap_big_write_t*)this; } uint32_t get_size(blockstore_heap_t *heap); uint32_t get_csum_size(blockstore_heap_t *heap); bool needs_recheck(blockstore_heap_t *heap); @@ -262,7 +292,7 @@ public: // unlock an entry bool unlock_entry(object_id oid, uint64_t copy_id); // set or verify checksums in a write request - bool calc_checksums(heap_write_t *wr, uint8_t *data, bool set); + bool calc_checksums(heap_write_t *wr, uint8_t *data, bool set, uint32_t offset = 0, uint32_t len = 0); // set or verify raw block checksums bool calc_block_checksums(uint32_t *block_csums, uint8_t *data, uint8_t *bitmap, uint32_t start, uint32_t end, bool set, std::function bad_block_cb); diff --git a/src/blockstore/blockstore_read.cpp b/src/blockstore/blockstore_read.cpp index a6533563..113c0eaf 100644 --- a/src/blockstore/blockstore_read.cpp +++ b/src/blockstore/blockstore_read.cpp @@ -169,12 +169,13 @@ uint32_t blockstore_impl_t::prepare_read_zero(std::vector & read_ uint32_t blockstore_impl_t::prepare_read_simple(std::vector & read_vec, heap_object_t *obj, heap_write_t *wr, uint32_t start, uint32_t end) { uint32_t res = 0; - if (wr->offset >= end || wr->offset+wr->len <= start) + if (wr->type() == BS_HEAP_SMALL_WRITE || wr->type() == BS_HEAP_INTENT_WRITE) { - return 0; + if (wr->small().offset >= end || wr->small().offset+wr->small().len <= start) + return 0; + start = start < wr->small().offset ? wr->small().offset : start; + end = end > wr->small().offset+wr->small().len ? wr->small().offset+wr->small().len : end; } - start = start < wr->offset ? wr->offset : start; - end = end > wr->offset+wr->len ? wr->offset+wr->len : end; find_holes(read_vec, start, end, [&](int & pos, uint32_t start, uint32_t end) { res += end-start; @@ -185,10 +186,10 @@ uint32_t blockstore_impl_t::prepare_read_simple(std::vector & rea .copy_flags = COPY_BUF_JOURNAL | COPY_BUF_SKIP_CSUM, .offset = start, .len = end-start, - .disk_loc = wr->location - wr->offset, + .disk_loc = wr->small().location - wr->small().offset, .disk_offset = start, .disk_len = end-start, - .buf = buffer_area + wr->location + start - wr->offset, + .buf = buffer_area + wr->small().location + start - wr->small().offset, .wr_lsn = wr->lsn, }); } @@ -202,14 +203,18 @@ uint32_t blockstore_impl_t::prepare_read_simple(std::vector & rea // the most complex case: read data from disk with padding uint32_t blk_start = start, blk_end = end; blk_start = (start/dsk.csum_block_size) * dsk.csum_block_size; - blk_start = blk_start < wr->offset ? wr->offset : blk_start; blk_end = ((end-1) / dsk.csum_block_size + 1) * dsk.csum_block_size; - blk_end = blk_end > wr->offset+wr->len ? wr->offset+wr->len : blk_end; + if (wr->type() == BS_HEAP_INTENT_WRITE || wr->type() == BS_HEAP_SMALL_WRITE) + { + blk_start = blk_start < wr->small().offset ? wr->small().offset : blk_start; + blk_end = blk_end > wr->small().offset+wr->small().len ? wr->small().offset+wr->small().len : blk_end; + } uint32_t skip_csum = 0; if (!perfect_csum_update && wr->type() == BS_HEAP_BIG_WRITE) { for (auto owr = obj->get_writes(); owr && owr != wr; owr = owr->next()) - if (owr->offset < blk_end && owr->offset+owr->len > blk_start) + if ((owr->type() == BS_HEAP_INTENT_WRITE || owr->type() == BS_HEAP_SMALL_WRITE) && + owr->small().offset < blk_end && owr->small().offset+owr->small().len > blk_start) skip_csum = COPY_BUF_SKIP_CSUM; } if ((blk_end-1)/dsk.csum_block_size == blk_start/dsk.csum_block_size || @@ -247,7 +252,9 @@ void blockstore_impl_t::prepare_disk_read(std::vector & read_vec, .copy_flags = (wr->type() == BS_HEAP_SMALL_WRITE ? COPY_BUF_JOURNAL : COPY_BUF_DATA) | copy_flags, .offset = start, .len = end-start, - .disk_loc = (wr->type() == BS_HEAP_INTENT_WRITE ? wr->next()->location : wr->location - (wr->type() == BS_HEAP_SMALL_WRITE ? wr->offset : 0)), + .disk_loc = (wr->type() == BS_HEAP_INTENT_WRITE ? wr->next()->big().location + : (wr->type() == BS_HEAP_SMALL_WRITE ? wr->small().location-wr->small().offset + : wr->big().location)), .disk_offset = blk_start, .disk_len = blk_end - blk_start, .wr_lsn = wr->lsn, @@ -367,7 +374,7 @@ bool blockstore_impl_t::verify_read_checksums(blockstore_op_t *op) uint8_t *buf = vec.buf ? vec.buf : (op->buf + vec.offset - op->offset); uint32_t *csums = (uint32_t*)(wr->get_checksums(heap) + (vec.disk_offset/dsk.csum_block_size)*(dsk.data_csum_type & 0xFF) - - ((wr->type() == BS_HEAP_BIG_WRITE) ? 0 : (wr->offset/dsk.csum_block_size)*(dsk.data_csum_type & 0xFF))); + - ((wr->type() == BS_HEAP_BIG_WRITE) ? 0 : (wr->small().offset/dsk.csum_block_size)*(dsk.data_csum_type & 0xFF))); if (!heap->calc_block_checksums(csums, buf, wr->get_int_bitmap(heap), vec.disk_offset, vec.disk_offset+vec.disk_len, false, [&](uint32_t mismatch_pos, uint32_t expected_csum, uint32_t real_csum) { diff --git a/src/blockstore/blockstore_write.cpp b/src/blockstore/blockstore_write.cpp index a50cd96e..492b4505 100644 --- a/src/blockstore/blockstore_write.cpp +++ b/src/blockstore/blockstore_write.cpp @@ -149,21 +149,21 @@ int blockstore_impl_t::dequeue_write(blockstore_op_t *op) BS_SUBMIT_CHECK_SQES(1); if (obj->get_writes()->type() == BS_HEAP_BIG_WRITE) { - PRIV(op)->location = obj->get_writes()->location; + PRIV(op)->location = obj->get_writes()->big().location; } else { assert(obj->get_writes()->next()->type() == BS_HEAP_BIG_WRITE); - PRIV(op)->location = obj->get_writes()->next()->location; + PRIV(op)->location = obj->get_writes()->next()->big().location; } process_intent: uint8_t wr_buf[heap->get_max_write_entry_size()]; heap_write_t *wr = (heap_write_t*)wr_buf; wr->version = op->version; - wr->offset = op->offset; - wr->len = op->len; - wr->location = 0; wr->entry_type = BS_HEAP_INTENT_WRITE | (op->opcode == BS_OP_WRITE_STABLE ? BS_HEAP_STABLE : 0); + wr->small().offset = op->offset; + wr->small().len = op->len; + wr->small().location = 0; if (op->bitmap) memcpy(wr->get_ext_bitmap(heap), op->bitmap, dsk.clean_entry_bitmap_size); heap->calc_checksums(wr, (uint8_t*)op->buf, true); @@ -208,11 +208,11 @@ process_intent: uint8_t wr_buf[heap->get_max_write_entry_size()]; heap_write_t *wr = (heap_write_t*)wr_buf; wr->version = op->version; - wr->offset = op->offset; - wr->len = op->len; - wr->location = loc; - PRIV(op)->location = loc; wr->entry_type = BS_HEAP_SMALL_WRITE | (op->opcode == BS_OP_WRITE_STABLE ? BS_HEAP_STABLE : 0); + wr->small().offset = op->offset; + wr->small().len = op->len; + wr->small().location = loc; + PRIV(op)->location = loc; if (op->bitmap) memcpy(wr->get_ext_bitmap(heap), op->bitmap, dsk.clean_entry_bitmap_size); heap->calc_checksums(wr, (uint8_t*)op->buf, true); @@ -267,16 +267,14 @@ int blockstore_impl_t::make_big_write(blockstore_op_t *op, uint32_t offset, uint { uint8_t wr_buf[heap->get_max_write_entry_size()]; heap_write_t *wr = (heap_write_t*)wr_buf; - wr->version = op->version; - wr->offset = offset; - wr->len = len; - wr->location = PRIV(op)->location; wr->entry_type = BS_HEAP_BIG_WRITE | (op->opcode == BS_OP_WRITE_STABLE ? BS_HEAP_STABLE : 0); + wr->version = op->version; + wr->big().location = PRIV(op)->location; if (op->bitmap) memcpy(wr->get_ext_bitmap(heap), op->bitmap, dsk.clean_entry_bitmap_size); memset(wr->get_int_bitmap(heap), 0, dsk.clean_entry_bitmap_size); bitmap_set(wr->get_int_bitmap(heap), offset, len, dsk.bitmap_granularity); - heap->calc_checksums(wr, (uint8_t*)op->buf, true); + heap->calc_checksums(wr, (uint8_t*)op->buf, true, offset, len); int res = heap->post_write(op->oid, wr, modified_block, moved_from_block); if (res != 0) return res; diff --git a/src/disk_tool/disk_tool_discard.cpp b/src/disk_tool/disk_tool_discard.cpp index 82ca7dd6..1b68c9bf 100644 --- a/src/disk_tool/disk_tool_discard.cpp +++ b/src/disk_tool/disk_tool_discard.cpp @@ -61,7 +61,7 @@ int disk_tool_t::trim_data(std::string device) { if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE) { - data_alloc->set(wr->location / dsk.data_block_size, true); + data_alloc->set(wr->big().location / dsk.data_block_size, true); } } }, diff --git a/src/disk_tool/disk_tool_meta.cpp b/src/disk_tool/disk_tool_meta.cpp index 4b9ceab4..b8059907 100644 --- a/src/disk_tool/disk_tool_meta.cpp +++ b/src/disk_tool/disk_tool_meta.cpp @@ -349,7 +349,7 @@ void disk_tool_t::dump_heap_entry_as_old(blockstore_heap_t *heap, heap_object_t #define ENTRY_FMT "{\"block\":%ju,\"pool\":%u,\"inode\":\"0x%jx\",\"stripe\":\"0x%jx\",\"version\":%ju" (first_entry ? ENTRY_FMT : (",\n" ENTRY_FMT)), #undef ENTRY_FMT - wr->location/dsk.data_block_size, INODE_POOL(obj->inode), INODE_NO_POOL(obj->inode), + wr->big().location/dsk.data_block_size, INODE_POOL(obj->inode), INODE_NO_POOL(obj->inode), obj->stripe, wr->version ); printf(",\"bitmap\":\""); @@ -395,27 +395,36 @@ void disk_tool_t::dump_heap_entry(blockstore_heap_t *heap, heap_object_t *obj) for (wr = obj->get_writes(); wr; wr = wr->next()) { printf( -#define ENTRY_FMT "{\"lsn\":%ju,\"version\":%ju,\"type\":\"%s\",\"stable\":%s,\"offset\":%u,\"len\":%u" +#define ENTRY_FMT "{\"lsn\":%ju,\"version\":%ju,\"type\":\"%s\",\"stable\":%s" (first_wr ? ENTRY_FMT : ("," ENTRY_FMT)), #undef ENTRY_FMT wr->lsn, wr->version, (wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE ? "small" : ( (wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE ? "big" : ( (wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_INTENT_WRITE ? "intent" : ( (wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_TOMBSTONE ? "tombstone" : "unknown"))), - (wr->entry_type & BS_HEAP_STABLE) ? "true" : "false", - wr->offset, wr->len + (wr->entry_type & BS_HEAP_STABLE) ? "true" : "false" ); - if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE || - (wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE && !dump_with_data) + if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE) { - printf(",\"location\":%ju", wr->location); + printf(",\"location\":%ju", wr->big().location); } - else if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE && dump_with_data) + else if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_INTENT_WRITE) { - printf(",\"data\":\""); - for (uint32_t i = 0; i < wr->len; i++) - printf("%02x", buffer_area[wr->location + i]); - printf("\""); + printf(",\"offset\":%u,\"len\":%u", wr->small().offset, wr->small().len); + } + else if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE) + { + if (!dump_with_data) + { + printf(",\"offset\":%u,\"len\":%u,\"location\":%ju", wr->small().offset, wr->small().len, wr->small().location); + } + else + { + printf(",\"data\":\""); + for (uint32_t i = 0; i < wr->small().len; i++) + printf("%02x", buffer_area[wr->small().location + i]); + printf("\""); + } } uint8_t* bitmap = wr->get_int_bitmap(heap); if (bitmap) @@ -640,21 +649,28 @@ int disk_tool_t::write_json_heap(json11::Json meta, json11::Json journal) wr->entry_type = wr_type | (write_entry["stable"].bool_value() ? BS_HEAP_STABLE : 0); wr->lsn = write_entry["lsn"].uint64_value(); wr->version = write_entry["version"].uint64_value(); - wr->offset = write_entry["offset"].uint64_value(); - wr->len = write_entry["len"].uint64_value(); - wr->location = write_entry["location"].uint64_value(); wr->size = wr->get_size(new_heap); wr->next_pos = wr->size; - if (wr_type == BS_HEAP_SMALL_WRITE && write_entry["data"].is_string() && wr->len > 0) + if (wr_type == BS_HEAP_SMALL_WRITE || wr_type == BS_HEAP_INTENT_WRITE) { - if (!new_journal_buf) + wr->small().offset = write_entry["offset"].uint64_value(); + wr->small().len = write_entry["len"].uint64_value(); + wr->small().location = write_entry["location"].uint64_value(); + if (wr_type == BS_HEAP_SMALL_WRITE && write_entry["data"].is_string() && wr->small().len > 0) { - fprintf(stderr, "Loading small write data requires overwriting buffer area\n"); - free_new_meta(); - return 1; + if (!new_journal_buf) + { + fprintf(stderr, "Loading small write data requires overwriting buffer area\n"); + free_new_meta(); + return 1; + } + wr->small().location = new_heap->find_free_buffer_area(wr->small().len); + fromhexstr(write_entry["data"].string_value(), wr->small().len, new_journal_buf + wr->small().location); } - wr->location = new_heap->find_free_buffer_area(wr->len); - fromhexstr(write_entry["data"].string_value(), wr->len, new_journal_buf + wr->location); + } + else if (wr_type == BS_HEAP_BIG_WRITE) + { + wr->big().location = write_entry["location"].uint64_value(); } if (write_entry["bitmap"].is_string() && wr->get_int_bitmap(new_heap)) { @@ -778,9 +794,7 @@ close_err: wr->entry_type = BS_HEAP_BIG_WRITE|BS_HEAP_STABLE; wr->lsn = ++next_lsn; wr->version = sscanf_json(NULL, meta_entry["version"]); - wr->offset = 0; - wr->len = new_meta_hdr->data_block_size; - wr->location = meta_entry["block"].uint64_value() * new_meta_hdr->data_block_size; + wr->big().location = meta_entry["block"].uint64_value() * new_meta_hdr->data_block_size; wr->size = wr->get_size(&heap); fromhexstr(meta_entry["bitmap"].string_value(), new_clean_entry_bitmap_size, wr->get_int_bitmap(&heap)); fromhexstr(meta_entry["ext_bitmap"].string_value(), new_clean_entry_bitmap_size, wr->get_ext_bitmap(&heap)); @@ -795,36 +809,39 @@ close_err: wr->next_pos = 0; wr->lsn = ++next_lsn; wr->version = rec["ver"].uint64_value(); - wr->offset = rec["offset"].uint64_value(); - wr->len = rec["len"].uint64_value(); + uint64_t wr_offset = rec["offset"].uint64_value(); + uint64_t wr_len = rec["len"].uint64_value(); if (rec["type"] == "small_write" || rec["type"] == "small_write_instant") { - if (wr->len > 0 && !rec["data"].is_string()) + if (wr_len > 0 && !rec["data"].is_string()) { fprintf(stderr, "Error: entry data is missing, please generate the dump with --json --format data\n"); goto close_err; } wr->entry_type = BS_HEAP_SMALL_WRITE | (rec["type"] == "small_write_instant" ? BS_HEAP_STABLE : 0); + wr->small().offset = wr_offset; + wr->small().len = wr_len; + wr->small().location = buffer_pos; fromhexstr(rec["bitmap"].string_value(), new_clean_entry_bitmap_size, wr->get_ext_bitmap(&heap)); - fromhexstr(rec["data"].string_value(), wr->len, new_journal_buf+buffer_pos); - if (wr->len > 0) + fromhexstr(rec["data"].string_value(), wr_len, new_journal_buf+buffer_pos); + if (wr_len > 0) { if (!new_meta_hdr->data_csum_type) - *wr->get_checksum(&heap) = crc32c(0, new_journal_buf+buffer_pos, wr->len); + *wr->get_checksum(&heap) = crc32c(0, new_journal_buf+buffer_pos, wr_len); else - heap.calc_block_checksums((uint32_t*)wr->get_checksums(&heap), new_journal_buf+buffer_pos, NULL, wr->offset, wr->offset+wr->len, true, NULL); + heap.calc_block_checksums((uint32_t*)wr->get_checksums(&heap), new_journal_buf+buffer_pos, NULL, wr_offset, wr_offset+wr_len, true, NULL); } - buffer_pos += wr->len; + buffer_pos += wr_len; } else if (rec["type"] == "big_write" || rec["type"] == "big_write_instant") { wr->entry_type = BS_HEAP_BIG_WRITE | (rec["type"] == "big_write_instant" ? BS_HEAP_STABLE : 0); - wr->location = sscanf_json(NULL, rec["loc"]); - bitmap_set(wr->get_int_bitmap(&heap), wr->offset, wr->len, new_meta_hdr->bitmap_granularity); + wr->big().location = sscanf_json(NULL, rec["loc"]); + bitmap_set(wr->get_int_bitmap(&heap), wr_offset, wr_len, new_meta_hdr->bitmap_granularity); fromhexstr(rec["bitmap"].string_value(), new_clean_entry_bitmap_size, wr->get_ext_bitmap(&heap)); if (new_meta_hdr->data_csum_type != 0) { - if ((wr->offset % new_meta_hdr->csum_block_size) || (wr->len % new_meta_hdr->csum_block_size)) + if ((wr_offset % new_meta_hdr->csum_block_size) || (wr_len % new_meta_hdr->csum_block_size)) { fprintf(stderr, "Error: big_write journal entries not aligned to csum_block_size can't be converted between v0.9 and v3.0 metadata\n" @@ -832,8 +849,8 @@ close_err: goto close_err; } fromhexstr(rec["block_csums"].string_value(), - ((wr->offset+wr->len+new_meta_hdr->csum_block_size-1)/new_meta_hdr->csum_block_size - - wr->offset/new_meta_hdr->csum_block_size) * (new_meta_hdr->data_csum_type & 0xFF), + ((wr_offset+wr_len+new_meta_hdr->csum_block_size-1)/new_meta_hdr->csum_block_size + - wr_offset/new_meta_hdr->csum_block_size) * (new_meta_hdr->data_csum_type & 0xFF), wr->get_checksums(&heap)); } } diff --git a/src/disk_tool/disk_tool_resize.cpp b/src/disk_tool/disk_tool_resize.cpp index e1d6fc35..f3bc09b9 100644 --- a/src/disk_tool/disk_tool_resize.cpp +++ b/src/disk_tool/disk_tool_resize.cpp @@ -43,7 +43,7 @@ int disk_tool_t::raw_resize() { if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE) { - data_alloc->set(wr->location / dsk.data_block_size, true); + data_alloc->set(wr->big().location / dsk.data_block_size, true); } } }, @@ -569,13 +569,7 @@ int disk_tool_t::resize_rebuild_meta() { if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE) { - if (wr->next() && new_meta_hdr->data_csum_type != 0 && - ((wr->offset % new_meta_hdr->csum_block_size) || (wr->len % new_meta_hdr->csum_block_size))) - { - fprintf(stderr, "Error: big_write journal entries not aligned to csum_block_size can't be converted between v0.9 and v3.0 metadata\n"); - exit(1); - } - auto block_num = wr->location / dsk.data_block_size; + auto block_num = wr->big().location / dsk.data_block_size; auto remap_it = data_remap.find(block_num); if (remap_it != data_remap.end()) block_num = remap_it->second; @@ -585,20 +579,20 @@ int disk_tool_t::resize_rebuild_meta() exit(1); } block_num += data_idx_diff; - wr->location = block_num * dsk.data_block_size; + wr->big().location = block_num * dsk.data_block_size; } else if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE) { - if (new_heap && wr->len > 0) + if (new_heap && wr->small().len > 0) { - if (new_journal_ptr-new_journal_buf+wr->len > new_journal_len) + if (new_journal_ptr-new_journal_buf+wr->small().len > new_journal_len) { fprintf(stderr, "Small write data doesn't fit into the new buffer area\n"); exit(1); } - memcpy(new_journal_ptr, buffer_area+wr->location, wr->len); - wr->location = new_journal_ptr-new_journal_buf; - new_journal_ptr += wr->len; + memcpy(new_journal_ptr, buffer_area+wr->small().location, wr->small().len); + wr->small().location = new_journal_ptr-new_journal_buf; + new_journal_ptr += wr->small().len; } } else if (!new_heap) @@ -626,8 +620,9 @@ int disk_tool_t::resize_rebuild_meta() { auto wr = writes[i]; assert((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE || wr->entry_type == BS_HEAP_BIG_WRITE); - uint32_t je_size = dsk.dirty_dyn_size(wr->offset, wr->len) + - ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE ? sizeof(journal_entry_small_write) : sizeof(journal_entry_big_write)); + uint32_t je_size = ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE + ? sizeof(journal_entry_small_write) + dsk.dirty_dyn_size(wr->small().offset, wr->small().len) + : sizeof(journal_entry_big_write) + dsk.dirty_dyn_size(0, dsk.data_block_size)); choose_journal_block(je_size); journal_entry *je = (journal_entry*)(new_journal_ptr + new_journal_in_pos); je->magic = JOURNAL_MAGIC; @@ -636,28 +631,30 @@ int disk_tool_t::resize_rebuild_meta() je->crc32_prev = new_crc32_prev; je->small_write.oid = (object_id){ .inode = obj->inode, .stripe = obj->stripe }; je->small_write.version = wr->version; - je->small_write.offset = wr->offset; - je->small_write.len = wr->len; - if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE) + if (wr->type() == BS_HEAP_SMALL_WRITE) { + je->small_write.offset = wr->small().offset; + je->small_write.len = wr->small().len; je->small_write.data_offset = new_journal_data-new_journal_buf; if (je->small_write.data_offset + je->small_write.len > new_journal_len) { fprintf(stderr, "Error: live entries don't fit to the new journal\n"); exit(1); } - memcpy(new_journal_data, buffer_area+wr->location, je->small_write.len); + memcpy(new_journal_data, buffer_area+wr->small().location, je->small_write.len); new_journal_data += je->small_write.len; if (dsk.data_csum_type == 0 && wr->get_checksum(heap)) je->small_write.crc32_data = *wr->get_checksum(heap); } else { - je->big_write.location = wr->location; + je->big_write.location = wr->big().location; } memcpy((uint8_t*)je + je->size, wr->get_ext_bitmap(heap), new_clean_entry_bitmap_size); if (dsk.data_csum_type != 0 && wr->get_checksums(heap)) - memcpy((uint8_t*)je + je->size + new_clean_entry_bitmap_size, wr->get_checksums(heap), new_data_csum_size); + { + memcpy((uint8_t*)je + je->size + new_clean_entry_bitmap_size, wr->get_checksums(heap), wr->get_csum_size(heap)); + } je->crc32 = je_crc32(je); new_journal_in_pos += je->size; new_crc32_prev = je->crc32; @@ -666,7 +663,7 @@ int disk_tool_t::resize_rebuild_meta() if (writes[writes.size()-1]->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE) { auto big_wr = writes[writes.size()-1]; - uint64_t block_num = big_wr->location / dsk.data_block_size; + uint64_t block_num = big_wr->big().location / dsk.data_block_size; clean_disk_entry *new_entry = (clean_disk_entry*)(new_meta_buf + dsk.meta_block_size + dsk.meta_block_size*(block_num / new_entries_per_block) + new_clean_entry_size*(block_num % new_entries_per_block)); @@ -697,10 +694,8 @@ int disk_tool_t::resize_rebuild_meta() uint8_t wr_buf[new_heap->get_max_write_entry_size()]; heap_write_t *wr = (heap_write_t*)wr_buf; wr->entry_type = BS_HEAP_BIG_WRITE|BS_HEAP_STABLE; - wr->location = block_num * dsk.data_block_size; + wr->big().location = block_num * dsk.data_block_size; wr->next_pos = 0; - wr->offset = 0; - wr->len = 0; wr->size = wr->get_size(new_heap); if (bitmap) { diff --git a/src/test/test_blockstore.cpp b/src/test/test_blockstore.cpp index 457662cd..ef4836bb 100644 --- a/src/test/test_blockstore.cpp +++ b/src/test/test_blockstore.cpp @@ -398,6 +398,8 @@ static void test_padded_csum_intent(bool perfect) // (intent is not collapsible because of csum_block_size > bitmap_granularity) heap_object_t *obj = test.bs->heap->read_entry((object_id){ .inode = 1, .stripe = 0 }, NULL); assert(obj); + assert(obj->get_writes()->next()); + assert(obj->get_writes()->next()->next()); assert(!obj->get_writes()->next()->next()->next()); assert(obj->get_writes()->entry_type == BS_HEAP_SMALL_WRITE); assert(obj->get_writes()->next()->entry_type == (perfect ? BS_HEAP_SMALL_WRITE : BS_HEAP_INTENT_WRITE)); diff --git a/src/test/test_heap.cpp b/src/test/test_heap.cpp index 71a5bf9f..bc013a8a 100644 --- a/src/test/test_heap.cpp +++ b/src/test/test_heap.cpp @@ -67,12 +67,10 @@ int _test_do_big_write(blockstore_heap_t & heap, blockstore_disk_t & dsk, uint64 uint8_t wr_buf[heap.get_max_write_entry_size()]; heap_write_t *wr = (heap_write_t*)wr_buf; wr->version = version; - wr->offset = offset; - wr->len = len; - wr->location = location; + wr->big().location = location; wr->entry_type = BS_HEAP_BIG_WRITE | (stable ? BS_HEAP_STABLE : 0); assert(heap.get_max_write_entry_size() >= wr->get_size(&heap)); - assert(wr->get_size(&heap) == sizeof(heap_write_t) + 2*dsk.clean_entry_bitmap_size + (dsk.csum_block_size + assert(wr->get_size(&heap) == sizeof(heap_big_write_t) + 2*dsk.clean_entry_bitmap_size + (dsk.csum_block_size ? dsk.data_block_size/dsk.csum_block_size*4 : 0)); memset(wr->get_ext_bitmap(&heap), 0xff, dsk.clean_entry_bitmap_size); memset(wr->get_int_bitmap(&heap), 0, dsk.clean_entry_bitmap_size); @@ -105,11 +103,11 @@ int _test_do_small_write(blockstore_heap_t & heap, blockstore_disk_t & dsk, uint uint8_t wr_buf[heap.get_max_write_entry_size()]; heap_write_t *wr = (heap_write_t*)wr_buf; wr->version = version; - wr->offset = offset; - wr->len = len; - wr->location = location; + wr->small().offset = offset; + wr->small().len = len; + wr->small().location = location; wr->entry_type = (is_intent ? BS_HEAP_INTENT_WRITE : BS_HEAP_SMALL_WRITE) | (stable ? BS_HEAP_STABLE : 0); - assert(wr->get_size(&heap) == sizeof(heap_write_t) + dsk.clean_entry_bitmap_size + (dsk.csum_block_size + assert(wr->get_size(&heap) == sizeof(heap_small_write_t) + dsk.clean_entry_bitmap_size + (dsk.csum_block_size ? ((offset+len+dsk.csum_block_size-1)/dsk.csum_block_size - offset/dsk.csum_block_size)*4 : 4)); memset(wr->get_ext_bitmap(&heap), 0xff, dsk.clean_entry_bitmap_size); assert(!wr->get_int_bitmap(&heap)); @@ -173,7 +171,7 @@ void test_mvcc(bool csum) assert(heap.find_free_data() == 0); _test_big_write(heap, dsk, 1, 0, 1, 0); - assert(heap.get_meta_block_used_space(0) == sizeof(heap_object_t) + sizeof(heap_write_t) + + assert(heap.get_meta_block_used_space(0) == sizeof(heap_object_t) + sizeof(heap_big_write_t) + 2*dsk.clean_entry_bitmap_size + (dsk.csum_block_size ? dsk.data_block_size/dsk.csum_block_size*4 : 0)); assert(check_used_space(heap, dsk, 0)); assert(heap.get_meta_used_space() == heap.get_meta_block_used_space(0)); @@ -188,11 +186,9 @@ void test_mvcc(bool csum) assert(count_writes(obj) == 1); heap_write_t *wr = obj->get_writes(); assert(wr->lsn == 1); - assert(wr->version == 1); - assert(wr->offset == 0); - assert(wr->len == dsk.data_block_size); - assert(wr->location == 0); assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); + assert(wr->version == 1); + assert(wr->big().location == 0); uint64_t old_size = obj->size + wr->size; assert(heap.read_locked_entry(oid, copy_id) == obj); @@ -293,11 +289,11 @@ void test_compact_block() blockstore_heap_t heap(&dsk, buffer_area.data()); heap.finish_load(); - uint32_t big_write_size = (sizeof(heap_object_t) + sizeof(heap_write_t) + 2*dsk.clean_entry_bitmap_size + dsk.data_block_size/dsk.csum_block_size*4); - uint32_t small_write_size = (sizeof(heap_write_t) + dsk.clean_entry_bitmap_size + 4); - assert(big_write_size == 198); + uint32_t big_write_size = (sizeof(heap_object_t) + sizeof(heap_big_write_t) + 2*dsk.clean_entry_bitmap_size + dsk.data_block_size/dsk.csum_block_size*4); + uint32_t small_write_size = (sizeof(heap_small_write_t) + dsk.clean_entry_bitmap_size + 4); + assert(big_write_size == 190); assert(small_write_size == 45); - uint32_t nwr = dsk.meta_block_size/(big_write_size+small_write_size); + uint32_t nwr = (dsk.meta_block_size-heap.get_max_write_entry_size())/(big_write_size+small_write_size); { for (uint32_t i = 0; i < nwr*2; i++) @@ -319,8 +315,7 @@ void test_compact_block() _test_big_write(heap, dsk, 1, nwr*2*0x20000, 1, nwr*2*0x20000); _test_big_write(heap, dsk, 1, (nwr*2+1)*0x20000, 1, (nwr*2+1)*0x20000); _test_big_write(heap, dsk, 1, (nwr*2+2)*0x20000, 1, (nwr*2+2)*0x20000); - assert(count_free_fragments(heap, dsk, 0) == nwr+1); - assert(count_free_fragments(heap, dsk, 1) == 1); + assert(count_free_fragments(heap, dsk, 0) == 1); } printf("OK test_compact_block\n"); @@ -562,11 +557,9 @@ void test_recheck(bool async, bool csum, bool intent) assert(count_writes(obj) == 1); heap_write_t *wr = obj->get_writes(); assert(wr->lsn == 1); - assert(wr->version == 1); - assert(wr->offset == 0); - assert(wr->len == dsk.data_block_size); - assert(wr->location == 0x20000); assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); + assert(wr->version == 1); + assert(wr->big().location == 0x20000); // read object 2 - both writes should be present oid = { .inode = INODE_WITH_POOL(1, 2), .stripe = 0 }; @@ -575,11 +568,11 @@ void test_recheck(bool async, bool csum, bool intent) assert(count_writes(obj) == 2); wr = obj->get_writes(); assert(wr->lsn == 4); - assert(wr->version == 2); - assert(wr->offset == 8192); - assert(wr->len == 12*1024); - assert(wr->location == 24*1024); assert(wr->entry_type == BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE); + assert(wr->version == 2); + assert(wr->small().offset == 8192); + assert(wr->small().len == 12*1024); + assert(wr->small().location == 24*1024); } printf("OK test_recheck %s %s %s\n", async ? "async" : "sync", csum ? "csum" : "no_csum", intent ? "intent" : "buffered"); @@ -616,9 +609,6 @@ void test_corruption() uint8_t wr_buf[heap.get_max_write_entry_size()]; heap_write_t *wr = (heap_write_t*)wr_buf; wr->version = 2; - wr->offset = 0; - wr->len = 0; - wr->location = 0; wr->entry_type = BS_HEAP_TOMBSTONE|BS_HEAP_STABLE; assert(!wr->get_checksums(&heap)); res = heap.post_write(oid, wr, NULL, NULL); @@ -657,8 +647,8 @@ void test_corruption() assert(obj); assert(count_writes(obj) == 1); heap_write_t *wr = obj->get_writes(); - assert(wr->location == 0x40000); assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); + assert(wr->big().location == 0x40000); // object 3 should be present oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0x40000 }; @@ -666,8 +656,8 @@ void test_corruption() assert(obj); assert(count_writes(obj) == 1); wr = obj->get_writes(); - assert(wr->location == 0x60000); assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); + assert(wr->big().location == 0x60000); // object 4 should be a tombstone oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0x60000 }; @@ -742,12 +732,12 @@ void test_full_overwrite(bool stable) assert(count_writes(obj) == 2); heap_write_t *wr = obj->get_writes(); assert(wr->version == 4); - assert(wr->location == 20480); assert(wr->entry_type == BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE); + assert(wr->small().location == 20480); wr = wr->next(); assert(wr->version == 3); - assert(wr->location == 0x40000); assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); + assert(wr->big().location == 0x40000); // check that the data block 0x20000 is freed and 0x40000 is used assert(!heap.is_data_used(0x20000)); @@ -852,7 +842,7 @@ void _test_invalid_data_setup(blockstore_disk_t & dsk, std::vector & bu wr->lsn = 1; wr->version = 1; wr->entry_type = BS_HEAP_TOMBSTONE; - wr->size = sizeof(heap_write_t); + wr->size = sizeof(heap_tombstone_t); obj->crc32c = obj->calc_crc32c(); obj = (heap_object_t*)((uint8_t*)wr + wr->size); @@ -865,7 +855,7 @@ void _test_invalid_data_setup(blockstore_disk_t & dsk, std::vector & bu wr->lsn = 1; wr->version = 1; wr->entry_type = BS_HEAP_TOMBSTONE; - wr->size = sizeof(heap_write_t); + wr->size = sizeof(heap_tombstone_t); obj->crc32c = obj->calc_crc32c(); obj = (heap_object_t*)(tmp.data() + dsk.meta_block_size); @@ -877,7 +867,7 @@ void _test_invalid_data_setup(blockstore_disk_t & dsk, std::vector & bu wr->lsn = 2; wr->version = 1; wr->entry_type = BS_HEAP_TOMBSTONE; - wr->size = sizeof(heap_write_t); + wr->size = sizeof(heap_tombstone_t); obj->crc32c = obj->calc_crc32c(); } @@ -889,6 +879,7 @@ void test_invalid_data() std::vector tmp; // Too small object + printf("too small:\n"); { _test_invalid_data_setup(dsk, buffer_area, tmp); heap_object_t *obj = (heap_object_t*)tmp.data(); @@ -907,6 +898,7 @@ void test_invalid_data() } // Too large object + printf("too large:\n"); { _test_invalid_data_setup(dsk, buffer_area, tmp); heap_object_t *obj = (heap_object_t*)tmp.data(); @@ -925,6 +917,7 @@ void test_invalid_data() } // No writes + printf("no writes:\n"); { _test_invalid_data_setup(dsk, buffer_area, tmp); heap_object_t *obj = (heap_object_t*)tmp.data(); @@ -946,6 +939,7 @@ void test_invalid_data() } // Bad crc32c + printf("bad crc:\n"); { _test_invalid_data_setup(dsk, buffer_area, tmp); heap_object_t *obj = (heap_object_t*)tmp.data(); @@ -967,6 +961,7 @@ void test_invalid_data() } // Bad write size + printf("bad write size:\n"); { _test_invalid_data_setup(dsk, buffer_area, tmp); heap_object_t *obj = (heap_object_t*)tmp.data(); @@ -991,15 +986,16 @@ void test_invalid_data() // 4) intersects with object beginning for (int i = 0; i < 4; i++) { + printf("bad write positions - %d:\n", i); _test_invalid_data_setup(dsk, buffer_area, tmp); tmp.resize(dsk.meta_block_size*3); memmove(tmp.data()+dsk.meta_block_size, tmp.data(), 2*dsk.meta_block_size); memset(tmp.data(), 0, dsk.meta_block_size); - heap_object_t *obj = (heap_object_t*)(tmp.data() + dsk.meta_block_size + sizeof(heap_object_t) + sizeof(heap_write_t)); + heap_object_t *obj = (heap_object_t*)(tmp.data() + dsk.meta_block_size + sizeof(heap_object_t) + sizeof(heap_tombstone_t)); if (i == 0) - obj->write_pos = -(int16_t)(sizeof(heap_object_t)+sizeof(heap_write_t)+1); + obj->write_pos = -(int16_t)(sizeof(heap_object_t)+sizeof(heap_tombstone_t)+1); else if (i == 1) - obj->write_pos = dsk.meta_block_size-sizeof(heap_object_t)-2*sizeof(heap_write_t)+1; + obj->write_pos = dsk.meta_block_size-sizeof(heap_object_t)-2*sizeof(heap_tombstone_t)+1; else if (i == 2) obj->write_pos = -1; else if (i == 3) @@ -1022,16 +1018,17 @@ void test_invalid_data() // Object write intersects with other writes { + printf("write intersections:\n"); _test_invalid_data_setup(dsk, buffer_area, tmp); // Object2 Object1 BadLength Write2 uint8_t *nb = tmp.data() + dsk.meta_block_size; - memcpy(nb, tmp.data() + sizeof(heap_object_t) + sizeof(heap_write_t), sizeof(heap_object_t)); + memcpy(nb, tmp.data() + sizeof(heap_object_t) + sizeof(heap_tombstone_t), sizeof(heap_object_t)); nb += sizeof(heap_object_t); memcpy(nb, tmp.data(), sizeof(heap_object_t)); nb += sizeof(heap_object_t); - *((uint16_t*)nb) = sizeof(heap_write_t) + 4; + *((uint16_t*)nb) = sizeof(heap_tombstone_t) + 4; nb += 2; - memcpy(nb, tmp.data() + 2*sizeof(heap_object_t) + sizeof(heap_write_t), sizeof(heap_write_t)); + memcpy(nb, tmp.data() + 2*sizeof(heap_object_t) + sizeof(heap_tombstone_t), sizeof(heap_write_t)); heap_object_t *obj = (heap_object_t*)(tmp.data() + dsk.meta_block_size); obj->write_pos = 2*sizeof(heap_object_t) + 2; @@ -1057,12 +1054,13 @@ void test_invalid_data() // Write list entry exceeds block boundaries for (int i = 0; i < 2; i++) { + printf("write exceeds boundary - %d:\n", i); _test_invalid_data_setup(dsk, buffer_area, tmp); tmp.resize(dsk.meta_block_size*3); memmove(tmp.data()+dsk.meta_block_size, tmp.data(), 2*dsk.meta_block_size); memset(tmp.data(), 0, dsk.meta_block_size); heap_object_t *obj = (heap_object_t*)(tmp.data() + dsk.meta_block_size); - obj->get_writes()->next_pos = (i == 0 ? -sizeof(heap_object_t)-1 : dsk.meta_block_size - sizeof(heap_object_t) - sizeof(heap_write_t) + 1); + obj->get_writes()->next_pos = (i == 0 ? -sizeof(heap_object_t)-1 : dsk.meta_block_size - sizeof(heap_object_t) - sizeof(heap_tombstone_t) + 1); obj->crc32c = obj->calc_crc32c(); blockstore_heap_t heap(&dsk, buffer_area.data()); @@ -1182,13 +1180,13 @@ void test_rollback() assert(count_writes(obj) == 2); heap_write_t *wr = obj->get_writes(); assert(wr->version == 2); - assert(wr->location == 16384); - assert(wr->len == 4096); assert(wr->entry_type == BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE); + assert(wr->small().location == 16384); + assert(wr->small().len == 4096); wr = wr->next(); assert(wr->version == 1); - assert(wr->location == 0x20000); assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); + assert(wr->big().location == 0x20000); assert(heap.is_data_used(0x20000)); assert(!heap.is_data_used(0x40000)); @@ -1298,12 +1296,14 @@ void test_full_alloc() heap.finish_load(); assert(heap.get_meta_total_space() == 4*4096); - uint32_t big_write_size = (sizeof(heap_object_t) + sizeof(heap_write_t) + 2*dsk.clean_entry_bitmap_size + dsk.data_block_size/dsk.csum_block_size*4); - uint32_t small_write_size = (sizeof(heap_write_t) + dsk.clean_entry_bitmap_size + 4); - assert(big_write_size == 198); + uint32_t big_write_size = (sizeof(heap_object_t) + sizeof(heap_big_write_t) + 2*dsk.clean_entry_bitmap_size + dsk.data_block_size/dsk.csum_block_size*4); + uint32_t small_write_size = (sizeof(heap_small_write_t) + dsk.clean_entry_bitmap_size + 4); + assert(big_write_size == 190); assert(small_write_size == 45); - uint32_t b_4s = (big_write_size + 4*small_write_size); // 377 - uint32_t epb = (4096-800+b_4s-1)/b_4s; // entries per block + uint32_t b_4s = (big_write_size + 4*small_write_size); + assert(b_4s == 370); + const uint32_t min_alloc = (sizeof(heap_object_t) + sizeof(heap_tombstone_t)); + uint32_t epb = (4096 - 800 + 800 % min_alloc + b_4s-1) / b_4s; for (int j = 0; j < 4; j++) { assert(heap.get_meta_nearfull_blocks() == j); @@ -1322,27 +1322,29 @@ void test_full_alloc() } // After filling all blocks to (4096-800), most free blocks should start to be allocated first - for (int i = 0; i < 8; i++) + const int nwr2 = 12; + for (int i = 0; i < nwr2; i++) { assert(heap.get_meta_nearfull_blocks() == 4); - _test_big_write(heap, dsk, 1, (40+i)*0x20000, 1, (40+i)*0x20000); + _test_big_write(heap, dsk, 1, (epb*4+i)*0x20000, 1, (epb*4+i)*0x20000); } for (int i = 0; i < 4; i++) { - assert(heap.get_meta_block_used_space(i) == (epb*b_4s + big_write_size*2)); + assert(heap.get_meta_block_used_space(i) == (epb*b_4s + big_write_size*3)); } // New writes are prevented if it may lead to inability to overwrite any object // - i.e. if the block doesn't have at least free space as the result - assert(_test_do_big_write(heap, dsk, 1, 48*0x20000, 1, 48*0x20000) == ENOSPC); + assert(_test_do_big_write(heap, dsk, 1, (epb*4+nwr2)*0x20000, 1, (epb*4+nwr2)*0x20000) == ENOSPC); // Overwrites are, however, allowed until the block is almost empty - for (int i = 0; i < 6; i++) + const int nwr3 = 4; + for (int i = 0; i < nwr3; i++) { assert(_test_do_small_write(heap, dsk, 1, 0, 6+i, 0, 4096, epb*4*16384+i*4096) == 0); } assert(dsk.meta_block_size-heap.get_meta_block_used_space(0) < big_write_size); - assert(_test_do_small_write(heap, dsk, 1, 0, 12, 0, 4096, 48*16384+8*4096) == EAGAIN); + assert(_test_do_small_write(heap, dsk, 1, 0, 6+nwr3, 0, 4096, 48*16384+8*4096) == EAGAIN); // Check that used_alloc_queue doesn't return used blocks { @@ -1407,8 +1409,8 @@ void test_duplicate() assert(count_writes(obj) == 1); heap_write_t *wr = obj->get_writes(); assert(wr->version == 2); - assert(wr->location == 0x40000); assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); + assert(wr->big().location == 0x40000); assert(heap.get_meta_block_used_space(0) == 0); assert(heap.get_meta_block_used_space(1) == obj->size+wr->size); @@ -1431,8 +1433,8 @@ void test_duplicate() assert(count_writes(obj) == 1); heap_write_t *wr = obj->get_writes(); assert(wr->version == 2); - assert(wr->location == 0x40000); assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); + assert(wr->big().location == 0x40000); assert(heap.get_meta_block_used_space(0) == 0); assert(heap.get_meta_block_used_space(1) == obj->size+wr->size); @@ -1500,25 +1502,23 @@ void test_autocompact(bool csum) assert(count_writes(obj) == 3); heap_write_t *wr = obj->get_writes(); assert(wr->lsn == 5); - assert(wr->version == 5); - assert(wr->offset == 7*4096); - assert(wr->len == 4096); - assert(wr->location == 7*4096); assert(wr->entry_type == BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE); + assert(wr->version == 5); + assert(wr->small().offset == 7*4096); + assert(wr->small().len == 4096); + assert(wr->small().location == 7*4096); wr = wr->next(); assert(wr->lsn == 4); - assert(wr->version == 4); - assert(wr->offset == 5*4096); - assert(wr->len == 4096); - assert(wr->location == 6*4096); assert(wr->entry_type == BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE); + assert(wr->version == 4); + assert(wr->small().offset == 5*4096); + assert(wr->small().len == 4096); + assert(wr->small().location == 6*4096); wr = wr->next(); assert(wr->lsn == 3); - assert(wr->version == 3); - assert(wr->offset == 0); - assert(wr->len == dsk.data_block_size); - assert(wr->location == 0x20000); assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); + assert(wr->version == 3); + assert(wr->big().location == 0x20000); // check that blocks are auto-freed assert(heap.is_data_used(0x20000)); @@ -1558,8 +1558,7 @@ void test_intent_write(bool csum) assert(obj); assert(count_writes(obj) == 2); // intent overwrites previous intent assert(obj->get_writes()->lsn == 3); - assert(obj->get_writes()->next()->offset == 0); - assert(obj->get_writes()->next()->len == 12288); + assert(obj->get_writes()->next()->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); uint8_t ref_int_bitmap[dsk.clean_entry_bitmap_size]; memset(ref_int_bitmap, 0, dsk.clean_entry_bitmap_size); @@ -1599,9 +1598,9 @@ void test_move() heap.finish_load(); assert(heap.get_meta_total_space() == 4*4096); - uint32_t big_write_size = (sizeof(heap_object_t) + sizeof(heap_write_t) + 2*dsk.clean_entry_bitmap_size + dsk.data_block_size/dsk.csum_block_size*4); - uint32_t small_write_size = (sizeof(heap_write_t) + dsk.clean_entry_bitmap_size + 4); - assert(big_write_size == 198); + uint32_t big_write_size = (sizeof(heap_object_t) + sizeof(heap_big_write_t) + 2*dsk.clean_entry_bitmap_size + dsk.data_block_size/dsk.csum_block_size*4); + uint32_t small_write_size = (sizeof(heap_small_write_t) + dsk.clean_entry_bitmap_size + 4); + assert(big_write_size == 190); assert(small_write_size == 45); // Fill block 1 almost completely with unstable small writes