Do not store offset & len in big_writes
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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::function<void(bool is_data, ui
|
||||
if (wr->needs_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,
|
||||
|
||||
@@ -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<void(uint32_t, uint32_t, uint32_t)> bad_block_cb);
|
||||
|
||||
@@ -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 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<copy_buffer_t> & 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<copy_buffer_t> & 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<copy_buffer_t> & 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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user