Do not store offset & len in big_writes

This commit is contained in:
Vitaliy Filippov
2025-12-02 01:52:12 +03:00
parent 94f3634602
commit ac8e0ef231
10 changed files with 330 additions and 270 deletions
+9 -14
View File
@@ -224,7 +224,7 @@ resume_1:
goto resume_0; goto resume_0;
} }
assert(!end_wr->next() && end_wr->entry_type == (BS_HEAP_BIG_WRITE|BS_HEAP_STABLE)); 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) 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); 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++; flusher->active_flushers++;
@@ -241,8 +241,6 @@ resume_1:
{ {
overwrite_start = read_vec[0].offset; overwrite_start = read_vec[0].offset;
overwrite_end = read_vec[read_vec.size()-1].offset + read_vec[read_vec.size()-1].len; 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; read_to_fill_incomplete = false;
if (bs->dsk.csum_block_size > bs->dsk.bitmap_granularity) 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; read_to_fill_incomplete = true;
uint32_t blk_begin = (hole_start - hole_start % bs->dsk.csum_block_size); 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);
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); 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 || 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.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, .copy_flags = COPY_BUF_DATA | copy_flags,
.offset = blk_begin, .offset = blk_begin,
.len = blk_end - blk_begin, .len = blk_end - blk_begin,
.disk_loc = end_wr->location, .disk_loc = end_wr->big().location,
.disk_offset = blk_begin, .disk_offset = blk_begin,
.disk_len = blk_end - blk_begin, .disk_len = blk_end - blk_begin,
.buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, 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); assert(wr);
uint32_t *csums = (uint32_t*)(wr->get_checksums(bs->heap) uint32_t *csums = (uint32_t*)(wr->get_checksums(bs->heap)
+ (vec.disk_offset/bs->dsk.csum_block_size)*(bs->dsk.data_csum_type & 0xFF) + (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( bs->heap->calc_block_checksums(
csums, vec.buf, wr->get_int_bitmap(bs->heap), vec.disk_offset, vec.disk_offset+vec.disk_len, false, 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) [&](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) 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); 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); 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 // Update block checksums
size_t i = 0; size_t i = 0;
while (i < read_vec.size() && !(read_vec[i].copy_flags & COPY_BUF_CSUM_FILL)) 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; end = read_vec[i].offset+read_vec[i].len;
i++; i++;
} }
// `read_vec` should contain aligned items (with respect to big_start/big_end), possibly split into pieces // `read_vec` should contain aligned items, possibly split into pieces
assert(!(start % bs->dsk.csum_block_size) || start == big_start); assert(!(start % bs->dsk.csum_block_size));
assert(!(end % bs->dsk.csum_block_size) || end == big_end); assert(!(end % bs->dsk.csum_block_size));
uint32_t csum_off = (start/bs->dsk.csum_block_size - big_start/bs->dsk.csum_block_size) * (bs->dsk.data_csum_type & 0xFF); uint32_t csum_off = start/bs->dsk.csum_block_size * (bs->dsk.data_csum_type & 0xFF);
bs->heap->calc_block_checksums( bs->heap->calc_block_checksums(
(uint32_t*)(csums+csum_off), bmp, start, end, (uint32_t*)(csums+csum_off), bmp, start, end,
[&](uint32_t start, uint32_t & len) [&](uint32_t start, uint32_t & len)
+102 -85
View File
@@ -20,7 +20,7 @@
#define HEAP_INFLIGHT_DONE 1 #define HEAP_INFLIGHT_DONE 1
#define HEAP_INFLIGHT_COMPACTABLE 2 #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; 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) uint32_t heap_write_t::get_size(blockstore_heap_t *heap)
{ {
return (sizeof(heap_write_t) + if (type() == BS_HEAP_BIG_WRITE)
(type() != BS_HEAP_TOMBSTONE {
? heap->dsk->clean_entry_bitmap_size return sizeof(heap_big_write_t) + heap->dsk->clean_entry_bitmap_size*2 + get_csum_size(heap);
: 0) + }
(type() == BS_HEAP_BIG_WRITE if (type() == BS_HEAP_TOMBSTONE)
? heap->dsk->clean_entry_bitmap_size {
: 0) + return sizeof(heap_tombstone_t);
get_csum_size(heap)); }
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) 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 // 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 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); * (heap->dsk->data_csum_type & 0xFF);
} }
bool heap_write_t::needs_recheck(blockstore_heap_t *heap) bool heap_write_t::needs_recheck(blockstore_heap_t *heap)
{ {
return len > 0 && lsn > heap->compacted_lsn && if (type() != BS_HEAP_SMALL_WRITE && type() != BS_HEAP_INTENT_WRITE)
(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) bool heap_write_t::needs_compact(blockstore_heap_t *heap)
{ {
return (entry_type == (BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE) || if (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))); 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) 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) 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 || if (type() == BS_HEAP_BIG_WRITE || type() == BS_HEAP_TOMBSTONE)
!(offset % heap->dsk->csum_block_size) && !(len % heap->dsk->csum_block_size); {
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) 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) if (type() == BS_HEAP_TOMBSTONE)
return NULL; 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) uint8_t *heap_write_t::get_int_bitmap(blockstore_heap_t *heap)
{ {
if (type() != BS_HEAP_BIG_WRITE) if (type() != BS_HEAP_BIG_WRITE)
return NULL; 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) uint8_t *heap_write_t::get_checksums(blockstore_heap_t *heap)
{ {
if (!heap->dsk->csum_block_size) if (!heap->dsk->csum_block_size)
return NULL; return NULL;
if (len && (type() == BS_HEAP_SMALL_WRITE || if ((type() == BS_HEAP_SMALL_WRITE || type() == BS_HEAP_INTENT_WRITE) && small().len > 0)
type() == BS_HEAP_INTENT_WRITE)) return ((uint8_t*)this + sizeof(heap_small_write_t) + heap->dsk->clean_entry_bitmap_size);
return ((uint8_t*)this + sizeof(heap_write_t) + heap->dsk->clean_entry_bitmap_size);
if (type() != BS_HEAP_BIG_WRITE) if (type() != BS_HEAP_BIG_WRITE)
return NULL; 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) uint32_t *heap_write_t::get_checksum(blockstore_heap_t *heap)
{ {
if (heap->dsk->csum_block_size || !len || if (heap->dsk->csum_block_size ||
type() != BS_HEAP_SMALL_WRITE && type() != BS_HEAP_INTENT_WRITE) type() != BS_HEAP_SMALL_WRITE && type() != BS_HEAP_INTENT_WRITE ||
small().len == 0)
{
return NULL; 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() 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), log_level(log_level),
meta_block_count(dsk->meta_area_size/dsk->meta_block_size-1), // first block is the superblock 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), 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*/)) (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); assert(target_block_free_space < dsk->meta_block_size);
@@ -343,13 +362,13 @@ skip_unseen:
goto skip_unseen; goto skip_unseen;
} }
// Verify write chain // 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", 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); obj->inode, obj->stripe, block_num, block_offset, obj->write_pos);
goto skip_corrupted; 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)) 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", 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; continue;
} }
if (wr->type() == BS_HEAP_SMALL_WRITE && 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", 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); obj->inode, obj->stripe, wr->version, wr->lsn);
@@ -449,8 +468,7 @@ skip_unseen:
abort(); abort();
goto skip_object; goto skip_object;
} }
if (wr->type() == BS_HEAP_BIG_WRITE && if (wr->type() == BS_HEAP_BIG_WRITE && is_data_used(wr->big().location))
is_data_used(wr->location))
{ {
fprintf(stderr, "Error: write %jx:%jx v%lu (l%lu) data overlaps with other writes, skipping object\n", 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); obj->inode, obj->stripe, wr->version, wr->lsn);
@@ -465,7 +483,7 @@ skip_unseen:
to_recheck = true; to_recheck = true;
} }
// recheck small write data immediately // 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 // entry is invalid (not fully written before OSD crash) - remove it and all newer (previous) entries too
if (wr->type() == BS_HEAP_INTENT_WRITE && 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; used_space += wr->size;
if (wr->type() == BS_HEAP_SMALL_WRITE) 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) else if (wr->type() == BS_HEAP_BIG_WRITE)
{ {
// Mark data block as used // Mark data block as used
use_data(obj->inode, wr->location); use_data(obj->inode, wr->big().location);
} }
if (wr->lsn > this->compacted_lsn) if (wr->lsn > this->compacted_lsn)
{ {
@@ -618,17 +636,21 @@ void blockstore_heap_t::finish_load()
tmp_compact_queue.clear(); 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 (!dsk->csum_block_size)
{ {
if (wr->type() == BS_HEAP_BIG_WRITE)
{
return true;
}
// Single checksum // Single checksum
uint32_t *wr_csum = wr->get_checksum(this); uint32_t *wr_csum = wr->get_checksum(this);
if (!wr_csum) if (!wr_csum)
{ {
return true; return true;
} }
uint32_t real_csum = crc32c(0, data, wr->len); uint32_t real_csum = crc32c(0, data, wr->small().len);
if (set) if (set)
{ {
*wr_csum = real_csum; *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); return ((*wr_csum) == real_csum);
} }
uint32_t offset = (wr->type() == BS_HEAP_BIG_WRITE if (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), return calc_block_checksums((uint32_t*)(wr->get_checksums(this) + offset/dsk->csum_block_size * (dsk->data_csum_type & 0xFF)),
wr->offset, wr->offset+wr->len, set, NULL); 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, 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::function<void(bool is_data, ui
if (wr->needs_recheck(this)) if (wr->needs_recheck(this))
{ {
bool is_intent = wr->type() == BS_HEAP_INTENT_WRITE; bool is_intent = wr->type() == BS_HEAP_INTENT_WRITE;
uint64_t loc = wr->location; uint64_t loc = wr->small().location;
if (is_intent) if (is_intent)
{ {
auto next_wr = wr->next(); auto next_wr = wr->next();
assert(next_wr && next_wr->entry_type == (BS_HEAP_BIG_WRITE | (wr->entry_type & BS_HEAP_STABLE))); 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++; 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) 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; uint32_t block_num = 0;
heap_object_t *obj = read_entry(oid, &block_num); 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) if (compacted_wr_count)
{ {
bool is_last = !wr->next(); 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) if (wr->type() == BS_HEAP_BIG_WRITE)
{ {
big_wr = wr; big_wr = wr;
} }
// all subsequent small write entries must also be compacted else if (!new_csums && !wr->can_be_collapsed(this))
assert(compacted_wr_count == 1 || wr->is_allowed_before_compacted(compact_lsn, is_last));
if (!new_csums && !wr->can_be_collapsed(this))
{ {
skip_csums = true; 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 // Collapse compacted_wrs[] into big_wr
big_wr->lsn = compacted_wrs[0]->lsn; big_wr->lsn = compacted_wrs[0]->lsn;
big_wr->version = compacted_wrs[0]->version; 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); 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 *int_bmp = big_wr->get_int_bitmap(this);
uint8_t *csums = big_wr->get_checksums(this); uint8_t *csums = big_wr->get_checksums(this);
const uint32_t csum_size = (dsk->data_csum_type & 0xFF); const uint32_t csum_size = (dsk->data_csum_type & 0xFF);
for (int i = compacted_wr_count-1; i >= 0; i--) for (int i = compacted_wr_count-1; i >= 0; i--)
{ {
auto cur_wr = compacted_wrs[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 // copy checksums
if (csums && !skip_csums && !new_csums) if (csums && !skip_csums && !new_csums)
{ {
assert(i == compacted_wr_count-1 || assert(i == compacted_wr_count-1 ||
(cur_wr->offset % dsk->csum_block_size) == 0 && (cur_wr->small().offset % dsk->csum_block_size) == 0 &&
(cur_wr->len % dsk->csum_block_size) == 0); (cur_wr->small().len % dsk->csum_block_size) == 0);
memcpy(csums + cur_wr->offset/dsk->csum_block_size*csum_size, memcpy(csums + cur_wr->small().offset/dsk->csum_block_size*csum_size,
cur_wr->get_checksums(this), cur_wr->len/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) 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) 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 (wr->entry_type & BS_HEAP_STABLE)
{ {
if (!for_obj) if (!for_obj)
@@ -1475,9 +1492,9 @@ bool blockstore_heap_t::mvcc_save_copy(heap_object_t *obj)
add_ref = 1; 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 :-) // 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) 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 }); 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->location] += !tracking_active; 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 }); 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->location] += !tracking_active; mvcc_buffer_refs[wr->small().location] += !tracking_active;
} }
wr = wr->next(); 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 // MVCC reference tracking is in action for the object, increase the refcount
if (wr->type() == BS_HEAP_BIG_WRITE) 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; 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)) first_wr->can_be_collapsed(this))
{ {
auto second_wr = first_wr->next(); 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->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); bitmap_set(second_wr->get_int_bitmap(this), first_offset, first_len, dsk->bitmap_granularity);
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);
if (dsk->csum_block_size) if (dsk->csum_block_size)
{ {
const uint32_t csum_size = (dsk->data_csum_type & 0xFF); 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, memcpy(second_wr->get_checksums(this) + first_offset/dsk->csum_block_size*csum_size,
first_wr->get_checksums(this), first_wr->len/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); used_delta -= free_writes(first_wr, second_wr);
new_wr->next_pos = (uint8_t*)second_wr - (uint8_t*)new_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) 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)) if (mode == BS_HEAP_FREE_MVCC && (wr->entry_type & BS_HEAP_STABLE))
{ {
// Stop at the last visible version // Stop at the last visible version
break; 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); auto & inf = block_info.at(block_num);
meta_used_space += used_delta; 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; auto old_used_space = inf.used_space;
inf.used_space += used_delta; inf.used_space += used_delta;
meta_alloc->change(block_num, meta_alloc->change(block_num,
+34 -4
View File
@@ -31,6 +31,37 @@ struct pool_shard_settings_t
class blockstore_heap_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 struct __attribute__((__packed__)) heap_write_t
{ {
// size should have top bit cleared // size should have top bit cleared
@@ -39,9 +70,6 @@ struct __attribute__((__packed__)) heap_write_t
uint8_t entry_type = 0; // BS_HEAP_* uint8_t entry_type = 0; // BS_HEAP_*
uint64_t lsn = 0; uint64_t lsn = 0;
uint64_t version = 0; uint64_t version = 0;
uint32_t offset = 0;
uint32_t len = 0;
uint64_t location = 0;
// uint8_t[] external_bitmap // uint8_t[] external_bitmap
// uint8_t[] internal_bitmap // uint8_t[] internal_bitmap
@@ -49,6 +77,8 @@ struct __attribute__((__packed__)) heap_write_t
heap_write_t *next(); heap_write_t *next();
inline uint8_t type() const { return (entry_type & BS_HEAP_TYPE); } 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_size(blockstore_heap_t *heap);
uint32_t get_csum_size(blockstore_heap_t *heap); uint32_t get_csum_size(blockstore_heap_t *heap);
bool needs_recheck(blockstore_heap_t *heap); bool needs_recheck(blockstore_heap_t *heap);
@@ -262,7 +292,7 @@ public:
// unlock an entry // unlock an entry
bool unlock_entry(object_id oid, uint64_t copy_id); bool unlock_entry(object_id oid, uint64_t copy_id);
// set or verify checksums in a write request // 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 // 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 calc_block_checksums(uint32_t *block_csums, uint8_t *data, uint8_t *bitmap, uint32_t start, uint32_t end,
bool set, std::function<void(uint32_t, uint32_t, uint32_t)> bad_block_cb); bool set, std::function<void(uint32_t, uint32_t, uint32_t)> bad_block_cb);
+18 -11
View File
@@ -169,12 +169,13 @@ uint32_t blockstore_impl_t::prepare_read_zero(std::vector<copy_buffer_t> & read_
uint32_t blockstore_impl_t::prepare_read_simple(std::vector<copy_buffer_t> & read_vec, heap_object_t *obj, heap_write_t *wr, uint32_t start, uint32_t end) uint32_t blockstore_impl_t::prepare_read_simple(std::vector<copy_buffer_t> & read_vec, heap_object_t *obj, heap_write_t *wr, uint32_t start, uint32_t end)
{ {
uint32_t res = 0; 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) find_holes(read_vec, start, end, [&](int & pos, uint32_t start, uint32_t end)
{ {
res += end-start; res += end-start;
@@ -185,10 +186,10 @@ uint32_t blockstore_impl_t::prepare_read_simple(std::vector<copy_buffer_t> & rea
.copy_flags = COPY_BUF_JOURNAL | COPY_BUF_SKIP_CSUM, .copy_flags = COPY_BUF_JOURNAL | COPY_BUF_SKIP_CSUM,
.offset = start, .offset = start,
.len = end-start, .len = end-start,
.disk_loc = wr->location - wr->offset, .disk_loc = wr->small().location - wr->small().offset,
.disk_offset = start, .disk_offset = start,
.disk_len = end-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, .wr_lsn = wr->lsn,
}); });
} }
@@ -202,14 +203,18 @@ uint32_t blockstore_impl_t::prepare_read_simple(std::vector<copy_buffer_t> & rea
// the most complex case: read data from disk with padding // the most complex case: read data from disk with padding
uint32_t blk_start = start, blk_end = end; uint32_t blk_start = start, blk_end = end;
blk_start = (start/dsk.csum_block_size) * dsk.csum_block_size; 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 = ((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; uint32_t skip_csum = 0;
if (!perfect_csum_update && wr->type() == BS_HEAP_BIG_WRITE) if (!perfect_csum_update && wr->type() == BS_HEAP_BIG_WRITE)
{ {
for (auto owr = obj->get_writes(); owr && owr != wr; owr = owr->next()) 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; skip_csum = COPY_BUF_SKIP_CSUM;
} }
if ((blk_end-1)/dsk.csum_block_size == blk_start/dsk.csum_block_size || 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<copy_buffer_t> & read_vec,
.copy_flags = (wr->type() == BS_HEAP_SMALL_WRITE ? COPY_BUF_JOURNAL : COPY_BUF_DATA) | copy_flags, .copy_flags = (wr->type() == BS_HEAP_SMALL_WRITE ? COPY_BUF_JOURNAL : COPY_BUF_DATA) | copy_flags,
.offset = start, .offset = start,
.len = end-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_offset = blk_start,
.disk_len = blk_end - blk_start, .disk_len = blk_end - blk_start,
.wr_lsn = wr->lsn, .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); uint8_t *buf = vec.buf ? vec.buf : (op->buf + vec.offset - op->offset);
uint32_t *csums = (uint32_t*)(wr->get_checksums(heap) uint32_t *csums = (uint32_t*)(wr->get_checksums(heap)
+ (vec.disk_offset/dsk.csum_block_size)*(dsk.data_csum_type & 0xFF) + (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), 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) vec.disk_offset, vec.disk_offset+vec.disk_len, false, [&](uint32_t mismatch_pos, uint32_t expected_csum, uint32_t real_csum)
{ {
+12 -14
View File
@@ -149,21 +149,21 @@ int blockstore_impl_t::dequeue_write(blockstore_op_t *op)
BS_SUBMIT_CHECK_SQES(1); BS_SUBMIT_CHECK_SQES(1);
if (obj->get_writes()->type() == BS_HEAP_BIG_WRITE) 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 else
{ {
assert(obj->get_writes()->next()->type() == BS_HEAP_BIG_WRITE); 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: process_intent:
uint8_t wr_buf[heap->get_max_write_entry_size()]; uint8_t wr_buf[heap->get_max_write_entry_size()];
heap_write_t *wr = (heap_write_t*)wr_buf; heap_write_t *wr = (heap_write_t*)wr_buf;
wr->version = op->version; 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->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) if (op->bitmap)
memcpy(wr->get_ext_bitmap(heap), op->bitmap, dsk.clean_entry_bitmap_size); memcpy(wr->get_ext_bitmap(heap), op->bitmap, dsk.clean_entry_bitmap_size);
heap->calc_checksums(wr, (uint8_t*)op->buf, true); 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()]; uint8_t wr_buf[heap->get_max_write_entry_size()];
heap_write_t *wr = (heap_write_t*)wr_buf; heap_write_t *wr = (heap_write_t*)wr_buf;
wr->version = op->version; 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->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) if (op->bitmap)
memcpy(wr->get_ext_bitmap(heap), op->bitmap, dsk.clean_entry_bitmap_size); memcpy(wr->get_ext_bitmap(heap), op->bitmap, dsk.clean_entry_bitmap_size);
heap->calc_checksums(wr, (uint8_t*)op->buf, true); 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()]; uint8_t wr_buf[heap->get_max_write_entry_size()];
heap_write_t *wr = (heap_write_t*)wr_buf; 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->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) if (op->bitmap)
memcpy(wr->get_ext_bitmap(heap), op->bitmap, dsk.clean_entry_bitmap_size); 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); memset(wr->get_int_bitmap(heap), 0, dsk.clean_entry_bitmap_size);
bitmap_set(wr->get_int_bitmap(heap), offset, len, dsk.bitmap_granularity); 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); int res = heap->post_write(op->oid, wr, modified_block, moved_from_block);
if (res != 0) if (res != 0)
return res; return res;
+1 -1
View File
@@ -61,7 +61,7 @@ int disk_tool_t::trim_data(std::string device)
{ {
if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE) 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);
} }
} }
}, },
+55 -38
View File
@@ -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" #define ENTRY_FMT "{\"block\":%ju,\"pool\":%u,\"inode\":\"0x%jx\",\"stripe\":\"0x%jx\",\"version\":%ju"
(first_entry ? ENTRY_FMT : (",\n" ENTRY_FMT)), (first_entry ? ENTRY_FMT : (",\n" ENTRY_FMT)),
#undef 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 obj->stripe, wr->version
); );
printf(",\"bitmap\":\""); 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()) for (wr = obj->get_writes(); wr; wr = wr->next())
{ {
printf( 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)), (first_wr ? ENTRY_FMT : ("," ENTRY_FMT)),
#undef ENTRY_FMT #undef ENTRY_FMT
wr->lsn, wr->version, (wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE ? "small" : ( 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_BIG_WRITE ? "big" : (
(wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_INTENT_WRITE ? "intent" : ( (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_TYPE) == BS_HEAP_TOMBSTONE ? "tombstone" : "unknown"))),
(wr->entry_type & BS_HEAP_STABLE) ? "true" : "false", (wr->entry_type & BS_HEAP_STABLE) ? "true" : "false"
wr->offset, wr->len
); );
if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE || if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE)
(wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE && !dump_with_data)
{ {
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\":\""); printf(",\"offset\":%u,\"len\":%u", wr->small().offset, wr->small().len);
for (uint32_t i = 0; i < wr->len; i++) }
printf("%02x", buffer_area[wr->location + i]); else if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE)
printf("\""); {
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); uint8_t* bitmap = wr->get_int_bitmap(heap);
if (bitmap) 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->entry_type = wr_type | (write_entry["stable"].bool_value() ? BS_HEAP_STABLE : 0);
wr->lsn = write_entry["lsn"].uint64_value(); wr->lsn = write_entry["lsn"].uint64_value();
wr->version = write_entry["version"].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->size = wr->get_size(new_heap);
wr->next_pos = wr->size; 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"); if (!new_journal_buf)
free_new_meta(); {
return 1; 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)) 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->entry_type = BS_HEAP_BIG_WRITE|BS_HEAP_STABLE;
wr->lsn = ++next_lsn; wr->lsn = ++next_lsn;
wr->version = sscanf_json(NULL, meta_entry["version"]); wr->version = sscanf_json(NULL, meta_entry["version"]);
wr->offset = 0; wr->big().location = meta_entry["block"].uint64_value() * new_meta_hdr->data_block_size;
wr->len = new_meta_hdr->data_block_size;
wr->location = meta_entry["block"].uint64_value() * new_meta_hdr->data_block_size;
wr->size = wr->get_size(&heap); 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["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)); 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->next_pos = 0;
wr->lsn = ++next_lsn; wr->lsn = ++next_lsn;
wr->version = rec["ver"].uint64_value(); wr->version = rec["ver"].uint64_value();
wr->offset = rec["offset"].uint64_value(); uint64_t wr_offset = rec["offset"].uint64_value();
wr->len = rec["len"].uint64_value(); uint64_t wr_len = rec["len"].uint64_value();
if (rec["type"] == "small_write" || rec["type"] == "small_write_instant") 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"); fprintf(stderr, "Error: entry data is missing, please generate the dump with --json --format data\n");
goto close_err; goto close_err;
} }
wr->entry_type = BS_HEAP_SMALL_WRITE | (rec["type"] == "small_write_instant" ? BS_HEAP_STABLE : 0); 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["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); fromhexstr(rec["data"].string_value(), wr_len, new_journal_buf+buffer_pos);
if (wr->len > 0) if (wr_len > 0)
{ {
if (!new_meta_hdr->data_csum_type) 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 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") 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->entry_type = BS_HEAP_BIG_WRITE | (rec["type"] == "big_write_instant" ? BS_HEAP_STABLE : 0);
wr->location = sscanf_json(NULL, rec["loc"]); wr->big().location = sscanf_json(NULL, rec["loc"]);
bitmap_set(wr->get_int_bitmap(&heap), wr->offset, wr->len, new_meta_hdr->bitmap_granularity); 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)); fromhexstr(rec["bitmap"].string_value(), new_clean_entry_bitmap_size, wr->get_ext_bitmap(&heap));
if (new_meta_hdr->data_csum_type != 0) 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, 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" "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; goto close_err;
} }
fromhexstr(rec["block_csums"].string_value(), 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+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/new_meta_hdr->csum_block_size) * (new_meta_hdr->data_csum_type & 0xFF),
wr->get_checksums(&heap)); wr->get_checksums(&heap));
} }
} }
+21 -26
View File
@@ -43,7 +43,7 @@ int disk_tool_t::raw_resize()
{ {
if ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE) 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->entry_type & BS_HEAP_TYPE) == BS_HEAP_BIG_WRITE)
{ {
if (wr->next() && new_meta_hdr->data_csum_type != 0 && auto block_num = wr->big().location / dsk.data_block_size;
((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 remap_it = data_remap.find(block_num); auto remap_it = data_remap.find(block_num);
if (remap_it != data_remap.end()) if (remap_it != data_remap.end())
block_num = remap_it->second; block_num = remap_it->second;
@@ -585,20 +579,20 @@ int disk_tool_t::resize_rebuild_meta()
exit(1); exit(1);
} }
block_num += data_idx_diff; 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) 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"); fprintf(stderr, "Small write data doesn't fit into the new buffer area\n");
exit(1); exit(1);
} }
memcpy(new_journal_ptr, buffer_area+wr->location, wr->len); memcpy(new_journal_ptr, buffer_area+wr->small().location, wr->small().len);
wr->location = new_journal_ptr-new_journal_buf; wr->small().location = new_journal_ptr-new_journal_buf;
new_journal_ptr += wr->len; new_journal_ptr += wr->small().len;
} }
} }
else if (!new_heap) else if (!new_heap)
@@ -626,8 +620,9 @@ int disk_tool_t::resize_rebuild_meta()
{ {
auto wr = writes[i]; auto wr = writes[i];
assert((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE || wr->entry_type == BS_HEAP_BIG_WRITE); 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) + uint32_t je_size = ((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE
((wr->entry_type & BS_HEAP_TYPE) == BS_HEAP_SMALL_WRITE ? sizeof(journal_entry_small_write) : sizeof(journal_entry_big_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); choose_journal_block(je_size);
journal_entry *je = (journal_entry*)(new_journal_ptr + new_journal_in_pos); journal_entry *je = (journal_entry*)(new_journal_ptr + new_journal_in_pos);
je->magic = JOURNAL_MAGIC; je->magic = JOURNAL_MAGIC;
@@ -636,28 +631,30 @@ int disk_tool_t::resize_rebuild_meta()
je->crc32_prev = new_crc32_prev; je->crc32_prev = new_crc32_prev;
je->small_write.oid = (object_id){ .inode = obj->inode, .stripe = obj->stripe }; je->small_write.oid = (object_id){ .inode = obj->inode, .stripe = obj->stripe };
je->small_write.version = wr->version; je->small_write.version = wr->version;
je->small_write.offset = wr->offset; if (wr->type() == BS_HEAP_SMALL_WRITE)
je->small_write.len = wr->len;
if ((wr->entry_type & BS_HEAP_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; je->small_write.data_offset = new_journal_data-new_journal_buf;
if (je->small_write.data_offset + je->small_write.len > new_journal_len) 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"); fprintf(stderr, "Error: live entries don't fit to the new journal\n");
exit(1); 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; new_journal_data += je->small_write.len;
if (dsk.data_csum_type == 0 && wr->get_checksum(heap)) if (dsk.data_csum_type == 0 && wr->get_checksum(heap))
je->small_write.crc32_data = *wr->get_checksum(heap); je->small_write.crc32_data = *wr->get_checksum(heap);
} }
else 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); 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)) 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); je->crc32 = je_crc32(je);
new_journal_in_pos += je->size; new_journal_in_pos += je->size;
new_crc32_prev = je->crc32; 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) if (writes[writes.size()-1]->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE)
{ {
auto big_wr = writes[writes.size()-1]; 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 + 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) + dsk.meta_block_size*(block_num / new_entries_per_block) +
new_clean_entry_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()]; uint8_t wr_buf[new_heap->get_max_write_entry_size()];
heap_write_t *wr = (heap_write_t*)wr_buf; heap_write_t *wr = (heap_write_t*)wr_buf;
wr->entry_type = BS_HEAP_BIG_WRITE|BS_HEAP_STABLE; 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->next_pos = 0;
wr->offset = 0;
wr->len = 0;
wr->size = wr->get_size(new_heap); wr->size = wr->get_size(new_heap);
if (bitmap) if (bitmap)
{ {
+2
View File
@@ -398,6 +398,8 @@ static void test_padded_csum_intent(bool perfect)
// (intent is not collapsible because of csum_block_size > bitmap_granularity) // (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); heap_object_t *obj = test.bs->heap->read_entry((object_id){ .inode = 1, .stripe = 0 }, NULL);
assert(obj); assert(obj);
assert(obj->get_writes()->next());
assert(obj->get_writes()->next()->next());
assert(!obj->get_writes()->next()->next()->next()); assert(!obj->get_writes()->next()->next()->next());
assert(obj->get_writes()->entry_type == BS_HEAP_SMALL_WRITE); 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)); assert(obj->get_writes()->next()->entry_type == (perfect ? BS_HEAP_SMALL_WRITE : BS_HEAP_INTENT_WRITE));
+76 -77
View File
@@ -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()]; uint8_t wr_buf[heap.get_max_write_entry_size()];
heap_write_t *wr = (heap_write_t*)wr_buf; heap_write_t *wr = (heap_write_t*)wr_buf;
wr->version = version; wr->version = version;
wr->offset = offset; wr->big().location = location;
wr->len = len;
wr->location = location;
wr->entry_type = BS_HEAP_BIG_WRITE | (stable ? BS_HEAP_STABLE : 0); wr->entry_type = BS_HEAP_BIG_WRITE | (stable ? BS_HEAP_STABLE : 0);
assert(heap.get_max_write_entry_size() >= wr->get_size(&heap)); 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)); ? 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_ext_bitmap(&heap), 0xff, dsk.clean_entry_bitmap_size);
memset(wr->get_int_bitmap(&heap), 0, 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()]; uint8_t wr_buf[heap.get_max_write_entry_size()];
heap_write_t *wr = (heap_write_t*)wr_buf; heap_write_t *wr = (heap_write_t*)wr_buf;
wr->version = version; wr->version = version;
wr->offset = offset; wr->small().offset = offset;
wr->len = len; wr->small().len = len;
wr->location = location; wr->small().location = location;
wr->entry_type = (is_intent ? BS_HEAP_INTENT_WRITE : BS_HEAP_SMALL_WRITE) | (stable ? BS_HEAP_STABLE : 0); 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)); ? ((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); memset(wr->get_ext_bitmap(&heap), 0xff, dsk.clean_entry_bitmap_size);
assert(!wr->get_int_bitmap(&heap)); assert(!wr->get_int_bitmap(&heap));
@@ -173,7 +171,7 @@ void test_mvcc(bool csum)
assert(heap.find_free_data() == 0); assert(heap.find_free_data() == 0);
_test_big_write(heap, dsk, 1, 0, 1, 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)); 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(check_used_space(heap, dsk, 0));
assert(heap.get_meta_used_space() == heap.get_meta_block_used_space(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); assert(count_writes(obj) == 1);
heap_write_t *wr = obj->get_writes(); heap_write_t *wr = obj->get_writes();
assert(wr->lsn == 1); 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->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; uint64_t old_size = obj->size + wr->size;
assert(heap.read_locked_entry(oid, copy_id) == obj); 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()); blockstore_heap_t heap(&dsk, buffer_area.data());
heap.finish_load(); 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 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_write_t) + dsk.clean_entry_bitmap_size + 4); uint32_t small_write_size = (sizeof(heap_small_write_t) + dsk.clean_entry_bitmap_size + 4);
assert(big_write_size == 198); assert(big_write_size == 190);
assert(small_write_size == 45); 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++) 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*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+1)*0x20000, 1, (nwr*2+1)*0x20000);
_test_big_write(heap, dsk, 1, (nwr*2+2)*0x20000, 1, (nwr*2+2)*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, 0) == 1);
assert(count_free_fragments(heap, dsk, 1) == 1);
} }
printf("OK test_compact_block\n"); printf("OK test_compact_block\n");
@@ -562,11 +557,9 @@ void test_recheck(bool async, bool csum, bool intent)
assert(count_writes(obj) == 1); assert(count_writes(obj) == 1);
heap_write_t *wr = obj->get_writes(); heap_write_t *wr = obj->get_writes();
assert(wr->lsn == 1); 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->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 // read object 2 - both writes should be present
oid = { .inode = INODE_WITH_POOL(1, 2), .stripe = 0 }; 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); assert(count_writes(obj) == 2);
wr = obj->get_writes(); wr = obj->get_writes();
assert(wr->lsn == 4); 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->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"); 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()]; uint8_t wr_buf[heap.get_max_write_entry_size()];
heap_write_t *wr = (heap_write_t*)wr_buf; heap_write_t *wr = (heap_write_t*)wr_buf;
wr->version = 2; wr->version = 2;
wr->offset = 0;
wr->len = 0;
wr->location = 0;
wr->entry_type = BS_HEAP_TOMBSTONE|BS_HEAP_STABLE; wr->entry_type = BS_HEAP_TOMBSTONE|BS_HEAP_STABLE;
assert(!wr->get_checksums(&heap)); assert(!wr->get_checksums(&heap));
res = heap.post_write(oid, wr, NULL, NULL); res = heap.post_write(oid, wr, NULL, NULL);
@@ -657,8 +647,8 @@ void test_corruption()
assert(obj); assert(obj);
assert(count_writes(obj) == 1); assert(count_writes(obj) == 1);
heap_write_t *wr = obj->get_writes(); heap_write_t *wr = obj->get_writes();
assert(wr->location == 0x40000);
assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE);
assert(wr->big().location == 0x40000);
// object 3 should be present // object 3 should be present
oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0x40000 }; oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0x40000 };
@@ -666,8 +656,8 @@ void test_corruption()
assert(obj); assert(obj);
assert(count_writes(obj) == 1); assert(count_writes(obj) == 1);
wr = obj->get_writes(); wr = obj->get_writes();
assert(wr->location == 0x60000);
assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE);
assert(wr->big().location == 0x60000);
// object 4 should be a tombstone // object 4 should be a tombstone
oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0x60000 }; oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0x60000 };
@@ -742,12 +732,12 @@ void test_full_overwrite(bool stable)
assert(count_writes(obj) == 2); assert(count_writes(obj) == 2);
heap_write_t *wr = obj->get_writes(); heap_write_t *wr = obj->get_writes();
assert(wr->version == 4); assert(wr->version == 4);
assert(wr->location == 20480);
assert(wr->entry_type == BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE); assert(wr->entry_type == BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE);
assert(wr->small().location == 20480);
wr = wr->next(); wr = wr->next();
assert(wr->version == 3); assert(wr->version == 3);
assert(wr->location == 0x40000);
assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); 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 // check that the data block 0x20000 is freed and 0x40000 is used
assert(!heap.is_data_used(0x20000)); assert(!heap.is_data_used(0x20000));
@@ -852,7 +842,7 @@ void _test_invalid_data_setup(blockstore_disk_t & dsk, std::vector<uint8_t> & bu
wr->lsn = 1; wr->lsn = 1;
wr->version = 1; wr->version = 1;
wr->entry_type = BS_HEAP_TOMBSTONE; wr->entry_type = BS_HEAP_TOMBSTONE;
wr->size = sizeof(heap_write_t); wr->size = sizeof(heap_tombstone_t);
obj->crc32c = obj->calc_crc32c(); obj->crc32c = obj->calc_crc32c();
obj = (heap_object_t*)((uint8_t*)wr + wr->size); obj = (heap_object_t*)((uint8_t*)wr + wr->size);
@@ -865,7 +855,7 @@ void _test_invalid_data_setup(blockstore_disk_t & dsk, std::vector<uint8_t> & bu
wr->lsn = 1; wr->lsn = 1;
wr->version = 1; wr->version = 1;
wr->entry_type = BS_HEAP_TOMBSTONE; wr->entry_type = BS_HEAP_TOMBSTONE;
wr->size = sizeof(heap_write_t); wr->size = sizeof(heap_tombstone_t);
obj->crc32c = obj->calc_crc32c(); obj->crc32c = obj->calc_crc32c();
obj = (heap_object_t*)(tmp.data() + dsk.meta_block_size); 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<uint8_t> & bu
wr->lsn = 2; wr->lsn = 2;
wr->version = 1; wr->version = 1;
wr->entry_type = BS_HEAP_TOMBSTONE; wr->entry_type = BS_HEAP_TOMBSTONE;
wr->size = sizeof(heap_write_t); wr->size = sizeof(heap_tombstone_t);
obj->crc32c = obj->calc_crc32c(); obj->crc32c = obj->calc_crc32c();
} }
@@ -889,6 +879,7 @@ void test_invalid_data()
std::vector<uint8_t> tmp; std::vector<uint8_t> tmp;
// Too small object // Too small object
printf("too small:\n");
{ {
_test_invalid_data_setup(dsk, buffer_area, tmp); _test_invalid_data_setup(dsk, buffer_area, tmp);
heap_object_t *obj = (heap_object_t*)tmp.data(); heap_object_t *obj = (heap_object_t*)tmp.data();
@@ -907,6 +898,7 @@ void test_invalid_data()
} }
// Too large object // Too large object
printf("too large:\n");
{ {
_test_invalid_data_setup(dsk, buffer_area, tmp); _test_invalid_data_setup(dsk, buffer_area, tmp);
heap_object_t *obj = (heap_object_t*)tmp.data(); heap_object_t *obj = (heap_object_t*)tmp.data();
@@ -925,6 +917,7 @@ void test_invalid_data()
} }
// No writes // No writes
printf("no writes:\n");
{ {
_test_invalid_data_setup(dsk, buffer_area, tmp); _test_invalid_data_setup(dsk, buffer_area, tmp);
heap_object_t *obj = (heap_object_t*)tmp.data(); heap_object_t *obj = (heap_object_t*)tmp.data();
@@ -946,6 +939,7 @@ void test_invalid_data()
} }
// Bad crc32c // Bad crc32c
printf("bad crc:\n");
{ {
_test_invalid_data_setup(dsk, buffer_area, tmp); _test_invalid_data_setup(dsk, buffer_area, tmp);
heap_object_t *obj = (heap_object_t*)tmp.data(); heap_object_t *obj = (heap_object_t*)tmp.data();
@@ -967,6 +961,7 @@ void test_invalid_data()
} }
// Bad write size // Bad write size
printf("bad write size:\n");
{ {
_test_invalid_data_setup(dsk, buffer_area, tmp); _test_invalid_data_setup(dsk, buffer_area, tmp);
heap_object_t *obj = (heap_object_t*)tmp.data(); heap_object_t *obj = (heap_object_t*)tmp.data();
@@ -991,15 +986,16 @@ void test_invalid_data()
// 4) intersects with object beginning // 4) intersects with object beginning
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
printf("bad write positions - %d:\n", i);
_test_invalid_data_setup(dsk, buffer_area, tmp); _test_invalid_data_setup(dsk, buffer_area, tmp);
tmp.resize(dsk.meta_block_size*3); tmp.resize(dsk.meta_block_size*3);
memmove(tmp.data()+dsk.meta_block_size, tmp.data(), 2*dsk.meta_block_size); memmove(tmp.data()+dsk.meta_block_size, tmp.data(), 2*dsk.meta_block_size);
memset(tmp.data(), 0, 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) 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) 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) else if (i == 2)
obj->write_pos = -1; obj->write_pos = -1;
else if (i == 3) else if (i == 3)
@@ -1022,16 +1018,17 @@ void test_invalid_data()
// Object write intersects with other writes // Object write intersects with other writes
{ {
printf("write intersections:\n");
_test_invalid_data_setup(dsk, buffer_area, tmp); _test_invalid_data_setup(dsk, buffer_area, tmp);
// Object2 Object1 BadLength Write2 // Object2 Object1 BadLength Write2
uint8_t *nb = tmp.data() + dsk.meta_block_size; 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); nb += sizeof(heap_object_t);
memcpy(nb, tmp.data(), sizeof(heap_object_t)); memcpy(nb, tmp.data(), sizeof(heap_object_t));
nb += 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; 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); heap_object_t *obj = (heap_object_t*)(tmp.data() + dsk.meta_block_size);
obj->write_pos = 2*sizeof(heap_object_t) + 2; obj->write_pos = 2*sizeof(heap_object_t) + 2;
@@ -1057,12 +1054,13 @@ void test_invalid_data()
// Write list entry exceeds block boundaries // Write list entry exceeds block boundaries
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
printf("write exceeds boundary - %d:\n", i);
_test_invalid_data_setup(dsk, buffer_area, tmp); _test_invalid_data_setup(dsk, buffer_area, tmp);
tmp.resize(dsk.meta_block_size*3); tmp.resize(dsk.meta_block_size*3);
memmove(tmp.data()+dsk.meta_block_size, tmp.data(), 2*dsk.meta_block_size); memmove(tmp.data()+dsk.meta_block_size, tmp.data(), 2*dsk.meta_block_size);
memset(tmp.data(), 0, 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); 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(); obj->crc32c = obj->calc_crc32c();
blockstore_heap_t heap(&dsk, buffer_area.data()); blockstore_heap_t heap(&dsk, buffer_area.data());
@@ -1182,13 +1180,13 @@ void test_rollback()
assert(count_writes(obj) == 2); assert(count_writes(obj) == 2);
heap_write_t *wr = obj->get_writes(); heap_write_t *wr = obj->get_writes();
assert(wr->version == 2); 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->entry_type == BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE);
assert(wr->small().location == 16384);
assert(wr->small().len == 4096);
wr = wr->next(); wr = wr->next();
assert(wr->version == 1); assert(wr->version == 1);
assert(wr->location == 0x20000);
assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); 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(0x20000));
assert(!heap.is_data_used(0x40000)); assert(!heap.is_data_used(0x40000));
@@ -1298,12 +1296,14 @@ void test_full_alloc()
heap.finish_load(); heap.finish_load();
assert(heap.get_meta_total_space() == 4*4096); 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 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_write_t) + dsk.clean_entry_bitmap_size + 4); uint32_t small_write_size = (sizeof(heap_small_write_t) + dsk.clean_entry_bitmap_size + 4);
assert(big_write_size == 198); assert(big_write_size == 190);
assert(small_write_size == 45); assert(small_write_size == 45);
uint32_t b_4s = (big_write_size + 4*small_write_size); // 377 uint32_t b_4s = (big_write_size + 4*small_write_size);
uint32_t epb = (4096-800+b_4s-1)/b_4s; // entries per block 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++) for (int j = 0; j < 4; j++)
{ {
assert(heap.get_meta_nearfull_blocks() == 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 // 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); 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++) 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 // New writes are prevented if it may lead to inability to overwrite any object
// - i.e. if the block doesn't have at least <max_overwrite_size> free space as the result // - i.e. if the block doesn't have at least <max_overwrite_size> 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 // 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(_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(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 // Check that used_alloc_queue doesn't return used blocks
{ {
@@ -1407,8 +1409,8 @@ void test_duplicate()
assert(count_writes(obj) == 1); assert(count_writes(obj) == 1);
heap_write_t *wr = obj->get_writes(); heap_write_t *wr = obj->get_writes();
assert(wr->version == 2); assert(wr->version == 2);
assert(wr->location == 0x40000);
assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); 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(0) == 0);
assert(heap.get_meta_block_used_space(1) == obj->size+wr->size); assert(heap.get_meta_block_used_space(1) == obj->size+wr->size);
@@ -1431,8 +1433,8 @@ void test_duplicate()
assert(count_writes(obj) == 1); assert(count_writes(obj) == 1);
heap_write_t *wr = obj->get_writes(); heap_write_t *wr = obj->get_writes();
assert(wr->version == 2); assert(wr->version == 2);
assert(wr->location == 0x40000);
assert(wr->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE); 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(0) == 0);
assert(heap.get_meta_block_used_space(1) == obj->size+wr->size); 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); assert(count_writes(obj) == 3);
heap_write_t *wr = obj->get_writes(); heap_write_t *wr = obj->get_writes();
assert(wr->lsn == 5); 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->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(); wr = wr->next();
assert(wr->lsn == 4); 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->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(); wr = wr->next();
assert(wr->lsn == 3); 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->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE);
assert(wr->version == 3);
assert(wr->big().location == 0x20000);
// check that blocks are auto-freed // check that blocks are auto-freed
assert(heap.is_data_used(0x20000)); assert(heap.is_data_used(0x20000));
@@ -1558,8 +1558,7 @@ void test_intent_write(bool csum)
assert(obj); assert(obj);
assert(count_writes(obj) == 2); // intent overwrites previous intent assert(count_writes(obj) == 2); // intent overwrites previous intent
assert(obj->get_writes()->lsn == 3); assert(obj->get_writes()->lsn == 3);
assert(obj->get_writes()->next()->offset == 0); assert(obj->get_writes()->next()->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE);
assert(obj->get_writes()->next()->len == 12288);
uint8_t ref_int_bitmap[dsk.clean_entry_bitmap_size]; uint8_t ref_int_bitmap[dsk.clean_entry_bitmap_size];
memset(ref_int_bitmap, 0, 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(); heap.finish_load();
assert(heap.get_meta_total_space() == 4*4096); 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 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_write_t) + dsk.clean_entry_bitmap_size + 4); uint32_t small_write_size = (sizeof(heap_small_write_t) + dsk.clean_entry_bitmap_size + 4);
assert(big_write_size == 198); assert(big_write_size == 190);
assert(small_write_size == 45); assert(small_write_size == 45);
// Fill block 1 almost completely with unstable small writes // Fill block 1 almost completely with unstable small writes