diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index ec3e2e83..5bd0a96e 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -306,6 +306,78 @@ jobs: echo "" done + test_dump_load: + runs-on: ubuntu-latest + needs: build + container: ${{env.TEST_IMAGE}}:${{github.sha}} + steps: + - name: Run test + id: test + timeout-minutes: 3 + run: /root/vitastor/tests/test_dump_load.sh + - name: Print logs + if: always() && steps.test.outcome == 'failure' + run: | + for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do + echo "-------- $i --------" + cat $i + echo "" + done + + test_dump_load_32k: + runs-on: ubuntu-latest + needs: build + container: ${{env.TEST_IMAGE}}:${{github.sha}} + steps: + - name: Run test + id: test + timeout-minutes: 3 + run: TEST_NAME=32k OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k" OFFSET_ARGS="$OSD_ARGS" /root/vitastor/tests/test_dump_load.sh + - name: Print logs + if: always() && steps.test.outcome == 'failure' + run: | + for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do + echo "-------- $i --------" + cat $i + echo "" + done + + test_old_dump_load: + runs-on: ubuntu-latest + needs: build + container: ${{env.TEST_IMAGE}}:${{github.sha}} + steps: + - name: Run test + id: test + timeout-minutes: 3 + run: OLD=1 /root/vitastor/tests/test_dump_load.sh + - name: Print logs + if: always() && steps.test.outcome == 'failure' + run: | + for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do + echo "-------- $i --------" + cat $i + echo "" + done + + test_dump_load_old_32k: + runs-on: ubuntu-latest + needs: build + container: ${{env.TEST_IMAGE}}:${{github.sha}} + steps: + - name: Run test + id: test + timeout-minutes: 3 + run: TEST_NAME=old_32k OLD=1 OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k" OFFSET_ARGS="$OSD_ARGS" /root/vitastor/tests/test_dump_load.sh + - name: Print logs + if: always() && steps.test.outcome == 'failure' + run: | + for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do + echo "-------- $i --------" + cat $i + echo "" + done + test_old_interrupted_rebalance: runs-on: ubuntu-latest needs: build diff --git a/src/disk_tool/disk_tool_journal.cpp b/src/disk_tool/disk_tool_journal.cpp index 1d10ef37..1d0db5f6 100644 --- a/src/disk_tool/disk_tool_journal.cpp +++ b/src/disk_tool/disk_tool_journal.cpp @@ -477,11 +477,15 @@ int disk_tool_t::write_json_journal(json11::Json entries) uint16_t type = t_it->second; if (type == JE_START) continue; + uint32_t offset = (uint32_t)rec["offset"].uint64_value(); + uint32_t len = (uint32_t)rec["len"].uint64_value(); + uint32_t data_csum_blocks = !dsk.data_csum_type || !len ? 0 : + (((offset + len - 1)/dsk.csum_block_size - offset/dsk.csum_block_size + 1)); + uint32_t data_csum_size = data_csum_blocks*(dsk.data_csum_type & 0xFF); uint32_t entry_size = (type == JE_START ? sizeof(journal_entry_start) : (type == JE_SMALL_WRITE || type == JE_SMALL_WRITE_INSTANT - ? sizeof(journal_entry_small_write) + dsk.clean_entry_bitmap_size + - (dsk.data_csum_type ? rec["len"].uint64_value()/dsk.csum_block_size*(dsk.data_csum_type & 0xFF) : 0) + ? sizeof(journal_entry_small_write) + dsk.clean_entry_bitmap_size + data_csum_size : (type == JE_BIG_WRITE || type == JE_BIG_WRITE_INSTANT ? sizeof(journal_entry_big_write) + dsk.clean_entry_bitmap_size + (dsk.data_csum_type ? rec["len"].uint64_value()/dsk.csum_block_size*(dsk.data_csum_type & 0xFF) : 0) @@ -523,15 +527,12 @@ int disk_tool_t::write_json_journal(json11::Json entries) .stripe = sscanf_json(NULL, rec["stripe"]), }, .version = rec["ver"].uint64_value(), - .offset = (uint32_t)rec["offset"].uint64_value(), - .len = (uint32_t)rec["len"].uint64_value(), + .offset = offset, + .len = len, .data_offset = (uint64_t)(new_journal_data-new_journal_buf), .crc32_data = !dsk.data_csum_type ? 0 : (uint32_t)sscanf_json("%x", rec["data_crc32"]), }; - uint32_t data_csum_blocks = !dsk.data_csum_type ? 0 : - (((ne->small_write.offset+ne->small_write.len)/dsk.csum_block_size - ne->small_write.len/dsk.csum_block_size)); - uint32_t data_csum_size = data_csum_blocks*(dsk.data_csum_type & 0xFF); - fromhexstr(rec["bitmap"].string_value(), dsk.clean_entry_bitmap_size, ((uint8_t*)ne) + sizeof(journal_entry_small_write) + data_csum_size); + fromhexstr(rec["bitmap"].string_value(), dsk.clean_entry_bitmap_size, ((uint8_t*)ne) + sizeof(journal_entry_small_write)); fromhexstr(rec["data"].string_value(), ne->small_write.len, new_journal_data); if (ne->small_write.len > 0 && !rec["data"].is_string()) { @@ -545,7 +546,7 @@ int disk_tool_t::write_json_journal(json11::Json entries) ne->small_write.crc32_data = crc32c(0, new_journal_data, ne->small_write.len); else if (dsk.data_csum_type == BLOCKSTORE_CSUM_CRC32C) { - uint32_t *block_csums = (uint32_t*)(((uint8_t*)ne) + sizeof(journal_entry_small_write)); + uint32_t *block_csums = (uint32_t*)(((uint8_t*)ne) + sizeof(journal_entry_small_write) + dsk.clean_entry_bitmap_size); for (uint32_t i = 0; i < data_csum_blocks; i++) { uint32_t block_begin = (ne->small_write.offset/dsk.csum_block_size + i) * dsk.csum_block_size; @@ -574,12 +575,9 @@ int disk_tool_t::write_json_journal(json11::Json entries) .len = (uint32_t)rec["len"].uint64_value(), .location = sscanf_json(NULL, rec["loc"]), }; - uint32_t data_csum_blocks = !dsk.data_csum_type ? 0 : - (((ne->small_write.offset+ne->small_write.len)/dsk.csum_block_size - ne->small_write.len/dsk.csum_block_size)); - uint32_t data_csum_size = data_csum_blocks*(dsk.data_csum_type & 0xFF); - fromhexstr(rec["bitmap"].string_value(), dsk.clean_entry_bitmap_size, ((uint8_t*)ne) + sizeof(journal_entry_big_write) + data_csum_size); + fromhexstr(rec["bitmap"].string_value(), dsk.clean_entry_bitmap_size, ((uint8_t*)ne) + sizeof(journal_entry_big_write)); if (dsk.data_csum_type) - fromhexstr(rec["block_csums"].string_value(), data_csum_size, ((uint8_t*)ne) + sizeof(journal_entry_big_write)); + fromhexstr(rec["block_csums"].string_value(), data_csum_size, ((uint8_t*)ne) + sizeof(journal_entry_big_write) + dsk.clean_entry_bitmap_size); } else if (type == JE_STABLE || type == JE_ROLLBACK || type == JE_DELETE) { diff --git a/src/disk_tool/disk_tool_meta.cpp b/src/disk_tool/disk_tool_meta.cpp index da4fac25..5441a5b9 100644 --- a/src/disk_tool/disk_tool_meta.cpp +++ b/src/disk_tool/disk_tool_meta.cpp @@ -95,6 +95,12 @@ close_error: journal_pos += read_len; } } + dsk.meta_format = hdr->version; + dsk.data_block_size = hdr->data_block_size; + dsk.csum_block_size = hdr->csum_block_size; + dsk.data_csum_type = hdr->data_csum_type; + dsk.bitmap_granularity = hdr->bitmap_granularity; + dsk.clean_entry_bitmap_size = (hdr->data_block_size / hdr->bitmap_granularity + 7) / 8; blockstore_heap_t *heap = new blockstore_heap_t(&dsk, buffer_area, log_level); // Load heap and just iterate it in memory hdr_fn(hdr); @@ -575,7 +581,7 @@ int disk_tool_t::write_json_meta(json11::Json meta) { if (new_data_csum_size) { - fromhexstr(e["data_csum"].string_value(), new_data_csum_size, + fromhexstr(e["block_csums"].string_value(), new_data_csum_size, ((uint8_t*)new_entry) + sizeof(clean_disk_entry) + 2*new_clean_entry_bitmap_size); } uint32_t *new_entry_csum = (uint32_t*)(((uint8_t*)new_entry) + new_clean_entry_size - 4); @@ -616,6 +622,12 @@ int disk_tool_t::write_json_heap(json11::Json meta, json11::Json journal) new_data_csum_size = (new_meta_hdr->csum_block_size ? ((new_meta_hdr->data_block_size+new_meta_hdr->csum_block_size-1)/new_meta_hdr->csum_block_size*(new_meta_hdr->data_csum_type & 0xFF)) : 0); + dsk.meta_format = new_meta_hdr->version; + dsk.data_block_size = new_meta_hdr->data_block_size; + dsk.csum_block_size = new_meta_hdr->csum_block_size; + dsk.data_csum_type = new_meta_hdr->data_csum_type; + dsk.bitmap_granularity = new_meta_hdr->bitmap_granularity; + dsk.clean_entry_bitmap_size = (new_meta_hdr->data_block_size / new_meta_hdr->bitmap_granularity + 7) / 8; new_journal_buf = NULL; if (new_journal_len) { @@ -696,7 +708,7 @@ close_err0: wr->entry_type = wr_type | (write_entry["stable"].bool_value() ? BS_HEAP_STABLE : 0); wr->lsn = write_entry["lsn"].uint64_value(); wr->version = write_entry["version"].uint64_value(); - wr->size = wr->get_size(&heap); + wr->size = wr_size; if (wr_type == BS_HEAP_SMALL_WRITE || wr_type == BS_HEAP_INTENT_WRITE) { wr->small().offset = wr_offset; @@ -736,6 +748,7 @@ close_err0: bi.offset = wr_offset; bi.len = wr_len; } + wr->size = wr->get_size(&heap); if (write_entry["bitmap"].is_string() && wr->get_int_bitmap(&heap)) { fromhexstr(write_entry["bitmap"].string_value(), new_clean_entry_bitmap_size, wr->get_int_bitmap(&heap)); @@ -794,7 +807,7 @@ close_err: 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)); if (new_data_csum_size) - fromhexstr(meta_entry["data_csum"].string_value(), new_data_csum_size, wr->get_checksums(&heap)); + fromhexstr(meta_entry["block_csums"].string_value(), new_data_csum_size, wr->get_checksums(&heap)); wr->crc32c = wr->calc_crc32c(); assert((uint8_t*)wr + wr->size == new_meta_buf + meta_offset + used_space); auto j_it = journal_by_object.find(oid); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 1109aa31..1130c742 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -24,6 +24,11 @@ IMMEDIATE_COMMIT=1 ./test_interrupted_rebalance.sh SCHEME=ec ./test_interrupted_rebalance.sh SCHEME=ec IMMEDIATE_COMMIT=1 ./test_interrupted_rebalance.sh +./test_dump_load.sh +TEST_NAME=32k OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k" OFFSET_ARGS="$OSD_ARGS" ./test_dump_load.sh +OLD=1 ./test_dump_load.sh +TEST_NAME=old_32k OLD=1 OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k" OFFSET_ARGS="$OSD_ARGS" ./test_dump_load.sh + OLD=1 ./test_interrupted_rebalance.sh OLD=1 IMMEDIATE_COMMIT=1 ./test_interrupted_rebalance.sh OLD=1 SCHEME=ec ./test_interrupted_rebalance.sh diff --git a/tests/test_dump_load.sh b/tests/test_dump_load.sh new file mode 100755 index 00000000..2a3e0253 --- /dev/null +++ b/tests/test_dump_load.sh @@ -0,0 +1,40 @@ +#!/bin/bash -ex + +PG_COUNT=${PG_COUNT:-32} + +. `dirname $0`/run_3osds.sh + +$VITASTOR_FIO -bs=4M -direct=1 -iodepth=4 \ + -rw=write -end_fsync=1 -pool=1 -inode=1 -size=256M -runtime=10 + +$VITASTOR_FIO -bs=4k -direct=1 -iodepth=32 \ + -rw=randwrite -end_fsync=1 -pool=1 -inode=1 -size=256M -runtime=10 -number_ios=1024 + +for i in $(seq 1 $OSD_COUNT); do + pid=OSD${i}_PID + pid=${!pid} + kill -9 $pid +done + +offsets=$(build/src/disk_tool/vitastor-disk simple-offsets --format json ./testdata/bin/test_osd1.bin $OFFSET_ARGS) +opts=$(build/src/disk_tool/vitastor-disk simple-offsets --format options ./testdata/bin/test_osd1.bin $OFFSET_ARGS) +meta_format=$(echo $offsets | jq -r .meta_format) +journal_offset=$(echo $offsets | jq -r .journal_offset) +meta_offset=$(echo $offsets | jq -r .meta_offset) +data_offset=$(echo $offsets | jq -r .data_offset) +if [[ "$meta_format" = "3" ]]; then + build/src/disk_tool/vitastor-disk dump-meta --io cached $opts | jq '. + { "entries": .entries | sort_by(.stripe) }' >./testdata/meta.json + build/src/disk_tool/vitastor-disk write-meta --io cached $opts <./testdata/meta.json + build/src/disk_tool/vitastor-disk dump-meta --io cached $opts | jq '. + { "entries": .entries | sort_by(.stripe) }' >./testdata/meta2.json +else + build/src/disk_tool/vitastor-disk dump-journal --io cached --json ./testdata/bin/test_osd1.bin 4096 $journal_offset $((meta_offset-journal_offset)) | jq 'map(del(.crc32, .crc32_prev)) | map(if .type == "small_write" or .type == "small_write_instant" then del(.loc) elif .type == "start" then del(.start) else . end)' >./testdata/journal.json + build/src/disk_tool/vitastor-disk write-journal --io cached --json ./testdata/bin/test_osd1.bin 4096 4 $journal_offset $((meta_offset-journal_offset)) <./testdata/journal.json + build/src/disk_tool/vitastor-disk dump-journal --io cached --json ./testdata/bin/test_osd1.bin 4096 $journal_offset $((meta_offset-journal_offset)) | jq 'map(del(.crc32, .crc32_prev)) | map(if .type == "small_write" or .type == "small_write_instant" then del(.loc) elif .type == "start" then del(.start) else . end)' >./testdata/journal2.json + diff ./testdata/journal.json ./testdata/journal2.json + build/src/disk_tool/vitastor-disk dump-meta --io cached ./testdata/bin/test_osd1.bin 4096 $meta_offset $((data_offset-meta_offset)) >./testdata/meta.json + build/src/disk_tool/vitastor-disk write-meta --io cached $opts <./testdata/meta.json + build/src/disk_tool/vitastor-disk dump-meta --io cached ./testdata/bin/test_osd1.bin 4096 $meta_offset $((data_offset-meta_offset)) >./testdata/meta2.json +fi +diff ./testdata/meta.json ./testdata/meta2.json + +format_green OK