Commit Graph

472 Commits

Author SHA1 Message Date
Kir Kolyshkin e25b8cfcd5 libct/cg/utils: use fscommon.ReadFile
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-10-05 14:07:57 -07:00
Kir Kolyshkin 6bae53f589 libct/cg/fs2: use fscommon.ReadFile
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-10-05 14:07:15 -07:00
Kir Kolyshkin 2588e6f1b8 libct/cg/fs/cpuset: use fscommon.ReadFile
While at it,

 - change some functions to not be methods of CpusetCgroup as
   they don't use any members;
 - simplify isEmpty.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-10-05 14:07:15 -07:00
Kir Kolyshkin 1d20cf49f1 libct/cg/fs/cpuacct: use fscommon.ReadFile
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-10-05 14:07:15 -07:00
Kir Kolyshkin 9e78b66e88 libct/cg/systemd/v1.enableKmem: use fscommon.ReadFile
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-10-05 14:07:15 -07:00
Kir Kolyshkin 316344364c libct/cg/fs2.CreateCgroupPath: use fscommon.*File
fscommon's ReadFile and WriteFile are tailored to cgroupfs,
so let's use them here.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-10-05 14:07:15 -07:00
Kir Kolyshkin b7092d84ee libct/cg/fs.setKernelMemory: use fscommon.WriteFile
fscommon.WriteFile is added specifically to work with cgroup files,
and the error it returns does not need to be wrapped.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-10-05 14:07:15 -07:00
Kir Kolyshkin 619de9773e libct/cg/fscommon_test: rm cgroups dependency
This removes package dependency on cgroup, as following commits
make cgroup use fscommon, which would result in dependency cycle.

The code to find out memory cgroup root is not really needed,
as 99% of test envrionments will have it at /sys/fs/cgroup/memory.
If not, that means we're either on cgroupv2 or on some very custom
system, so just skip the test.

The code that checks if we're on cgroupv2 is replaced by the check
of the particular v1 control file.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-10-05 14:07:15 -07:00
Mrunal Patel f671f6bf3d Merge pull request #2597 from kolyshkin/hugepages
Fix/improve GetHugePageSize
2020-10-02 19:23:23 -07:00
Akihiro Suda 750036e41d Merge pull request #2609 from thaJeztah/byte_trim
libcontainer: prefer bytes.TrimSpace() over strings.TrimSpace()
2020-10-02 14:22:39 +09:00
Ashok Pon Kumar fcf210d631 Fix goreport warnings of ineffassign and misspell
Signed-off-by: Ashok Pon Kumar <ashokponkumar@gmail.com>
2020-10-02 09:03:45 +05:30
Sebastiaan van Stijn 28b452bf65 libcontainer: unconvert
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-10-01 18:36:56 +02:00
Sebastiaan van Stijn b3a8b0742c libcontainer: prefer bytes.TrimSpace() over strings.TrimSpace()
Perform trimming before converting to a string, which should be
somewhat more performant.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-10-01 18:36:53 +02:00
Kenta Tada b76652fbeb libcontainer: remove removePath from cgroups
`removePath` is unused as below
https://github.com/opencontainers/runc/commit/11fb94965cab5b2a54da9dca50d0e36d0ee36ef0

Signed-off-by: Kenta Tada <Kenta.Tada@sony.com>
2020-10-01 12:22:12 +09:00
Akihiro Suda a220b9c6cc Merge pull request #2608 from thaJeztah/no_join
libcontainer: remove redundant strings.Join()
2020-10-01 10:20:23 +09:00
Sebastiaan van Stijn 3eb469b029 libcontainer: remove redundant strings.Join()
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-10-01 00:00:47 +02:00
Sebastiaan van Stijn bc9a7bda58 setFreezer: explicitly return nil
errors.Wrap(err, "some error") returns nil if err is nil, so it's
slightly clearer to just return early than to set the error to nil
and call errors.Wrap(). This is also somewhat defensive in case
we decide to replace `errors.Wrap()` for golang's native `%w`
wrapping.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-09-30 23:41:07 +02:00
Mrunal Patel d5098eaae4 Merge pull request #2604 from kolyshkin/fscommon-I
libct/cgroups/fscommon: nits
2020-09-30 13:12:16 -07:00
Kir Kolyshkin 360981ae1d libct/cgroups: rewrite getHugePageSizeFromFilenames
This is a function to convert huge page sizes (obtained by reading
/sys/kernel/mm/hugepages directory entries) to strings user for hugetlb
cgroup controller resource files. Those strings are when used to get the
hugetlb resource statistics.

