diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 1c1ed1d8..768a6797 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -78,3 +78,7 @@ add_test(NAME test_blockstore COMMAND test_blockstore) ## test_shit #add_executable(test_shit test_shit.cpp osd_peering_pg.cpp) #target_link_libraries(test_shit ${LIBURING_LIBRARIES} m) + +# test_atomic +add_executable(test_atomic test_atomic.cpp ../util/ringloop.cpp) +target_link_libraries(test_atomic ${LIBURING_LIBRARIES}) diff --git a/src/test/test_atomic.cpp b/src/test/test_atomic.cpp new file mode 100644 index 00000000..c5963f18 --- /dev/null +++ b/src/test/test_atomic.cpp @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "addr_util.h" +#include "ringloop.h" +#include "epoll_manager.h" +#include "messenger.h" + +int main(int narg, char *args[]) +{ + if (narg < 2) + { + fprintf(stderr, "USAGE: ./test_atomic [--verify]\n"); + return 1; + } + uint64_t write_size = 128*1024; + ring_consumer_t looper; + ring_loop_t *ringloop = new ring_loop_t(RINGLOOP_DEFAULT_SIZE); + uint8_t *buf = (uint8_t*)memalign_or_die(4096, write_size); + memset(buf, 0xA7, write_size); + int fd = open(args[1], O_DIRECT|O_RDWR|O_EXCL); + if (fd < 0) + { + perror("open"); + return 1; + } + bool verify = narg >= 3 && !strcmp(args[2], "--verify"); + fprintf(stderr, "%s %s\n", verify ? "Verifying" : "Writing", args[1]); + int inflight = 0; + uint64_t offset = 0; + uint64_t prev_offset = 0; + looper.loop = [&]() + { + while (inflight < 16 && offset < (uint64_t)50*1000*1024*1024-write_size) + { + io_uring_sqe *sqe = ringloop->get_sqe(); + ring_data_t *data = (ring_data_t*)sqe->user_data; + if (!verify) + { + data->iov = { buf, write_size }; + io_uring_prep_writev(sqe, fd, &data->iov, 1, offset); + data->callback = [&, offset](ring_data_t *data) + { + if (data->res != write_size) + { + fprintf(stderr, "Error writing at offset %lu: %s (code %d)\n", offset, strerror(-data->res), -data->res); + exit(1); + } + inflight--; + }; + } + else + { + uint8_t *buf2 = (uint8_t*)memalign_or_die(4096, write_size); + memset(buf2, 0, write_size); + data->iov = { buf2, write_size }; + io_uring_prep_readv(sqe, fd, &data->iov, 1, offset); + data->callback = [&, buf2, offset](ring_data_t *data) + { + if (data->res != write_size) + { + fprintf(stderr, "Error reading at offset %ju: %s (code %d)\n", offset, strerror(-data->res), -data->res); + exit(1); + } + for (uint64_t i = 0; i < write_size; i++) + { + if (buf2[i] != buf2[0]) + { + fprintf(stderr, "Atomicity broken at offset %ju+%ju: byte is %02x\n", offset, i, buf2[i]); + exit(1); + } + } + free(buf2); + inflight--; + if (offset >= prev_offset+1024*1024*1024) + { + fprintf(stderr, "Verified at %ju\n", offset); + prev_offset = offset; + } + }; + } + offset += write_size + 4096; + inflight++; + } + ringloop->submit(); + }; + ringloop->register_consumer(&looper); + while (true) + { + ringloop->loop(); + ringloop->wait(); + } + close(fd); + free(buf); + delete ringloop; + return 0; +}