Complete small/intent writes explicitly, not implicitly on metadata block write

This commit is contained in:
Vitaliy Filippov
2025-12-02 01:52:12 +03:00
parent 04eefce30b
commit eaff4509ca
6 changed files with 83 additions and 41 deletions
+45 -24
View File
@@ -23,6 +23,7 @@
#define HEAP_INFLIGHT_COMPACTABLE 2 #define HEAP_INFLIGHT_COMPACTABLE 2
#define HEAP_INFLIGHT_COMPACTED 4 #define HEAP_INFLIGHT_COMPACTED 4
#define HEAP_INFLIGHT_GC 8 #define HEAP_INFLIGHT_GC 8
#define HEAP_INFLIGHT_EXPLICIT 16
static inline heap_list_item_t *list_item(heap_entry_t *wr) static inline heap_list_item_t *list_item(heap_entry_t *wr)
{ {
@@ -697,7 +698,7 @@ bool blockstore_heap_t::recheck_small_writes(std::function<void(bool is_data, ui
else if (wr->type() == BS_HEAP_BIG_INTENT) else if (wr->type() == BS_HEAP_BIG_INTENT)
{ {
auto & bi = wr->big_intent(); auto & bi = wr->big_intent();
loc = bi.block_num * dsk->data_block_size + bi.offset; loc = (uint64_t)bi.block_num * dsk->data_block_size + bi.offset;
len = bi.len; len = bi.len;
from_data = true; from_data = true;
} }
@@ -1147,7 +1148,7 @@ void blockstore_heap_t::insert_list_item(heap_list_item_t *li)
} }
int blockstore_heap_t::add_entry(uint32_t wr_size, uint32_t *modified_block, int blockstore_heap_t::add_entry(uint32_t wr_size, uint32_t *modified_block,
bool allow_last_free, std::function<void(heap_entry_t *wr)> fill_entry) bool allow_last_free, bool explicit_complete, std::function<void(heap_entry_t *wr)> fill_entry)
{ {
uint32_t block_num; uint32_t block_num;
int res = allocate_entry(wr_size, &block_num, allow_last_free); int res = allocate_entry(wr_size, &block_num, allow_last_free);
@@ -1172,6 +1173,7 @@ int blockstore_heap_t::add_entry(uint32_t wr_size, uint32_t *modified_block,
inf.mod_lsn_to = next_lsn; inf.mod_lsn_to = next_lsn;
// Remember the object as dirty and remove older entries when this block is written and fsynced // Remember the object as dirty and remove older entries when this block is written and fsynced
push_inflight_lsn(next_lsn, new_wr, push_inflight_lsn(next_lsn, new_wr,
(explicit_complete ? HEAP_INFLIGHT_EXPLICIT : 0) |
(new_wr->is_overwrite() ? HEAP_INFLIGHT_COMPACTED : 0) | (new_wr->is_overwrite() ? HEAP_INFLIGHT_COMPACTED : 0) |
(new_wr->is_compactable() ? HEAP_INFLIGHT_COMPACTABLE : 0)); (new_wr->is_compactable() ? HEAP_INFLIGHT_COMPACTABLE : 0));
insert_list_item(li); insert_list_item(li);
@@ -1183,17 +1185,19 @@ int blockstore_heap_t::add_entry(uint32_t wr_size, uint32_t *modified_block,
// 1st step: post a write // 1st step: post a write
int blockstore_heap_t::add_small_write(object_id oid, heap_entry_t *old_head, uint16_t type, uint64_t version, int blockstore_heap_t::add_small_write(object_id oid, heap_entry_t **obj_ptr, uint16_t type, uint64_t version,
uint32_t offset, uint32_t len, uint64_t location, uint8_t *bitmap, uint8_t *data, uint32_t *modified_block) uint32_t offset, uint32_t len, uint64_t location, uint8_t *bitmap, uint8_t *data, uint32_t *modified_block)
{ {
if (!old_head || old_head->type() == BS_HEAP_DELETE || old_head->version > version || auto obj = *obj_ptr;
if (!obj || obj->type() == BS_HEAP_DELETE || obj->version > version ||
type != (BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE) && type != BS_HEAP_SMALL_WRITE && type != (BS_HEAP_INTENT_WRITE|BS_HEAP_STABLE) || type != (BS_HEAP_SMALL_WRITE|BS_HEAP_STABLE) && type != BS_HEAP_SMALL_WRITE && type != (BS_HEAP_INTENT_WRITE|BS_HEAP_STABLE) ||
(type & BS_HEAP_STABLE) && !(old_head->entry_type & BS_HEAP_STABLE)) (type & BS_HEAP_STABLE) && !(obj->entry_type & BS_HEAP_STABLE))
{ {
return EINVAL; return EINVAL;
} }
uint32_t wr_size = get_small_entry_size(offset, len); uint32_t wr_size = get_small_entry_size(offset, len);
return add_entry(wr_size, modified_block, false, [&](heap_entry_t *wr) // Small writes are written in parallel with buffered data so they require explicit_complete
return add_entry(wr_size, modified_block, false, true, [&](heap_entry_t *wr)
{ {
wr->entry_type = type; wr->entry_type = type;
wr->inode = oid.inode; wr->inode = oid.inode;
@@ -1204,11 +1208,12 @@ int blockstore_heap_t::add_small_write(object_id oid, heap_entry_t *old_head, ui
wr->small().location = location; wr->small().location = location;
if (bitmap) if (bitmap)
memcpy(wr->get_ext_bitmap(this), bitmap, dsk->clean_entry_bitmap_size); memcpy(wr->get_ext_bitmap(this), bitmap, dsk->clean_entry_bitmap_size);
else if (old_head) else if (obj)
memcpy(wr->get_ext_bitmap(this), old_head->get_ext_bitmap(this), dsk->clean_entry_bitmap_size); memcpy(wr->get_ext_bitmap(this), obj->get_ext_bitmap(this), dsk->clean_entry_bitmap_size);
else else
memset(wr->get_ext_bitmap(this), 0, dsk->clean_entry_bitmap_size); memset(wr->get_ext_bitmap(this), 0, dsk->clean_entry_bitmap_size);
calc_checksums(wr, (uint8_t*)data, true); calc_checksums(wr, (uint8_t*)data, true);
*obj_ptr = wr;
}); });
} }
@@ -1220,7 +1225,8 @@ int blockstore_heap_t::add_big_write(object_id oid, heap_entry_t *old_head, bool
return EINVAL; return EINVAL;
} }
uint32_t wr_size = get_big_entry_size(); uint32_t wr_size = get_big_entry_size();
return add_entry(wr_size, modified_block, false, [&](heap_entry_t *wr) // 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_WRITE | (stable ? BS_HEAP_STABLE : 0); wr->entry_type = BS_HEAP_BIG_WRITE | (stable ? BS_HEAP_STABLE : 0);
wr->inode = oid.inode; wr->inode = oid.inode;
@@ -1241,18 +1247,20 @@ int blockstore_heap_t::add_big_write(object_id oid, heap_entry_t *old_head, bool
}); });
} }
int blockstore_heap_t::add_big_intent(object_id oid, heap_entry_t *old_head, uint64_t version, 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) uint32_t offset, uint32_t len, uint8_t *bitmap, uint8_t *data, uint8_t *checksums, uint32_t *modified_block)
{ {
if (!old_head || auto obj = *obj_ptr;
old_head->entry_type != (BS_HEAP_BIG_INTENT|BS_HEAP_STABLE) && if (!obj ||
old_head->entry_type != (BS_HEAP_BIG_WRITE|BS_HEAP_STABLE) || obj->entry_type != (BS_HEAP_BIG_INTENT|BS_HEAP_STABLE) &&
obj->entry_type != (BS_HEAP_BIG_WRITE|BS_HEAP_STABLE) ||
dsk->csum_block_size > dsk->bitmap_granularity && !checksums) dsk->csum_block_size > dsk->bitmap_granularity && !checksums)
{ {
return EINVAL; return EINVAL;
} }
uint32_t wr_size = get_big_intent_entry_size(); uint32_t wr_size = get_big_intent_entry_size();
return add_entry(wr_size, modified_block, false, [&](heap_entry_t *wr) // Big intents are written before writing data so they require explicit_complete
return add_entry(wr_size, modified_block, false, true, [&](heap_entry_t *wr)
{ {
wr->entry_type = BS_HEAP_BIG_INTENT | BS_HEAP_STABLE; wr->entry_type = BS_HEAP_BIG_INTENT | BS_HEAP_STABLE;
wr->inode = oid.inode; wr->inode = oid.inode;
@@ -1261,14 +1269,14 @@ int blockstore_heap_t::add_big_intent(object_id oid, heap_entry_t *old_head, uin
auto & bi = wr->big_intent(); auto & bi = wr->big_intent();
bi.offset = offset; bi.offset = offset;
bi.len = len; bi.len = len;
bi.block_num = (old_head->type() == BS_HEAP_BIG_INTENT bi.block_num = (obj->type() == BS_HEAP_BIG_INTENT
? old_head->big_intent().block_num ? obj->big_intent().block_num
: old_head->big().block_num); : obj->big().block_num);
if (bitmap) if (bitmap)
memcpy(wr->get_ext_bitmap(this), bitmap, dsk->clean_entry_bitmap_size); memcpy(wr->get_ext_bitmap(this), bitmap, dsk->clean_entry_bitmap_size);
else else
memcpy(wr->get_ext_bitmap(this), old_head->get_ext_bitmap(this), dsk->clean_entry_bitmap_size); memcpy(wr->get_ext_bitmap(this), obj->get_ext_bitmap(this), dsk->clean_entry_bitmap_size);
memcpy(wr->get_int_bitmap(this), old_head->get_int_bitmap(this), dsk->clean_entry_bitmap_size); memcpy(wr->get_int_bitmap(this), obj->get_int_bitmap(this), dsk->clean_entry_bitmap_size);
bitmap_set(wr->get_int_bitmap(this), offset, len, dsk->bitmap_granularity); bitmap_set(wr->get_int_bitmap(this), offset, len, dsk->bitmap_granularity);
if (dsk->data_csum_type) if (dsk->data_csum_type)
{ {
@@ -1276,12 +1284,13 @@ int blockstore_heap_t::add_big_intent(object_id oid, heap_entry_t *old_head, uin
memcpy(wr->get_checksums(this), checksums, dsk->clean_entry_bitmap_size); memcpy(wr->get_checksums(this), checksums, dsk->clean_entry_bitmap_size);
else else
{ {
memcpy(wr->get_checksums(this), old_head->get_checksums(this), dsk->clean_entry_bitmap_size); memcpy(wr->get_checksums(this), obj->get_checksums(this), dsk->clean_entry_bitmap_size);
calc_checksums(wr, (uint8_t*)data, true, offset, len); calc_checksums(wr, (uint8_t*)data, true, offset, len);
} }
} }
else else
calc_checksums(wr, (uint8_t*)data, true); calc_checksums(wr, (uint8_t*)data, true);
*obj_ptr = wr;
}); });
} }
@@ -1290,7 +1299,7 @@ int blockstore_heap_t::add_compact(heap_entry_t *obj, uint64_t compact_version,
{ {
if (do_delete) if (do_delete)
{ {
return add_entry(get_simple_entry_size(), modified_block, false, [&](heap_entry_t *wr) return add_entry(get_simple_entry_size(), modified_block, false, false, [&](heap_entry_t *wr)
{ {
wr->entry_type = BS_HEAP_DELETE|BS_HEAP_STABLE; wr->entry_type = BS_HEAP_DELETE|BS_HEAP_STABLE;
wr->inode = obj->inode; wr->inode = obj->inode;
@@ -1300,7 +1309,8 @@ int blockstore_heap_t::add_compact(heap_entry_t *obj, uint64_t compact_version,
}); });
} }
uint32_t wr_size = get_big_entry_size(); uint32_t wr_size = get_big_entry_size();
return add_entry(wr_size, modified_block, true, [&](heap_entry_t *new_wr) // Compaction entry is added after copying data so it doesn't require explicit_complete
return add_entry(wr_size, modified_block, true, false, [&](heap_entry_t *new_wr)
{ {
new_wr->entry_type = BS_HEAP_BIG_WRITE|BS_HEAP_STABLE; new_wr->entry_type = BS_HEAP_BIG_WRITE|BS_HEAP_STABLE;
new_wr->inode = obj->inode; new_wr->inode = obj->inode;
@@ -1335,7 +1345,8 @@ int blockstore_heap_t::punch_holes(heap_entry_t *wr, uint8_t *new_bitmap, uint8_
int blockstore_heap_t::add_simple(heap_entry_t *obj, uint64_t version, uint32_t *modified_block, uint32_t entry_type) int blockstore_heap_t::add_simple(heap_entry_t *obj, uint64_t version, uint32_t *modified_block, uint32_t entry_type)
{ {
uint32_t wr_size = get_simple_entry_size(); uint32_t wr_size = get_simple_entry_size();
return add_entry(wr_size, modified_block, false, [&](heap_entry_t *wr) // Simple entries don't have data so they don't require explicit_complete
return add_entry(wr_size, modified_block, false, false, [&](heap_entry_t *wr)
{ {
wr->entry_type = entry_type; wr->entry_type = entry_type;
wr->inode = obj->inode; wr->inode = obj->inode;
@@ -1518,12 +1529,22 @@ void blockstore_heap_t::complete_block_write(uint32_t block_num)
for (uint64_t lsn = mod_lsn; lsn <= mod_lsn_to; lsn++, it++) for (uint64_t lsn = mod_lsn; lsn <= mod_lsn_to; lsn++, it++)
{ {
assert(!(it->flags & HEAP_INFLIGHT_DONE)); assert(!(it->flags & HEAP_INFLIGHT_DONE));
it->flags |= HEAP_INFLIGHT_DONE; if (!(it->flags & HEAP_INFLIGHT_EXPLICIT))
it->flags |= HEAP_INFLIGHT_DONE;
} }
mark_completed_lsns(mod_lsn); mark_completed_lsns(mod_lsn);
} }
} }
void blockstore_heap_t::complete_lsn_write(uint64_t lsn)
{
auto it = inflight_lsn.begin() + (lsn-first_inflight_lsn);
assert(!(it->flags & HEAP_INFLIGHT_DONE));
assert(it->flags & HEAP_INFLIGHT_EXPLICIT);
it->flags |= HEAP_INFLIGHT_DONE;
mark_completed_lsns(lsn);
}
void blockstore_heap_t::mark_garbage_up_to(heap_entry_t *wr) void blockstore_heap_t::mark_garbage_up_to(heap_entry_t *wr)
{ {
auto mvcc_it = object_mvcc.find((object_id){ .inode = wr->inode, .stripe = wr->stripe }); auto mvcc_it = object_mvcc.find((object_id){ .inode = wr->inode, .stripe = wr->stripe });
+4 -3
View File
@@ -213,7 +213,7 @@ class blockstore_heap_t
int allocate_entry(uint32_t entry_size, uint32_t *block_num, bool allow_last_free); int allocate_entry(uint32_t entry_size, uint32_t *block_num, bool allow_last_free);
void insert_list_item(heap_list_item_t *li); void insert_list_item(heap_list_item_t *li);
int add_entry(uint32_t wr_size, uint32_t *modified_block, bool allow_last_free, int add_entry(uint32_t wr_size, uint32_t *modified_block, bool allow_last_free,
std::function<void(heap_entry_t *wr)> fill_entry); bool explicit_complete, std::function<void(heap_entry_t *wr)> fill_entry);
int add_simple(heap_entry_t *obj, uint64_t version, uint32_t *modified_block, uint32_t entry_type); int add_simple(heap_entry_t *obj, uint64_t version, uint32_t *modified_block, uint32_t entry_type);
uint32_t meta_alloc_pos(const heap_block_info_t & inf); uint32_t meta_alloc_pos(const heap_block_info_t & inf);
void modify_alloc(uint32_t block_num, std::function<void(heap_block_info_t &)> change_cb); void modify_alloc(uint32_t block_num, std::function<void(heap_block_info_t &)> change_cb);
@@ -260,13 +260,13 @@ public:
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);
// adds a small_write or intent_write entry to an object // adds a small_write or intent_write entry to an object
// return 0 if OK, or maybe ENOSPC // return 0 if OK, or maybe ENOSPC
int add_small_write(object_id oid, heap_entry_t *old_head, uint16_t type, uint64_t version, int add_small_write(object_id oid, heap_entry_t **obj_ptr, uint16_t type, uint64_t version,
uint32_t offset, uint32_t len, uint64_t location, uint8_t *bitmap, uint8_t *data, uint32_t *modified_block); uint32_t offset, uint32_t len, uint64_t location, uint8_t *bitmap, uint8_t *data, uint32_t *modified_block);
// adds a big_write (overwrite) entry to an object // 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, 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); 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 // adds a big_intent (atomic partial modification) entry to an object
int add_big_intent(object_id oid, heap_entry_t *old_head, uint64_t version, 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); uint32_t offset, uint32_t len, uint8_t *bitmap, uint8_t *data, uint8_t *checksums, uint32_t *modified_block);
// adds a compacted up to <version> entry to an object // adds a compacted up to <version> entry to an object
int add_compact(heap_entry_t *obj, uint64_t compact_version, uint64_t compact_lsn, uint64_t compact_location, int add_compact(heap_entry_t *obj, uint64_t compact_version, uint64_t compact_lsn, uint64_t compact_location,
@@ -299,6 +299,7 @@ public:
// inflight write tracking // inflight write tracking
void start_block_write(uint32_t block_num); void start_block_write(uint32_t block_num);
void complete_block_write(uint32_t block_num); void complete_block_write(uint32_t block_num);
void complete_lsn_write(uint64_t lsn);
uint64_t get_completed_lsn(); uint64_t get_completed_lsn();
uint64_t get_fsynced_lsn(); uint64_t get_fsynced_lsn();
void mark_lsn_fsynced(uint64_t lsn); void mark_lsn_fsynced(uint64_t lsn);
+4 -1
View File
@@ -47,8 +47,11 @@ struct blockstore_op_private_t
// Read // Read
std::vector<copy_buffer_t> read_vec; std::vector<copy_buffer_t> read_vec;
// Read, write
uint64_t lsn;
// Write // Write
uint64_t location; // or lsn for read uint64_t location;
uint32_t write_type; uint32_t write_type;
// Stabilize, rollback // Stabilize, rollback
+4 -4
View File
@@ -17,7 +17,7 @@ int blockstore_impl_t::dequeue_read(blockstore_op_t *op)
} }
uint32_t fulfilled = 0; uint32_t fulfilled = 0;
PRIV(op)->pending_ops = 0; PRIV(op)->pending_ops = 0;
PRIV(op)->location = 0; PRIV(op)->lsn = 0;
auto & rv = PRIV(op)->read_vec; auto & rv = PRIV(op)->read_vec;
uint64_t result_version = 0; uint64_t result_version = 0;
bool found = false; bool found = false;
@@ -26,7 +26,7 @@ int blockstore_impl_t::dequeue_read(blockstore_op_t *op)
bool need_skip = dsk.csum_block_size > dsk.bitmap_granularity && !perfect_csum_update; bool need_skip = dsk.csum_block_size > dsk.bitmap_granularity && !perfect_csum_update;
if (need_skip) if (need_skip)
{ {
PRIV(op)->location = obj->lsn; PRIV(op)->lsn = obj->lsn;
blk_start = op->offset - op->offset%dsk.csum_block_size; blk_start = op->offset - op->offset%dsk.csum_block_size;
blk_end = op->offset + op->len; blk_end = op->offset + op->len;
if (blk_end % dsk.csum_block_size) if (blk_end % dsk.csum_block_size)
@@ -395,10 +395,10 @@ void blockstore_impl_t::handle_read_event(ring_data_t *data, blockstore_op_t *op
bool blockstore_impl_t::verify_read_checksums(blockstore_op_t *op) bool blockstore_impl_t::verify_read_checksums(blockstore_op_t *op)
{ {
bool skip_all = false; bool skip_all = false;
if (PRIV(op)->location) if (PRIV(op)->lsn)
{ {
heap_entry_t *obj = heap->read_entry(op->oid); heap_entry_t *obj = heap->read_entry(op->oid);
if (obj->lsn != PRIV(op)->location) // check top lsn if (obj->lsn != PRIV(op)->lsn) // check top lsn
{ {
skip_all = true; skip_all = true;
} }
+16 -6
View File
@@ -211,8 +211,12 @@ enospc:
// FIXME: Support RMW mode for csum_block_size > bitmap_granularity // FIXME: Support RMW mode for csum_block_size > bitmap_granularity
PRIV(op)->write_type = BS_HEAP_BIG_INTENT; PRIV(op)->write_type = BS_HEAP_BIG_INTENT;
PRIV(op)->location = obj->big_location(heap); PRIV(op)->location = obj->big_location(heap);
res = heap->add_big_intent(op->oid, obj, op->version, op->offset, op->len, op->bitmap, res = heap->add_big_intent(op->oid, &obj, op->version, op->offset, op->len, op->bitmap,
(uint8_t*)op->buf, NULL, &PRIV(op)->modified_block); (uint8_t*)op->buf, NULL, &PRIV(op)->modified_block);
if (res == ENOSPC)
goto enospc;
assert(res == 0);
PRIV(op)->lsn = obj->lsn;
} }
else else
{ {
@@ -224,12 +228,13 @@ enospc:
} }
assert(wr && (wr->type() == BS_HEAP_BIG_WRITE || wr->type() == BS_HEAP_BIG_INTENT)); assert(wr && (wr->type() == BS_HEAP_BIG_WRITE || wr->type() == BS_HEAP_BIG_INTENT));
PRIV(op)->location = wr->big_location(heap); PRIV(op)->location = wr->big_location(heap);
res = heap->add_small_write(op->oid, obj, (BS_HEAP_INTENT_WRITE | (op->opcode == BS_OP_WRITE_STABLE ? BS_HEAP_STABLE : 0)), res = heap->add_small_write(op->oid, &obj, (BS_HEAP_INTENT_WRITE | (op->opcode == BS_OP_WRITE_STABLE ? BS_HEAP_STABLE : 0)),
op->version, op->offset, op->len, 0, op->bitmap, (uint8_t*)op->buf, &PRIV(op)->modified_block); op->version, op->offset, op->len, 0, op->bitmap, (uint8_t*)op->buf, &PRIV(op)->modified_block);
if (res == ENOSPC)
goto enospc;
assert(res == 0);
PRIV(op)->lsn = obj->lsn;
} }
if (res == ENOSPC)
goto enospc;
assert(res == 0);
prepare_meta_block_write(PRIV(op)->modified_block); prepare_meta_block_write(PRIV(op)->modified_block);
intent_write_counter++; intent_write_counter++;
PRIV(op)->pending_ops++; PRIV(op)->pending_ops++;
@@ -251,11 +256,12 @@ enospc:
} }
// There is sufficient space. Check SQE(s) // There is sufficient space. Check SQE(s)
BS_SUBMIT_CHECK_SQES(1 + (op->len > 0 ? 1 : 0)); BS_SUBMIT_CHECK_SQES(1 + (op->len > 0 ? 1 : 0));
int res = heap->add_small_write(op->oid, obj, (BS_HEAP_SMALL_WRITE | (op->opcode == BS_OP_WRITE_STABLE ? BS_HEAP_STABLE : 0)), int res = heap->add_small_write(op->oid, &obj, (BS_HEAP_SMALL_WRITE | (op->opcode == BS_OP_WRITE_STABLE ? BS_HEAP_STABLE : 0)),
op->version, op->offset, op->len, loc, op->bitmap, (uint8_t*)op->buf, &PRIV(op)->modified_block); op->version, op->offset, op->len, loc, op->bitmap, (uint8_t*)op->buf, &PRIV(op)->modified_block);
if (res == ENOSPC) if (res == ENOSPC)
goto enospc; goto enospc;
assert(res == 0); assert(res == 0);
PRIV(op)->lsn = obj->lsn;
if (op->len) if (op->len)
heap->use_buffer_area(op->oid.inode, loc, op->len); heap->use_buffer_area(op->oid.inode, loc, op->len);
prepare_meta_block_write(PRIV(op)->modified_block); prepare_meta_block_write(PRIV(op)->modified_block);
@@ -418,6 +424,10 @@ resume_8:
printf("Ack write %jx:%jx v%ju\n", op->oid.inode, op->oid.stripe, op->version); printf("Ack write %jx:%jx v%ju\n", op->oid.inode, op->oid.stripe, op->version);
#endif #endif
op->retval = op->len; op->retval = op->len;
if (PRIV(op)->write_type == BS_HEAP_BIG_INTENT ||
PRIV(op)->write_type == BS_HEAP_INTENT_WRITE ||
PRIV(op)->write_type == BS_HEAP_SMALL_WRITE)
heap->complete_lsn_write(PRIV(op)->lsn);
if (PRIV(op)->write_type == BS_HEAP_BIG_WRITE || if (PRIV(op)->write_type == BS_HEAP_BIG_WRITE ||
PRIV(op)->write_type == BS_HEAP_BIG_INTENT || PRIV(op)->write_type == BS_HEAP_BIG_INTENT ||
PRIV(op)->write_type == BS_HEAP_INTENT_WRITE) PRIV(op)->write_type == BS_HEAP_INTENT_WRITE)
+10 -3
View File
@@ -73,10 +73,13 @@ void _test_big_write(blockstore_heap_t & heap, blockstore_disk_t & dsk, uint64_t
} }
int _test_do_small_write(blockstore_heap_t & heap, blockstore_disk_t & dsk, uint64_t inode, uint64_t stripe, uint64_t version, int _test_do_small_write(blockstore_heap_t & heap, blockstore_disk_t & dsk, uint64_t inode, uint64_t stripe, uint64_t version,
uint32_t offset, uint32_t len, uint64_t location, bool stable, uint8_t *data, bool is_intent = false, uint32_t *mblock = NULL) uint32_t offset, uint32_t len, uint64_t location, bool stable, uint8_t *data, bool is_intent = false, uint32_t *mblock = NULL, heap_entry_t **obj = NULL)
{ {
object_id oid = { .inode = INODE_WITH_POOL(1, inode), .stripe = stripe }; object_id oid = { .inode = INODE_WITH_POOL(1, inode), .stripe = stripe };
heap_entry_t *obj = heap.read_entry(oid); heap_entry_t *local_obj;
if (!obj)
obj = &local_obj;
*obj = heap.read_entry(oid);
uint16_t type = (is_intent ? BS_HEAP_INTENT_WRITE : BS_HEAP_SMALL_WRITE) | (stable ? BS_HEAP_STABLE : 0); uint16_t type = (is_intent ? BS_HEAP_INTENT_WRITE : BS_HEAP_SMALL_WRITE) | (stable ? BS_HEAP_STABLE : 0);
uint8_t ext_bitmap[dsk.clean_entry_bitmap_size]; uint8_t ext_bitmap[dsk.clean_entry_bitmap_size];
memset(ext_bitmap, 0xff, dsk.clean_entry_bitmap_size); memset(ext_bitmap, 0xff, dsk.clean_entry_bitmap_size);
@@ -90,13 +93,15 @@ void _test_small_write(blockstore_heap_t & heap, blockstore_disk_t & dsk, uint64
if (!is_intent) if (!is_intent)
heap.use_buffer_area(INODE_WITH_POOL(1, inode), location, len); // blocks are allocated before write and outside the heap_t heap.use_buffer_area(INODE_WITH_POOL(1, inode), location, len); // blocks are allocated before write and outside the heap_t
uint32_t mblock = 999999; uint32_t mblock = 999999;
int res = _test_do_small_write(heap, dsk, inode, stripe, version, offset, len, location, stable, data, is_intent, &mblock); heap_entry_t *obj = NULL;
int res = _test_do_small_write(heap, dsk, inode, stripe, version, offset, len, location, stable, data, is_intent, &mblock, &obj);
assert(res == 0); assert(res == 0);
if (!is_intent) if (!is_intent)
assert(!heap.is_buffer_area_free(location, len)); assert(!heap.is_buffer_area_free(location, len));
assert(mblock == expected_mblock || expected_mblock == UINT32_MAX); assert(mblock == expected_mblock || expected_mblock == UINT32_MAX);
heap.start_block_write(mblock); heap.start_block_write(mblock);
heap.complete_block_write(mblock); heap.complete_block_write(mblock);
heap.complete_lsn_write(obj->lsn);
} }
void _test_init(blockstore_disk_t & dsk, bool csum, std::function<void(std::map<std::string, std::string> &)> cfg_cb = NULL) void _test_init(blockstore_disk_t & dsk, bool csum, std::function<void(std::map<std::string, std::string> &)> cfg_cb = NULL)
@@ -1234,6 +1239,8 @@ void test_intent_write(bool csum)
printf("OK test_intent_write %s\n", csum ? "csum" : "no_csum"); printf("OK test_intent_write %s\n", csum ? "csum" : "no_csum");
} }
// FIXME: Add a test for big_intent, incl. explicit_complete with big_intent over big_write over deletion over big_write :)
int main(int narg, char *args[]) int main(int narg, char *args[])
{ {
test_mvcc(false); test_mvcc(false);