You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by gi...@apache.org on 2017/07/31 22:46:14 UTC
[3/5] mesos git commit: Added stats/control helpers for the Blkio
cgroup subsystem.
Added stats/control helpers for the Blkio cgroup subsystem.
- Data structure for Blkio entities
- Stats helpers for blkio.throttle.io* (generic blkio stats)
- Stats helpers for blkio.io* (CFQ related stats)
- Comments from the kernel blkio doc for helper functions
Review: https://reviews.apache.org/r/60933/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/1b89fb07
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/1b89fb07
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/1b89fb07
Branch: refs/heads/master
Commit: 1b89fb07419aa53cae661a1715b3258a8e75c140
Parents: 9ed6840
Author: Gilbert Song <so...@gmail.com>
Authored: Mon Jul 31 15:45:36 2017 -0700
Committer: Gilbert Song <so...@gmail.com>
Committed: Mon Jul 31 15:45:36 2017 -0700
----------------------------------------------------------------------
src/linux/cgroups.cpp | 345 +++++++++++++++++++++++++++++++++++++++++++++
src/linux/cgroups.hpp | 237 +++++++++++++++++++++++++++++++
2 files changed, 582 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/1b89fb07/src/linux/cgroups.cpp
----------------------------------------------------------------------
diff --git a/src/linux/cgroups.cpp b/src/linux/cgroups.cpp
index 334005a..28c31f6 100644
--- a/src/linux/cgroups.cpp
+++ b/src/linux/cgroups.cpp
@@ -1925,6 +1925,351 @@ Result<string> cgroup(pid_t pid, const string& subsystem)
} // namespace internal {
+namespace blkio {
+
+Result<string> cgroup(pid_t pid)
+{
+ return internal::cgroup(pid, "blkio");
+}
+
+
+Try<Device> Device::parse(const string& s)
+{
+ vector<string> device = strings::tokenize(s, ":");
+ if (device.size() != 2) {
+ return Error("Invalid major:minor device number: '" + s + "'");
+ }
+
+ Try<unsigned int> major = numify<unsigned int>(device[0]);
+ if (major.isError()) {
+ return Error("Invalid device major number: '" + device[0] + "'");
+ }
+
+ Try<unsigned int> minor = numify<unsigned int>(device[1]);
+ if (minor.isError()) {
+ return Error("Invalid device minor number: '" + device[1] + "'");
+ }
+
+ return Device(makedev(major.get(), minor.get()));
+}
+
+
+static bool isOperation(const string& s)
+{
+ return (s == "Total" ||
+ s == "Read" ||
+ s == "Write" ||
+ s == "Sync" ||
+ s == "Async");
+}
+
+
+static Try<Operation> parseOperation(const string& s)
+{
+ if (s == "Total") {
+ return Operation::TOTAL;
+ } else if (s == "Read") {
+ return Operation::READ;
+ } else if (s == "Write") {
+ return Operation::WRITE;
+ } else if (s == "Sync") {
+ return Operation::SYNC;
+ } else if (s == "Async") {
+ return Operation::ASYNC;
+ }
+
+ return Error("Invalid Operation value: '" + s + "'");
+}
+
+
+Try<Value> Value::parse(const string& s)
+{
+ vector<string> tokens = strings::tokenize(s, " ");
+ if (tokens.size() == 1) {
+ Try<uint64_t> value = numify<uint64_t>(tokens[0]);
+ if (value.isError()) {
+ return Error("Value is not a number: '" + tokens[0] + "'");
+ }
+
+ return Value{None(), None(), value.get()};
+ }
+
+ Option<Device> device;
+ int offset = 0;
+
+ if (tokens.size() == 3) {
+ Try<Device> dev = Device::parse(tokens[0]);
+ if (dev.isError()) {
+ return Error(dev.error());
+ }
+
+ device = dev.get();
+ offset++;
+ } else if (tokens.size() != 2) {
+ return Error("Invalid blkio value: '" + s + "'");
+ }
+
+ if (!isOperation(tokens[offset])) {
+ Try<Device> dev = Device::parse(tokens[offset]);
+ if (dev.isError()) {
+ return Error(dev.error());
+ }
+
+ Try<uint64_t> value = numify<uint64_t>(tokens[offset + 1]);
+ if (value.isError()) {
+ return Error("Value is not a number: '" + tokens[offset + 1] + "'");
+ }
+
+ return Value{dev.get(), None(), value.get()};
+ }
+
+ Try<Operation> operation = parseOperation(tokens[offset]);
+ if (operation.isError()) {
+ return Error(operation.error());
+ }
+
+ Try<uint64_t> value = numify<uint64_t>(tokens[offset + 1]);
+ if (value.isError()) {
+ return Error("Value is not a number: " + value.error());
+ }
+
+ return Value{device, operation.get(), value.get()};
+}
+
+
+static Try<vector<Value>> readEntries(
+ const string& hierarchy,
+ const string& cgroup,
+ const string& control)
+{
+ Try<string> read = cgroups::read(hierarchy, cgroup, control);
+ if (read.isError()) {
+ return Error("Failed to read from '" + control + "': " + read.error());
+ }
+
+ vector<Value> entries;
+
+ foreach (const string& s, strings::tokenize(read.get(), "\n")) {
+ Try<Value> value = Value::parse(s);
+ if (value.isError()) {
+ return Error("Failed to parse blkio value '" + s + "' from '" +
+ control + "': " + value.error());
+ }
+
+ entries.push_back(value.get());
+ }
+
+ return entries;
+}
+
+
+namespace cfq {
+
+Try<vector<Value>> time(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.time");
+}
+
+
+Try<vector<Value>> time_recursive(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.time_recursive");
+}
+
+
+Try<vector<Value>> sectors(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.sectors");
+}
+
+
+Try<vector<Value>> sectors_recursive(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.sectors_recursive");
+}
+
+
+Try<vector<Value>> io_merged(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.io_merged");
+}
+
+
+Try<vector<Value>> io_merged_recursive(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.io_merged_recursive");
+}
+
+
+Try<vector<Value>> io_queued(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.io_queued");
+}
+
+
+Try<vector<Value>> io_queued_recursive(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.io_queued_recursive");
+}
+
+
+Try<vector<Value>> io_service_bytes(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.io_service_bytes");
+}
+
+
+Try<vector<Value>> io_service_bytes_recursive(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.io_service_bytes_recursive");
+}
+
+
+Try<vector<Value>> io_service_time(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.io_service_time");
+}
+
+
+Try<vector<Value>> io_service_time_recursive(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.io_service_time_recursive");
+}
+
+
+Try<vector<Value>> io_serviced(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.io_serviced");
+}
+
+
+Try<vector<Value>> io_serviced_recursive(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.io_serviced_recursive");
+}
+
+
+Try<vector<Value>> io_wait_time(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.io_wait_time");
+}
+
+
+Try<vector<Value>> io_wait_time_recursive(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.io_wait_time_recursive");
+}
+
+} // namespace cfq {
+
+
+namespace throttle {
+
+Try<vector<Value>> io_service_bytes(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.throttle.io_service_bytes");
+}
+
+
+Try<vector<Value>> io_serviced(
+ const string& hierarchy,
+ const string& cgroup)
+{
+ return readEntries(
+ hierarchy,
+ cgroup,
+ "blkio.throttle.io_serviced");
+}
+
+} // namespace throttle {
+} // namespace blkio {
+
+
namespace cpu {
Result<string> cgroup(pid_t pid)
http://git-wip-us.apache.org/repos/asf/mesos/blob/1b89fb07/src/linux/cgroups.hpp
----------------------------------------------------------------------
diff --git a/src/linux/cgroups.hpp b/src/linux/cgroups.hpp
index eaf0dca..964543c 100644
--- a/src/linux/cgroups.hpp
+++ b/src/linux/cgroups.hpp
@@ -401,6 +401,243 @@ Try<hashmap<std::string, uint64_t>> stat(
const std::string& file);
+// Blkio subsystem.
+namespace blkio {
+
+// Returns the cgroup that the specified pid is a member of within the
+// hierarchy that the 'blkio' subsystem is mounted, or None if the subsystem
+// is not mounted or the pid is not a member of a cgroup.
+Result<std::string> cgroup(pid_t pid);
+
+
+// Wrapper class for dev_t.
+class Device
+{
+public:
+ constexpr Device(dev_t device) : value(device) {}
+ inline unsigned int getMajor() const { return major(value); }
+ inline unsigned int getMinor() const { return minor(value); }
+
+ inline bool operator==(const Device& that) const
+ {
+ return value == that.value;
+ }
+
+ inline bool operator!=(const Device& that) const
+ {
+ return value != that.value;
+ }
+
+ inline operator dev_t() const { return value; }
+
+public:
+ static Try<Device> parse(const std::string& s);
+
+private:
+ dev_t value;
+};
+
+
+enum class Operation {
+ TOTAL,
+ READ,
+ WRITE,
+ SYNC,
+ ASYNC,
+};
+
+
+// Entry for a blkio file. The format of each entry can either be:
+// 1. <value>
+// 2. <dev> <value>
+// 3. <dev> <op> <value>
+// 4. <op> <value>
+//
+// For details:
+// https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt
+struct Value
+{
+ Option<Device> device;
+ Option<Operation> op;
+ uint64_t value;
+
+ static Try<Value> parse(const std::string& s);
+};
+
+
+namespace cfq {
+
+Try<std::vector<Value>> time(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+Try<std::vector<Value>> time_recursive(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+Try<std::vector<Value>> sectors(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+Try<std::vector<Value>> sectors_recursive(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the total number of bios/requests merged into requests
+// belonging to the given cgroup from blkio.io_merged.
+Try<std::vector<Value>> io_merged(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the total number of bios/requests merged into requests
+// belonging to the given cgroup and all its descendants from
+// blkio.io_merged_recursive.
+Try<std::vector<Value>> io_merged_recursive(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the total number of requests queued up in the given
+// cgroup from blkio.io_queued.
+Try<std::vector<Value>> io_queued(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the total number of requests queued up in the given
+// cgroup and all its descendants from blkio.io_queued_recursive.
+Try<std::vector<Value>> io_queued_recursive(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the number of bytes transferred to/from the disk by
+// the given cgroup from blkio.io_service_bytes.
+Try<std::vector<Value>> io_service_bytes(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the number of bytes transferred to/from the disk by
+// the given cgroup and all its descendants from
+// blkio.io_service_bytes_recursive.
+Try<std::vector<Value>> io_service_bytes_recursive(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the total amount of time between request dispatch and
+// completion by the IOs done by the given cgroup from
+// blkio.io_service_time.
+Try<std::vector<Value>> io_service_time(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the total amount of time between request dispatch and
+// completion by the IOs done by the given cgroup and all its
+// descendants from blkio.io_service_time_recursive.
+Try<std::vector<Value>> io_service_time_recursive(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the number of IOs (bio) issued to the disk by the given
+// cgroup from blkio.io_serviced.
+Try<std::vector<Value>> io_serviced(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the number of IOs (bio) issued to the disk by the given
+// cgroup and all its descendants from blkio.io_serviced_recursive.
+Try<std::vector<Value>> io_serviced_recursive(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the total amount of time the IOs for the given cgroup
+// spent waiting in the schedule queues for service from
+// blkio.io_wait_time.
+Try<std::vector<Value>> io_wait_time(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the total amount of time the IOs for the given cgroup
+// and all its descendants spent waiting in the scheduler queues
+// for service from blkio.io_wait_time_recursive.
+Try<std::vector<Value>> io_wait_time_recursive(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+} // namespace cfq {
+
+
+namespace throttle {
+
+// Returns the numbers of bytes transferred to/from the disk for
+// the given cgroup from blkio.throttle.io_service_bytes.
+Try<std::vector<Value>> io_service_bytes(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+
+// Returns the numbers of IOs (bio) issued to the disk for the
+// given cgroup from blkio.throttle.io_serviced.
+Try<std::vector<Value>> io_serviced(
+ const std::string& hierarchy,
+ const std::string& cgroup);
+
+} // namespace throttle {
+
+
+inline std::ostream& operator<<(std::ostream& stream, const Device& device)
+{
+ return stream << device.getMajor() << ':' << device.getMinor();
+}
+
+
+inline std::ostream& operator<<(std::ostream& stream, const Operation op)
+{
+ switch (op) {
+ case Operation::TOTAL:
+ return stream << "Total";
+ case Operation::READ:
+ return stream << "Read";
+ case Operation::WRITE:
+ return stream << "Write";
+ case Operation::SYNC:
+ return stream << "Sync";
+ case Operation::ASYNC:
+ return stream << "Async";
+ }
+
+ UNREACHABLE();
+}
+
+
+inline std::ostream& operator<<(std::ostream& stream, const Value& value)
+{
+ if (value.device.isSome()) {
+ stream << value.device.get() << ' ';
+ }
+
+ if (value.op.isSome()) {
+ stream << value.op.get() << ' ';
+ }
+
+ return stream << value.value;
+}
+
+} // namespace blkio {
+
+
// Cpu controls.
namespace cpu {