Add a regression test for the last 2 fixed bugs
This commit is contained in:
@@ -72,7 +72,7 @@ int ring_loop_mock_t::register_eventfd()
|
||||
|
||||
io_uring_sqe* ring_loop_mock_t::get_sqe()
|
||||
{
|
||||
if (free_ring_datas.size() == 0)
|
||||
if (free_ring_datas.size() == 0 || is_full && is_full())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -399,3 +399,8 @@ bool disk_mock_t::submit(io_uring_sqe *sqe)
|
||||
// 3) when fsync is enabled, write cache should be sometimes lost during a simulated power outage
|
||||
return true;
|
||||
}
|
||||
|
||||
void ring_loop_mock_t::set_fake_full(std::function<bool()> is_full)
|
||||
{
|
||||
this->is_full = is_full;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,11 @@ class ring_loop_mock_t: public ring_loop_i
|
||||
std::vector<ring_data_t *> submit_ring_datas;
|
||||
std::vector<ring_data_t *> completed_ring_datas;
|
||||
std::function<void(io_uring_sqe *)> submit_cb;
|
||||
bool in_loop;
|
||||
bool loop_again;
|
||||
bool fake_full = false;
|
||||
bool in_loop = false;
|
||||
bool loop_again = false;
|
||||
bool support_zc = false;
|
||||
std::function<bool()> is_full;
|
||||
|
||||
public:
|
||||
ring_loop_mock_t(int qd, std::function<void(io_uring_sqe *)> submit_cb);
|
||||
@@ -40,6 +42,7 @@ public:
|
||||
void restore(unsigned sqe_tail);
|
||||
|
||||
void mark_completed(ring_data_t *data);
|
||||
void set_fake_full(std::function<bool()> is_full);
|
||||
};
|
||||
|
||||
class disk_mock_t
|
||||
|
||||
@@ -376,9 +376,89 @@ static void test_validate_padded_journal()
|
||||
free(read_op.buf);
|
||||
}
|
||||
|
||||
// Check that read is retried and temporary read buffers are freed correctly (LSAN)
|
||||
// TODO: Check retries in other configuration
|
||||
static void test_read_retry_on_ring_full_1M_csum4k_clean()
|
||||
{
|
||||
printf("\n-- test_read_retry_on_ring_full_1M_csum4k_clean\n");
|
||||
|
||||
bs_test_t test;
|
||||
test.default_cfg();
|
||||
test.config["inmemory_metadata"] = "0";
|
||||
test.config["block_size"] = "1048576";
|
||||
test.config["data_csum_type"] = "crc32c";
|
||||
test.config["csum_block_size"] = "4096";
|
||||
test.init();
|
||||
printf("blockstore initialized\n");
|
||||
|
||||
// Big_write without external bitmap(!) - also checks if journaled big_writes
|
||||
// are handled correctly (they don't have an external bitmap)
|
||||
printf("write v1 0+1M\n");
|
||||
blockstore_op_t op;
|
||||
op.opcode = BS_OP_WRITE_STABLE;
|
||||
op.oid = { .inode = 1, .stripe = 0 };
|
||||
op.version = 1;
|
||||
op.offset = 0;
|
||||
op.len = 1024*1024;
|
||||
op.buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, op.len);
|
||||
memset(op.buf, 0xAA, op.len);
|
||||
test.exec_op(&op);
|
||||
assert(op.retval == op.len);
|
||||
|
||||
// Wait for flushing
|
||||
printf("triggering compaction\n");
|
||||
test.flusher()->request_trim();
|
||||
while (test.flusher()->get_queue_size())
|
||||
test.ringloop->loop();
|
||||
while (test.flusher()->is_active())
|
||||
test.ringloop->loop();
|
||||
test.flusher()->release_trim();
|
||||
assert(!test.flusher()->get_queue_size());
|
||||
printf("compaction complete\n");
|
||||
|
||||
// Read with retry
|
||||
printf("read with ring-full-retries\n");
|
||||
blockstore_op_t read_op;
|
||||
read_op.opcode = BS_OP_READ;
|
||||
read_op.oid = { .inode = 1, .stripe = 0 };
|
||||
read_op.version = 2;
|
||||
read_op.offset = 0;
|
||||
read_op.len = 1024*1024;
|
||||
read_op.buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, read_op.len);
|
||||
int req_count = 0;
|
||||
int retry_on = 0;
|
||||
bool done = false;
|
||||
read_op.callback = [&](blockstore_op_t *op)
|
||||
{
|
||||
done = true;
|
||||
};
|
||||
// Force a retry after each sqe
|
||||
test.ringloop->set_fake_full([&]
|
||||
{
|
||||
if (req_count == retry_on)
|
||||
{
|
||||
printf("hit retry on sqe %d\n", req_count);
|
||||
req_count = 0;
|
||||
retry_on++;
|
||||
return true;
|
||||
}
|
||||
req_count++;
|
||||
return false;
|
||||
});
|
||||
test.bs->enqueue_op(&read_op);
|
||||
while (!done)
|
||||
test.ringloop->loop();
|
||||
read_op.callback = nullptr;
|
||||
assert(read_op.retval == read_op.len);
|
||||
|
||||
free(op.buf);
|
||||
free(read_op.buf);
|
||||
}
|
||||
|
||||
int main(int narg, char *args[])
|
||||
{
|
||||
test_preserve_corruption();
|
||||
test_validate_padded_journal();
|
||||
test_read_retry_on_ring_full_1M_csum4k_clean();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user