0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-29 10:12:39 +01:00

ircd::fs: Add iov util header; make aio interface to fs exclusively iov.

This commit is contained in:
Jason Volk 2018-11-28 16:53:04 -08:00
parent 67772facef
commit eff4c475e3
5 changed files with 117 additions and 60 deletions

View file

@ -81,6 +81,7 @@ enum ircd::fs::index
}; };
#include "error.h" #include "error.h"
#include "iov.h"
#include "fd.h" #include "fd.h"
#include "aio.h" #include "aio.h"
#include "read.h" #include "read.h"

31
include/ircd/fs/iov.h Normal file
View file

@ -0,0 +1,31 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_FS_IOV_H
extern "C"
{
struct iovec;
};
namespace ircd::fs
{
// utility; count the total bytes of an iov.
size_t bytes(const vector_view<const struct ::iovec> &);
// Transforms our buffers to struct iovec ones. This is done using an
// internal thread_local array of IOV_MAX. The returned view is of that
// array. We get away with using a single buffer because the synchronous
// readv()/writev() calls block the thread and for AIO the iov is copied out
// of userspace on io_submit().
vector_view<const struct ::iovec> make_iov(const vector_view<const const_buffer> &);
vector_view<const struct ::iovec> make_iov(const vector_view<const mutable_buffer> &);
}

View file

