0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2025-01-16 09:36:54 +01:00

ircd::fs: Further simplify AIO interface.

This commit is contained in:
Jason Volk 2018-01-17 22:03:07 -08:00
parent 09e32dce56
commit 9f6eda4c3d

View file

@ -82,32 +82,28 @@ struct ircd::fs::aio::request
ssize_t retval {0}; ssize_t retval {0};
ssize_t errcode {0}; ssize_t errcode {0};
ctx::ctx *waiter {nullptr}; ctx::ctx *waiter {ctx::current};
/// called if close_fd is true void handle();
void close_fildes() noexcept;
/// Overriden by types of requests
virtual void handle() = 0;
public: public:
// Submit a request. ctx overload will properly yield size_t operator()();
size_t operator()(ctx::ctx &waiter);
void operator()();
void cancel(); void cancel();
request(const int &fd); request(const int &fd);
virtual ~request() noexcept; ~request() noexcept;
}; };
ircd::fs::aio::request::request(const int &fd) ircd::fs::aio::request::request(const int &fd)
:iocb{0} :iocb{0}
{ {
assert(aioctx); assert(aioctx);
assert(ctx::current);
aio_flags = IOCB_FLAG_RESFD; aio_flags = IOCB_FLAG_RESFD;
aio_resfd = aioctx->resfd.native_handle(); aio_resfd = aioctx->resfd.native_handle();
aio_fildes = fd; aio_fildes = fd;
aio_data = uintptr_t(this);
} }
/// vtable base /// vtable base
@ -130,23 +126,26 @@ ircd::fs::aio::request::cancel()
aioctx->handle_event(result); aioctx->handle_event(result);
} }
/// Submit a request and properly yield the ircd::ctx. The ctx argument /// Submit a request and properly yield the ircd::ctx. When this returns the
/// must be the currently running ctx (or ctx::current) for now; there is /// result will be available or an exception will be thrown.
/// no other usage. When this returns the result will be available or
/// exception will be thrown.
size_t size_t
ircd::fs::aio::request::operator()(ctx::ctx &waiter) ircd::fs::aio::request::operator()()
try try
{ {
// Cooperation strategy is to set this->waiter to the ctx and wait for assert(aioctx);
// notification with this->waiter set to null to ignore spurious notes. assert(ctx::current);
assert(&waiter == ctx::current); assert(waiter == ctx::current);
this->waiter = &waiter;
operator()(); do struct iocb *const cbs[]
{
static_cast<iocb *>(this)
};
syscall<SYS_io_submit>(aioctx->idp, 1, &cbs); do
{ {
ctx::wait(); ctx::wait();
} }
while(this->waiter); while(!retval && !errcode);
if(retval == -1) if(retval == -1)
throw_system_error(errcode); throw_system_error(errcode);
@ -158,34 +157,22 @@ catch(const ctx::interrupted &e)
// When the ctx is interrupted we're obligated to cancel the request. // When the ctx is interrupted we're obligated to cancel the request.
// The handler callstack is invoked directly from here by cancel() for // The handler callstack is invoked directly from here by cancel() for
// what it's worth but we rethrow the interrupt anyway. // what it's worth but we rethrow the interrupt anyway.
this->waiter = nullptr;
cancel(); cancel();
throw; throw;
} }
/// Submit a request.
void void
ircd::fs::aio::request::operator()() ircd::fs::aio::request::handle()
{ {
struct iocb *const cbs[] assert(this->retval || errcode);
{ if(likely(waiter && waiter != ctx::current))
static_cast<iocb *>(this) ircd::ctx::notify(*waiter);
};
assert(aioctx);
syscall<SYS_io_submit>(aioctx->idp, 1, &cbs);
/*
log::debug("AIO request(%p) fd:%u op:%d bytes:%lu off:%ld prio:%d ctx:%p submit",
this,
this->aio_fildes,
this->aio_lio_opcode,
this->aio_nbytes,
this->aio_offset,
this->aio_reqprio,
this->waiter);
*/
} }
//
// aio
//
void void
ircd::fs::aio::set_handle() ircd::fs::aio::set_handle()
{ {
@ -253,7 +240,7 @@ ircd::fs::aio::handle_event(const io_event &event)
noexcept try noexcept try
{ {
// Our extended control block is passed in event.data // Our extended control block is passed in event.data
auto *const request auto *const &request
{ {
reinterpret_cast<aio::request *>(event.data) reinterpret_cast<aio::request *>(event.data)
}; };
@ -282,9 +269,6 @@ noexcept try
request->retval, request->retval,
request->errcode); request->errcode);
*/ */
// virtual dispatch based on the request type. Alternatively, we could
// switch() on the iocb lio_opcode and downcast... but that's what vtable
// does for us right here.
request->handle(); request->handle();
} }
catch(const std::exception &e) catch(const std::exception &e)
@ -295,21 +279,6 @@ catch(const std::exception &e)
e.what()); e.what());
} }
/// If requested, close the file descriptor. Errors here can be logged but
/// must be otherwise ignored.
void
ircd::fs::aio::request::close_fildes()
noexcept try
{
syscall(::close, aio_fildes);
}
catch(const std::exception &e)
{
log::error("Failed to close request(%p) fd:%d: %s",
this,
aio_fildes);
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// fs/read.h // fs/read.h
@ -325,8 +294,6 @@ namespace ircd::fs
struct ircd::fs::aio::request::read struct ircd::fs::aio::request::read
:request :request
{ {
virtual void handle() final override;
read(const int &fd, const mutable_raw_buffer &buf, const read_opts &opts); read(const int &fd, const mutable_raw_buffer &buf, const read_opts &opts);
}; };
@ -335,7 +302,6 @@ ircd::fs::aio::request::read::read(const int &fd,
const read_opts &opts) const read_opts &opts)
:request{fd} :request{fd}
{ {
aio_data = uintptr_t(this);
aio_reqprio = opts.priority; aio_reqprio = opts.priority;
aio_lio_opcode = IOCB_CMD_PREAD; aio_lio_opcode = IOCB_CMD_PREAD;
@ -344,16 +310,6 @@ ircd::fs::aio::request::read::read(const int &fd,
aio_offset = opts.offset; aio_offset = opts.offset;
} }
void
ircd::fs::aio::request::read::handle()
{
if(!waiter)
return;
ircd::ctx::notify(*waiter);
waiter = nullptr;
}
// //
// Interface // Interface
// //
@ -396,7 +352,7 @@ ircd::fs::read__aio(const string_view &path,
const size_t bytes const size_t bytes
{ {
request(ctx::cur()) request()
}; };
ret.resize(bytes); ret.resize(bytes);
@ -429,7 +385,7 @@ ircd::fs::read__aio(const string_view &path,
const size_t bytes const size_t bytes
{ {
request(ctx::cur()) request()
}; };
const string_view view const string_view view