diff --git a/include/ircd/ircd.h b/include/ircd/ircd.h index 5bbeeeb13..c71a09fc2 100644 --- a/include/ircd/ircd.h +++ b/include/ircd/ircd.h @@ -56,11 +56,8 @@ #include "time.h" #include "logger.h" #include "info.h" -#include "nacl.h" #include "rand.h" #include "crh.h" -#include "ed25519.h" -#include "color.h" #include "lex_cast.h" #include "base.h" #include "stringops.h" @@ -72,9 +69,12 @@ #include "iov.h" #include "grammar.h" #include "parse.h" +#include "color.h" #include "rfc1459.h" #include "json/json.h" #include "cbor/cbor.h" +#include "nacl.h" +#include "ed25519.h" #include "openssl.h" #include "pbc.h" #include "fmt.h" @@ -83,6 +83,7 @@ #include "conf.h" #include "magic.h" #include "stats.h" +#include "sys.h" #include "prof/prof.h" #include "fs/fs.h" #include "ios.h" diff --git a/include/ircd/sys.h b/include/ircd/sys.h new file mode 100644 index 000000000..f6027ed39 --- /dev/null +++ b/include/ircd/sys.h @@ -0,0 +1,168 @@ +// The Construct +// +// Copyright (C) The Construct Developers, Authors & Contributors +// Copyright (C) 2016-2020 Jason Volk +// +// 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_SYS_H + +namespace ircd::sys +{ + enum call :uint; + + template + long call(function&&, args&&...); + + template + long call(args&&... a); + + // sysfs read to buffer + string_view get(const mutable_buffer &out, const string_view &path); + + // sysfs read cast to type or defaults + template + R get(const string_view &path, const R &def = 0); + + extern log::log log; +} + +/// System call template options; changes behaviors. +enum ircd::sys::call +:uint +{ + NOTHROW = 0x01, + UNINTERRUPTIBLE = 0x02, +}; + +/// Return a lex_cast'able (an integer) from a sysfs target. +template +inline T +ircd::sys::get(const string_view &path, + const T &def) +{ + char buf[bufmax]; + const string_view val + { + get(buf, path) + }; + + return lex_castable(val)? + lex_cast(val): + def; +} + +/// This template requires a system call number in the parameters. The +/// arguments are only the actual arguments passed to the syscall because +/// the number is given in the template. +/// +template +inline long +ircd::sys::call(args&&... a) +{ + return call(::syscall, number, std::forward(a)...); +} + +/// Posix system call template to check for returned error value and throw the +/// approps errno in the proper std::system_error exception. Note the usage +/// here, the libc wrapper function is the first argument i.e: +/// syscall(::foo, bar, baz) not syscall(::foo(bar, baz)); +/// +/// when uninterruptible posix system call template; the syscall is +/// restarted until it no longer returns with EINTR. +/// +template +inline long +ircd::sys::call(function&& f, + args&&... a) +{ + constexpr auto uninterruptible + { + opts & call::UNINTERRUPTIBLE + }; + + long ret; do + { + ret = f(std::forward(a)...); + } + while(unlikely(uninterruptible && ret == -1 && errno == EINTR)); + + constexpr auto nothrow + { + opts & call::NOTHROW + }; + + if(unlikely(!nothrow && ret == -1L)) + throw std::system_error + { + errno, std::system_category() + }; + + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Legacy convenience forwarder interface +// +namespace ircd { + +template +inline auto +syscall(function&& f, + args&&... a) +{ + return sys::call(std::forward(f), std::forward(a)...); +} + +template +inline auto +syscall(args&&... a) +{ + return sys::call(std::forward(a)...); +} + +template +inline auto +syscall_nointr(function&& f, + args&&... a) +{ + constexpr enum sys::call opts + { + sys::call::UNINTERRUPTIBLE + }; + + return sys::call(std::forward(f), std::forward(a)...); +} + +template +inline auto +syscall_nointr(args&&... a) +{ + constexpr enum sys::call opts + { + sys::call::UNINTERRUPTIBLE + }; + + return sys::call(std::forward(a)...); +} + +} // namespace ircd diff --git a/include/ircd/util/util.h b/include/ircd/util/util.h index a67288580..eeb602fcb 100644 --- a/include/ircd/util/util.h +++ b/include/ircd/util/util.h @@ -39,7 +39,6 @@ namespace ircd #include "reentrance.h" #include "enum.h" #include "custom_ptr.h" -#include "syscall.h" #include "env.h" #include "va_rtti.h" #include "unique_iterator.h" diff --git a/ircd/Makefile.am b/ircd/Makefile.am index 0a77ba4c5..a7781ac15 100644 --- a/ircd/Makefile.am +++ b/ircd/Makefile.am @@ -169,6 +169,7 @@ endif if IOU libircd_la_SOURCES += fs_iou.cc endif +libircd_la_SOURCES += sys.cc libircd_la_SOURCES += mods.cc if LINUX libircd_la_SOURCES += mods_ldso.cc diff --git a/ircd/fs_dev.cc b/ircd/fs_dev.cc index 74971970c..107965c30 100644 --- a/ircd/fs_dev.cc +++ b/ircd/fs_dev.cc @@ -60,51 +60,16 @@ ircd::string_view ircd::fs::dev::sysfs(const mutable_buffer &out, const ulong &id, const string_view &relpath) -try { + thread_local char path_buf[1024]; const string_view path{fmt::sprintf { - path_scratch, "%s/%s/%s", - blk::BASE_PATH, + path_buf, "dev/block/%s/%s", sysfs_id(name_scratch, id), relpath }}; - fs::fd::opts fdopts; - fdopts.errlog = false; - const fs::fd fd - { - path, fdopts - }; - - fs::read_opts ropts; - ropts.aio = false; - string_view ret - { - fs::read(fd, out, ropts) - }; - - ret = rstrip(ret, '\n'); - ret = rstrip(ret, ' '); - return ret; -} -catch(const ctx::interrupted &) -{ - throw; -} -catch(const std::exception &e) -{ - #if 0 - log::derror - { - log, "sysfs query dev_id:%lu `%s' :%s", - id, - relpath, - e.what(), - }; - #endif - - return {}; + return sys::get(out, path); } ircd::string_view diff --git a/ircd/sys.cc b/ircd/sys.cc new file mode 100644 index 000000000..c5d8b0789 --- /dev/null +++ b/ircd/sys.cc @@ -0,0 +1,60 @@ +// The Construct +// +// Copyright (C) The Construct Developers, Authors & Contributors +// Copyright (C) 2016-2020 Jason Volk +// +// 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. + +decltype(ircd::sys::log) +ircd::sys::log +{ + "sys" +}; + +ircd::string_view +ircd::sys::get(const mutable_buffer &out, + const string_view &relpath) +try +{ + thread_local char buf[1024]; + string_view path(relpath); + path = lstrip(relpath, "/sys/"_sv); // tolerate any errant /sys/ prefix + path = strlcpy(buf, "/sys/"_sv); + path = strlcat(buf, relpath); + + fs::fd::opts fdopts; + fdopts.errlog = false; + const fs::fd fd + { + path, fdopts + }; + + string_view ret + { + data(out), sys::call(::read, fd, data(out), size(out)) + }; + + ret = rstrip(ret, '\n'); + ret = rstrip(ret, ' '); + return ret; +} +catch(const ctx::interrupted &) +{ + throw; +} +catch(const std::exception &e) +{ + #if 0 + log::derror + { + log, "sysfs query `%s' :%s", + relpath, + e.what(), + }; + #endif + + return {}; +}