@ -16,7 +16,6 @@
namespace ircd::fs::aio namespace ircd::fs::aio
{ {
static int reqprio(int); static int reqprio(int);
static size_t bytes(const vector_view<const struct ::iovec> &);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -85,17 +84,9 @@ ircd::fs::aio::fdsync(const fd &fd,
// //
ircd::fs::aio::request::read::read(const int &fd, ircd::fs::aio::request::read::read(const int &fd,
const mutable_buffer &buf, const vector_view<const struct ::iovec> &iov,
const read_opts &opts) const read_opts &opts)
:request{fd} :request{fd}
,iov
{
// struct iovec
{
buffer::data(buf),
buffer::size(buf)
},
}
{ {
aio_reqprio = reqprio(opts.priority); aio_reqprio = reqprio(opts.priority);
aio_lio_opcode = IOCB_CMD_PREADV; aio_lio_opcode = IOCB_CMD_PREADV;
@ -105,14 +96,14 @@ ircd::fs::aio::request::read::read(const int &fd,
aio_offset = opts.offset; aio_offset = opts.offset;
} }
ircd::const_buffer size_t
ircd::fs::aio::read(const fd &fd, ircd::fs::aio::read(const fd &fd,
const mutable_buffer &buf, const vector_view<const mutable_buffer> &bufs,
const read_opts &opts) const read_opts &opts)
{ {
aio::request::read request aio::request::read request
{ {
fd, buf, opts fd, make_iov(bufs), opts
}; };
const size_t bytes const size_t bytes
@ -120,14 +111,9 @@ ircd::fs::aio::read(const fd &fd,
request() request()
}; };
const const_buffer view
{
const_cast<const char *>(data(buf)), bytes
};
aio::stats.read_bytes += bytes; aio::stats.read_bytes += bytes;
aio::stats.reads++; aio::stats.reads++;
return view; return bytes;
} }
// //
@ -135,17 +121,9 @@ ircd::fs::aio::read(const fd &fd,
// //
ircd::fs::aio::request::write::write(const int &fd, ircd::fs::aio::request::write::write(const int &fd,
const const_buffer &buf, const vector_view<const struct ::iovec> &iov,
const write_opts &opts) const write_opts &opts)
:request{fd} :request{fd}
,iov
{{
// struct iovec
{
const_cast<char *>(buffer::data(buf)),
buffer::size(buf)
},
}}
{ {
aio_reqprio = reqprio(opts.priority); aio_reqprio = reqprio(opts.priority);
aio_lio_opcode = IOCB_CMD_PWRITEV; aio_lio_opcode = IOCB_CMD_PWRITEV;
@ -155,31 +133,34 @@ ircd::fs::aio::request::write::write(const int &fd,
aio_offset = opts.offset; aio_offset = opts.offset;
} }
ircd::const_buffer size_t
ircd::fs::aio::write(const fd &fd, ircd::fs::aio::write(const fd &fd,
const const_buffer &buf, const vector_view<const const_buffer> &bufs,
const write_opts &opts) const write_opts &opts)
{ {
aio::request::write request aio::request::write request
{ {
fd, buf, opts fd, make_iov(bufs), opts
}; };
#ifndef _NDEBUG
const size_t req_bytes
{
fs::bytes(request.iovec())
};
#endif
const size_t bytes const size_t bytes
{ {
request() request()
}; };
const const_buffer view
{
data(buf), bytes
};
// Does linux ever not complete all bytes for an AIO? // Does linux ever not complete all bytes for an AIO?
assert(size(view) == size(buf)); assert(bytes == req_bytes);
aio::stats.write_bytes += bytes; aio::stats.write_bytes += bytes;
aio::stats.writes++; aio::stats.writes++;
return view; return bytes;
} }
// //
@ -198,16 +179,6 @@ ircd::fs::aio::prefetch(const fd &fd,
// internal util // internal util
// //
size_t
ircd::fs::aio::bytes(const vector_view<const struct ::iovec> &iov)
{
return std::accumulate(begin(iov), end(iov), size_t(0), []
(auto ret, const auto &iov)
{
return ret += iov.iov_len;
});
}
int int
ircd::fs::aio::reqprio(int input) ircd::fs::aio::reqprio(int input)
{ {
@ -508,13 +479,13 @@ try
static_cast<iocb *>(this) static_cast<iocb *>(this)
}; };
syscall<SYS_io_submit>(context->idp, 1, &cbs);
const size_t submitted_bytes const size_t submitted_bytes
{ {
bytes(iovec()) bytes(iovec())
}; };
syscall<SYS_io_submit>(context->idp, 1, &cbs);
// Update stats for submission phase // Update stats for submission phase
aio::stats.requests_bytes += submitted_bytes; aio::stats.requests_bytes += submitted_bytes;
aio::stats.requests++; aio::stats.requests++;

View file

@ -17,8 +17,8 @@ namespace ircd::fs::aio
struct request; struct request;
void prefetch(const fd &, const size_t &, const read_opts &); void prefetch(const fd &, const size_t &, const read_opts &);
const_buffer write(const fd &, const const_buffer &, const write_opts &); size_t write(const fd &, const vector_view<const const_buffer> &, const write_opts &);
const_buffer read(const fd &, const mutable_buffer &, const read_opts &); size_t read(const fd &, const vector_view<const mutable_buffer> &, const read_opts &);
void fdsync(const fd &, const fsync_opts &); void fdsync(const fd &, const fsync_opts &);
void fsync(const fd &, const fsync_opts &); void fsync(const fd &, const fsync_opts &);
} }
@ -87,18 +87,14 @@ struct ircd::fs::aio::request
struct ircd::fs::aio::request::read struct ircd::fs::aio::request::read
:request :request
{ {
std::array<struct ::iovec, 1> iov; read(const int &fd, const vector_view<const struct ::iovec> &, const read_opts &);
read(const int &fd, const mutable_buffer &, const read_opts &);
}; };
/// Write request control block /// Write request control block
struct ircd::fs::aio::request::write struct ircd::fs::aio::request::write
:request :request
{ {
std::array<struct ::iovec, 1> iov; write(const int &fd, const vector_view<const struct ::iovec> &, const write_opts &);
write(const int &fd, const const_buffer &, const write_opts &);
}; };
/// fdsync request control block /// fdsync request control block

View file

@ -582,7 +582,10 @@ try
{ {
#ifdef IRCD_USE_AIO #ifdef IRCD_USE_AIO
if(likely(aio::context)) if(likely(aio::context))
return aio::read(fd, buf, opts); return
{
data(buf), aio::read(fd, {&buf, 1}, opts)
};
#endif #endif
return return
@ -746,7 +749,10 @@ try
{ {
#ifdef IRCD_USE_AIO #ifdef IRCD_USE_AIO
if(likely(aio::context)) if(likely(aio::context))
return aio::write(fd, buf, opts); return
{
data(buf), aio::write(fd, {&buf, 1}, opts)
};
#endif #endif
return return
@ -1011,6 +1017,58 @@ noexcept(false)
syscall(::close, fdno); syscall(::close, fdno);
} }
///////////////////////////////////////////////////////////////////////////////
//
// fs/iov.h
//
namespace ircd::fs
{
thread_local std::array<struct ::iovec, IOV_MAX> _iov_;
}
ircd::vector_view<const struct ::iovec>
ircd::fs::make_iov(const vector_view<const mutable_buffer> &bufs)
{
size_t i(0);
for(; i < bufs.size(); ++i)
_iov_.at(i) =
{
buffer::data(bufs[i]), buffer::size(bufs[i])
};
return
{
_iov_.data(), i
};
}
ircd::vector_view<const struct ::iovec>
ircd::fs::make_iov(const vector_view<const const_buffer> &bufs)
{
size_t i(0);
for(; i < bufs.size(); ++i)
_iov_.at(i) =
{
const_cast<char *>(buffer::data(bufs[i])), buffer::size(bufs[i])
};
return
{
_iov_.data(), i
};
}
size_t
ircd::fs::bytes(const vector_view<const struct ::iovec> &iov)
{
return std::accumulate(begin(iov), end(iov), size_t(0), []
(auto ret, const auto &iov)
{
return ret += iov.iov_len;
});
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// fs/error.h // fs/error.h