mirror of
https://github.com/matrix-construct/construct
synced 2024-11-26 00:32:35 +01:00
ircd::fs: Add iov util header; make aio interface to fs exclusively iov.
This commit is contained in:
parent
67772facef
commit
eff4c475e3
5 changed files with 117 additions and 60 deletions
|
@ -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
31
include/ircd/fs/iov.h
Normal 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> &);
|
||||||
|
}
|
71
ircd/aio.cc
71
ircd/aio.cc
|
@ -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++;
|
||||||
|
|
12
ircd/aio.h
12
ircd/aio.h
|
@ -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
|
||||||
|
|
62
ircd/fs.cc
62
ircd/fs.cc
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue