carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package cgroup
4
5import (
6 "errors"
7
8 "github.com/carlosframework/platform/internal/controlname"
9 "golang.org/x/sys/unix"
10)
11
12type ContainmentIdentity struct{ Device, Inode uint64 }
13
14func (p *Prepared) Identity() (ContainmentIdentity, error) {
15 if p == nil || p.strictPreparedState == nil {
16 return ContainmentIdentity{}, ErrStrictState
17 }
18 p.mu.Lock()
19 defer p.mu.Unlock()
20 if err := p.identityOK(); err != nil {
21 return ContainmentIdentity{}, err
22 }
23 return ContainmentIdentity{Device: p.identity.device, Inode: p.identity.inode}, nil
24}
25
26// PrepareRoleChild pins a newly empty role group below the host parent. It
27// never reuses the parent's populated group and inherits its aggregate limits.
28func (p *Prepared) PrepareRoleChild(role string) (*Prepared, error) {
29 return p.prepareRoleChild(role, nil)
30}
31
32// PrepareRoleChildWithIntent requires a new name and persists the caller's
33// intention under the pinned parent before mkdir. A failed preparation retains
34// that intention for stop recovery; it never authorizes execution by itself.
35func (p *Prepared) PrepareRoleChildWithIntent(role string, intent func(ContainmentIdentity) error) (*Prepared, error) {
36 if intent == nil {
37 return nil, ErrStrictRefused
38 }
39 return p.prepareRoleChild(role, intent)
40}
41
42func (p *Prepared) prepareRoleChild(role string, intent func(ContainmentIdentity) error) (out *Prepared, err error) {
43 if p == nil || p.strictPreparedState == nil || !controlname.ValidLabel(role) {
44 return nil, ErrStrictRefused
45 }
46 p.mu.Lock()
47 defer p.mu.Unlock()
48 if p.parent != nil || p.empty || p.draining.Load() {
49 return nil, ErrStrictState
50 }
51 if err = p.identityOK(); err != nil {
52 return nil, err
53 }
54 name := "role-" + role
55 beforeMkdir := func() error {
56 if intent != nil {
57 var st unix.Stat_t
58 if e := unix.Fstatat(int(p.dir.Fd()), name, &st, unix.AT_SYMLINK_NOFOLLOW); !errors.Is(e, unix.ENOENT) {
59 return ErrStrictRefused
60 }
61 if e := intent(ContainmentIdentity{Device: p.identity.device, Inode: p.identity.inode}); e != nil {
62 return e
63 }
64 }
65 return nil
66 }
67 allowExisting := intent == nil
68 child, err := pinChild(p, name, beforeMkdir, allowExisting)
69 if err != nil {
70 return nil, err
71 }
72 return child, nil
73}
74