[block-cache] unit tests + debug io_engine and copier
This commit is contained in:
@@ -12,7 +12,12 @@ using namespace bcache;
|
||||
using namespace boost;
|
||||
using namespace std;
|
||||
|
||||
#define SECTOR_SHIFT 9
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
unsigned const SECTOR_SHIFT = 9;
|
||||
unsigned const PAGE_SIZE = 4096;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
@@ -55,23 +60,22 @@ control_block_set::context(iocb *cb) const
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
io_engine::io_engine(unsigned max_io)
|
||||
aio_engine::aio_engine(unsigned max_io)
|
||||
: aio_context_(0),
|
||||
cbs_(max_io),
|
||||
events_(max_io)
|
||||
cbs_(max_io)
|
||||
{
|
||||
int r = io_setup(max_io, &aio_context_);
|
||||
if (r < 0)
|
||||
throw runtime_error("io_setup failed");
|
||||
}
|
||||
|
||||
io_engine::~io_engine()
|
||||
aio_engine::~aio_engine()
|
||||
{
|
||||
io_destroy(aio_context_);
|
||||
}
|
||||
|
||||
io_engine::handle
|
||||
io_engine:: open_file(std::string const &path, mode m)
|
||||
aio_engine::handle
|
||||
aio_engine::open_file(std::string const &path, mode m)
|
||||
{
|
||||
int flags = (m == READ_ONLY) ? O_RDONLY : O_RDWR;
|
||||
int fd = ::open(path.c_str(), O_DIRECT | flags);
|
||||
@@ -87,7 +91,7 @@ io_engine:: open_file(std::string const &path, mode m)
|
||||
}
|
||||
|
||||
void
|
||||
io_engine::close_file(handle h)
|
||||
aio_engine::close_file(handle h)
|
||||
{
|
||||
for (auto it = descriptors_.begin(); it != descriptors_.end(); ++it) {
|
||||
unsigned it_h = it->get();
|
||||
@@ -103,71 +107,60 @@ io_engine::close_file(handle h)
|
||||
}
|
||||
|
||||
bool
|
||||
io_engine::issue_io(handle h, dir d, sector_t b, sector_t e, void *data, unsigned context)
|
||||
aio_engine::issue_io(handle h, dir d, sector_t b, sector_t e, void *data, unsigned context)
|
||||
{
|
||||
auto cb = cbs_.alloc(context);
|
||||
if (reinterpret_cast<uint64_t>(data) & (PAGE_SIZE - 1))
|
||||
throw runtime_error("Data passed to issue_io must be page aligned\n");
|
||||
|
||||
iocb *cb;
|
||||
|
||||
cb = cbs_.alloc(context);
|
||||
if (!cb)
|
||||
return false;
|
||||
|
||||
memset(cb, 0, sizeof(*cb));
|
||||
|
||||
cb->aio_fildes = static_cast<int>(h);
|
||||
cb->u.c.buf = data;
|
||||
cb->u.c.offset = b << SECTOR_SHIFT;
|
||||
cb->u.c.nbytes = (e - b) << SECTOR_SHIFT;
|
||||
|
||||
cb->aio_lio_opcode = (d == READ) ? IO_CMD_PREAD : IO_CMD_PWRITE;
|
||||
|
||||
int r = io_submit(aio_context_, 1, &cb);
|
||||
if (r != 1) {
|
||||
std::ostringstream out;
|
||||
out << "couldn't issue "
|
||||
<< ((d == READ) ? "READ" : "WRITE")
|
||||
<< " io: io_submit ";
|
||||
if (r < 0)
|
||||
out << "failed with " << r;
|
||||
else
|
||||
out << "succeeded, but queued no io";
|
||||
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
|
||||
return true;
|
||||
return r == 1;
|
||||
}
|
||||
|
||||
std::pair<bool, io_engine::handle>
|
||||
io_engine::wait()
|
||||
aio_engine::wait()
|
||||
{
|
||||
int r;
|
||||
unsigned i;
|
||||
struct io_event event;
|
||||
|
||||
r = io_getevents(aio_context_, 1, events_.size(), &events_[0], NULL);
|
||||
memset(&event, 0, sizeof(event));
|
||||
|
||||
r = io_getevents(aio_context_, 1, 1, &event, NULL);
|
||||
if (r < 0) {
|
||||
std::ostringstream out;
|
||||
out << "io_getevents failed: " << r;
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
|
||||
for (i = 0; i < static_cast<unsigned>(r); i++) {
|
||||
io_event const &e = events_[i];
|
||||
iocb *cb = reinterpret_cast<iocb *>(e.obj);
|
||||
unsigned context = cbs_.context(cb);
|
||||
iocb *cb = reinterpret_cast<iocb *>(event.obj);
|
||||
unsigned context = cbs_.context(cb);
|
||||
|
||||
if (event.res == cb->u.c.nbytes) {
|
||||
cbs_.free(cb);
|
||||
return make_pair(true, context);
|
||||
|
||||
if (e.res == cb->u.c.nbytes)
|
||||
return make_pair(true, context);
|
||||
} else if (static_cast<int>(event.res) < 0) {
|
||||
cbs_.free(cb);
|
||||
return make_pair(false, context);
|
||||
|
||||
else {
|
||||
std::ostringstream out;
|
||||
out << "io failed"
|
||||
<< ", e.res = " << e.res
|
||||
<< ", e.res2 = " << e.res2
|
||||
<< ", offset = " << cb->u.c.offset
|
||||
<< ", nbytes = " << cb->u.c.nbytes;
|
||||
return make_pair(false, context);
|
||||
}
|
||||
} else {
|
||||
cbs_.free(cb);
|
||||
return make_pair(false, context);
|
||||
}
|
||||
|
||||
|
||||
// shouldn't get here
|
||||
return make_pair(false, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user