diff --git a/src/blockstore/blockstore_heap.cpp b/src/blockstore/blockstore_heap.cpp index 6a3ea764..ba3c3c58 100644 --- a/src/blockstore/blockstore_heap.cpp +++ b/src/blockstore/blockstore_heap.cpp @@ -1267,6 +1267,34 @@ int blockstore_heap_t::add_big_write(object_id oid, heap_entry_t *old_head, bool }); } +int blockstore_heap_t::add_redirect_intent(object_id oid, heap_entry_t **obj_ptr, uint64_t version, + uint32_t offset, uint32_t len, uint64_t location, uint8_t *bitmap, uint8_t *data, uint32_t *modified_block) +{ + uint32_t wr_size = get_big_intent_entry_size(); + // Big-redirect intents, just like regular big writes, are written after writing data so they don't require explicit_complete + return add_entry(wr_size, modified_block, false, false, [&](heap_entry_t *wr) + { + wr->entry_type = BS_HEAP_BIG_INTENT|BS_HEAP_STABLE; + wr->inode = oid.inode; + wr->stripe = oid.stripe; + wr->version = version; + wr->set_big_location(this, location); + auto & bi = wr->big_intent(); + bi.offset = offset; + bi.len = len; + if (bitmap) + memcpy(wr->get_ext_bitmap(this), bitmap, dsk->clean_entry_bitmap_size); + else + memset(wr->get_ext_bitmap(this), 0, dsk->clean_entry_bitmap_size); + memset(wr->get_int_bitmap(this), 0, dsk->clean_entry_bitmap_size); + bitmap_set(wr->get_int_bitmap(this), offset, len, dsk->bitmap_granularity); + if (dsk->data_csum_type) + memset(wr->get_checksums(this), 0, get_csum_size(wr)); + calc_checksums(wr, (uint8_t*)data, true, offset, len); + *obj_ptr = wr; + }); +} + int blockstore_heap_t::add_big_intent(object_id oid, heap_entry_t **obj_ptr, uint64_t version, uint32_t offset, uint32_t len, uint8_t *bitmap, uint8_t *data, uint8_t *checksums, uint32_t *modified_block) { diff --git a/src/blockstore/blockstore_heap.h b/src/blockstore/blockstore_heap.h index 3723aa13..122b6881 100644 --- a/src/blockstore/blockstore_heap.h +++ b/src/blockstore/blockstore_heap.h @@ -265,6 +265,9 @@ public: // adds a big_write (overwrite) entry to an object int add_big_write(object_id oid, heap_entry_t *old_head, bool stable, uint64_t version, uint32_t offset, uint32_t len, uint64_t location, uint8_t *bitmap, uint8_t *data, uint32_t *modified_block); + // adds a "redirecting" big_intent entry to an object (same as big_write, used to avoid fsync on desktop SSDs) + int add_redirect_intent(object_id oid, heap_entry_t **obj_ptr, uint64_t version, + uint32_t offset, uint32_t len, uint64_t location, uint8_t *bitmap, uint8_t *data, uint32_t *modified_block); // adds a big_intent (atomic partial modification) entry to an object int add_big_intent(object_id oid, heap_entry_t **obj_ptr, uint64_t version, uint32_t offset, uint32_t len, uint8_t *bitmap, uint8_t *data, uint8_t *checksums, uint32_t *modified_block); diff --git a/src/blockstore/blockstore_write.cpp b/src/blockstore/blockstore_write.cpp index d156efca..86e12814 100644 --- a/src/blockstore/blockstore_write.cpp +++ b/src/blockstore/blockstore_write.cpp @@ -5,6 +5,8 @@ #include "blockstore_internal.h" #include "allocator.h" +#define _REDIRECT_INTENT 0x101 + bool blockstore_impl_t::enqueue_write(blockstore_op_t *op) { clock_gettime(CLOCK_REALTIME, &PRIV(op)->tv_begin); @@ -138,13 +140,12 @@ int blockstore_impl_t::dequeue_write(blockstore_op_t *op) PRIV(op)->op_state = 5; write_iodepth++; } - // FIXME: Add 'big_intent' write mode // FIXME: Allow to do initial writes as buffered, not redirected // FIXME: Allow to do direct writes over holes else if (!obj || obj->type() == BS_HEAP_DELETE || op->offset == 0 && op->len == dsk.data_block_size) { // Big (redirect) write - PRIV(op)->write_type = BS_HEAP_BIG_WRITE; + PRIV(op)->write_type = dsk.disable_data_fsync || op->opcode != BS_OP_WRITE_STABLE ? BS_HEAP_BIG_WRITE : _REDIRECT_INTENT; BS_SUBMIT_CHECK_SQES(1); PRIV(op)->location = heap->find_free_data(); if (PRIV(op)->location == UINT64_MAX) @@ -176,9 +177,14 @@ enospc: data->callback = [this, op](ring_data_t *data) { handle_write_event(data, op); }; io_uring_prep_writev(sqe, dsk.data_fd, &data->iov, 1, dsk.data_offset + loc + op->offset); PRIV(op)->pending_ops++; - PRIV(op)->op_state = 1; write_iodepth++; - inflight_big++; + if (PRIV(op)->write_type == BS_HEAP_BIG_WRITE) + { + PRIV(op)->op_state = 1; + inflight_big++; + } + else + PRIV(op)->op_state = 3; } else if (intent_write_allowed(op, obj)) { @@ -344,8 +350,17 @@ resume_12: resume_4: { auto obj = heap->read_entry(op->oid); - int res = heap->add_big_write(op->oid, obj, (op->opcode == BS_OP_WRITE_STABLE), op->version, - op->offset, op->len, PRIV(op)->location, op->bitmap, (uint8_t*)op->buf, &PRIV(op)->modified_block); + int res = 0; + if (PRIV(op)->write_type == _REDIRECT_INTENT) + { + res = heap->add_redirect_intent(op->oid, &obj, op->version, op->offset, op->len, + PRIV(op)->location, op->bitmap, (uint8_t*)op->buf, &PRIV(op)->modified_block); + } + else + { + res = heap->add_big_write(op->oid, obj, op->opcode == BS_OP_WRITE_STABLE, + op->version, op->offset, op->len, PRIV(op)->location, op->bitmap, (uint8_t*)op->buf, &PRIV(op)->modified_block); + } if (res == ENOSPC) { if (!heap->get_to_compact_count()) diff --git a/src/test/test_heap.cpp b/src/test/test_heap.cpp index ac2cf52e..b074260d 100644 --- a/src/test/test_heap.cpp +++ b/src/test/test_heap.cpp @@ -1240,6 +1240,7 @@ void test_intent_write(bool csum) } // FIXME: Add a test for big_intent, incl. explicit_complete with big_intent over big_write over deletion over big_write :) +// FIXME: Add a test for redirect_intent int main(int narg, char *args[]) {