Josh Soref abce91d14b
Spelling (#12954)
* link: Collect WSL logs (recommended method)

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: Advanced Authoring Tests in C++

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: CMake Documentation and Community

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: Collect WSL logs for networking issues

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: Collect WSL logs (recommended method)

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: ; otherwise,

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: a

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: access

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: accessible

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: across

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: actively

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: adapters

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: address

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: addresses

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: and

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: appropriate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: argument

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: associated

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: attach

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: available

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: beginning

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: between

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: binaries

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: bound

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: buffer

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: buffers

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: cannot

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: canonical

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: capabilities

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: case-insensitive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: case-sensitive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: certified

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: command

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: committer

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: communication

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: complains

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: configuration

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: consumed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: continue

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: converted

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: currently

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: customers

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: daemon

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: deferred

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: definitions

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: delimiter

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: delivered

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: dellink

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: derived

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: descriptor

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destined

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destruct

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destructible

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destructor

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: detach

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: differentiate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: directories

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: disassociate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: disposition

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: distribution

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: distro

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: duping

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: emitted

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: empty

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: environment

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: every time

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: exclusive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: expected

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: expire

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: explicitly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: fall back

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: false

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: fastfail

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: filesystem

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: first

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: followed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: for

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: functionality

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: functionally

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: github

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: greater

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: guarantee

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: guaranteed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: handles

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hangup

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hierarchy

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hogwarts

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hydrated

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: icrnl

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: implementation

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: implementing

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: initialize

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: instance

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: instantiate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: instantiations

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: intentionally

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: interpret

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: interpreter

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: irreversibly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: iteration

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: iterator

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: its

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: kernel

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: kmsg

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: knowledge

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: maximum

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: mirrored

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: msftconnecttest

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: multi

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: multiple

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: mutable

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: namespace

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: nonexistent

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: notifications

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: occurred

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: occurring

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: otherwise,

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: outstanding

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: overridden

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: partition

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: pass through

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: passthrough

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: performs

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: periodically

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: positional

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: precedence

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: preexisting

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: preferring

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: prepopulate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: previous

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: privileges

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: process

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: processes

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: programmatically

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: protection

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: provided

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: reasonable

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: receive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: received

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: red hat

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: reentrant

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: registered

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: regularly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: relay

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: release

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: representing

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: requests

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: response

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: resurrect

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: retention

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: returned

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: security

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: semaphore

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: separate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: separator

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: service

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: set up

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: setup

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: severely

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: should

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: signal

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: similarly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: simple

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: simplified

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: single

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: specified

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: splitting

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: standard

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: stress

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: succeed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: success

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: successfully

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: supplementary

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: synced

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: system

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: take

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: than

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: that opening

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: the

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: threadpool

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: to

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: true

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: truncate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: tunneling

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unexpected

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: uninitialize

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unique

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unprivileged

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unregistered

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: untrusted

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: upgrade

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: utility

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: validating

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: variant

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: variation

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: variations

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: verify

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: visible

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: whether

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: winget

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: worker

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: written

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: wslservice

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* format source

---------

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
Co-authored-by: Ben Hillis <benhillis@gmail.com>
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
2025-07-23 15:19:00 -07:00

1101 lines
29 KiB
C

/*++
Copyright (c) Microsoft. All rights reserved.
Module Name:
cgroup.c
Abstract:
This file contains unit tests for cgroup support.
N.B. This test depends on libmount, which is part of the libmount-dev
apt package.
N.B. To pass on native Linux this test requires cgroups to not be managed by
an OS daemon. cgclear can be used to remove some subsystems.
--*/
#include "lxtcommon.h"
#include "unittests.h"
#include <sys/mount.h>
#include <linux/capability.h>
#include <libgen.h>
#include <fcntl.h>
#include <stdlib.h>
#include <libmount/libmount.h>
#include <sys/mman.h>
#include "lxtmount.h"
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#define LXT_NAME "cgroup"
#define CGROUP_TEST_PATH "/data"
#define CGROUP_TEST_MOUNT_NAME "cgroup"
#define CGROUP_TEST_MOUNT_POINT_NAME "cgroup_mount_test"
#define CGROUP_TEST_MOUNT_POINT CGROUP_TEST_PATH "/" CGROUP_TEST_MOUNT_POINT_NAME
#define CGROUP_TEST_MOUNT_POINT2 "/sys/fs/cgroup"
#define CGROUP_TEST_MOUNT_POINT_DIR1_NAME "dir1"
#define CGROUP_TEST_MOUNT_POINT_DIR1 CGROUP_TEST_MOUNT_POINT "/" CGROUP_TEST_MOUNT_POINT_DIR1_NAME
#define CGROUP_TEST_MOUNT_POINT2_DIR1 CGROUP_TEST_MOUNT_POINT2 "/" CGROUP_TEST_MOUNT_POINT_DIR1_NAME
#define CGROUP_TEST_MOUNT_POINT_DIR1_CHILD_NAME "child"
#define CGROUP_TEST_MOUNT_POINT_DIR1_CHILD CGROUP_TEST_MOUNT_POINT_DIR1 "/" CGROUP_TEST_MOUNT_POINT_DIR1_CHILD_NAME
#define CGROUP_TEST_DEFAULT_BUFFER_SIZE 128
#define CGROUP_TEST_MAX_CGROUPS 12
#define CGROUP_TEST_MAX_NAME_LENGTH 32
#define CGROUP_TEST_MAX_PIDS 2048
#define CGROUP_TEST_DEVICES_DEFAULT_LIST "a *:* rwm\n"
LXT_VARIATION_HANDLER CgroupTestBasicMount;
LXT_VARIATION_HANDLER CgroupTestMkdir;
LXT_VARIATION_HANDLER CgroupTestThreads;
LXT_VARIATION_HANDLER CgroupTestProcfs;
LXT_VARIATION_HANDLER CgroupTestProcsFile;
LXT_VARIATION_HANDLER CgroupTestMountReuse;
LXT_VARIATION_HANDLER CgroupTestDevices;
//
// TODO_LX: Enable all files when supported.
//
static const LXT_CHILD_INFO g_CgroupRootChildren[] = {
{"cgroup.sane_behavior", DT_REG},
/* {"cgroup.clone_children", DT_REG},
{"cgroup.event_control", DT_REG}, */
{"cgroup.procs", DT_REG}};
/* {"notify_on_release", DT_REG},
{"release_agent", DT_REG},
{"tasks", DT_REG}};*/
static const LXT_CHILD_INFO g_CgroupDefaultChildren[] = {/* {"cgroup.clone_children", DT_REG},
{"cgroup.event_control", DT_REG}, */
{"cgroup.procs", DT_REG}};
/* {"notify_on_release", DT_REG},
{"release_agent", DT_REG},
{"tasks", DT_REG}};*/
static const LXT_CHILD_INFO g_CgroupDevicesChildren[] = {{"devices.allow", DT_REG}, {"devices.deny", DT_REG}, {"devices.list", DT_REG}};
//
// Global constants
//
static const LXT_VARIATION g_LxtVariations[] = {
{"cgroup - basic mount", CgroupTestBasicMount},
{"cgroup - mkdir", CgroupTestMkdir},
{"cgroup - threads", CgroupTestThreads},
{"cgroup - procfs", CgroupTestProcfs},
{"cgroup - cgroup.procs file", CgroupTestProcsFile},
{"cgroup - mount reuse", CgroupTestMountReuse},
{"cgroup - devices subsystem", CgroupTestDevices}};
static int g_TestPathMountId;
int CgroupTestEntry(int Argc, char* Argv[])
/*++
--*/
{
LXT_ARGS Args;
int Result;
//
// Clean-up from previous iterations.
//
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1_CHILD);
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1);
umount(CGROUP_TEST_MOUNT_POINT2);
umount(CGROUP_TEST_MOUNT_POINT);
rmdir(CGROUP_TEST_MOUNT_POINT);
rmdir(CGROUP_TEST_MOUNT_POINT2);
//
// Run the test variations.
//
LxtCheckResult(g_TestPathMountId = MountGetMountId(CGROUP_TEST_PATH));
LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
//
// Mount cgroup with a folder to test the instance uninitialize path.
//
LxtCheckErrnoZeroSuccess(mkdir(CGROUP_TEST_MOUNT_POINT, 0777));
LxtCheckErrnoZeroSuccess(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT, CGROUP_TEST_MOUNT_NAME, 0, "devices"));
LxtCheckErrno(mkdir(CGROUP_TEST_MOUNT_POINT_DIR1, 0777));
ErrorExit:
LxtUninitialize();
return !LXT_SUCCESS(Result);
}
int CgroupTestBasicMount(PLXT_ARGS Args)
/*++
Description:
This routine tests the mount and umount system calls for cgroups.
Arguments:
Args - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
int MountId;
int Result;
//
// Create the directory and ensure it's not a mount point yet.
//
LxtCheckErrnoZeroSuccess(mkdir(CGROUP_TEST_MOUNT_POINT, 0777));
LxtCheckResult(MountCheckIsNotMount(CGROUP_TEST_MOUNT_POINT));
//
// Mount a cgroup instance and check it was mounted.
//
LxtCheckErrnoZeroSuccess(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT, CGROUP_TEST_MOUNT_NAME, 0, NULL));
LxtCheckResult(
MountId = MountCheckIsMount(
CGROUP_TEST_MOUNT_POINT,
g_TestPathMountId,
"mycgroupnew",
CGROUP_TEST_MOUNT_NAME,
"/",
"rw,relatime",
"rw,devices",
"rw,relatime,devices",
0));
//
// Mounting again should fail.
//
LxtCheckErrnoFailure(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT, CGROUP_TEST_MOUNT_NAME, 0, NULL), EBUSY);
LxtCheckErrnoFailure(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT, CGROUP_TEST_MOUNT_NAME, 0, "devices"), EBUSY);
//
// Unmount and check it was unmounted.
//
LxtCheckErrnoZeroSuccess(umount(CGROUP_TEST_MOUNT_POINT));
LxtCheckResult(MountCheckIsNotMount(CGROUP_TEST_MOUNT_POINT));
ErrorExit:
umount(CGROUP_TEST_MOUNT_POINT);
rmdir(CGROUP_TEST_MOUNT_POINT);
return Result;
}
int CgroupTestMkdir(PLXT_ARGS Args)
/*++
Description:
This routine tests the mkdir and rmdir system calls for cgroups.
Arguments:
Args - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
LXT_CHILD_INFO ChildInfo;
char ChildPidBuffer[CGROUP_TEST_DEFAULT_BUFFER_SIZE];
int ChildPidBufferLength;
char Path[512];
int ProcsFd;
int MountId;
int Result;
ProcsFd = -1;
//
// Mount cgroup.
//
LxtCheckErrnoZeroSuccess(mkdir(CGROUP_TEST_MOUNT_POINT, 0777));
LxtCheckErrnoZeroSuccess(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT, CGROUP_TEST_MOUNT_NAME, 0, "devices"));
//
// Removing the mount point root directory should fail.
//
LxtCheckErrnoFailure(rmdir(CGROUP_TEST_MOUNT_POINT), EBUSY);
//
// Create two subdirectories.
//
LxtCheckResult(LxtCheckDirectoryContents(CGROUP_TEST_MOUNT_POINT, g_CgroupRootChildren, LXT_COUNT_OF(g_CgroupRootChildren)));
LxtCheckErrno(mkdir(CGROUP_TEST_MOUNT_POINT_DIR1, 0777));
ChildInfo.FileType = DT_DIR;
ChildInfo.Name = CGROUP_TEST_MOUNT_POINT_DIR1_NAME;
LxtCheckResult(LxtCheckDirectoryContents(CGROUP_TEST_MOUNT_POINT, &ChildInfo, 1));
LxtCheckErrno(mkdir(CGROUP_TEST_MOUNT_POINT_DIR1_CHILD, 0777));
ChildInfo.Name = CGROUP_TEST_MOUNT_POINT_DIR1_CHILD_NAME;
LxtCheckResult(LxtCheckDirectoryContents(CGROUP_TEST_MOUNT_POINT_DIR1, &ChildInfo, 1));
//
// Removing the first directory should fail if the second one still exists,
// otherwise it succeeds.
//
LxtCheckErrnoFailure(rmdir(CGROUP_TEST_MOUNT_POINT_DIR1), EBUSY);
LxtCheckErrno(rmdir(CGROUP_TEST_MOUNT_POINT_DIR1_CHILD));
LxtCheckErrno(rmdir(CGROUP_TEST_MOUNT_POINT_DIR1));
//
// Check that removing the first directory fails if a thread is still
// associated; otherwise, it succeeds.
//
LxtCheckErrno(mkdir(CGROUP_TEST_MOUNT_POINT_DIR1, 0777));
sprintf(Path, "%s/%s", CGROUP_TEST_MOUNT_POINT_DIR1, "cgroup.procs");
LxtCheckErrno(ProcsFd = open(Path, O_WRONLY));
ChildPidBufferLength = sprintf(ChildPidBuffer, "%d\n", getpid());
LxtCheckErrno(write(ProcsFd, ChildPidBuffer, ChildPidBufferLength));
LxtClose(ProcsFd);
ProcsFd = -1;
LxtCheckErrnoFailure(rmdir(CGROUP_TEST_MOUNT_POINT_DIR1), EBUSY);
sprintf(Path, "%s/%s", CGROUP_TEST_MOUNT_POINT, "cgroup.procs");
LxtCheckErrno(ProcsFd = open(Path, O_WRONLY));
LxtCheckErrno(write(ProcsFd, ChildPidBuffer, ChildPidBufferLength));
LxtClose(ProcsFd);
ProcsFd = -1;
LxtCheckErrno(rmdir(CGROUP_TEST_MOUNT_POINT_DIR1));
//
// Unmount cgroup.
//
LxtCheckErrnoZeroSuccess(umount(CGROUP_TEST_MOUNT_POINT));
LxtCheckResult(MountCheckIsNotMount(CGROUP_TEST_MOUNT_POINT));
ErrorExit:
if (ProcsFd != -1)
{
LxtClose(ProcsFd);
}
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1_CHILD);
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1);
umount(CGROUP_TEST_MOUNT_POINT);
rmdir(CGROUP_TEST_MOUNT_POINT);
return Result;
}
int CgroupTestThreads(PLXT_ARGS Args)
/*++
Description:
This routine tests thread behavior with cgroups mounts.
Arguments:
Args - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
pid_t ChildPid;
int MountId;
LXT_PIPE Pipe = {-1, -1};
int Result;
//
// Create a thread, mount cgroup, and signal the thread to exit to test
// cgroup assignment during mount.
//
LxtCheckResult(LxtCreatePipe(&Pipe));
LxtCheckResult(ChildPid = fork());
if (ChildPid == 0)
{
read(Pipe.Read, &Result, sizeof(Result));
_exit(Result);
}
LxtCheckErrnoZeroSuccess(mkdir(CGROUP_TEST_MOUNT_POINT, 0777));
LxtCheckErrnoZeroSuccess(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT, CGROUP_TEST_MOUNT_NAME, 0, NULL));
write(Pipe.Write, &Result, sizeof(Result));
LxtWaitPidPoll(ChildPid, 0);
//
// Create a thread to test cgroup inheritance.
//
LxtCheckResult(ChildPid = fork());
if (ChildPid == 0)
{
_exit(Result);
}
LxtWaitPidPoll(ChildPid, 0);
//
// Unmount and exit.
//
LxtCheckErrnoZeroSuccess(umount(CGROUP_TEST_MOUNT_POINT));
LxtCheckResult(MountCheckIsNotMount(CGROUP_TEST_MOUNT_POINT));
ErrorExit:
write(Pipe.Write, &Result, sizeof(Result));
LxtClosePipe(&Pipe);
umount(CGROUP_TEST_MOUNT_POINT);
rmdir(CGROUP_TEST_MOUNT_POINT);
return Result;
}
typedef struct _CGROUP_TEST_PROCFS_ENTRY
{
char Name[CGROUP_TEST_MAX_NAME_LENGTH];
int Hierarchy;
int NumCgroups;
int Enabled;
} CGROUP_TEST_PROCFS_ENTRY, *PCGROUP_TEST_PROCFS_ENTRY;
typedef struct _CGROUP_TEST_PROCFS
{
int EntryCount;
CGROUP_TEST_PROCFS_ENTRY Entries[CGROUP_TEST_MAX_CGROUPS];
} CGROUP_TEST_PROCFS, *PCGROUP_TEST_PROCFS;
int CgroupTestReadProcfs(PCGROUP_TEST_PROCFS Data)
/*++
Description:
This routine parses /proc/cgroups.
Arguments:
Data - Supplies a buffer to store the data
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
char Line[CGROUP_TEST_DEFAULT_BUFFER_SIZE];
FILE* CgroupFile;
int NumCgroups;
int Result;
memset(Data, 0, sizeof(*Data));
CgroupFile = fopen("/proc/cgroups", "r");
LxtCheckNotEqual(CgroupFile, NULL, "%p");
if (fgets(Line, LXT_COUNT_OF(Line), CgroupFile) == NULL)
{
Result = LXT_RESULT_FAILURE;
LxtLogError("Failed to read header");
goto ErrorExit;
}
LxtCheckStringEqual(Line, "#subsys_name\thierarchy\tnum_cgroups\tenabled\n");
NumCgroups = 0;
while (fgets(Line, LXT_COUNT_OF(Line), CgroupFile) != NULL)
{
sscanf(
Line,
"%s\t%d\t%d\t%d",
Data->Entries[NumCgroups].Name,
&Data->Entries[NumCgroups].Hierarchy,
&Data->Entries[NumCgroups].NumCgroups,
&Data->Entries[NumCgroups].Enabled);
NumCgroups += 1;
}
Data->EntryCount = NumCgroups;
ErrorExit:
if (CgroupFile != NULL)
{
fclose(CgroupFile);
}
return Result;
}
typedef struct _CGROUP_TEST_PROCFS_PID_ENTRY
{
int Hierarchy;
char Subsystems[CGROUP_TEST_DEFAULT_BUFFER_SIZE];
char CgroupPath[CGROUP_TEST_DEFAULT_BUFFER_SIZE];
} CGROUP_TEST_PROCFS_PID_ENTRY, *PCGROUP_TEST_PROCFS_PID_ENTRY;
typedef struct _CGROUP_TEST_PROCFS_PID
{
int EntryCount;
CGROUP_TEST_PROCFS_PID_ENTRY Entries[CGROUP_TEST_MAX_CGROUPS];
} CGROUP_TEST_PROCFS_PID, *PCGROUP_TEST_PROCFS_PID;
int CgroupTestReadProcfsPid(PCGROUP_TEST_PROCFS_PID Data)
/*++
Description:
This routine parses /proc/self/cgroup.
Arguments:
Data - Supplies a buffer to store the data
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
char Line[CGROUP_TEST_DEFAULT_BUFFER_SIZE];
FILE* CgroupFile;
int NumCgroups;
int Result;
memset(Data, 0, sizeof(*Data));
CgroupFile = fopen("/proc/self/cgroup", "r");
LxtCheckNotEqual(CgroupFile, NULL, "%p");
NumCgroups = 0;
while (fgets(Line, LXT_COUNT_OF(Line), CgroupFile) != NULL)
{
sscanf(
Line,
"%d:%[^:]:%[^:\n]",
&Data->Entries[NumCgroups].Hierarchy,
Data->Entries[NumCgroups].Subsystems,
Data->Entries[NumCgroups].CgroupPath);
NumCgroups += 1;
}
Data->EntryCount = NumCgroups;
ErrorExit:
if (CgroupFile != NULL)
{
fclose(CgroupFile);
}
return Result;
}
int CgroupTestProcfs(PLXT_ARGS Args)
/*++
Description:
This routine tests the cgroup procfs files.
Arguments:
Args - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
int BytesRead;
int Found;
int Index;
int MountId;
CGROUP_TEST_PROCFS ProcfsNew;
CGROUP_TEST_PROCFS ProcfsOrig;
CGROUP_TEST_PROCFS_PID ProcfsPidNew;
CGROUP_TEST_PROCFS_PID ProcfsPidOrig;
int Result;
//
// Create the cgroup mount.
//
LxtCheckErrnoZeroSuccess(mkdir(CGROUP_TEST_MOUNT_POINT, 0777));
LxtCheckErrnoZeroSuccess(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT, CGROUP_TEST_MOUNT_NAME, 0, "devices"));
//
// Read the procfs files before cgroups are mounted, staring
// with /proc/cgroup.
//
LxtCheckResult(CgroupTestReadProcfs(&ProcfsNew));
LxtCheckNotEqual(ProcfsNew.EntryCount, 0, "%d");
Found = 0;
for (Index = 0; Index < ProcfsNew.EntryCount; ++Index)
{
LxtCheckNotEqual(ProcfsNew.Entries[Index].NumCgroups, 0, "%d");
LxtCheckEqual(ProcfsNew.Entries[Index].Enabled, 1, "%d");
if (strcmp(ProcfsNew.Entries[Index].Name, "devices") == 0)
{
LxtCheckNotEqual(Found, 1, "%d");
LxtCheckNotEqual(ProcfsNew.Entries[Index].Hierarchy, 0, "%d");
Found = 1;
}
}
LxtCheckEqual(Found, 1, "%d");
//
// Now /proc/self/cgroup.
//
LxtCheckResult(CgroupTestReadProcfsPid(&ProcfsPidNew));
Found = 0;
for (Index = 0; Index < ProcfsPidNew.EntryCount; ++Index)
{
if (strstr(ProcfsPidNew.Entries[Index].Subsystems, "devices") != NULL)
{
LxtCheckNotEqual(Found, 1, "%d");
LxtCheckNotEqual(ProcfsPidNew.Entries[Index].Hierarchy, 0, "%d");
LxtCheckStringEqual(ProcfsPidNew.Entries[Index].CgroupPath, "/");
Found = 1;
}
}
LxtCheckEqual(Found, 1, "%d");
//
// Unmount and recheck the original.
//
LxtCheckErrnoZeroSuccess(umount(CGROUP_TEST_MOUNT_POINT));
LxtCheckResult(MountCheckIsNotMount(CGROUP_TEST_MOUNT_POINT));
ErrorExit:
umount(CGROUP_TEST_MOUNT_POINT);
rmdir(CGROUP_TEST_MOUNT_POINT);
return Result;
}
int CgroupTestGetProcsFileIds(char* CgroupPath, pid_t* IdArray[], int* IdArrayCount)
/*++
Description:
This routine tests the behavior of the cgroup.procs file.
Arguments:
Path - Supplies the path to query.
IdArray - Supplies a buffer to store the array of ids.
IdArrayCount - Supplies a buffer to store the number of ids.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
pid_t* Array;
int Count;
int Index;
FILE* File;
char Line[CGROUP_TEST_DEFAULT_BUFFER_SIZE];
char Path[512];
int PathLength;
int Result;
Array = NULL;
File = NULL;
sprintf(Path, "%s/%s", CgroupPath, "cgroup.procs");
File = fopen(Path, "r");
LxtCheckNotEqual(File, NULL, "%p");
Array = LxtAlloc(sizeof(*Array) * CGROUP_TEST_MAX_PIDS);
if (Array == NULL)
{
Result = LXT_RESULT_FAILURE;
goto ErrorExit;
}
Count = 0;
while (fgets(Line, LXT_COUNT_OF(Line), File) != NULL)
{
if (Count > CGROUP_TEST_MAX_PIDS)
{
LxtLogError("Unexpected count");
Result = LXT_RESULT_FAILURE;
goto ErrorExit;
}
sscanf(Line, "%d\n", &Array[Count]);
Count += 1;
}
for (Index = 1; Index < Count; ++Index)
{
if (Array[Index - 1] >= Array[Index])
{
LxtLogError("Unexpected value %d, %d", Array[Index - 1], Array[Index]);
Result = LXT_RESULT_FAILURE;
goto ErrorExit;
}
}
*IdArray = Array;
Array = NULL;
*IdArrayCount = Count;
ErrorExit:
if (File != NULL)
{
fclose(File);
}
if (Array != NULL)
{
LxtFree(Array);
}
return Result;
}
int CgroupTestProcsFile(PLXT_ARGS Args)
/*++
Description:
This routine tests the behavior of the cgroup.procs file.
Arguments:
Args - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
pid_t* Array;
pid_t ChildPid;
char ChildPidBuffer[CGROUP_TEST_DEFAULT_BUFFER_SIZE];
int ChildPidBufferLength;
int Count;
int Index;
int MountId;
char Path[512];
int ProcsFd;
LXT_PIPE Pipe = {-1, -1};
int Result;
Array = NULL;
ProcsFd = -1;
LxtCheckErrnoZeroSuccess(mkdir(CGROUP_TEST_MOUNT_POINT, 0777));
LxtCheckErrnoZeroSuccess(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT, CGROUP_TEST_MOUNT_NAME, 0, "devices"));
//
// Create a threadgroup and check that it is in the root folder.
//
LxtCheckResult(LxtCreatePipe(&Pipe));
LxtCheckResult(ChildPid = fork());
if (ChildPid == 0)
{
read(Pipe.Read, &Result, sizeof(Result));
_exit(0);
}
LxtCheckResult(CgroupTestGetProcsFileIds(CGROUP_TEST_MOUNT_POINT, &Array, &Count));
for (Index = 0; Index < Count; ++Index)
{
if (Array[Index] == ChildPid)
{
break;
}
}
LxtCheckNotEqual(Index, Count, "%d");
LxtFree(Array);
Array = NULL;
//
// Create a folder and check that it is empty.
//
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1);
LxtCheckErrno(mkdir(CGROUP_TEST_MOUNT_POINT_DIR1, 0777));
LxtCheckResult(CgroupTestGetProcsFileIds(CGROUP_TEST_MOUNT_POINT_DIR1, &Array, &Count));
LxtCheckEqual(0, Count, "%d");
LxtFree(Array);
Array = NULL;
//
// Move the thread to the folder and check that the thread was moved.
//
sprintf(Path, "%s/%s", CGROUP_TEST_MOUNT_POINT_DIR1, "cgroup.procs");
LxtCheckErrno(ProcsFd = open(Path, O_WRONLY));
ChildPidBufferLength = sprintf(ChildPidBuffer, "%d\n", ChildPid);
LxtCheckErrno(write(ProcsFd, ChildPidBuffer, ChildPidBufferLength));
LxtCheckResult(CgroupTestGetProcsFileIds(CGROUP_TEST_MOUNT_POINT_DIR1, &Array, &Count));
for (Index = 0; Index < Count; ++Index)
{
if (Array[Index] == ChildPid)
{
break;
}
}
LxtCheckNotEqual(Index, Count, "%d");
LxtFree(Array);
Array = NULL;
LxtCheckResult(CgroupTestGetProcsFileIds(CGROUP_TEST_MOUNT_POINT, &Array, &Count));
for (Index = 0; Index < Count; ++Index)
{
if (Array[Index] == ChildPid)
{
break;
}
}
LxtCheckEqual(Index, Count, "%d");
LxtFree(Array);
Array = NULL;
LxtClose(ProcsFd);
ProcsFd = -1;
//
// Move the thread to the root and check that the thread was moved.
//
sprintf(Path, "%s/%s", CGROUP_TEST_MOUNT_POINT, "cgroup.procs");
LxtCheckErrno(ProcsFd = open(Path, O_WRONLY));
ChildPidBufferLength = sprintf(ChildPidBuffer, "%d\n", ChildPid);
LxtCheckErrno(write(ProcsFd, ChildPidBuffer, ChildPidBufferLength));
LxtCheckResult(CgroupTestGetProcsFileIds(CGROUP_TEST_MOUNT_POINT_DIR1, &Array, &Count));
LxtCheckEqual(0, Count, "%d");
LxtFree(Array);
Array = NULL;
LxtCheckResult(CgroupTestGetProcsFileIds(CGROUP_TEST_MOUNT_POINT, &Array, &Count));
for (Index = 0; Index < Count; ++Index)
{
if (Array[Index] == ChildPid)
{
break;
}
}
LxtCheckNotEqual(Index, Count, "%d");
LxtFree(Array);
Array = NULL;
LxtClose(ProcsFd);
ProcsFd = -1;
//
// Unmount and exit.
//
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1);
LxtCheckErrnoZeroSuccess(umount(CGROUP_TEST_MOUNT_POINT));
LxtCheckResult(MountCheckIsNotMount(CGROUP_TEST_MOUNT_POINT));
ErrorExit:
write(Pipe.Write, &Result, sizeof(Result));
LxtClosePipe(&Pipe);
if (Array != NULL)
{
LxtFree(Array);
}
if (ProcsFd != -1)
{
LxtClose(ProcsFd);
}
umount(CGROUP_TEST_MOUNT_POINT);
rmdir(CGROUP_TEST_MOUNT_POINT);
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1);
return Result;
}
int CgroupTestMountReuse(PLXT_ARGS Args)
/*++
Description:
This routine tests the behavior of reusing cgroup hierarchy mounts.
Arguments:
Args - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
LXT_CHILD_INFO ChildInfo;
char ChildPidBuffer[CGROUP_TEST_DEFAULT_BUFFER_SIZE];
int ChildPidBufferLength;
int Found;
int Index;
char Path[512];
int ProcsFd;
CGROUP_TEST_PROCFS ProcfsNew;
int MountId;
int Result;
ProcsFd = -1;
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1_CHILD);
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1);
umount(CGROUP_TEST_MOUNT_POINT);
rmdir(CGROUP_TEST_MOUNT_POINT);
//
// Mount cgroup.
//
LxtCheckErrnoZeroSuccess(mkdir(CGROUP_TEST_MOUNT_POINT, 0777));
LxtCheckErrnoZeroSuccess(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT, CGROUP_TEST_MOUNT_NAME, 0, "devices"));
//
// A cgroup with a directory should be reported as active when unmounted
//
LxtCheckErrno(mkdir(CGROUP_TEST_MOUNT_POINT_DIR1, 0777));
LxtCheckErrno(access(CGROUP_TEST_MOUNT_POINT_DIR1, F_OK));
LxtCheckErrnoZeroSuccess(umount(CGROUP_TEST_MOUNT_POINT));
LxtCheckErrnoFailure(access(CGROUP_TEST_MOUNT_POINT_DIR1, F_OK), ENOENT);
LxtCheckResult(CgroupTestReadProcfs(&ProcfsNew));
LxtCheckNotEqual(ProcfsNew.EntryCount, 0, "%d");
Found = 0;
for (Index = 0; Index < ProcfsNew.EntryCount; ++Index)
{
LxtCheckNotEqual(ProcfsNew.Entries[Index].NumCgroups, 0, "%d");
LxtCheckEqual(ProcfsNew.Entries[Index].Enabled, 1, "%d");
if (strcmp(ProcfsNew.Entries[Index].Name, "devices") == 0)
{
LxtCheckNotEqual(Found, 1, "%d");
LxtCheckNotEqual(ProcfsNew.Entries[Index].Hierarchy, 0, "%d");
Found = 1;
}
}
LxtCheckEqual(Found, 1, "%d");
//
// When remounted the directory is present
//
LxtCheckErrnoZeroSuccess(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT, CGROUP_TEST_MOUNT_NAME, 0, "devices"));
LxtCheckErrno(access(CGROUP_TEST_MOUNT_POINT_DIR1, F_OK));
//
// When that cgroup is mounted again, the directory should be present
//
LxtCheckErrnoZeroSuccess(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT2, CGROUP_TEST_MOUNT_NAME, 0, "devices"));
LxtCheckErrno(access(CGROUP_TEST_MOUNT_POINT2_DIR1, F_OK));
umount(CGROUP_TEST_MOUNT_POINT2);
//
// Failing variation to check the mount all case.
//
// TODO_LX: This variation needs to be updated once multiple subsystems are
// supported.
//
LxtCheckErrnoZeroSuccess(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT2, CGROUP_TEST_MOUNT_NAME, 0, NULL));
LxtCheckErrno(access(CGROUP_TEST_MOUNT_POINT2_DIR1, F_OK));
//
// Unmount and exit.
//
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1);
LxtCheckErrnoZeroSuccess(umount(CGROUP_TEST_MOUNT_POINT2));
LxtCheckErrnoZeroSuccess(umount(CGROUP_TEST_MOUNT_POINT));
LxtCheckResult(MountCheckIsNotMount(CGROUP_TEST_MOUNT_POINT));
ErrorExit:
if (ProcsFd != -1)
{
LxtClose(ProcsFd);
}
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1_CHILD);
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1);
umount(CGROUP_TEST_MOUNT_POINT2);
umount(CGROUP_TEST_MOUNT_POINT);
rmdir(CGROUP_TEST_MOUNT_POINT);
rmdir(CGROUP_TEST_MOUNT_POINT2);
return Result;
}
int CgroupTestDevices(PLXT_ARGS Args)
/*++
Description:
This routine tests the files for the devices subsystem.
Arguments:
Args - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
int BytesRead;
int CgroupFd;
char DevicesListBuffer[32];
char Path[512];
char PidBuffer[CGROUP_TEST_DEFAULT_BUFFER_SIZE];
int PidBufferLength;
int Result;
CgroupFd = -1;
PidBufferLength = sprintf(PidBuffer, "%d\n", getpid());
//
// Mount cgroup.
//
LxtCheckErrnoZeroSuccess(mkdir(CGROUP_TEST_MOUNT_POINT, 0777));
LxtCheckErrnoZeroSuccess(mount("mycgroupnew", CGROUP_TEST_MOUNT_POINT, CGROUP_TEST_MOUNT_NAME, 0, "devices"));
//
// Check for the expected default files and devices files in the root.
//
LxtCheckResult(LxtCheckDirectoryContents(CGROUP_TEST_MOUNT_POINT, g_CgroupRootChildren, LXT_COUNT_OF(g_CgroupRootChildren)));
LxtCheckResult(LxtCheckDirectoryContents(CGROUP_TEST_MOUNT_POINT, g_CgroupDevicesChildren, LXT_COUNT_OF(g_CgroupDevicesChildren)));
//
// Check for the expected default files and devices files in a subdirectory.
//
// N.B. A thread has to exist in the cgroup for some files to successfully
// be read.
//
LxtCheckErrno(mkdir(CGROUP_TEST_MOUNT_POINT_DIR1, 0777));
sprintf(Path, "%s/%s", CGROUP_TEST_MOUNT_POINT_DIR1, "cgroup.procs");
LxtCheckErrno(CgroupFd = open(Path, O_WRONLY));
LxtCheckErrno(write(CgroupFd, PidBuffer, PidBufferLength));
LxtClose(CgroupFd);
CgroupFd = -1;
LxtCheckResult(LxtCheckDirectoryContents(CGROUP_TEST_MOUNT_POINT_DIR1, g_CgroupDefaultChildren, LXT_COUNT_OF(g_CgroupDefaultChildren)));
LxtCheckResult(LxtCheckDirectoryContents(CGROUP_TEST_MOUNT_POINT_DIR1, g_CgroupDevicesChildren, LXT_COUNT_OF(g_CgroupDevicesChildren)));
//
// Check for the expected value of the devices.list file in both folders.
//
sprintf(Path, "%s/%s", CGROUP_TEST_MOUNT_POINT, "devices.list");
LxtCheckErrno(CgroupFd = open(Path, O_RDONLY));
LxtCheckErrno(BytesRead = read(CgroupFd, DevicesListBuffer, sizeof(DevicesListBuffer) - 1));
DevicesListBuffer[BytesRead] = 0;
LxtClose(CgroupFd);
CgroupFd = -1;
LxtCheckStringEqual(DevicesListBuffer, CGROUP_TEST_DEVICES_DEFAULT_LIST);
sprintf(Path, "%s/%s", CGROUP_TEST_MOUNT_POINT_DIR1, "devices.list");
LxtCheckErrno(CgroupFd = open(Path, O_RDONLY));
LxtCheckErrno(BytesRead = read(CgroupFd, DevicesListBuffer, sizeof(DevicesListBuffer) - 1));
DevicesListBuffer[BytesRead] = 0;
LxtClose(CgroupFd);
CgroupFd = -1;
LxtCheckStringEqual(DevicesListBuffer, CGROUP_TEST_DEVICES_DEFAULT_LIST);
//
// Unmount cgroup.
//
sprintf(Path, "%s/%s", CGROUP_TEST_MOUNT_POINT, "cgroup.procs");
LxtCheckErrno(CgroupFd = open(Path, O_WRONLY));
LxtCheckErrno(write(CgroupFd, PidBuffer, PidBufferLength));
LxtClose(CgroupFd);
CgroupFd = -1;
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1);
LxtCheckErrnoZeroSuccess(umount(CGROUP_TEST_MOUNT_POINT));
LxtCheckResult(MountCheckIsNotMount(CGROUP_TEST_MOUNT_POINT));
ErrorExit:
if (CgroupFd != -1)
{
LxtClose(CgroupFd);
}
rmdir(CGROUP_TEST_MOUNT_POINT_DIR1);
umount(CGROUP_TEST_MOUNT_POINT);
rmdir(CGROUP_TEST_MOUNT_POINT);
return Result;
}