diff --git a/include/ircd/fs/dev.h b/include/ircd/fs/dev.h index cc54b7852..5064cb9eb 100644 --- a/include/ircd/fs/dev.h +++ b/include/ircd/fs/dev.h @@ -13,9 +13,9 @@ namespace ircd::fs::dev { - struct init; - struct blkdev; + struct blk; using major_minor = std::pair; + using blk_closure = std::function; // Convert device ID's with the major(3) / minor(3) / makedev(3) ulong id(const major_minor &); @@ -27,15 +27,23 @@ namespace ircd::fs::dev // Read data for a device from sysfs; path is relative to /sys/dev/block/$id/... string_view sysfs(const mutable_buffer &out, const ulong &id, const string_view &path); - template T sysfs(const ulong &id, const string_view &path, const T &def = 0); - extern std::map block; + // Read data for a device lexical_cast'ed to type + template + R + sysfs(const ulong &id, + const string_view &path, + const R &def = 0); + + bool for_each(const string_view &devtype, const blk_closure &); + bool for_each(const blk_closure &); } -struct ircd::fs::dev::blkdev +struct ircd::fs::dev::blk { - bool is_device {false}; - bool is_queue {false}; + static string_view devtype(const mutable_buffer &, const ulong &id); + std::string type; std::string vendor; std::string model; @@ -45,14 +53,8 @@ struct ircd::fs::dev::blkdev size_t nr_requests {0}; bool rotational {false}; - blkdev(const ulong &id); - blkdev() = default; -}; - -struct ircd::fs::dev::init -{ - init(); - ~init() noexcept; + blk(const ulong &id); + blk() = default; }; /// Return a lex_cast'able (an integer) from a sysfs target. diff --git a/include/ircd/fs/fs.h b/include/ircd/fs/fs.h index 42a8e894d..c45da294d 100644 --- a/include/ircd/fs/fs.h +++ b/include/ircd/fs/fs.h @@ -78,7 +78,6 @@ namespace ircd::fs /// Filesystem interface init / fini held by ircd::main(). struct ircd::fs::init { - dev::init _dev_; iou::init _iou_; aio::init _aio_; diff --git a/ircd/fs_aio.cc b/ircd/fs_aio.cc index dd70c0aae..b464f4272 100644 --- a/ircd/fs_aio.cc +++ b/ircd/fs_aio.cc @@ -100,12 +100,16 @@ ircd::fs::aio::init::init() // tune to it. The caveat here is that if the application makes heavy use // of an inferior device on the same system, it wont be optimally utilized. if(max_events == 0UL) - for(const auto &[mm, bd] : fs::dev::block) - if(bd.is_device && bd.type == "disk") - max_events._value = std::clamp - ( - bd.queue_depth, size_t(max_events), MAX_EVENTS - ); + fs::dev::for_each("disk", [] + (const ulong &id, const fs::dev::blk &device) + { + max_events._value = std::clamp + ( + device.queue_depth, size_t(max_events), MAX_EVENTS + ); + + return true; + }); // If max_events is still not determined here set a sane default. if(max_events == 0UL) diff --git a/ircd/fs_dev.cc b/ircd/fs_dev.cc index e71c9629e..662c29f0d 100644 --- a/ircd/fs_dev.cc +++ b/ircd/fs_dev.cc @@ -10,16 +10,16 @@ #include (major), lex_cast(minor) + dev::id({lex_cast(major), lex_cast(minor)}) }; - const auto iit - { - block.emplace(device_major_minor, id(device_major_minor)) - }; + char dtbuf[32]; + if(type && blk::devtype(dtbuf, id) != type) + continue; - assert(iit.second); - const auto &bd(iit.first->second); - if(!bd.is_device || bd.type != "disk") - block.erase(iit.first); + if(!closure(id, blk(id))) + return false; + } + catch(const ctx::interrupted &) + { + throw; } catch(const std::exception &e) { - log::derror + log::error { log, "%s :%s", dir, e.what(), }; } - #endif - - for(const auto &[mm, bd] : block) - { - char pbuf[48]; - log::info - { - log, "%s %u:%2u %s %s %s %s queue depth:%zu requests:%zu", - bd.type, - std::get<0>(mm), - std::get<1>(mm), - bd.vendor, - bd.model, - bd.rev, - pretty(pbuf, iec(bd.size)), - bd.queue_depth, - bd.nr_requests, - }; - } + return true; } -ircd::fs::dev::init::~init() -noexcept -{ -} - -// -// fs::dev -// - -#ifdef __linux__ ircd::string_view ircd::fs::dev::sysfs(const mutable_buffer &out, const ulong &id, @@ -96,11 +69,18 @@ try relpath }}; - fs::read_opts opts; - opts.aio = false; + 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(path, out, opts) + fs::read(fd, out, ropts) }; ret = rstrip(ret, '\n'); @@ -113,6 +93,7 @@ catch(const ctx::interrupted &) } catch(const std::exception &e) { + #if 0 log::derror { log, "sysfs query dev_id:%lu `%s' :%s", @@ -120,21 +101,10 @@ catch(const std::exception &e) relpath, e.what(), }; + #endif return {}; } -#else -ircd::string_view -ircd::fs::dev::sysfs(const mutable_buffer &out, - const ulong &id, - const string_view &relpath) -{ - throw panic - { - "sysfs(5) is not available." - }; -} -#endif ircd::string_view ircd::fs::dev::sysfs_id(const mutable_buffer &out, @@ -169,53 +139,21 @@ ircd::fs::dev::id(const ulong &id) } // -// dev::device +// dev::blk // -ircd::fs::dev::blkdev::blkdev(const ulong &id) -:is_device +ircd::fs::dev::blk::blk(const ulong &id) +:type { - fs::is_dir(fmt::sprintf - { - path_scratch, "/sys/dev/block/%s/device", - sysfs_id(name_scratch, id), - }) -} -,is_queue -{ - fs::is_dir(fmt::sprintf - { - path_scratch, "/sys/dev/block/%s/queue", - sysfs_id(name_scratch, id), - }) -} -,type -{ - !is_device? std::string{}: - ircd::string(8, [&id] + ircd::string(15, [&id] (const mutable_buffer &buf) { - char tmp[128]; - string_view ret; - tokens(sysfs(tmp, id, "uevent"), '\n', [&buf, &ret] - (const string_view &kv) - { - const auto &[key, value] - { - split(kv, '=') - }; - - if(key == "DEVTYPE") - ret = strlcpy(buf, value); - }); - - return ret; + return devtype(buf, id); }) } ,vendor { - !is_device? std::string{}: - ircd::string(12, [&id] + ircd::string(15, [&id] (const mutable_buffer &buf) { return sysfs(buf, id, "device/vendor"); @@ -223,7 +161,6 @@ ircd::fs::dev::blkdev::blkdev(const ulong &id) } ,model { - !is_device? std::string{}: ircd::string(64, [&id] (const mutable_buffer &buf) { @@ -232,8 +169,7 @@ ircd::fs::dev::blkdev::blkdev(const ulong &id) } ,rev { - !is_device? std::string{}: - ircd::string(12, [&id] + ircd::string(15, [&id] (const mutable_buffer &buf) { return sysfs(buf, id, "device/rev"); @@ -253,7 +189,28 @@ ircd::fs::dev::blkdev::blkdev(const ulong &id) } ,rotational { - sysfs(id, "queue/rotational", true) + sysfs(id, "queue/rotational", false) } { } + +ircd::string_view +ircd::fs::dev::blk::devtype(const mutable_buffer &buf, + const ulong &id) +{ + char tmp[128]; + string_view ret; + tokens(sysfs(tmp, id, "uevent"), '\n', [&buf, &ret] + (const string_view &kv) + { + const auto &[key, value] + { + split(kv, '=') + }; + + if(key == "DEVTYPE") + ret = strlcpy(buf, value); + }); + + return ret; +} diff --git a/modules/console.cc b/modules/console.cc index 3a3660f5c..2f8b50a97 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -913,6 +913,42 @@ console_cmd__fs__ls(opt &out, const string_view &line) return true; } +bool +console_cmd__fs__dev(opt &out, const string_view &line) +{ + const params param{line, " ", + { + "type" + }}; + + const string_view type + { + param["type"] + }; + + fs::dev::for_each(type, [&out] + (const ulong &id, const fs::dev::blk &dev) + { + const auto mm(fs::dev::id(id)); + char pbuf[48]; + out + << std::setw(16) << dev.type << ' ' + << std::setw(3) << std::right << std::get<0>(mm) << ':' + << std::setw(3) << std::left << std::get<1>(mm) << ' ' + << std::setw(16) << dev.vendor << ' ' + << std::setw(20) << dev.model << ' ' + << std::setw(10) << dev.rev << ' ' + << "qd:" << std::setw(3) << dev.queue_depth << ' ' + << "nr:" << std::setw(3) << dev.nr_requests << ' ' + << pretty(pbuf, iec(dev.size)) << ' ' + << std::endl; + return true; + }); + + return true; +} + + bool console_cmd__ls(opt &out, const string_view &line) {