This function used external library, floating point numbers, and can
(theoretically) produce invalid values, since the kernel only uses KB,
MB, and GB suffixes.

Rewrite it to produce the same strings as used in the kernel (see [1]).
As a result, it's also faster, more future-proof (entries that do not
start with "hugepages-" and/or incorrect suffix are skipped), and does
more input sanity checks. As a side effect, libcontainer no longer
depends on docker/go-units.

While at it, add more test cases.

Before:
	BenchmarkGetHugePageSize-8       	  187452	      6265 ns/op
	BenchmarkGetHugePageSizeImpl-8   	  396769	      2998 ns/op

After:
	BenchmarkGetHugePageSize-8       	  222898	      4554 ns/op
	BenchmarkGetHugePageSizeImpl-8   	 4738924	       241 ns/op

NOTE on removing HugePageSizeUnitList -- this was added by commit
6f77e35da and was used by kubernetes code in [2], which was later
superceded by [3], so there are (hopefully) no external users.
If there are any, they should not be doing that.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/hugetlb_cgroup.c?id=eff48ddeab782e35e58ccc8853f7386bbae9dec4#n574
[2] https://github.com/kubernetes/kubernetes/pull/78495
[3] https://github.com/kubernetes/kubernetes/pull/84154

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-30 10:58:31 -07:00
Akihiro Suda 890cc2aa60 Merge pull request #2612 from thaJeztah/concat
use string-concatenation instead of sprintf for simple cases
2020-10-01 01:56:28 +09:00
Kir Kolyshkin 22f11bafc3 Merge pull request #2611 from thaJeztah/const
libcontainer/cgroups: use const for templates
2020-09-30 09:01:42 -07:00
Sebastiaan van Stijn 8bf216728c use string-concatenation instead of sprintf for simple cases
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-09-30 10:51:59 +02:00
Kir Kolyshkin 38447895a5 libct/cgroups/systemd: eliminate runc/systemd race
In case it takes more than 1 second for systemd to create a unit,
startUnit() times out with a warning and then runc proceeds
(to create cgroups using fs manager and so on).

Now runc and systemd are racing, and multiple scenarios are possible.

In one such scenario, by the time runc calls systemd manager's Apply()
the unit is not yet created, the dbusConnection.SetUnitProperties()
call fails with "unit xxx.scope not found", and the whole container
start also fails.

To eliminate the race, we need to return an error in case the timeout is
hit.

To reduce the chance to fail, increase the timeout from 1 to 30 seconds,
to not error out too early on a busy/slow system (and times like 3-5
seconds are not unrealistic).

While at it, as the timeout is quite long now, make sure to not leave
a stray timer.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-29 17:43:15 -07:00
Kir Kolyshkin 6c83d23ffc libcontainer/cgroups/fscommon: improve doc
Document ReadFile and WriteFile. Fix doc for ParseUint to be in
canonical form.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-29 11:58:14 -07:00
Kir Kolyshkin 31f0f5b7e0 libct/cg/fscommon.GetCgroupParamUint: improve
1. Use GetCgroupParamString as the initial part of both functions are
   the same and we can reuse it. This also gives us whatever security
   measures GetCgroupParamString has (see previous commit).

2. Fix the error wrapping to not add the value, as it is already a part
   of the error returned by ParseUint.

3. Improve docstring.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-29 11:58:14 -07:00
Kir Kolyshkin e76ac1c054 libct/cg/fscommon.GetCgroupParamString: use ReadFile
1. Use own ReadFile wrapper instead of ioutils.ReadFile.
   This makes it use the security measures of ReadFile.

2. Improve doc.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-29 11:58:14 -07:00
Kir Kolyshkin aac4d1f5c3 libct/cg/fscommon/GetCgroupParamKeyValue: nits
2. Fix wrapping the error to not have the value as it's already
   part of the error returned from ParseUint.

