blob: 65f0958e150e83a784073cb00ec6f6a04a3bfa26 [file] [log] [blame]
/**
* 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 <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 {
// Default number of retry attempts when trying to freeze a cgroup.
const unsigned int FREEZE_RETRIES = 50;
const unsigned int EMPTY_WATCHER_RETRIES = 50;
// 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);
// 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 a hierarchy and remove the directory associated with
// it. This function will return error if the given hierarchy is not
// valid. Also, 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 under a given hierarchy. This function will return error if
// the given hierarchy is not valid. The cgroup will NOT be created recursively.
// In other words, if the parent cgroup does not exist, this function will just
// return error.
// @param hierarchy Path to the hierarchy root.
// @param cgroup Path to the cgroup relative to the hierarchy root.
// @return Some if the operation succeeds.
// Error if the operation fails.
Try<Nothing> create(const std::string& hierarchy, const std::string& cgroup);
// Remove a cgroup under a given hierarchy. This function will return error if
// the given hierarchy or the given cgroup is not valid. The cgroup will NOT be
// removed recursively. In other words, if the cgroup has sub-cgroups inside,
// the function will return error. Also, if any process is attached to the
// given cgroup, the removal operation will also fail.
// @param hierarchy Path to the hierarchy root.
// @param cgroup Path to the cgroup relative to the hierarchy root.
Try<Nothing> remove(const std::string& hierarchy, const std::string& cgroup);
// 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.
// Error if the operation fails (i.e., hierarchy is not mounted).
Try<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
// will return error if the given hierarchy is not mounted or the cgroup does
// not exist. 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.
// @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 used to monitor and control cgroups.
// This function will verify all the parameters. If the given hierarchy is not
// properly mounted with appropriate subsystems, or the given cgroup is not
// valid, or the given control file is not valid, the function will return
// error.
// @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. Parameter checking is similar to read.
// @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 Some if the check succeeds.
// Error if the check fails.
Try<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
// will return error if the given hierarchy or the given cgroup is not 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);
// Assign a given process specified by its pid to a given cgroup. This function
// will return error if the given hierarchy or the given cgroup is not valid.
// Also, 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);
// Listen on an event notifier and return a future which will become ready when
// the certain event happens. This function will return a future failure if some
// expected happens (e.g. the given hierarchy does not have the proper
// subsystems attached).
// @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());
// Freeze all the processes in a given cgroup. We try to use the freezer
// subsystem implemented in cgroups. More detail can be found in
// <kernel-source>/Documentation/cgroups/freezer-subsystem.txt. This function
// will return a future which will become ready when all the processes have been
// frozen (FROZEN). The future can be discarded to cancel the operation. The
// freezer state after the cancellation is not defined. So the users need to
// read the control file if they need to know the freezer state after the
// cancellation. This function will return future failure if the freezer
// subsystem is not available or it is not attached to the given hierarchy, or
// the given cgroup is not valid, or the given cgroup has already been frozen.
// @param hierarchy Path to the hierarchy root.
// @param cgroup Path to the cgroup relative to the hierarchy root.
// @param interval The time interval between two state check
// requests (default: 0.1 seconds).
// @param retries Number of retry attempts before giving up. None
// indicates infinite retries. (default: 50 attempts).
// @return A future which will become true when all processes are frozen, or
// false when all retries have occurred unsuccessfully.
// Error if something unexpected happens.
process::Future<bool> freeze(
const std::string& hierarchy,
const std::string& cgroup,
const Duration& interval = Milliseconds(100),
const unsigned int retries = FREEZE_RETRIES);
// Thaw the given cgroup. This is a revert operation of freezeCgroup. It will
// return error if the given cgroup is already thawed. Same as
// freezeCgroup, this function will return a future which can be discarded to
// allow users to cancel the operation.
// @param hierarchy Path to the hierarchy root.
// @param cgroup Path to the cgroup relative to the hierarchy root.
// @param interval The time interval between two state check
// requests (default: 0.1 seconds).
// @return A future which will become ready when all processes are thawed.
// Error if something unexpected happens.
process::Future<bool> thaw(
const std::string& hierarchy,
const std::string& cgroup,
const Duration& interval = Milliseconds(100));
// 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 will return an error if the given hierarchy
// or the given cgroup does not exist or 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.
// @param interval The time interval between two state check
// requests (default: 0.1 seconds).
// @return A future which will become ready when the operation is done.
// Error if something unexpected happens.
process::Future<bool> destroy(
const std::string& hierarchy,
const std::string& cgroup = "/",
const Duration& interval = Milliseconds(100));
// 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.
// @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);
// Cpu controls.
namespace cpu {
// Sets the cpu shares using cpu.shares.
Try<Nothing> shares(
const std::string& hierarchy,
const std::string& cgroup,
size_t shares);
// Sets the cfs period using cpu.cfs_period_us.
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.
Try<Duration> cfs_quota_us(
const std::string& hierarchy,
const std::string& cgroup);
// Sets the cfs quota using cpu.cfs_quota_us.
Try<Nothing> cfs_quota_us(
const std::string& hierarchy,
const std::string& cgroup,
const Duration& duration);
} // namespace cpu {
// Memory controls.
namespace memory {
// Returns the memory limit from memory.limit_in_bytes.
Try<Bytes> limit_in_bytes(
const std::string& hierarchy,
const std::string& cgroup);
// Sets the memory limit using memory.limit_in_bytes.
Try<Nothing> 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.
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.
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.
Try<Bytes> usage_in_bytes(
const std::string& hierarchy,
const std::string& cgroup);
// Returns the max memory usage from memory.max_usage_in_bytes.
Try<Bytes> max_usage_in_bytes(
const std::string& hierarchy,
const std::string& cgroup);
} // namespace memory {
} // namespace cgroups {
#endif // __CGROUPS_HPP__