2018-02-03 18:22:01 -08:00
|
|
|
// Matrix Construct
|
|
|
|
//
|
2018-01-10 21:30:31 -08:00
|
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
2018-02-03 18:22:01 -08:00
|
|
|
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
2018-01-10 21:30:31 -08:00
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
2018-02-03 18:22:01 -08:00
|
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
|
|
// full license for this software is available in the LICENSE file.
|
2018-01-10 21:30:31 -08:00
|
|
|
|
|
|
|
#pragma once
|
2019-01-23 13:20:38 -08:00
|
|
|
#define HAVE_FS_AIO_H
|
2018-01-10 21:30:31 -08:00
|
|
|
#include <linux/aio_abi.h>
|
|
|
|
|
2019-04-29 15:03:33 -07:00
|
|
|
/// Define this to try all read requests with RWF_NOWAIT first and indicate
|
|
|
|
/// EAGAIN failure with a log dwarning. On EAGAIN the request is resubmitted
|
|
|
|
/// without RWF_NOWAIT if the user expected blocking behavior.
|
|
|
|
//#define RB_DEBUG_FS_AIO_READ_BLOCKING
|
|
|
|
|
2019-04-29 17:48:06 -07:00
|
|
|
/// Define to time the io_submit() system call with a syscall_usage_warning.
|
|
|
|
/// This emits a warning when the kernel spent a lot of time in io_submit().
|
|
|
|
/// The resolution is very low at 10ms but it is not expensive to use.
|
|
|
|
//#define RB_DEBUG_FS_AIO_SUBMIT_BLOCKING
|
|
|
|
|
2018-11-27 18:09:12 -08:00
|
|
|
namespace ircd::fs::aio
|
2018-08-20 22:45:06 -07:00
|
|
|
{
|
2018-12-28 15:02:02 -08:00
|
|
|
struct system;
|
2018-11-27 18:09:12 -08:00
|
|
|
struct request;
|
|
|
|
|
2018-12-18 13:40:46 -08:00
|
|
|
size_t write(const fd &, const const_iovec_view &, const write_opts &);
|
|
|
|
size_t read(const fd &, const const_iovec_view &, const read_opts &);
|
2018-12-13 16:54:09 -08:00
|
|
|
void fsync(const fd &, const sync_opts &);
|
2018-08-20 22:45:06 -07:00
|
|
|
}
|
|
|
|
|
2018-12-28 15:02:02 -08:00
|
|
|
/// AIO context instance from the system. Right now this is a singleton with
|
2018-11-27 18:09:12 -08:00
|
|
|
/// an extern instance pointer at fs::aio::context maintained by fs::aio::init.
|
2018-12-28 15:02:02 -08:00
|
|
|
struct ircd::fs::aio::system
|
2018-01-10 21:30:31 -08:00
|
|
|
{
|
2019-03-30 13:11:39 -07:00
|
|
|
struct aio_context;
|
2019-03-27 01:52:37 -07:00
|
|
|
|
2018-12-29 16:32:09 -08:00
|
|
|
static const int eventfd_flags;
|
|
|
|
|
2018-12-27 12:04:48 -08:00
|
|
|
/// io_getevents vector (in)
|
|
|
|
std::vector<io_event> event;
|
|
|
|
uint64_t ecount {0};
|
2018-03-12 16:26:55 -07:00
|
|
|
|
2018-12-27 10:36:27 -08:00
|
|
|
/// io_submit queue (out)
|
|
|
|
std::vector<iocb *> queue;
|
|
|
|
size_t qcount {0};
|
|
|
|
|
2018-12-27 12:04:48 -08:00
|
|
|
/// other state
|
|
|
|
ctx::dock dock;
|
|
|
|
size_t in_flight {0};
|
2019-01-17 12:24:47 -08:00
|
|
|
bool handle_set {false};
|
2018-01-10 21:30:31 -08:00
|
|
|
|
2019-03-27 03:06:46 -07:00
|
|
|
size_t handle_size {0};
|
|
|
|
std::unique_ptr<uint8_t[]> handle_data;
|
|
|
|
static ios::descriptor handle_descriptor;
|
|
|
|
|
2018-12-28 15:02:02 -08:00
|
|
|
/// An eventfd which will be notified by the system; we integrate this with
|
2018-01-10 21:30:31 -08:00
|
|
|
/// the ircd io_service core epoll() event loop. The EFD_SEMAPHORE flag is
|
2018-12-27 12:04:48 -08:00
|
|
|
/// not used to reduce the number of triggers. The semaphore value is the
|
|
|
|
/// ecount (above) which will reflect a hint for how many AIO's are done.
|
2018-02-05 22:42:40 -08:00
|
|
|
asio::posix::stream_descriptor resfd;
|
2018-01-10 21:30:31 -08:00
|
|
|
|
2018-12-28 15:02:02 -08:00
|
|
|
/// Handler to the io context we submit requests to the system with
|
2019-03-30 13:11:39 -07:00
|
|
|
const custom_ptr<const aio_context> head;
|
|
|
|
const io_event *ring {nullptr};
|
2018-01-10 21:30:31 -08:00
|
|
|
|
2019-01-13 14:02:03 -08:00
|
|
|
size_t max_events() const;
|
|
|
|
size_t max_submit() const;
|
|
|
|
size_t request_count() const; // qcount + in_flight
|
|
|
|
size_t request_avail() const; // max_events - request_count()
|
|
|
|
|
2018-01-10 21:30:31 -08:00
|
|
|
// Callback stack invoked when the sigfd is notified of completed events.
|
|
|
|
void handle_event(const io_event &) noexcept;
|
|
|
|
void handle_events() noexcept;
|
2018-03-08 09:27:32 -08:00
|
|
|
void handle(const boost::system::error_code &, const size_t) noexcept;
|
2018-01-10 21:30:31 -08:00
|
|
|
void set_handle();
|
|
|
|
|
2019-03-14 11:49:57 -07:00
|
|
|
void dequeue_one(const std::error_code &);
|
|
|
|
void dequeue_all(const std::error_code &);
|
|
|
|
size_t io_submit();
|
2019-04-20 20:34:01 -07:00
|
|
|
size_t submit() noexcept;
|
2018-12-27 10:36:27 -08:00
|
|
|
void chase() noexcept;
|
|
|
|
|
2019-04-22 09:29:09 -07:00
|
|
|
bool submit(request &);
|
2019-04-20 20:34:01 -07:00
|
|
|
bool cancel(request &);
|
2019-04-22 09:29:09 -07:00
|
|
|
bool wait(request &);
|
2018-12-21 10:30:04 -08:00
|
|
|
|
|
|
|
// Control panel
|
2018-08-18 22:58:43 -07:00
|
|
|
bool wait();
|
2018-03-12 16:26:55 -07:00
|
|
|
bool interrupt();
|
|
|
|
|
2019-01-13 14:02:03 -08:00
|
|
|
system(const size_t &max_events,
|
|
|
|
const size_t &max_submit);
|
|
|
|
|
2018-12-28 15:02:02 -08:00
|
|
|
~system() noexcept;
|
2018-01-10 21:30:31 -08:00
|
|
|
};
|
|
|
|
|
2019-03-30 13:11:39 -07:00
|
|
|
struct ircd::fs::aio::system::aio_context
|
2019-03-27 01:52:37 -07:00
|
|
|
{
|
|
|
|
static constexpr uint MAGIC {0xA10A10A1};
|
|
|
|
|
|
|
|
uint id; // kernel internal index number
|
|
|
|
uint nr; // number of io_events
|
|
|
|
uint head;
|
|
|
|
uint tail;
|
|
|
|
uint magic;
|
|
|
|
uint compat_features;
|
|
|
|
uint incompat_features;
|
2019-03-30 13:11:39 -07:00
|
|
|
uint header_length; // size of aio_context
|
2019-03-27 01:52:37 -07:00
|
|
|
struct io_event io_events[0];
|
|
|
|
};
|
|
|
|
// 128 bytes + ring size
|
|
|
|
|
2018-01-10 21:30:31 -08:00
|
|
|
/// Generic request control block.
|
|
|
|
struct ircd::fs::aio::request
|
|
|
|
:iocb
|
|
|
|
{
|
|
|
|
struct read;
|
|
|
|
struct write;
|
2018-08-18 22:58:43 -07:00
|
|
|
struct fsync;
|
2018-01-10 21:30:31 -08:00
|
|
|
|
2019-04-21 00:20:44 -07:00
|
|
|
ssize_t retval {-2L};
|
|
|
|
ssize_t errcode {0L};
|
2018-12-29 20:02:22 -08:00
|
|
|
const struct opts *opts {nullptr};
|
2019-08-19 20:19:51 -07:00
|
|
|
ctx::dock waiter;
|
2018-01-10 21:30:31 -08:00
|
|
|
|
|
|
|
public:
|
2018-12-01 15:33:30 -08:00
|
|
|
const_iovec_view iovec() const;
|
2019-03-10 19:12:16 -07:00
|
|
|
bool completed() const;
|
2019-04-21 00:20:44 -07:00
|
|
|
bool queued() const;
|
2019-08-19 20:19:51 -07:00
|
|
|
bool wait();
|
2018-11-27 19:54:24 -08:00
|
|
|
|
2018-01-17 22:03:07 -08:00
|
|
|
size_t operator()();
|
2019-04-20 20:34:01 -07:00
|
|
|
bool cancel();
|
2018-01-10 21:30:31 -08:00
|
|
|
|
2018-12-29 20:02:22 -08:00
|
|
|
request(const int &fd, const struct opts *const &);
|
2018-01-17 22:03:07 -08:00
|
|
|
~request() noexcept;
|
2018-01-10 21:30:31 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Read request control block
|
|
|
|
struct ircd::fs::aio::request::read
|
|
|
|
:request
|
|
|
|
{
|
2018-12-01 15:33:30 -08:00
|
|
|
read(const int &fd, const const_iovec_view &, const read_opts &);
|
2018-01-10 21:30:31 -08:00
|
|
|
};
|
2018-02-05 23:28:33 -08:00
|
|
|
|
|
|
|
/// Write request control block
|
|
|
|
struct ircd::fs::aio::request::write
|
|
|
|
:request
|
|
|
|
{
|
2018-12-01 15:33:30 -08:00
|
|
|
write(const int &fd, const const_iovec_view &, const write_opts &);
|
2018-02-05 23:28:33 -08:00
|
|
|
};
|
2018-08-18 22:58:43 -07:00
|
|
|
|
|
|
|
/// fsync request control block
|
|
|
|
struct ircd::fs::aio::request::fsync
|
|
|
|
:request
|
|
|
|
{
|
2018-12-13 16:54:09 -08:00
|
|
|
fsync(const int &fd, const sync_opts &);
|
2018-08-18 22:58:43 -07:00
|
|
|
};
|