0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-26 15:33:54 +01:00

ircd::fs: Eliminate uses of GNU ifunc.

This commit is contained in:
Jason Volk 2019-06-04 16:37:29 -07:00
parent 129676d06e
commit 0575f9c500

View file

@ -1000,56 +1000,23 @@ ircd::fs::append(const string_view &path,
return append(fd, bufs, opts);
}
// Platform-specific append() implementations.
namespace ircd::fs
{
static size_t _append__rwf(const fd &, const const_buffers &, const write_opts &);
static size_t _append__no_rwf(const fd &, const const_buffers &, const write_opts &);
extern "C" decltype(_append__rwf) *ircd_fs_append__resolve();
}
#if defined(HAVE_PWRITEV2) && defined(RWF_APPEND)
size_t
ircd::fs::append(const fd &fd,
const const_buffers &bufs,
const write_opts &opts_)
__attribute__((ifunc("ircd_fs_append__resolve")));
/// This function allows the linker to dynamically resolve the append() definition
/// we'll be using during this execution. We check for fs::support_append which was
/// initialized based on the kernel version.
extern "C" decltype(ircd::fs::_append__rwf) *
ircd::fs::ircd_fs_append__resolve()
{
log::logf
{
log, support_append? log::DEBUG : log::DWARNING,
"This host '%s %s' %s the RWF_APPEND flag to pwritev2(2).",
info::kernel_name,
string_view{info::kernel_version},
support_append? "supports"_sv : "does not support"_sv,
};
return support_append? _append__rwf : _append__no_rwf;
}
/// When we have RWF_APPEND. We unconditionally set the offset to the
/// value -1.
size_t
ircd::fs::_append__rwf(const fd &fd,
const const_buffers &bufs,
const write_opts &opts_)
{
auto opts(opts_);
opts.offset = -1;
return write(fd, bufs, opts);
}
#else
/// When we don't have pwritev2() we have to eat the cost of an
/// extra lseek() to the end of the file.
size_t
ircd::fs::_append__no_rwf(const fd &fd,
const const_buffers &bufs,
const write_opts &opts_)
ircd::fs::append(const fd &fd,
const const_buffers &bufs,
const write_opts &opts_)
{
auto opts(opts_);
if(!opts.offset || opts.offset == -1)
@ -1057,6 +1024,7 @@ ircd::fs::_append__no_rwf(const fd &fd,
return write(fd, bufs, opts);
}
#endif defined(HAVE_PWRITEV2) && defined(RWF_APPEND)
//
// write
@ -1107,21 +1075,10 @@ ircd::fs::write(const string_view &path,
return write(fd, bufs, opts);
}
// Platform-specific write() implementations.
namespace ircd::fs
{
static int flags(const write_opts &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 &);
}
@ -1187,58 +1144,16 @@ ircd::fs::write(const fd &fd,
#ifdef IRCD_USE_AIO
if(likely(aio::system) && opts.aio)
return aio::write(fd, iov, opts);
#endif
#endif IRCD_USE_AIO
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::kernel_name,
string_view{info::kernel_version},
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)
{
ssize_t ret; do
{
ret = ::pwritev(int(fd), iov.data(), iov.size(), opts.offset);
}
while(!opts.interruptible && unlikely(ret == -1 && errno == EINTR));
static_assert(EAGAIN == EWOULDBLOCK);
if(unlikely(!opts.blocking && ret == -1 && errno == EAGAIN))
return 0UL;
if(unlikely(ret == -1))
throw std::system_error
{
errno, std::system_category()
};
return ret;
return _write(fd, iov, opts);
}
#ifdef HAVE_PWRITEV2
size_t
ircd::fs::_write__pwritev2(const fd &fd,
const const_iovec_view &iov,
const write_opts &opts)
ircd::fs::_write(const fd &fd,
const const_iovec_view &iov,
const write_opts &opts)
{
// 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
@ -1273,16 +1188,27 @@ ircd::fs::_write__pwritev2(const fd &fd,
}
#else
size_t
[[noreturn]]
ircd::fs::_write__pwritev2(const fd &fd,
const const_iovec_view &iov,
const write_opts &opts)
ircd::fs::_write(const fd &fd,
const const_iovec_view &iov,
const write_opts &opts)
{
ircd::terminate(panic
ssize_t ret; do
{
"This build does not support pwritev2()."
" This function should not have been selected."
});
ret = ::pwritev(int(fd), iov.data(), iov.size(), opts.offset);
}
while(!opts.interruptible && unlikely(ret == -1 && errno == EINTR));
static_assert(EAGAIN == EWOULDBLOCK);
if(unlikely(!opts.blocking && ret == -1 && errno == EAGAIN))
return 0UL;
if(unlikely(ret == -1))
throw std::system_error
{
errno, std::system_category()
};
return ret;
}
#endif