0
0
Fork 0
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:
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 "iov.h"
#include "fd.h"
#include "aio.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
{
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++;

View file

@ -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

View file

@ -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