Return new_lsn from erase and rollback
This commit is contained in:
@@ -1454,7 +1454,7 @@ int blockstore_heap_t::post_stabilize(object_id oid, uint64_t version, uint32_t
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blockstore_heap_t::post_rollback(object_id oid, uint64_t version, uint32_t *modified_block)
|
int blockstore_heap_t::post_rollback(object_id oid, uint64_t version, uint64_t *new_lsn, uint32_t *modified_block)
|
||||||
{
|
{
|
||||||
uint32_t block_num = 0;
|
uint32_t block_num = 0;
|
||||||
heap_object_t *obj = read_entry(oid, &block_num);
|
heap_object_t *obj = read_entry(oid, &block_num);
|
||||||
@@ -1490,6 +1490,10 @@ int blockstore_heap_t::post_rollback(object_id oid, uint64_t version, uint32_t *
|
|||||||
}
|
}
|
||||||
bool tracking_active = mvcc_save_copy(obj);
|
bool tracking_active = mvcc_save_copy(obj);
|
||||||
++next_lsn;
|
++next_lsn;
|
||||||
|
if (new_lsn)
|
||||||
|
{
|
||||||
|
*new_lsn = next_lsn;
|
||||||
|
}
|
||||||
push_inflight_lsn(oid, next_lsn, 0);
|
push_inflight_lsn(oid, next_lsn, 0);
|
||||||
if (!wr)
|
if (!wr)
|
||||||
{
|
{
|
||||||
@@ -1507,7 +1511,7 @@ int blockstore_heap_t::post_rollback(object_id oid, uint64_t version, uint32_t *
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blockstore_heap_t::post_delete(object_id oid, uint32_t *modified_block)
|
int blockstore_heap_t::post_delete(object_id oid, uint64_t *new_lsn, uint32_t *modified_block)
|
||||||
{
|
{
|
||||||
uint32_t block_num = 0;
|
uint32_t block_num = 0;
|
||||||
heap_object_t *obj = read_entry(oid, &block_num);
|
heap_object_t *obj = read_entry(oid, &block_num);
|
||||||
@@ -1524,6 +1528,10 @@ int blockstore_heap_t::post_delete(object_id oid, uint32_t *modified_block)
|
|||||||
auto & inf = block_info.at(block_num);
|
auto & inf = block_info.at(block_num);
|
||||||
assert(inf.data);
|
assert(inf.data);
|
||||||
++next_lsn;
|
++next_lsn;
|
||||||
|
if (new_lsn)
|
||||||
|
{
|
||||||
|
*new_lsn = next_lsn;
|
||||||
|
}
|
||||||
push_inflight_lsn(oid, next_lsn, 0);
|
push_inflight_lsn(oid, next_lsn, 0);
|
||||||
erase_object(block_num, obj, next_lsn, tracking_active);
|
erase_object(block_num, obj, next_lsn, tracking_active);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -232,10 +232,10 @@ public:
|
|||||||
int post_stabilize(object_id oid, uint64_t version, uint32_t *modified_block, uint64_t *new_lsn, uint64_t *new_to_lsn);
|
int post_stabilize(object_id oid, uint64_t version, uint32_t *modified_block, uint64_t *new_lsn, uint64_t *new_to_lsn);
|
||||||
// rollback an unstable object version
|
// rollback an unstable object version
|
||||||
// return 0 if OK, ENOENT if not exists, EBUSY if already stable
|
// return 0 if OK, ENOENT if not exists, EBUSY if already stable
|
||||||
int post_rollback(object_id oid, uint64_t version, uint32_t *modified_block);
|
int post_rollback(object_id oid, uint64_t version, uint64_t *new_lsn, uint32_t *modified_block);
|
||||||
// forget an object
|
// forget an object
|
||||||
// return error code
|
// return error code
|
||||||
int post_delete(object_id oid, uint32_t *modified_block);
|
int post_delete(object_id oid, uint64_t *new_lsn, uint32_t *modified_block);
|
||||||
// get the next object to compact
|
// get the next object to compact
|
||||||
// guaranteed to return objects in min lsn order
|
// guaranteed to return objects in min lsn order
|
||||||
// returns 0 if OK, ENOENT if nothing to compact
|
// returns 0 if OK, ENOENT if nothing to compact
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ int blockstore_impl_t::dequeue_stable(blockstore_op_t *op)
|
|||||||
uint64_t new_to_lsn = 0;
|
uint64_t new_to_lsn = 0;
|
||||||
int res = op->opcode == BS_OP_STABLE
|
int res = op->opcode == BS_OP_STABLE
|
||||||
? heap->post_stabilize(v[priv->stab_pos].oid, v[priv->stab_pos].version, &modified_block, &new_lsn, &new_to_lsn)
|
? heap->post_stabilize(v[priv->stab_pos].oid, v[priv->stab_pos].version, &modified_block, &new_lsn, &new_to_lsn)
|
||||||
: heap->post_rollback(v[priv->stab_pos].oid, v[priv->stab_pos].version, &modified_block);
|
: heap->post_rollback(v[priv->stab_pos].oid, v[priv->stab_pos].version, &new_lsn, &modified_block);
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
{
|
{
|
||||||
assert(res == ENOENT || res == EBUSY);
|
assert(res == ENOENT || res == EBUSY);
|
||||||
@@ -34,7 +34,7 @@ int blockstore_impl_t::dequeue_stable(blockstore_op_t *op)
|
|||||||
{
|
{
|
||||||
if (!priv->lsn)
|
if (!priv->lsn)
|
||||||
priv->lsn = new_lsn;
|
priv->lsn = new_lsn;
|
||||||
priv->to_lsn = new_to_lsn;
|
priv->to_lsn = op->opcode == BS_OP_STABLE ? new_to_lsn : new_lsn;
|
||||||
}
|
}
|
||||||
priv->stab_pos++;
|
priv->stab_pos++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ int blockstore_impl_t::dequeue_write(blockstore_op_t *op)
|
|||||||
}
|
}
|
||||||
BS_SUBMIT_CHECK_SQES(1);
|
BS_SUBMIT_CHECK_SQES(1);
|
||||||
uint32_t modified_block;
|
uint32_t modified_block;
|
||||||
int res = heap->post_delete(op->oid, &modified_block);
|
int res = heap->post_delete(op->oid, &PRIV(op)->lsn, &modified_block);
|
||||||
assert(res == 0);
|
assert(res == 0);
|
||||||
prepare_meta_block_write(op, modified_block);
|
prepare_meta_block_write(op, modified_block);
|
||||||
PRIV(op)->op_state = 5;
|
PRIV(op)->op_state = 5;
|
||||||
|
|||||||
+31
-12
@@ -140,6 +140,7 @@ void _test_init(blockstore_disk_t & dsk, bool csum)
|
|||||||
dsk.data_fd = 0;
|
dsk.data_fd = 0;
|
||||||
dsk.meta_fd = 1;
|
dsk.meta_fd = 1;
|
||||||
dsk.journal_fd = 2;
|
dsk.journal_fd = 2;
|
||||||
|
dsk.disable_journal_fsync = dsk.disable_meta_fsync = true;
|
||||||
dsk.calc_lengths();
|
dsk.calc_lengths();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,13 +251,16 @@ void test_delete(bool csum)
|
|||||||
assert(heap.get_data_used_space() == 0x40000);
|
assert(heap.get_data_used_space() == 0x40000);
|
||||||
|
|
||||||
object_id oid = { .inode = INODE_WITH_POOL(1, 2), .stripe = 0 };
|
object_id oid = { .inode = INODE_WITH_POOL(1, 2), .stripe = 0 };
|
||||||
int res = heap.post_delete(oid, NULL);
|
int res = heap.post_delete(oid, NULL, NULL);
|
||||||
assert(res == ENOENT);
|
assert(res == ENOENT);
|
||||||
|
|
||||||
uint32_t mblock = 1;
|
uint32_t mblock = 100;
|
||||||
|
uint64_t new_lsn = 0;
|
||||||
oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
||||||
res = heap.post_delete(oid, &mblock);
|
res = heap.post_delete(oid, &new_lsn, &mblock);
|
||||||
|
assert(mblock == 0);
|
||||||
assert(res == 0);
|
assert(res == 0);
|
||||||
|
heap.mark_lsn_completed(new_lsn);
|
||||||
|
|
||||||
uint64_t lsn = 0;
|
uint64_t lsn = 0;
|
||||||
heap_object_t *obj = heap.lock_and_read_entry(oid, lsn);
|
heap_object_t *obj = heap.lock_and_read_entry(oid, lsn);
|
||||||
@@ -657,6 +661,7 @@ void test_full_overwrite(bool stable)
|
|||||||
|
|
||||||
// big_write
|
// big_write
|
||||||
_test_big_write(heap, dsk, 1, 0, 1, 0x20000);
|
_test_big_write(heap, dsk, 1, 0, 1, 0x20000);
|
||||||
|
heap.mark_lsn_completed(1);
|
||||||
|
|
||||||
// read it to test mvcc
|
// read it to test mvcc
|
||||||
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
||||||
@@ -666,11 +671,13 @@ void test_full_overwrite(bool stable)
|
|||||||
|
|
||||||
// small_write
|
// small_write
|
||||||
_test_small_write(heap, dsk, 1, 0, 2, 8192, 4096, 16384, true);
|
_test_small_write(heap, dsk, 1, 0, 2, 8192, 4096, 16384, true);
|
||||||
|
heap.mark_lsn_completed(2);
|
||||||
|
|
||||||
// big_write again
|
// big_write again
|
||||||
_test_big_write(heap, dsk, 1, 0, 3, 0x40000, stable, 16384, 4096);
|
_test_big_write(heap, dsk, 1, 0, 3, 0x40000, stable, 16384, 4096);
|
||||||
assert(!heap.is_buffer_area_free(16384, 4096)); // should not be freed because MVCC includes it
|
assert(!heap.is_buffer_area_free(16384, 4096)); // should not be freed because MVCC includes it
|
||||||
assert(heap.is_data_used(0x20000)); // should NOT be freed - still referenced by MVCC
|
assert(heap.is_data_used(0x20000)); // should NOT be freed - still referenced by MVCC
|
||||||
|
heap.mark_lsn_completed(3);
|
||||||
|
|
||||||
// free mvcc
|
// free mvcc
|
||||||
heap.unlock_entry(oid, copy_id);
|
heap.unlock_entry(oid, copy_id);
|
||||||
@@ -686,10 +693,12 @@ void test_full_overwrite(bool stable)
|
|||||||
assert(res == EINVAL);
|
assert(res == EINVAL);
|
||||||
}
|
}
|
||||||
_test_small_write(heap, dsk, 1, 0, 4, 20480, 4096, 20480, stable);
|
_test_small_write(heap, dsk, 1, 0, 4, 20480, 4096, 20480, stable);
|
||||||
|
heap.mark_lsn_completed(4);
|
||||||
|
|
||||||
if (!stable)
|
if (!stable)
|
||||||
{
|
{
|
||||||
res = heap.post_stabilize(oid, 4, NULL, NULL, NULL);
|
res = heap.post_stabilize(oid, 4, NULL, NULL, NULL);
|
||||||
|
heap.mark_lsn_completed(5);
|
||||||
assert(res == 0);
|
assert(res == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -973,7 +982,9 @@ void test_rollback()
|
|||||||
|
|
||||||
// some writes
|
// some writes
|
||||||
_test_big_write(heap, dsk, 1, 0, 1, 0x20000);
|
_test_big_write(heap, dsk, 1, 0, 1, 0x20000);
|
||||||
|
heap.mark_lsn_completed(1);
|
||||||
_test_small_write(heap, dsk, 1, 0, 2, 8192, 4096, 16384, true);
|
_test_small_write(heap, dsk, 1, 0, 2, 8192, 4096, 16384, true);
|
||||||
|
heap.mark_lsn_completed(2);
|
||||||
|
|
||||||
// read it to test mvcc
|
// read it to test mvcc
|
||||||
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
||||||
@@ -982,15 +993,18 @@ void test_rollback()
|
|||||||
assert(obj);
|
assert(obj);
|
||||||
|
|
||||||
// already stable
|
// already stable
|
||||||
uint32_t mblock;
|
uint64_t new_lsn = 0;
|
||||||
res = heap.post_rollback(oid, 2, &mblock);
|
uint32_t mblock = 0;
|
||||||
|
res = heap.post_rollback(oid, 2, &new_lsn, &mblock);
|
||||||
assert(res == 0);
|
assert(res == 0);
|
||||||
res = heap.post_rollback(oid, 1, NULL);
|
res = heap.post_rollback(oid, 1, &new_lsn, NULL);
|
||||||
assert(res == EBUSY);
|
assert(res == EBUSY);
|
||||||
|
|
||||||
// unstable writes
|
// unstable writes
|
||||||
_test_big_write(heap, dsk, 1, 0, 3, 0x40000, false, 16384, 4096);
|
_test_big_write(heap, dsk, 1, 0, 3, 0x40000, false, 16384, 4096);
|
||||||
|
heap.mark_lsn_completed(3);
|
||||||
_test_small_write(heap, dsk, 1, 0, 4, 20480, 4096, 20480, false);
|
_test_small_write(heap, dsk, 1, 0, 4, 20480, 4096, 20480, false);
|
||||||
|
heap.mark_lsn_completed(4);
|
||||||
|
|
||||||
// second read
|
// second read
|
||||||
uint64_t copy2_id = 0;
|
uint64_t copy2_id = 0;
|
||||||
@@ -1003,12 +1017,13 @@ void test_rollback()
|
|||||||
assert(heap.is_data_used(0x40000));
|
assert(heap.is_data_used(0x40000));
|
||||||
assert(!heap.is_buffer_area_free(16384, 4096));
|
assert(!heap.is_buffer_area_free(16384, 4096));
|
||||||
assert(!heap.is_buffer_area_free(20480, 4096));
|
assert(!heap.is_buffer_area_free(20480, 4096));
|
||||||
res = heap.post_rollback({ .inode = INODE_WITH_POOL(1, 1), .stripe = 0x20000 }, 2, NULL);
|
res = heap.post_rollback({ .inode = INODE_WITH_POOL(1, 1), .stripe = 0x20000 }, 2, NULL, NULL);
|
||||||
assert(res == ENOENT);
|
assert(res == ENOENT);
|
||||||
res = heap.post_rollback(oid, 5, NULL);
|
res = heap.post_rollback(oid, 5, NULL, NULL);
|
||||||
assert(res == ENOENT);
|
assert(res == ENOENT);
|
||||||
res = heap.post_rollback(oid, 2, NULL);
|
res = heap.post_rollback(oid, 2, &new_lsn, NULL);
|
||||||
assert(res == 0);
|
assert(res == 0);
|
||||||
|
heap.mark_lsn_completed(new_lsn);
|
||||||
assert(heap.is_data_used(0x20000));
|
assert(heap.is_data_used(0x20000));
|
||||||
assert(heap.is_data_used(0x40000));
|
assert(heap.is_data_used(0x40000));
|
||||||
assert(!heap.is_buffer_area_free(16384, 4096));
|
assert(!heap.is_buffer_area_free(16384, 4096));
|
||||||
@@ -1049,8 +1064,10 @@ void test_rollback()
|
|||||||
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0x20000 };
|
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0x20000 };
|
||||||
_test_big_write(heap, dsk, 1, 0x20000, 1, 0x20000, false);
|
_test_big_write(heap, dsk, 1, 0x20000, 1, 0x20000, false);
|
||||||
|
|
||||||
res = heap.post_rollback(oid, 0, NULL);
|
uint64_t new_lsn = 0;
|
||||||
|
res = heap.post_rollback(oid, 0, &new_lsn, NULL);
|
||||||
assert(res == 0);
|
assert(res == 0);
|
||||||
|
heap.mark_lsn_completed(new_lsn);
|
||||||
|
|
||||||
assert(!heap.read_entry(oid, NULL));
|
assert(!heap.read_entry(oid, NULL));
|
||||||
assert(!heap.is_data_used(0x20000));
|
assert(!heap.is_data_used(0x20000));
|
||||||
@@ -1187,14 +1204,16 @@ void test_full_alloc()
|
|||||||
// Check that used_alloc_queue doesn't return used blocks
|
// Check that used_alloc_queue doesn't return used blocks
|
||||||
{
|
{
|
||||||
// object from block 2
|
// object from block 2
|
||||||
|
uint64_t new_lsn = 0;
|
||||||
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 11*0x20000 };
|
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 11*0x20000 };
|
||||||
int res = heap.post_delete(oid, NULL);
|
int res = heap.post_delete(oid, &new_lsn, NULL);
|
||||||
assert(res == 0);
|
assert(res == 0);
|
||||||
|
heap.mark_lsn_completed(new_lsn);
|
||||||
|
|
||||||
uint32_t block_num = 0;
|
uint32_t block_num = 0;
|
||||||
assert(!heap.read_entry(oid, &block_num));
|
assert(!heap.read_entry(oid, &block_num));
|
||||||
|
|
||||||
_test_big_write(heap, dsk, 1, 11*0x20000, 6, 11*0x20000);
|
_test_big_write(heap, dsk, 1, 11*0x20000, 6, 48*0x20000);
|
||||||
assert(heap.read_entry(oid, &block_num));
|
assert(heap.read_entry(oid, &block_num));
|
||||||
assert(block_num == 1);
|
assert(block_num == 1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user