forked from vitalif/vitastor
fio engine starts now
parent
a7dc759f74
commit
a8f250c68f
6
Makefile
6
Makefile
|
@ -1,15 +1,15 @@
|
||||||
BLOCKSTORE_OBJS := allocator.o blockstore.o blockstore_init.o blockstore_open.o blockstore_journal.o blockstore_read.o \
|
BLOCKSTORE_OBJS := allocator.o blockstore.o blockstore_init.o blockstore_open.o blockstore_journal.o blockstore_read.o \
|
||||||
blockstore_write.o blockstore_sync.o blockstore_stable.o blockstore_flush.o crc32c.o ringloop.o
|
blockstore_write.o blockstore_sync.o blockstore_stable.o blockstore_flush.o crc32c.o ringloop.o timerfd_interval.o
|
||||||
all: $(BLOCKSTORE_OBJS) test test_blockstore libfio_blockstore.so
|
all: $(BLOCKSTORE_OBJS) test test_blockstore libfio_blockstore.so
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o
|
rm -f *.o
|
||||||
crc32c.o: crc32c.c
|
crc32c.o: crc32c.c
|
||||||
g++ -fPIC -c -o $@ $<
|
g++ -fPIC -c -o $@ $<
|
||||||
%.o: %.cpp allocator.h blockstore_flush.h blockstore.h blockstore_init.h blockstore_journal.h crc32c.h ringloop.h xor.h
|
%.o: %.cpp allocator.h blockstore_flush.h blockstore.h blockstore_init.h blockstore_journal.h crc32c.h ringloop.h xor.h timerfd_interval.h
|
||||||
g++ -g -Wall -Wno-sign-compare -Wno-parentheses -fPIC -c -o $@ $<
|
g++ -g -Wall -Wno-sign-compare -Wno-parentheses -fPIC -c -o $@ $<
|
||||||
test: test.cpp
|
test: test.cpp
|
||||||
g++ -g -O3 -o test -luring test.cpp
|
g++ -g -O3 -o test -luring test.cpp
|
||||||
test_blockstore: $(BLOCKSTORE_OBJS) test_blockstore.cpp
|
test_blockstore: $(BLOCKSTORE_OBJS) test_blockstore.cpp
|
||||||
g++ -g -o test_blockstore -luring test_blockstore.cpp $(BLOCKSTORE_OBJS)
|
g++ -g -o test_blockstore -luring test_blockstore.cpp $(BLOCKSTORE_OBJS)
|
||||||
libfio_blockstore.so: fio_engine.cpp $(BLOCKSTORE_OBJS)
|
libfio_blockstore.so: fio_engine.cpp $(BLOCKSTORE_OBJS)
|
||||||
g++ -Wno-pointer-arith -fPIC -shared -luring -o libfio_blockstore.so fio_engine.cpp $(BLOCKSTORE_OBJS)
|
g++ -g -Wno-pointer-arith -fPIC -shared -luring -o libfio_blockstore.so fio_engine.cpp $(BLOCKSTORE_OBJS)
|
||||||
|
|
|
@ -43,7 +43,7 @@ static int bs_setup(struct thread_data *td)
|
||||||
int r;
|
int r;
|
||||||
//int64_t size;
|
//int64_t size;
|
||||||
|
|
||||||
bsd = (bs_data*)calloc(1, sizeof(*bsd));
|
bsd = new bs_data;
|
||||||
if (!bsd)
|
if (!bsd)
|
||||||
{
|
{
|
||||||
td_verror(td, errno, "calloc");
|
td_verror(td, errno, "calloc");
|
||||||
|
@ -71,7 +71,7 @@ static void bs_cleanup(struct thread_data *td)
|
||||||
if (bsd)
|
if (bsd)
|
||||||
{
|
{
|
||||||
|
|
||||||
free(bsd);
|
delete bsd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,9 +88,12 @@ static int bs_init(struct thread_data *td)
|
||||||
config["data_device"] = "./test_data.bin";
|
config["data_device"] = "./test_data.bin";
|
||||||
bsd->ringloop = new ring_loop_t(512);
|
bsd->ringloop = new ring_loop_t(512);
|
||||||
bsd->bs = new blockstore(config, bsd->ringloop);
|
bsd->bs = new blockstore(config, bsd->ringloop);
|
||||||
while (!bsd->bs->is_started())
|
while (1)
|
||||||
{
|
{
|
||||||
bsd->ringloop->loop();
|
bsd->ringloop->loop();
|
||||||
|
if (bsd->bs->is_started())
|
||||||
|
break;
|
||||||
|
bsd->ringloop->wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("fio: blockstore initialized\n");
|
log_info("fio: blockstore initialized\n");
|
||||||
|
@ -122,8 +125,9 @@ static enum fio_q_status bs_queue(struct thread_data *td, struct io_u *io_u)
|
||||||
};
|
};
|
||||||
op->offset = io_u->offset % bsd->bs->block_size;
|
op->offset = io_u->offset % bsd->bs->block_size;
|
||||||
op->len = io_u->xfer_buflen;
|
op->len = io_u->xfer_buflen;
|
||||||
op->callback = [&](blockstore_operation *op)
|
op->callback = [io_u](blockstore_operation *op)
|
||||||
{
|
{
|
||||||
|
bs_data *bsd = (bs_data*)io_u->engine_data;
|
||||||
bsd->completed.push_back(io_u);
|
bsd->completed.push_back(io_u);
|
||||||
delete op;
|
delete op;
|
||||||
};
|
};
|
||||||
|
@ -137,16 +141,18 @@ static enum fio_q_status bs_queue(struct thread_data *td, struct io_u *io_u)
|
||||||
};
|
};
|
||||||
op->offset = io_u->offset % bsd->bs->block_size;
|
op->offset = io_u->offset % bsd->bs->block_size;
|
||||||
op->len = io_u->xfer_buflen;
|
op->len = io_u->xfer_buflen;
|
||||||
op->callback = [&](blockstore_operation *op)
|
op->callback = [io_u](blockstore_operation *op)
|
||||||
{
|
{
|
||||||
|
bs_data *bsd = (bs_data*)io_u->engine_data;
|
||||||
bsd->completed.push_back(io_u);
|
bsd->completed.push_back(io_u);
|
||||||
delete op;
|
delete op;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case DDIR_SYNC:
|
case DDIR_SYNC:
|
||||||
op->flags = OP_SYNC;
|
op->flags = OP_SYNC;
|
||||||
op->callback = [&](blockstore_operation *op)
|
op->callback = [io_u](blockstore_operation *op)
|
||||||
{
|
{
|
||||||
|
bs_data *bsd = (bs_data*)io_u->engine_data;
|
||||||
if (bsd->bs->unstable_writes.size() > 0)
|
if (bsd->bs->unstable_writes.size() > 0)
|
||||||
{
|
{
|
||||||
op->flags = OP_STABLE;
|
op->flags = OP_STABLE;
|
||||||
|
@ -162,8 +168,9 @@ static enum fio_q_status bs_queue(struct thread_data *td, struct io_u *io_u)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
bsd->bs->enqueue_op(op);
|
bsd->bs->enqueue_op(op);
|
||||||
op->callback = [&](blockstore_operation *op)
|
op->callback = [io_u](blockstore_operation *op)
|
||||||
{
|
{
|
||||||
|
bs_data *bsd = (bs_data*)io_u->engine_data;
|
||||||
bsd->completed.push_back(io_u);
|
bsd->completed.push_back(io_u);
|
||||||
obj_ver_id *vers = (obj_ver_id*)op->buf;
|
obj_ver_id *vers = (obj_ver_id*)op->buf;
|
||||||
delete[] vers;
|
delete[] vers;
|
||||||
|
@ -192,9 +199,12 @@ static int bs_getevents(struct thread_data *td, unsigned int min, unsigned int m
|
||||||
{
|
{
|
||||||
bs_data *bsd = (bs_data*)td->io_ops_data;
|
bs_data *bsd = (bs_data*)td->io_ops_data;
|
||||||
// FIXME timeout
|
// FIXME timeout
|
||||||
while (bsd->completed.size() < min)
|
while (true)
|
||||||
{
|
{
|
||||||
bsd->ringloop->loop();
|
bsd->ringloop->loop();
|
||||||
|
if (bsd->completed.size() >= min)
|
||||||
|
break;
|
||||||
|
bsd->ringloop->wait();
|
||||||
}
|
}
|
||||||
return bsd->completed.size();
|
return bsd->completed.size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,5 +62,4 @@ void ring_loop_t::loop()
|
||||||
consumers[i].loop();
|
consumers[i].loop();
|
||||||
}
|
}
|
||||||
} while (loop_again);
|
} while (loop_again);
|
||||||
io_uring_wait_cqe(&ring, &cqe);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,4 +142,9 @@ public:
|
||||||
{
|
{
|
||||||
return io_uring_submit(&ring);
|
return io_uring_submit(&ring);
|
||||||
}
|
}
|
||||||
|
inline int wait()
|
||||||
|
{
|
||||||
|
struct io_uring_cqe *cqe;
|
||||||
|
return io_uring_wait_cqe(&ring, &cqe);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,75 +1,7 @@
|
||||||
#include <sys/timerfd.h>
|
|
||||||
#include <sys/poll.h>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "timerfd_interval.h"
|
||||||
#include "blockstore.h"
|
#include "blockstore.h"
|
||||||
|
|
||||||
class timerfd_interval
|
|
||||||
{
|
|
||||||
int wait_state;
|
|
||||||
int timerfd;
|
|
||||||
int status;
|
|
||||||
ring_loop_t *ringloop;
|
|
||||||
ring_consumer_t consumer;
|
|
||||||
std::function<void(void)> callback;
|
|
||||||
public:
|
|
||||||
timerfd_interval(ring_loop_t *ringloop, int seconds, std::function<void(void)> cb)
|
|
||||||
{
|
|
||||||
wait_state = 0;
|
|
||||||
timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
|
|
||||||
if (timerfd < 0)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(std::string("timerfd_create: ") + strerror(errno));
|
|
||||||
}
|
|
||||||
struct itimerspec exp = {
|
|
||||||
.it_interval = { seconds, 0 },
|
|
||||||
.it_value = { seconds, 0 },
|
|
||||||
};
|
|
||||||
if (timerfd_settime(timerfd, 0, &exp, NULL))
|
|
||||||
{
|
|
||||||
throw std::runtime_error(std::string("timerfd_settime: ") + strerror(errno));
|
|
||||||
}
|
|
||||||
consumer.loop = [this]() { loop(); };
|
|
||||||
ringloop->register_consumer(consumer);
|
|
||||||
this->ringloop = ringloop;
|
|
||||||
this->callback = cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
~timerfd_interval()
|
|
||||||
{
|
|
||||||
ringloop->unregister_consumer(consumer);
|
|
||||||
close(timerfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
if (wait_state == 1)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct io_uring_sqe *sqe = ringloop->get_sqe();
|
|
||||||
if (!sqe)
|
|
||||||
{
|
|
||||||
wait_state = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct ring_data_t *data = ((ring_data_t*)sqe->user_data);
|
|
||||||
my_uring_prep_poll_add(sqe, timerfd, POLLIN);
|
|
||||||
data->callback = [&](ring_data_t *data)
|
|
||||||
{
|
|
||||||
if (data->res < 0)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(std::string("waiting for timer failed: ") + strerror(-data->res));
|
|
||||||
}
|
|
||||||
uint64_t n;
|
|
||||||
read(timerfd, &n, 8);
|
|
||||||
wait_state = 0;
|
|
||||||
callback();
|
|
||||||
};
|
|
||||||
wait_state = 1;
|
|
||||||
ringloop->submit();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int narg, char *args[])
|
int main(int narg, char *args[])
|
||||||
{
|
{
|
||||||
spp::sparse_hash_map<std::string, std::string> config;
|
spp::sparse_hash_map<std::string, std::string> config;
|
||||||
|
@ -141,6 +73,7 @@ int main(int narg, char *args[])
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
ringloop->loop();
|
ringloop->loop();
|
||||||
|
ringloop->wait();
|
||||||
}
|
}
|
||||||
delete bs;
|
delete bs;
|
||||||
delete ringloop;
|
delete ringloop;
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
#include <sys/timerfd.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "timerfd_interval.h"
|
||||||
|
|
||||||
|
timerfd_interval::timerfd_interval(ring_loop_t *ringloop, int seconds, std::function<void(void)> cb)
|
||||||
|
{
|
||||||
|
wait_state = 0;
|
||||||
|
timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
|
||||||
|
if (timerfd < 0)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(std::string("timerfd_create: ") + strerror(errno));
|
||||||
|
}
|
||||||
|
struct itimerspec exp = {
|
||||||
|
.it_interval = { seconds, 0 },
|
||||||
|
.it_value = { seconds, 0 },
|
||||||
|
};
|
||||||
|
if (timerfd_settime(timerfd, 0, &exp, NULL))
|
||||||
|
{
|
||||||
|
throw std::runtime_error(std::string("timerfd_settime: ") + strerror(errno));
|
||||||
|
}
|
||||||
|
consumer.loop = [this]() { loop(); };
|
||||||
|
ringloop->register_consumer(consumer);
|
||||||
|
this->ringloop = ringloop;
|
||||||
|
this->callback = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
timerfd_interval::~timerfd_interval()
|
||||||
|
{
|
||||||
|
ringloop->unregister_consumer(consumer);
|
||||||
|
close(timerfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerfd_interval::loop()
|
||||||
|
{
|
||||||
|
if (wait_state == 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct io_uring_sqe *sqe = ringloop->get_sqe();
|
||||||
|
if (!sqe)
|
||||||
|
{
|
||||||
|
wait_state = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct ring_data_t *data = ((ring_data_t*)sqe->user_data);
|
||||||
|
my_uring_prep_poll_add(sqe, timerfd, POLLIN);
|
||||||
|
data->callback = [&](ring_data_t *data)
|
||||||
|
{
|
||||||
|
if (data->res < 0)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(std::string("waiting for timer failed: ") + strerror(-data->res));
|
||||||
|
}
|
||||||
|
uint64_t n;
|
||||||
|
read(timerfd, &n, 8);
|
||||||
|
wait_state = 0;
|
||||||
|
callback();
|
||||||
|
};
|
||||||
|
wait_state = 1;
|
||||||
|
ringloop->submit();
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ringloop.h"
|
||||||
|
|
||||||
|
class timerfd_interval
|
||||||
|
{
|
||||||
|
int wait_state;
|
||||||
|
int timerfd;
|
||||||
|
int status;
|
||||||
|
ring_loop_t *ringloop;
|
||||||
|
ring_consumer_t consumer;
|
||||||
|
std::function<void(void)> callback;
|
||||||
|
public:
|
||||||
|
timerfd_interval(ring_loop_t *ringloop, int seconds, std::function<void(void)> cb);
|
||||||
|
~timerfd_interval();
|
||||||
|
void loop();
|
||||||
|
};
|
Loading…
Reference in New Issue