diff --git a/ircd/fs.cc b/ircd/fs.cc index 941ba17fd..192a1c455 100644 --- a/ircd/fs.cc +++ b/ircd/fs.cc @@ -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