0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-02 10:08:56 +02:00

ircd::fs::dev: Add block device information system w/ sysfs.

This commit is contained in:
Jason Volk 2020-06-06 23:26:28 -07:00
parent 680c29601e
commit 22eb9b514b
3 changed files with 187 additions and 0 deletions

View file

@ -13,6 +13,8 @@
namespace ircd::fs::dev
{
struct init;
struct blkdev;
using major_minor = std::pair<ulong, ulong>;
// Convert device ID's with the major(3) / minor(3) / makedev(3)
@ -26,8 +28,33 @@ 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);
extern std::map<major_minor, blkdev> block;
}
struct ircd::fs::dev::blkdev
{
bool is_device {false};
bool is_queue {false};
std::string type;
std::string vendor;
std::string model;
std::string rev;
size_t size {0};
size_t queue_depth {0};
size_t nr_requests {0};
bool rotational {false};
blkdev(const ulong &id);
blkdev() = default;
};
struct ircd::fs::dev::init
{
init();
~init() noexcept;
};
/// Return a lex_cast'able (an integer) from a sysfs target.
template<class T,
size_t bufmax>

View file

@ -78,6 +78,7 @@ 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

@ -10,6 +10,69 @@
#include <RB_INC_SYS_SYSMACROS_H
decltype(ircd::fs::dev::block)
ircd::fs::dev::block;
//
// init
//
ircd::fs::dev::init::init()
{
#ifdef __linux__
for(const auto &dir : fs::ls("/sys/dev/block"))
{
const auto &[major, minor]
{
split(filename(path_scratch, dir), ':')
};
const major_minor device_major_minor
{
lex_cast<ulong>(major), lex_cast<ulong>(minor)
};
const auto iit
{
block.emplace(device_major_minor, id(device_major_minor))
};
assert(iit.second);
const auto &bd(iit.first->second);
if(!bd.is_device || bd.type != "disk")
block.erase(iit.first);
}
#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,
};
}
}
ircd::fs::dev::init::~init()
noexcept
{
}
//
// fs::dev
//
#ifdef __linux__
ircd::string_view
ircd::fs::dev::sysfs(const mutable_buffer &out,
@ -78,3 +141,99 @@ ircd::fs::dev::id(const ulong &id)
major(id), minor(id)
};
}
//
// dev::device
//
ircd::fs::dev::blkdev::blkdev(const ulong &id)
:is_device
{
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]
(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;
})
}
,vendor
{
!is_device? std::string{}:
ircd::string(12, [&id]
(const mutable_buffer &buf)
{
return sysfs(buf, id, "device/vendor");
})
}
,model
{
!is_device? std::string{}:
ircd::string(64, [&id]
(const mutable_buffer &buf)
{
return sysfs(buf, id, "device/model");
})
}
,rev
{
!is_device? std::string{}:
ircd::string(12, [&id]
(const mutable_buffer &buf)
{
return sysfs(buf, id, "device/rev");
})
}
,size
{
sysfs(id, "size")
}
,queue_depth
{
is_device?
sysfs(id, "device/queue_depth"):
0UL
}
,nr_requests
{
is_queue?
sysfs(id, "queue/nr_requests"):
0UL
}
,rotational
{
is_queue?
sysfs<bool>(id, "queue/rotational"):
true
}
{
}