3. Fix/improve doc.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-29 11:57:49 -07:00
Kir Kolyshkin d167be2925 libct/cgroups/fs2/statHugeTlb: error message nits
1. Don't wrap the error from fscommon.GetCgroupParamUint as it already
   contains the file name.

2. Don't put file name when wrapping the error from ioutil.ReadFile
   since it already has it.

3. Don't reconstruct file name, use existing one since it's available.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-29 11:57:18 -07:00
Sebastiaan van Stijn ab2b5dfa8a libcontainer/cgroups: use const for templates
The names of these templates overlapped with some local
variables, which made reading the code somewhat confusing.

Changing them to a const, given that these were not updated anywere.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-09-29 13:34:44 +02:00
Kir Kolyshkin b006f4a180 libct/cgroups: support Cgroups.Resources.Unified
Add support for unified resource map (as per [1]), and add some test
cases for the new functionality.

[1] https://github.com/opencontainers/runtime-spec/pull/1040

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-24 15:29:35 -07:00
Kir Kolyshkin 8ceae9f766 libct/cgroups/GetHugePageSize: use Readdirnames
ioutil.ReadFile does a stat() on every entry and returns a slice of
os.Stat structures. What we need here is just a file name.

This change both simplifies and speeds up the code a bit.

Before:
	BenchmarkGetHugePageSize-8       	  115213	      9400 ns/op

After:
	BenchmarkGetHugePageSize-8       	  190326	      6187 ns/op

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-22 16:08:56 -07:00
Kir Kolyshkin 9aff7aaeb6 libct/utils: add GetHugePageSize benchmark
On my laptop, I get

BenchmarkGetHugePageSize
BenchmarkGetHugePageSize-8       	  115213	      9400 ns/op
BenchmarkGetHugePageSizeImpl
BenchmarkGetHugePageSizeImpl-8   	  397873	      2971 ns/op

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-22 15:25:02 -07:00
Kir Kolyshkin 74b57fea54 fscommon.WriteFile: simplify error message
As the underlying error message from iotuils.WriteFile already contains
file name, there's no need to put it, otherwise we end up with something
like:

	failed to write "val" to "/sys/fs/cgroup/.../file": open /sys/fs/cgroup/.../file: permission denied

With this patch, the error will be

	failed to write "val": open /sys/fs/cgroup/.../file: permission denied

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-16 10:23:12 -07:00
Kir Kolyshkin 940e15479f cgroupv1/systemd: (re)use m.paths
In all these cases, getSubsystemPath() was already called, and its
result stored in m.paths map. It makes no sense to not reuse it.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-08-25 11:42:24 -07:00
Kir Kolyshkin f075084a47 cgroupv1/systemd: rework Apply/joinCgroups
We call joinCgroups() from Apply, and in there we iterate through the
list of subsystems, calling getSubsystemPath() for each. This is
expensive, since every getSubsystemPath() involves parsing mountinfo.

At the end of Apply(), we iterate through the list of subsystems to fill
the m.paths, again calling getSubsystemPath() for every subsystem.

As a result, we parse mountinfo about 20 times here.

Let's find the paths first and reuse m.paths in joinCgroups().

While at it, since join() is just two calls now, inline it.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-08-25 11:42:21 -07:00
Kir Kolyshkin fad92bbffa cgroupv1/Apply: do not overuse d.path/getSubsystemPath
When paths are set, we only need to place the PID into proper
cgroups, and we do know all the paths already.

Both fs/d.path() and systemd/v1/getSubsystemPath() parse
/proc/self/mountinfo, and the only reason they are used
here is to check whether the subsystem is available.

Use a much simpler/faster check instead.

Frankly, I am not sure why the check is needed at all. Maybe it should
be dropped.

