diff --git a/configure.ac b/configure.ac index 8e6ed95f7..b5452ccb8 100644 --- a/configure.ac +++ b/configure.ac @@ -1060,8 +1060,11 @@ dnl AC_CHECK_FUNCS([ \ backtrace \ + fadvise \ + madvise \ mlock2 \ posix_fadvise \ + posix_madvise \ preadv2 \ pwritev2 \ strlcat \ diff --git a/include/ircd/fs/map.h b/include/ircd/fs/map.h index cfa0a3a13..3d27c502b 100644 --- a/include/ircd/fs/map.h +++ b/include/ircd/fs/map.h @@ -14,6 +14,9 @@ namespace ircd::fs { struct map; + + size_t advise(const map &, const int &, const size_t &, const opts & = opts_default); + size_t evict(const map &, const size_t &size, const opts & = opts_default); } /// Interface to map file into memory. diff --git a/ircd/fs.cc b/ircd/fs.cc index 3c289e070..e1224e495 100644 --- a/ircd/fs.cc +++ b/ircd/fs.cc @@ -1746,6 +1746,98 @@ namespace ircd::fs static uint prot(const map::opts &); } +#if defined(MADV_NORMAL) && defined(POSIX_MADV_NORMAL) + static_assert(MADV_NORMAL == POSIX_MADV_NORMAL); +#endif + +#if defined(MADV_SEQUENTIAL) && defined(POSIX_MADV_SEQUENTIAL) + static_assert(MADV_SEQUENTIAL == POSIX_MADV_SEQUENTIAL); +#endif + +#if defined(MADV_RANDOM) && defined(POSIX_MADV_RANDOM) + static_assert(MADV_RANDOM == POSIX_MADV_RANDOM); +#endif + +#if defined(MADV_WILLNEED) && defined(POSIX_MADV_WILLNEED) + static_assert(MADV_WILLNEED == POSIX_MADV_WILLNEED); +#endif + +#if defined(MADV_DONTNEED) && defined(POSIX_MADV_DONTNEED) + static_assert(MADV_DONTNEED == POSIX_MADV_DONTNEED); +#endif + +size_t +ircd::fs::evict(const map &map, + const size_t &len, + const opts &opts) +{ + return advise(map, POSIX_MADV_DONTNEED, len, opts); +} + +#if defined(HAVE_MADVISE) && defined(__linux__) +size_t +ircd::fs::advise(const map &map, + const int &advice, + const size_t &len, + const opts &opts) +{ + const size_t offset + { + buffer::align(opts.offset, info::page_size) + }; + + const mutable_buffer buf + { + map + offset, len + }; + + assert(aligned(buf, info::page_size)); + switch(const auto res(::madvise(data(buf), size(buf), advice)); res) + { + case 0: + return size(buf); // success + + default: + throw_system_error(res); // error + } + + __builtin_unreachable(); +} +#elif defined(HAVE_POSIX_MADVISE) +size_t +ircd::fs::advise(const map &map, + const int &advice, + const size_t &len, + const opts &opts) +{ + const mutable_buffer buf + { + map + opts.offset, len + }; + + const auto res + { + syscall(::posix_madvise, data(buf), size(buf), advice) + }; + + return size(buf); +} +#else +#warning "posix_madvise(2) not available for this compilation." +size_t +ircd::fs::advise(const map &map, + const int &advice, + const size_t &len, + const opts &opts) +{ + return 0; +} +#endif + +// +// map::map +// + ircd::fs::map::map(const fd &fd, const opts &opts, const size_t &size) @@ -1768,6 +1860,19 @@ ircd::fs::map::map(const fd &fd, reinterpret_cast(ptr), map_size }; + + const int advise + { + #if defined(HAVE_POSIX_MADVISE) + opts.random? POSIX_MADV_RANDOM: + opts.sequential? POSIX_MADV_SEQUENTIAL: + opts.dontneed? POSIX_MADV_DONTNEED: + #endif + 0 + }; + + if(advise) + fs::advise(*this, advise, map_size); } ircd::fs::map::~map() @@ -1809,6 +1914,10 @@ noexcept return *this; } +// +// util +// + uint ircd::fs::prot(const map::opts &opts) {