diff --git a/src/blockstore/blockstore_flush.cpp b/src/blockstore/blockstore_flush.cpp index c7b93d0e..dc65b0c3 100644 --- a/src/blockstore/blockstore_flush.cpp +++ b/src/blockstore/blockstore_flush.cpp @@ -289,30 +289,41 @@ resume_1: { init_fsync_data(); } - if (bs->log_level > 10) + if (compact_info.do_delete) { - printf("Compacting %jx:%jx v%ju..v%ju / l%ju..l%ju (%d writes)\n", cur_oid.inode, cur_oid.stripe, - compact_info.clean_wr->version, compact_info.compact_version, - compact_info.clean_wr->lsn, compact_info.compact_lsn, copy_count); - } - mem_or(new_bmp, compact_info.clean_wr->get_int_bitmap(bs->heap), bs->dsk.clean_entry_bitmap_size); - if (!bitmap_copied) - { - memcpy(new_ext_bmp, compact_info.clean_wr->get_ext_bitmap(bs->heap), bs->dsk.clean_entry_bitmap_size); - bitmap_copied = true; - } - if (bs->dsk.csum_block_size && bs->dsk.csum_block_size <= bs->dsk.bitmap_granularity) - { - memcpy(new_csums, compact_info.clean_wr->get_checksums(bs->heap), bs->dsk.data_block_size/bs->dsk.csum_block_size * (bs->dsk.data_csum_type & 0xFF)); - for (size_t i = csum_copy.size(); i > 0; i--) + if (bs->log_level > 10) { - auto wr = csum_copy[i-1]; - memcpy(new_csums + wr->small().offset/bs->dsk.csum_block_size*(bs->dsk.data_csum_type & 0xFF), - wr->get_checksums(bs->heap), wr->small().len/bs->dsk.csum_block_size*(bs->dsk.data_csum_type & 0xFF)); + printf("Compacting %jx:%jx up to l%ju (delete)\n", cur_oid.inode, cur_oid.stripe, compact_info.compact_lsn); } - csum_copy.clear(); + clean_loc = UINT64_MAX; + } + else + { + if (bs->log_level > 10) + { + printf("Compacting %jx:%jx v%ju..v%ju / l%ju..l%ju (%d writes)\n", cur_oid.inode, cur_oid.stripe, + compact_info.clean_wr->version, compact_info.compact_version, + compact_info.clean_wr->lsn, compact_info.compact_lsn, copy_count); + } + mem_or(new_bmp, compact_info.clean_wr->get_int_bitmap(bs->heap), bs->dsk.clean_entry_bitmap_size); + if (!bitmap_copied) + { + memcpy(new_ext_bmp, compact_info.clean_wr->get_ext_bitmap(bs->heap), bs->dsk.clean_entry_bitmap_size); + bitmap_copied = true; + } + if (bs->dsk.csum_block_size && bs->dsk.csum_block_size <= bs->dsk.bitmap_granularity) + { + memcpy(new_csums, compact_info.clean_wr->get_checksums(bs->heap), bs->dsk.data_block_size/bs->dsk.csum_block_size * (bs->dsk.data_csum_type & 0xFF)); + for (size_t i = csum_copy.size(); i > 0; i--) + { + auto wr = csum_copy[i-1]; + memcpy(new_csums + wr->small().offset/bs->dsk.csum_block_size*(bs->dsk.data_csum_type & 0xFF), + wr->get_checksums(bs->heap), wr->small().len/bs->dsk.csum_block_size*(bs->dsk.data_csum_type & 0xFF)); + } + csum_copy.clear(); + } + clean_loc = compact_info.clean_wr->big_location(bs->heap); } - clean_loc = compact_info.clean_wr->big_location(bs->heap); overwrite_start = overwrite_end = 0; if (read_vec.size() > 0) { @@ -625,7 +636,7 @@ int journal_flusher_co::check_and_punch_checksums() bool journal_flusher_co::calc_block_checksums() { - if (bs->dsk.csum_block_size <= bs->dsk.bitmap_granularity) + if (bs->dsk.csum_block_size <= bs->dsk.bitmap_granularity || compact_info.do_delete) { return true; } diff --git a/src/test/test_blockstore.cpp b/src/test/test_blockstore.cpp index 7ba4b803..85f5689d 100644 --- a/src/test/test_blockstore.cpp +++ b/src/test/test_blockstore.cpp @@ -642,6 +642,63 @@ static void test_padded_csum_parallel_read(bool perfect, uint32_t offset) free(op2.buf); } +static void test_compact_rollback() +{ + printf("\n-- test_compact_rollback\n"); + + bs_test_t test; + test.default_cfg(); + test.config["csum_block_size"] = "16384"; + test.config["atomic_write_size"] = "0"; + test.init(); + + // Write + printf("write\n"); + blockstore_op_t op; + op.opcode = BS_OP_WRITE; + op.oid = { .inode = 1, .stripe = 0 }; + op.version = 1; + op.offset = 8192; + op.len = 16384; + op.buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, 16384); + memset(op.buf, 0xaa, 16384); + test.exec_op(&op); + assert(op.retval == op.len); + + // Rollback + printf("rollback\n"); + op.opcode = BS_OP_ROLLBACK; + op.len = 1; + ((obj_ver_id*)op.buf)[0] = { .oid = { .inode = 1, .stripe = 0 }, .version = 0 }; + test.exec_op(&op); + assert(op.retval == 0); + + // Trigger & wait compaction + test.bs->flusher->request_trim(); + while (test.bs->heap->get_compact_queue_size()) + test.ringloop->loop(); + while (test.bs->flusher->is_active()) + test.ringloop->loop(); + test.bs->flusher->release_trim(); + // Check that compaction succeeded + assert(!test.bs->heap->get_to_compact_count()); + + // Check that the object does not exist + printf("checking that the object does not exist\n"); + blockstore_op_t op2; + op2.opcode = BS_OP_READ; + op2.oid = { .inode = 1, .stripe = 0 }; + op2.version = 1; + op2.offset = 0; + op2.len = 128*1024; + op2.buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, 128*1024); + test.exec_op(&op2); + assert(op2.retval == -ENOENT); + + free(op.buf); + free(op2.buf); +} + // FIXME Add a simple intent_write / big_intent test int main(int narg, char *args[]) @@ -657,5 +714,6 @@ int main(int narg, char *args[]) test_padded_csum_parallel_read(true, 8192); test_padded_csum_parallel_read(false, 16384); test_padded_csum_parallel_read(true, 16384); + test_compact_rollback(); return 0; }