Also, for fs driver, since d is no longer used in this code path,
move its initialization to after it.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-08-25 11:40:58 -07:00
Mrunal Patel a5847db387 Merge pull request #2506 from kolyshkin/cgroup-fixes
cgroupv1 removal nits
2020-08-17 21:13:31 -07:00
Mrunal Patel b70de388e4 Merge pull request #2540 from kolyshkin/unify-test-inval-cgroup
cgroups/fs tests: unify TestInvalid*Cgroup*
2020-08-17 11:40:44 -07:00
Akihiro Suda f668854938 Merge pull request #2499 from kolyshkin/find-cgroup-mountpoint-fastpath
cgroupv1/FindCgroupMountpoint: add a fast path
2020-08-04 14:06:41 +09:00
Kir Kolyshkin 637d54b7ce cgroups/fs tests: unify TestInvalid*Cgroup*
All the test cases are doing the same checks, only input differs,
so we can unify those using a test data table.

While at it:
 - use t.Fatalf where it makes sense (no further checks are possible);
 - remove the "XXX" comments as we won't get rid of cgroup Name/Parent.

PS I tried using t.Parallel() as well but it did not result in any
noticeable speedup, so I dropped it for simplicity.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-07-31 18:02:05 -07:00
Akihiro Suda d6f5641c20 Merge pull request #2507 from kolyshkin/alt-to-2497
libct/cgroups/GetCgroupRoot: make it faster
2020-07-31 11:43:38 +09:00
Mrunal Patel 46243fcea1 Merge pull request #2500 from kolyshkin/fs-apply
libct/cgroups/fs: rework Apply()
2020-07-30 16:39:53 -07:00
Kir Kolyshkin e0c0b0cf32 libct/cgroups/GetCgroupRoot: make it faster
...by checking the default path first.

Quick benchmark shows it's about 5x faster on an idle system, and the
gain should be much more on a system doing mounts etc.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-07-30 13:45:21 -07:00
Mrunal Patel cf1273abf4 Merge pull request #2498 from kolyshkin/v1-code-cleanups
libct/cgroups/fs: code cleanups
2020-07-09 15:58:06 -07:00
Kir Kolyshkin a73ce38d16 cgroupv1/FindCgroupMountpoint: add a fast path
In case cgroupPath is under the default cgroup prefix, let's try to
guess the mount point by adding the subsystem name to the default
prefix, and resolving the resulting path in case it's a symlink.

In most cases, given the default cgroup setup, this trick
should result in returning the same result faster, and avoiding
/proc/self/mountinfo parsing which is relatively slow and problematic.

Be very careful with the default path, checking it is
 - a directory;
 - a mount point;
 - has cgroup fstype.

If something is not right, fall back to parsing mountinfo.

While at it, remove the obsoleted comment about mountinfo parsing.  The
comment belongs to findCgroupMountpointAndRootFromReader(), but rather
than moving it there, let's just remove it, since it does not add any
value in understanding the current code.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-07-07 13:57:33 -07:00
Kir Kolyshkin c1adc99a20 cgroup/fs: rework Apply()
In manager.Apply() method, a path to each subsystem is obtained by
calling d.path(sys.Name()), and the sys.Apply() is called that does
the same call to d.path() again.

d.path() is an expensive call, so rather than to call it twice, let's
reuse the result.

This results the number of times we parse mountinfo during container
start from 62 to 34 on my setup.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-07-07 10:58:37 -07:00
Aleksa Sarai 819fcc687e merge branch 'pr-2495'
Kir Kolyshkin (1):
  cgroups/fs/path: optimize

LGTMs: @mrunalp @cyphar
Closes #2495
2020-07-07 11:51:06 +10:00
Kir Kolyshkin 2a322e91ec cgroupv1: remove subsystemSet.Get()
Instead of iterating over m.paths, iterate over subsystems and look up
the path for each. This is faster since a map lookup is faster than
iterating over the names in Get. A quick benchmark shows that the new
way is 2.5x faster than the old one.

Note though that this is not done to make things faster, as savings are
negligible, but to make things simpler by removing some code.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-07-06 18:31:46 -07:00
Kir Kolyshkin daf30cb7ca cgroups/fs: rm getSubsystems
It does not add any value.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-07-06 18:29:14 -07:00
Kir Kolyshkin 2e22579946 libct/cgroups/fs.GetStats: drop PathExists check
Half of controllers' GetStats just return nil, and most of the others
ignore ENOENT on files, so it will be cheaper to not check that the
path exists in the main GetStats method, offloading that to the
controllers.

Drop PathExists check from GetStats, add it to those controllers'
GetStats where it was missing.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-07-06 18:02:17 -07:00