1
0
mirror of https://github.com/ARM-software/devlib.git synced 2025-01-31 02:00:45 +00:00

cgroups: add support for multi-controller hierarchies

Some systems mount multiple CGroup controllers in the same hierarchy, this
happens in desktop systems using systemd but it's also the default for
systems using CGroups v2. Unfortunately the current CGroup modules can
mount only single-controller hierarchies, thus failing when a controller
is already mounted with others in a single hierarchy.

This patch fixes this issue by:
- keeping track of which controllers are mounted in each hierarchy
- muting hierarchies instead of controllers
- creating Controller objects which reference the hierarchy they belong to

Thus, the new constructor of the Controller object requires to specify
the hierarchy ID as well as the list of controller which have to be
mounted in that hierarchy. The hierarchy ID is used to create a single
mount point for all the controllers in that hierarchy. This single mount
points are now named:
  <CGMOUNT>/devlib_cgh<ID>
where "cgh" stands for "CGroup Hierarchy" and <ID> is the specified
numerical identified of that hierarchy.

This patch removes also the Controller::__new__() method, which seems not to
have sense anymore, as well as the Controller::probe() method, which is
not more used. Indeed, all and only the available hierarchies are pre-mounted
at module initialization time.



Signed-off-by: Patrick Bellasi <patrick.bellasi@arm.com>
This commit is contained in:
Patrick Bellasi 2016-11-29 10:39:28 +00:00
parent 103f792736
commit b569a561a4

View File

@ -24,30 +24,33 @@ from devlib.utils.types import boolean
class Controller(object): class Controller(object):
def __new__(cls, arg): def __init__(self, kind, hid, clist):
if isinstance(arg, cls): """
return arg Initialize a controller given the hierarchy it belongs to.
else:
return object.__new__(cls, arg)
def __init__(self, kind): :param kind: the name of the controller
self.mount_name = 'devlib_'+kind :type kind: str
:param hid: the Hierarchy ID this controller is mounted on
:type hid: int
:param clist: the list of controller mounted in the same hierarchy
:type clist: list(str)
"""
self.mount_name = 'devlib_cgh{}'.format(hid)
self.kind = kind self.kind = kind
self.hid = hid
self.clist = clist
self.target = None self.target = None
self._noprefix = False self._noprefix = False
self.logger = logging.getLogger('cgroups.'+self.kind) self.logger = logging.getLogger('CGroup.'+self.kind)
self.logger.debug('Initialized [%s, %d, %s]',
self.kind, self.hid, self.clist)
self.mount_point = None self.mount_point = None
self._cgroups = {} self._cgroups = {}
def probe(self, target):
try:
exists = target.execute('{} grep {} /proc/cgroups'\
.format(target.busybox, self.kind))
except TargetError:
return False
return True
def mount(self, target, mount_root): def mount(self, target, mount_root):
mounted = target.list_file_systems() mounted = target.list_file_systems()
@ -64,7 +67,7 @@ class Controller(object):
target.execute('mkdir -p {} 2>/dev/null'\ target.execute('mkdir -p {} 2>/dev/null'\
.format(self.mount_point), as_root=True) .format(self.mount_point), as_root=True)
target.execute('mount -t cgroup -o {} {} {}'\ target.execute('mount -t cgroup -o {} {} {}'\
.format(self.kind, .format(','.join(self.clist),
self.mount_name, self.mount_name,
self.mount_point), self.mount_point),
as_root=True) as_root=True)
@ -324,20 +327,28 @@ class CgroupsModule(Module):
self.logger.warning('No CGroups controller available') self.logger.warning('No CGroups controller available')
return return
# Map hierarchy IDs into a list of controllers
hierarchy = {}
for ss in subsys:
try:
hierarchy[ss.hierarchy].append(ss.name)
except KeyError:
hierarchy[ss.hierarchy] = [ss.name]
self.logger.debug('Available hierarchies: %s', hierarchy)
# Initialize controllers # Initialize controllers
self.logger.info('Available controllers:') self.logger.info('Available controllers:')
self.controllers = {} self.controllers = {}
for ss in subsys: for ss in subsys:
controller = Controller(ss.name) hid = ss.hierarchy
self.logger.debug('Init %s controller...', controller.kind) controller = Controller(ss.name, hid, hierarchy[hid])
if not controller.probe(self.target):
continue
try: try:
controller.mount(self.target, self.cgroup_root) controller.mount(self.target, self.cgroup_root)
except TargetError: except TargetError:
message = 'cgroups {} controller is not supported by the target' message = 'Failed to mount "{}" controller'
raise TargetError(message.format(controller.kind)) raise TargetError(message.format(controller.kind))
self.logger.debug('Controller %s enabled', controller.kind) self.logger.info(' %-12s : %s', controller.kind,
controller.mount_point)
self.controllers[ss.name] = controller self.controllers[ss.name] = controller
def list_subsystems(self): def list_subsystems(self):