mirror of
https://github.com/matrix-construct/construct
synced 2024-12-28 16:34:13 +01:00
ircd::fs: Runtime binding for pwritev(2)/pwritev2(2) based on kernel version.
This commit is contained in:
parent
6fbf882e16
commit
1eaff2e91e
2 changed files with 67 additions and 13 deletions
|
@ -36,7 +36,8 @@ namespace ircd::fs
|
||||||
// may make forward-declared references to boost symbols.
|
// may make forward-declared references to boost symbols.
|
||||||
namespace filesystem = boost::filesystem;
|
namespace filesystem = boost::filesystem;
|
||||||
|
|
||||||
// RWF_ support
|
// Runtime-detected support lights.
|
||||||
|
extern const bool support_pwritev2;
|
||||||
extern const bool support_append;
|
extern const bool support_append;
|
||||||
extern const bool support_nowait;
|
extern const bool support_nowait;
|
||||||
extern const bool support_hipri;
|
extern const bool support_hipri;
|
||||||
|
|
77
ircd/fs.cc
77
ircd/fs.cc
|
@ -32,6 +32,17 @@ ircd::fs::log
|
||||||
"fs"
|
"fs"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
decltype(ircd::fs::support_pwritev2)
|
||||||
|
ircd::fs::support_pwritev2
|
||||||
|
{
|
||||||
|
#if defined(HAVE_PWRITEV2)
|
||||||
|
info::kversion[0] >= 4 &&
|
||||||
|
info::kversion[1] >= 6
|
||||||
|
#else
|
||||||
|
false
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
decltype(ircd::fs::support_sync)
|
decltype(ircd::fs::support_sync)
|
||||||
ircd::fs::support_sync
|
ircd::fs::support_sync
|
||||||
{
|
{
|
||||||
|
@ -934,10 +945,21 @@ ircd::fs::write(const string_view &path,
|
||||||
return write(fd, bufs, opts);
|
return write(fd, bufs, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Platform-specific write() implementations.
|
||||||
namespace ircd::fs
|
namespace ircd::fs
|
||||||
{
|
{
|
||||||
static int flags(const write_opts &opts);
|
static int flags(const write_opts &opts);
|
||||||
static size_t _write(const fd &, const const_iovec_view &, const write_opts &);
|
|
||||||
|
static size_t _write__pwritev2(const fd &, const const_iovec_view &, const write_opts &);
|
||||||
|
static size_t _write__pwritev1(const fd &, const const_iovec_view &, const write_opts &);
|
||||||
|
extern "C" decltype(_write__pwritev1) *ircd_fs_write_pwritev__resolve();
|
||||||
|
|
||||||
|
extern size_t
|
||||||
|
_write_pwritev(const fd &,
|
||||||
|
const const_iovec_view &,
|
||||||
|
const write_opts &)
|
||||||
|
__attribute__((ifunc("ircd_fs_write_pwritev__resolve")));
|
||||||
|
|
||||||
static size_t write(const fd &, const const_iovec_view &, const write_opts &);
|
static size_t write(const fd &, const const_iovec_view &, const write_opts &);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -998,14 +1020,43 @@ ircd::fs::write(const fd &fd,
|
||||||
return aio::write(fd, iov, opts);
|
return aio::write(fd, iov, opts);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return _write(fd, iov, opts);
|
return _write_pwritev(fd, iov, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function allows the linker to dynamically resolve the internal _write()
|
||||||
|
/// definition we'll be using during this execution. We check for the pwritev2
|
||||||
|
/// support flag which was initialized based on the kernel version.
|
||||||
|
extern "C" decltype(ircd::fs::_write__pwritev1) *
|
||||||
|
ircd::fs::ircd_fs_write_pwritev__resolve()
|
||||||
|
{
|
||||||
|
log::logf
|
||||||
|
{
|
||||||
|
log, support_pwritev2? log::DEBUG : log::DWARNING,
|
||||||
|
"This host '%s %s' %s the pwritev2(2) system call.",
|
||||||
|
info::kname,
|
||||||
|
info::kversion_str,
|
||||||
|
support_pwritev2? "SUPPORTS"_sv : "DOES NOT SUPPORT"_sv
|
||||||
|
};
|
||||||
|
|
||||||
|
return support_pwritev2? _write__pwritev2 : _write__pwritev1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::fs::_write__pwritev1(const fd &fd,
|
||||||
|
const const_iovec_view &iov,
|
||||||
|
const write_opts &opts)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
opts.interruptible?
|
||||||
|
syscall(::pwritev, fd, iov.data(), iov.size(), opts.offset):
|
||||||
|
syscall_nointr(::pwritev, fd, iov.data(), iov.size(), opts.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_PWRITEV2
|
#ifdef HAVE_PWRITEV2
|
||||||
size_t
|
size_t
|
||||||
ircd::fs::_write(const fd &fd,
|
ircd::fs::_write__pwritev2(const fd &fd,
|
||||||
const const_iovec_view &iov,
|
const const_iovec_view &iov,
|
||||||
const write_opts &opts)
|
const write_opts &opts)
|
||||||
{
|
{
|
||||||
// Manpages sez that when appending with RWF_APPEND, the offset has no
|
// Manpages sez that when appending with RWF_APPEND, the offset has no
|
||||||
// effect on the write; but if the value of the offset is -1 then the
|
// effect on the write; but if the value of the offset is -1 then the
|
||||||
|
@ -1027,14 +1078,16 @@ ircd::fs::_write(const fd &fd,
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
size_t
|
size_t
|
||||||
ircd::fs::_write(const fd &fd,
|
[[noreturn]]
|
||||||
const const_iovec_view &iov,
|
ircd::fs::_write__pwritev2(const fd &fd,
|
||||||
const write_opts &opts)
|
const const_iovec_view &iov,
|
||||||
|
const write_opts &opts)
|
||||||
{
|
{
|
||||||
return
|
ircd::terminate(panic
|
||||||
opts.interruptible?
|
{
|
||||||
syscall(::pwritev, fd, iov.data(), iov.size(), opts.offset):
|
"This build does not support pwritev2()."
|
||||||
syscall_nointr(::pwritev, fd, iov.data(), iov.size(), opts.offset);
|
" This function should not have been selected."
|
||||||
|
});
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue