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

ircd::fs::dev: Eliminate the static map; refactor interface; add console cmd.

This commit is contained in:
Jason Volk 2020-06-08 12:22:35 -07:00
parent 27d52c660b
commit bc3ad3f89c
5 changed files with 126 additions and 128 deletions

View file

@ -13,9 +13,9 @@
namespace ircd::fs::dev
{
struct init;
struct blkdev;
struct blk;
using major_minor = std::pair<ulong, ulong>;
using blk_closure = std::function<bool (const ulong &id, const blk &)>;
// 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<class T = size_t, size_t bufmax = 32> T sysfs(const ulong &id, const string_view &path, const T &def = 0);
extern std::map<major_minor, blkdev> block;
// Read data for a device lexical_cast'ed to type
template<class R = size_t,
size_t bufmax = 32>
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.

View file

@ -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_;

View file

@ -100,13 +100,17 @@ 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")
fs::dev::for_each("disk", []
(const ulong &id, const fs::dev::blk &device)
{
max_events._value = std::clamp
(
bd.queue_depth, size_t(max_events), MAX_EVENTS
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)
{

View file

@ -10,16 +10,16 @@
#include <RB_INC_SYS_SYSMACROS_H
decltype(ircd::fs::dev::block)
ircd::fs::dev::block;
//
// init
//
ircd::fs::dev::init::init()
bool
ircd::fs::dev::for_each(const blk_closure &closure)
{
return for_each(string_view{}, closure);
}
bool
ircd::fs::dev::for_each(const string_view &type,
const blk_closure &closure)
{
#ifdef __linux__
for(const auto &dir : fs::ls("/sys/dev/block")) try
{
const auto &[major, minor]
@ -27,62 +27,35 @@ ircd::fs::dev::init::init()
split(filename(path_scratch, dir), ':')
};
const major_minor device_major_minor
const ulong id
{
lex_cast<ulong>(major), lex_cast<ulong>(minor)
dev::id({lex_cast<ulong>(major), lex_cast<ulong>(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<bool>(id, "queue/rotational", true)
sysfs<bool>(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;
}

View file

@ -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)
{