| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef __CGROUPS_HPP__ |
| #define __CGROUPS_HPP__ |
| |
| #include <stdint.h> |
| #include <stdlib.h> |
| |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include <sys/types.h> |
| |
| #include <process/future.hpp> |
| #include <process/timeout.hpp> |
| |
| #include <stout/bytes.hpp> |
| #include <stout/duration.hpp> |
| #include <stout/hashmap.hpp> |
| #include <stout/nothing.hpp> |
| #include <stout/option.hpp> |
| #include <stout/try.hpp> |
| |
| namespace cgroups { |
| |
| // Freezing a cgroup may get stuck (see MESOS-1689 for details). To |
| // workaround, we may want to thaw the cgroup and retry freezing it. |
| // This is the suggested retry interval. |
| const Duration FREEZE_RETRY_INTERVAL = Seconds(10); |
| |
| |
| // Default number of assign attempts when moving threads to a cgroup. |
| const unsigned int THREAD_ASSIGN_RETRIES = 100; |
| |
| // We use the following notations throughout the cgroups code. The notations |
| // here are derived from the kernel documentation. More details can be found in |
| // <kernel-source>/Documentation/cgroups/cgroups.txt. |
| // |
| // Hierarchy - A hierarchy contains a set of cgroups arranged in a tree such |
| // that every task in the system is in exactly one of the cgroups |
| // in the hierarchy. One or more subsystems can be attached to a |
| // hierarchy. |
| // Subsystem - A subsystem (e.g. cpu, memory, cpuset, etc) in the kernel. Each |
| // subsystem can be attached to only one hierarchy. |
| // Cgroup - A cgroup is just a set of tasks with a set of controls for one |
| // or more subsystems. |
| // Control - A control file in a cgroup (e.g. tasks, cpu.shares). |
| |
| |
| // TODO(idownes): Rework all functions in this file to better support |
| // separately mounted subsystems. |
| |
| // Prepare a hierarchy which has the specified subsystem (and only that |
| // subsystem) mounted and also has the specified cgroup created. Returns the |
| // hierarchy. Checks are made to ensure that cgroups are supported and that |
| // nested cgroups can be created. |
| Try<std::string> prepare( |
| const std::string& baseHierarchy, |
| const std::string& subsystem, |
| const std::string& cgroup); |
| |
| |
| // Returns error if any of the following is true: |
| // (a) hierarchy is not mounted, |
| // (b) cgroup does not exist |
| // (c) control file does not exist. |
| Try<Nothing> verify( |
| const std::string& hierarchy, |
| const std::string& cgroup = "", |
| const std::string& control = ""); |
| |
| |
| // Check whether cgroups module is enabled on the current machine. |
| // @return True if cgroups module is enabled. |
| // False if cgroups module is not available. |
| bool enabled(); |
| |
| |
| // Return the currently active hierarchies. |
| // @return A set of active hierarchy paths (e.g., '/cgroup'). |
| // Error if unexpected happens. |
| Try<std::set<std::string>> hierarchies(); |
| |
| |
| // Get an already mounted hierarchy that has 'subsystems' attached. |
| // This function will return an error if we are unable to find the |
| // hierarchies or if we are unable to find if the subsystems are |
| // mounted at a given hierarchy. |
| // @param subsystems Comma-separated subsystem names. |
| // @return Path to the hierarchy root, if a hierarchy with all the |
| // given subsystems mounted exists. |
| // None, if no such hierarchy exists. |
| // Error, if the operation fails. |
| Result<std::string> hierarchy(const std::string& subsystems); |
| |
| |
| // Check whether all the given subsystems are enabled on the current machine. |
| // @param subsystems Comma-separated subsystem names. |
| // @return True if all the given subsystems are enabled. |
| // False if any of the given subsystems is not enabled. |
| // Error if something unexpected happens. |
| Try<bool> enabled(const std::string& subsystems); |
| |
| |
| // Return true if any of the given subsystems is currently attached to a |
| // hierarchy. |
| // @param subsystems Comma-separated subsystem names. |
| // @return True if any of the given subsystems is being attached. |
| // False if non of the given subsystems is being attached. |
| // Error if something unexpected happens. |
| Try<bool> busy(const std::string& subsystems); |
| |
| |
| // Return the currently enabled subsystems. |
| // @return A set of enabled subsystem names if succeeds. |
| // Error if unexpected happens. |
| Try<std::set<std::string>> subsystems(); |
| |
| |
| // Return a set of subsystems that are attached to a given hierarchy. An error |
| // will be returned if the given hierarchy is not currently mounted with a |
| // cgroups virtual file system. As a result, this function can be used to check |
| // whether a hierarchy is indeed a cgroups hierarchy root. |
| // @param hierarchy Path to the hierarchy root. |
| // @return A set of attached subsystem names. |
| // Error otherwise, (e.g., hierarchy does not exist or is not mounted). |
| Try<std::set<std::string>> subsystems(const std::string& hierarchy); |
| |
| |
| // Mount a cgroups hierarchy and attach the given subsystems to |
| // it. This function will return error if the path given for the |
| // hierarchy already exists. Also, the function will return error if |
| // a subsystem in the given subsystem list has already been attached |
| // to another hierarchy. On success, the cgroups virtual file system |
| // will be mounted with the proper subsystems attached. On failure, |
| // mount will be retried the specified number of times. |
| // @param hierarchy Path to the hierarchy root. |
| // @param subsystems Comma-separated subsystem names. |
| // @param retry Number of times to retry mount. |
| // @return Some if the operation succeeds. |
| // Error if the operation fails. |
| Try<Nothing> mount( |
| const std::string& hierarchy, |
| const std::string& subsystems, |
| int retry = 0); |
| |
| |
| // Unmount the cgroups virtual file system from the given hierarchy |
| // root. The caller must make sure to remove all cgroups in the |
| // hierarchy before unmount. This function assumes the given hierarchy |
| // is currently mounted with a cgroups virtual file system. It will |
| // return error if the given hierarchy has any cgroups. |
| // @param hierarchy Path to the hierarchy root. |
| // @return Some if the operation succeeds. |
| // Error if the operation fails. |
| Try<Nothing> unmount(const std::string& hierarchy); |
| |
| |
| // Returns true if the given hierarchy root is mounted as a cgroups |
| // virtual file system with the specified subsystems attached. |
| // @param hierarchy Path to the hierarchy root. |
| // @return True if the given directory is a hierarchy root and all of the |
| // specified subsystems are attached. |
| // False if the directory is not a hierarchy (or doesn't exist) |
| // or some of the specified subsystems are not attached. |
| // Error if the operation fails. |
| Try<bool> mounted( |
| const std::string& hierarchy, |
| const std::string& subsystems = ""); |
| |
| |
| // Create a cgroup in a given hierarchy. To create a cgroup, one just |
| // needs to create a directory in the cgroups virtual file system. The |
| // given cgroup is a relative path to the given hierarchy. This |
| // function assumes the given hierarchy is valid and is currently |
| // mounted with a cgroup virtual file system. The function also |
| // assumes the given cgroup is valid. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @param recursive Will create nested cgroups |
| // @return Some if the operation succeeds. |
| // Error if the operation fails. |
| Try<Nothing> create( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| bool recursive = false); |
| |
| |
| // Returns true if the given cgroup under a given hierarchy exists. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @return True if the cgroup exists. |
| // False if the cgroup does not exist. |
| bool exists(const std::string& hierarchy, const std::string& cgroup); |
| |
| |
| // Return all the cgroups under the given cgroup of a given hierarchy. |
| // By default, it returns all the cgroups under the given hierarchy. |
| // This function assumes that the given hierarchy and cgroup are |
| // valid. We use a post-order walk here to ease the removal of |
| // cgroups. |
| // @param hierarchy Path to the hierarchy root. |
| // @return A vector of cgroup names. |
| Try<std::vector<std::string>> get( |
| const std::string& hierarchy, |
| const std::string& cgroup = "/"); |
| |
| |
| // Send the specified signal to all process in a cgroup. This function |
| // assumes that the given hierarchy and cgroup are valid. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @param signal The signal to send to all tasks within the cgroup. |
| // @return Some on success. |
| // Error if something unexpected happens. |
| Try<Nothing> kill( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| int signal); |
| |
| |
| // Read a control file. Control files are the gateway to monitor and |
| // control cgroups. This function assumes the cgroups virtual file |
| // systems are properly mounted on the given hierarchy, and the given |
| // cgroup has been already created properly. The given control file |
| // name should also be valid. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @param control Name of the control file. |
| // @return The value read from the control file. |
| Try<std::string> read( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const std::string& control); |
| |
| |
| // Write a control file. This function assumes the cgroups virtual |
| // file systems are properly mounted on the given hierarchy, and the |
| // given cgroup has been already created properly. The given control |
| // file name should also be valid. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @param control Name of the control file. |
| // @param value Value to be written. |
| // @return Some if the operation succeeds. |
| // Error if the operation fails. |
| Try<Nothing> write( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const std::string& control, |
| const std::string& value); |
| |
| |
| // Check whether a control file is valid under a given cgroup and a |
| // given hierarchy. This function will return error if the given |
| // hierarchy is not properly mounted with appropriate subsystems, or |
| // the given cgroup does not exist, or the control file does not |
| // exist. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @param control Name of the control file. |
| // @return True if the check succeeds. |
| // False if the check fails. |
| bool exists( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const std::string& control); |
| |
| |
| // Return the set of process IDs in a given cgroup under a given |
| // hierarchy. It assumes the given hierarchy and cgroup are valid. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @return The set of process ids. |
| Try<std::set<pid_t>> processes( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| |
| // Return the set of thread IDs in a given cgroup under a given |
| // hierarchy. It assumes the given hierarchy and cgroup are valid. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @return The set of thread ids. |
| Try<std::set<pid_t>> threads( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| |
| // Assign a given process specified by its pid to a given cgroup. All |
| // threads in the pid's threadgroup will also be moved to the cgroup. |
| // This function assumes the given hierarchy and cgroup are valid. It |
| // will return error if the pid has no process associated with it. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @param pid The pid of the given process. |
| // @return Some if the operation succeeds. |
| // Error if the operation fails. |
| Try<Nothing> assign( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| pid_t pid); |
| |
| |
| // Isolate a given process specified by its 'pid' to a given cgroup by |
| // both creating the cgroup (recursively) if it doesn't exist and then |
| // assigning the process to that cgroup. It assumes the hierarchy is |
| // valid. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @param pid The pid of the given process. |
| // @return Nothing if the operation succeeds. |
| // Error if the operation fails. |
| Try<Nothing> isolate( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| pid_t pid); |
| |
| |
| namespace event { |
| |
| // Listen on an event notifier and return a future which will become |
| // ready when the certain event happens. This function assumes the |
| // given hierarchy, cgroup and control file are valid. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @param control Name of the control file. |
| // @param args Control specific arguments. |
| // @return A future which contains the value read from the file when ready. |
| // Error if something unexpected happens. |
| process::Future<uint64_t> listen( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const std::string& control, |
| const Option<std::string>& args = Option<std::string>::none()); |
| |
| } // namespace event { |
| |
| |
| // Destroy a cgroup under a given hierarchy. It will also recursively |
| // destroy any sub-cgroups. If the freezer subsystem is attached to |
| // the hierarchy, we attempt to kill all tasks in a given cgroup, |
| // before removing it. Otherwise, we just attempt to remove the |
| // cgroup. This function assumes the given hierarchy and cgroup are |
| // valid. It returns error if we failed to destroy any of the cgroups. |
| // NOTE: If cgroup is "/" (default), all cgroups under the |
| // hierarchy are destroyed. |
| // TODO(vinod): Add support for killing tasks when freezer subsystem |
| // is not present. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @return A future which will become ready when the operation is done. |
| // Error if something unexpected happens. |
| process::Future<Nothing> destroy( |
| const std::string& hierarchy, |
| const std::string& cgroup = "/"); |
| |
| |
| // Destroy a cgroup under a given hierarchy. This is a convenience |
| // function which wraps the cgroups::destroy() to add a timeout: if |
| // the cgroup(s) cannot be destroyed after timeout the operation will |
| // be discarded. |
| process::Future<Nothing> destroy( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const Duration& timeout); |
| |
| |
| // Cleanup the hierarchy, by first destroying all the underlying |
| // cgroups, unmounting the hierarchy and deleting the mount point. |
| // @param hierarchy Path to the hierarchy root. |
| // @return A future which will become ready when the operation is done. |
| // Error if something unexpected happens. |
| process::Future<bool> cleanup(const std::string& hierarchy); |
| |
| |
| // Returns the stat information from the given file. This function |
| // assumes the given hierarchy and cgroup are valid. |
| // @param hierarchy Path to the hierarchy root. |
| // @param cgroup Path to the cgroup relative to the hierarchy root. |
| // @param file The stat file to read from. (Ex: "memory.stat"). |
| // @return The stat information parsed from the file. |
| // Error if reading or parsing fails. |
| // TODO(bmahler): Consider namespacing stat for each subsystem (e.g. |
| // cgroups::memory::stat and cgroups::cpuacct::stat). |
| Try<hashmap<std::string, uint64_t>> stat( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| 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) {} |
| unsigned int getMajor() const; |
| unsigned int getMinor() const; |
| |
| 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, |
| DISCARD, |
| }; |
| |
| |
| // 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. This function |
| // assumes the given hierarchy and cgroup are valid. |
| 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. This function assumes the given |
| // hierarchy and cgroup are valid. |
| 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. This function assumes the given |
| // hierarchy and cgroup are valid. |
| 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. |
| // This function assumes the given hierarchy and cgroup are valid. |
| 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. This function assumes the |
| // given hierarchy and cgroup are valid. |
| 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. This function assumes the given |
| // hierarchy and cgroup are valid. |
| 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. This function assumes the given hierarchy |
| // and cgroup are valid. |
| 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. This function |
| // assumes the given hierarchy and cgroup are valid. |
| 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. This function assumes the given |
| // hierarchy and cgroup are valid. |
| 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. |
| // This function assumes the given hierarchy and cgroup are valid. |
| 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. |
| // This function assumes the given hierarchy and cgroup are valid. |
| 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. This function assumes |
| // the given hierarchy and cgroup are valid. |
| 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. This function |
| // assumes the given hierarchy and cgroup are valid. |
| 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. This function assumes the |
| // given hierarchy and cgroup are valid. |
| 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"; |
| case Operation::DISCARD: |
| return stream << "Discard"; |
| } |
| |
| 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 { |
| |
| // Returns the cgroup that the specified pid is a member of within the |
| // hierarchy that the 'cpu' 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); |
| |
| |
| // Sets the cpu shares using cpu.shares. This function assumes the |
| // given hierarchy and cgroup are valid. |
| Try<Nothing> shares( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| uint64_t shares); |
| |
| |
| // Returns the cpu shares from cpu.shares. This function assumes the |
| // given hierarchy and cgroup are valid. |
| Try<uint64_t> shares( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| |
| // Sets the cfs period using cpu.cfs_period_us. This function assumes |
| // the given hierarchy and cgroup are valid. |
| Try<Nothing> cfs_period_us( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const Duration& duration); |
| |
| |
| // Returns the cfs quota from cpu.cfs_quota_us. This function assumes |
| // the given hierarchy and cgroup are valid. |
| Try<Duration> cfs_quota_us( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| |
| // Sets the cfs quota using cpu.cfs_quota_us. This function assumes |
| // the given hierarchy and cgroup are valid. |
| Try<Nothing> cfs_quota_us( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const Duration& duration); |
| |
| } // namespace cpu { |
| |
| |
| // Cpuacct subsystem. |
| namespace cpuacct { |
| |
| // Returns the cgroup that the specified pid is a member of within the |
| // hierarchy that the 'cpuacct' subsytem is mounted or None if the |
| // subsystem is not mounted or the pid is not a member of a cgroup. |
| // |
| // @param pid process id for which cgroup is queried within the cpuacct |
| // subsytem. |
| // @return Some cgroup in case there was a valid cgroup found for the pid. |
| // Error if there was any error in processing. |
| Result<std::string> cgroup(pid_t pid); |
| |
| |
| // Encapsulates the 'stat' information exposed by the cpuacct subsystem. |
| struct Stats |
| { |
| const Duration user; |
| const Duration system; |
| }; |
| |
| |
| // Returns 'Stats' for a given hierarchy and cgroup. This function |
| // assumes the given hierarchy and cgroup are valid. |
| // |
| // @param hierarchy hierarchy for the 'cpuacct' subsystem. |
| // @param cgroup cgroup for a given process. |
| // @return Some<Stats> if successful. |
| // Error in case of any error during processing. |
| Try<Stats> stat( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| } // namespace cpuacct { |
| |
| |
| // Memory controls. |
| namespace memory { |
| |
| // Returns the cgroup that the specified pid is a member of within the |
| // hierarchy that the 'memory' subsytem 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); |
| |
| |
| // Returns the memory limit from memory.limit_in_bytes. This function |
| // assumes the given hierarchy and cgroup are valid. |
| Try<Bytes> limit_in_bytes( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| |
| // Sets the memory limit using memory.limit_in_bytes. This function |
| // assumes the given hierarchy and cgroup are valid. |
| Try<Nothing> limit_in_bytes( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const Bytes& limit); |
| |
| |
| // Returns the memory limit from memory.memsw.limit_in_bytes. Returns |
| // none if memory.memsw.limit_in_bytes is not supported (e.g., when |
| // swap is turned off). This function assumes the given hierarchy and |
| // cgroup are valid. |
| Result<Bytes> memsw_limit_in_bytes( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| |
| // Sets the memory limit using memory.memsw.limit_in_bytes. Returns |
| // false if memory.memsw.limit_in_bytes is not supported (e.g., when |
| // swap is turned off). This function assumes the given hierarchy and |
| // cgroup are valid. |
| Try<bool> memsw_limit_in_bytes( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const Bytes& limit); |
| |
| |
| // Returns the soft memory limit from memory.soft_limit_in_bytes. This |
| // function assumes the given hierarchy and cgroup are valid. |
| Try<Bytes> soft_limit_in_bytes( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| |
| // Sets the soft memory limit using memory.soft_limit_in_bytes. This |
| // function assumes the given hierarchy and cgroup are valid. |
| Try<Nothing> soft_limit_in_bytes( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const Bytes& limit); |
| |
| |
| // Returns the memory usage from memory.usage_in_bytes. This function |
| // assumes the given hierarchy and cgroup are valid. |
| Try<Bytes> usage_in_bytes( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| |
| // Returns the memory + swap usage from memory.memsw.usage_in_bytes. |
| // This function assumes the given hierarchy and cgroup are valid. |
| Try<Bytes> memsw_usage_in_bytes( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| |
| // Returns the max memory usage from memory.max_usage_in_bytes. This |
| // function assumes the given hierarchy and cgroup are valid. |
| Try<Bytes> max_usage_in_bytes( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| |
| // Out-of-memory (OOM) controls. |
| namespace oom { |
| |
| // Listen for an OOM event for the cgroup. This function assumes the |
| // given hierarchy and cgroup are valid. |
| process::Future<Nothing> listen( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| // OOM killer controls. |
| namespace killer { |
| |
| // Return whether the kernel OOM killer is enabled for the cgroup. |
| // This function assumes the given hierarchy and cgroup are valid. |
| Try<bool> enabled( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| // Enable the kernel OOM killer for the cgroup. The control file will |
| // only be written to if necessary. This function assumes the given |
| // hierarchy and cgroup are valid. |
| Try<Nothing> enable( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| // Disable the kernel OOM killer. The control file will only be |
| // written to if necessary. This function assumes the given hierarchy |
| // and cgroup are valid. |
| Try<Nothing> disable( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| } // namespace killer { |
| |
| } // namespace oom { |
| |
| |
| // Memory pressure counters. |
| namespace pressure { |
| |
| enum Level |
| { |
| LOW, |
| MEDIUM, |
| CRITICAL |
| }; |
| |
| |
| std::ostream& operator<<(std::ostream& stream, Level level); |
| |
| |
| // Forward declaration. |
| class CounterProcess; |
| |
| |
| // Counter is a primitive to listen on events of a given memory |
| // pressure level for a cgroup and keep track of the number of |
| // occurrence of that event. Use the public 'create' function to |
| // create a new counter; see 'value' for how to use. |
| class Counter |
| { |
| public: |
| // Create a memory pressure counter for the given cgroup on the |
| // specified level. This function assumes the given hierarchy and |
| // cgroup are valid. |
| static Try<process::Owned<Counter>> create( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| Level level); |
| |
| virtual ~Counter(); |
| |
| // Returns the current accumulated number of occurrences of the |
| // pressure event. Returns a failure if any error occurs while |
| // monitoring the pressure events, and any subsequent calls to |
| // 'value' will return the same failure. In such case, the user |
| // should consider creating a new Counter. |
| process::Future<uint64_t> value() const; |
| |
| private: |
| Counter(const std::string& hierarchy, |
| const std::string& cgroup, |
| Level level); |
| |
| process::Owned<CounterProcess> process; |
| }; |
| |
| } // namespace pressure { |
| |
| } // namespace memory { |
| |
| |
| // Device controls. |
| namespace devices { |
| |
| struct Entry |
| { |
| static Try<Entry> parse(const std::string& s); |
| |
| struct Selector |
| { |
| enum class Type |
| { |
| ALL, |
| BLOCK, |
| CHARACTER, |
| }; |
| |
| Type type; |
| Option<unsigned int> major; // Matches all `major` numbers if None. |
| Option<unsigned int> minor; // Matches all `minor` numbers if None. |
| }; |
| |
| struct Access |
| { |
| bool read; |
| bool write; |
| bool mknod; |
| }; |
| |
| Selector selector; |
| Access access; |
| }; |
| |
| std::ostream& operator<<( |
| std::ostream& stream, |
| const Entry::Selector::Type& type); |
| |
| std::ostream& operator<<( |
| std::ostream& stream, |
| const Entry::Selector& selector); |
| |
| std::ostream& operator<<( |
| std::ostream& stream, |
| const Entry::Access& access); |
| |
| std::ostream& operator<<( |
| std::ostream& stream, |
| const Entry& entry); |
| |
| |
| bool operator==( |
| const Entry::Selector& left, |
| const Entry::Selector& right); |
| |
| bool operator==( |
| const Entry::Access& left, |
| const Entry::Access& right); |
| |
| bool operator==( |
| const Entry& left, |
| const Entry& right); |
| |
| |
| // Returns the entries within devices.list. This function assumes the |
| // given hierarchy and cgroup are valid. |
| Try<std::vector<Entry>> list( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| // Writes the provided `entry` into devices.allow. This function |
| // assumes the given hierarchy and cgroup are valid. |
| Try<Nothing> allow( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const Entry& entry); |
| |
| // Writes the provided `entry` into devices.deny. This function |
| // assumes the given hierarchy and cgroup are valid. |
| Try<Nothing> deny( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const Entry& entry); |
| |
| } // namespace devices { |
| |
| |
| // Freezer controls. |
| // The freezer can be in one of three states: |
| // 1. THAWED : No process in the cgroup is frozen. |
| // 2. FREEZING : Freezing is in progress but not all processes are frozen. |
| // 3. FROZEN : All processes are frozen. |
| namespace freezer { |
| |
| // Freeze all processes in the given cgroup. This function will return |
| // a future which will become ready when all processes have been |
| // frozen (cgroup is in the FROZEN state). This function assumes the |
| // given hierarchy and cgroup are valid. |
| process::Future<Nothing> freeze( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| |
| // Thaw all processes in the given cgroup. This is a revert operation |
| // of freezer::freeze. This function will return a future which will |
| // become ready when all processes have been thawed (cgroup is in the |
| // THAWED state). This function assumes the given hierarchy and cgroup |
| // are valid. |
| process::Future<Nothing> thaw( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| } // namespace freezer { |
| |
| |
| // Net_cls subsystem. |
| namespace net_cls { |
| |
| // Read the uint32_t handle set in `net_cls.classid`. This function |
| // assumes the given hierarchy and cgroup are valid. |
| Try<uint32_t> classid( |
| const std::string& hierarchy, |
| const std::string& cgroup); |
| |
| |
| // Write the uint32_t handle to the `net_cls.classid`. This function |
| // assumes the given hierarchy and cgroup are valid. |
| Try<Nothing> classid( |
| const std::string& hierarchy, |
| const std::string& cgroup, |
| const uint32_t handle); |
| |
| } // namespace net_cls { |
| |
| |
| // Named hierarchy. |
| namespace named { |
| |
| // Returns the cgroup that the specified pid is a member of within the |
| // given named hierarchy is mounted or None if the named hierarchy is |
| // not mounted or the pid is not a member of a cgroup. |
| Result<std::string> cgroup(const std::string& hierarchyName, pid_t pid); |
| |
| } // namespace named { |
| |
| |
| } // namespace cgroups { |
| |
| namespace std { |
| |
| template <> |
| struct hash<cgroups::memory::pressure::Level> |
| { |
| typedef size_t result_type; |
| |
| typedef cgroups::memory::pressure::Level argument_type; |
| |
| result_type operator()(const argument_type& level) const |
| { |
| // Use the underlying type of the enum as hash value. |
| return static_cast<size_t>(level); |
| } |
| }; |
| |
| } // namespace std { |
| |
| #endif // __CGROUPS_HPP__ |