mirror of
https://github.com/matrix-construct/construct
synced 2024-11-25 16:22: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 "iov.h"
|
||||
#include "fd.h"
|
||||
#include "aio.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
|
||||
{
|
||||
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,
|
||||
const mutable_buffer &buf,
|
||||
const vector_view<const struct ::iovec> &iov,
|
||||
const read_opts &opts)
|
||||
:request{fd}
|
||||
,iov
|
||||
{
|
||||
// struct iovec
|
||||
{
|
||||
buffer::data(buf),
|
||||
buffer::size(buf)
|
||||
},
|
||||
}
|
||||
{
|
||||
aio_reqprio = reqprio(opts.priority);
|
||||
aio_lio_opcode = IOCB_CMD_PREADV;
|
||||
|
@ -105,14 +96,14 @@ ircd::fs::aio::request::read::read(const int &fd,
|
|||
aio_offset = opts.offset;
|
||||
}
|
||||
|
||||
ircd::const_buffer
|
||||
size_t
|
||||
ircd::fs::aio::read(const fd &fd,
|
||||
const mutable_buffer &buf,
|
||||
const vector_view<const mutable_buffer> &bufs,
|
||||
const read_opts &opts)
|
||||
{
|
||||
aio::request::read request
|
||||
{
|
||||
fd, buf, opts
|
||||
fd, make_iov(bufs), opts
|
||||
};
|
||||
|
||||
const size_t bytes
|
||||
|
@ -120,14 +111,9 @@ ircd::fs::aio::read(const fd &fd,
|
|||
request()
|
||||
};
|
||||
|
||||
const const_buffer view
|
||||
{
|
||||
const_cast<const char *>(data(buf)), bytes
|
||||
};
|
||||
|
||||
aio::stats.read_bytes += bytes;
|
||||
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,
|
||||
const const_buffer &buf,
|
||||
const vector_view<const struct ::iovec> &iov,
|
||||
const write_opts &opts)
|
||||
:request{fd}
|
||||
,iov
|
||||
{{
|
||||
// struct iovec
|
||||
{
|
||||
const_cast<char *>(buffer::data(buf)),
|
||||
buffer::size(buf)
|
||||
},
|
||||
}}
|
||||
{
|
||||
aio_reqprio = reqprio(opts.priority);
|
||||
aio_lio_opcode = IOCB_CMD_PWRITEV;
|
||||
|
@ -155,31 +133,34 @@ ircd::fs::aio::request::write::write(const int &fd,
|
|||
aio_offset = opts.offset;
|
||||
}
|
||||
|
||||
ircd::const_buffer
|
||||
size_t
|
||||
ircd::fs::aio::write(const fd &fd,
|
||||
const const_buffer &buf,
|
||||
const vector_view<const const_buffer> &bufs,
|
||||
const write_opts &opts)
|
||||
{
|
||||
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
|
||||
{
|
||||
request()
|
||||
};
|
||||
|
||||
const const_buffer view
|
||||
{
|
||||
data(buf), bytes
|
||||
};
|
||||
|
||||
// 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.writes++;
|
||||
return view;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -198,16 +179,6 @@ ircd::fs::aio::prefetch(const fd &fd,
|
|||
// 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
|
||||
ircd::fs::aio::reqprio(int input)
|
||||
{
|
||||
|
@ -508,13 +479,13 @@ try
|
|||
static_cast<iocb *>(this)
|
||||
};
|
||||
|
||||
syscall<SYS_io_submit>(context->idp, 1, &cbs);
|
||||
|
||||
const size_t submitted_bytes
|
||||
{
|
||||
bytes(iovec())
|
||||
};
|
||||
|
||||
syscall<SYS_io_submit>(context->idp, 1, &cbs);
|
||||
|
||||
// Update stats for submission phase
|
||||
aio::stats.requests_bytes += submitted_bytes;
|
||||
aio::stats.requests++;
|
||||
|
|
12
ircd/aio.h
12
ircd/aio.h
|
@ -17,8 +17,8 @@ namespace ircd::fs::aio
|
|||
struct request;
|
||||
|
||||
void prefetch(const fd &, const size_t &, const read_opts &);
|
||||
const_buffer write(const fd &, const const_buffer &, const write_opts &);
|
||||
const_buffer read(const fd &, const mutable_buffer &, const read_opts &);
|
||||
size_t write(const fd &, const vector_view<const const_buffer> &, const write_opts &);
|
||||
size_t read(const fd &, const vector_view<const mutable_buffer> &, const read_opts &);
|
||||
void fdsync(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
|
||||
:request
|
||||
{
|
||||
std::array<struct ::iovec, 1> iov;
|
||||
|
||||
read(const int &fd, const mutable_buffer &, const read_opts &);
|
||||
read(const int &fd, const vector_view<const struct ::iovec> &, const read_opts &);
|
||||
};
|
||||
|
||||
/// Write request control block
|
||||
struct ircd::fs::aio::request::write
|
||||
:request
|
||||
{
|
||||
std::array<struct ::iovec, 1> iov;
|
||||
|
||||
write(const int &fd, const const_buffer &, const write_opts &);
|
||||
write(const int &fd, const vector_view<const struct ::iovec> &, const write_opts &);
|
||||
};
|
||||
|
||||
/// fdsync request control block
|
||||
|
|
62
ircd/fs.cc
62
ircd/fs.cc
|
@ -582,7 +582,10 @@ try
|
|||
{
|
||||
#ifdef IRCD_USE_AIO
|
||||
if(likely(aio::context))
|
||||
return aio::read(fd, buf, opts);
|
||||
return
|
||||
{
|
||||
data(buf), aio::read(fd, {&buf, 1}, opts)
|
||||
};
|
||||
#endif
|
||||
|
||||
return
|
||||
|
@ -746,7 +749,10 @@ try
|
|||
{
|
||||
#ifdef IRCD_USE_AIO
|
||||
if(likely(aio::context))
|
||||
return aio::write(fd, buf, opts);
|
||||
return
|
||||
{
|
||||
data(buf), aio::write(fd, {&buf, 1}, opts)
|
||||
};
|
||||
#endif
|
||||
|
||||
return
|
||||
|
@ -1011,6 +1017,58 @@ noexcept(false)
|
|||
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
|
||||
|
|
Loading…
Reference in a new issue