gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

cpuset.go (3901B)


      1 /*
      2    Copyright The containerd Authors.
      3 
      4    Licensed under the Apache License, Version 2.0 (the "License");
      5    you may not use this file except in compliance with the License.
      6    You may obtain a copy of the License at
      7 
      8        http://www.apache.org/licenses/LICENSE-2.0
      9 
     10    Unless required by applicable law or agreed to in writing, software
     11    distributed under the License is distributed on an "AS IS" BASIS,
     12    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13    See the License for the specific language governing permissions and
     14    limitations under the License.
     15 */
     16 
     17 package cgroup1
     18 
     19 import (
     20 	"bytes"
     21 	"fmt"
     22 	"os"
     23 	"path/filepath"
     24 
     25 	specs "github.com/opencontainers/runtime-spec/specs-go"
     26 )
     27 
     28 func NewCpuset(root string) *cpusetController {
     29 	return &cpusetController{
     30 		root: filepath.Join(root, string(Cpuset)),
     31 	}
     32 }
     33 
     34 type cpusetController struct {
     35 	root string
     36 }
     37 
     38 func (c *cpusetController) Name() Name {
     39 	return Cpuset
     40 }
     41 
     42 func (c *cpusetController) Path(path string) string {
     43 	return filepath.Join(c.root, path)
     44 }
     45 
     46 func (c *cpusetController) Create(path string, resources *specs.LinuxResources) error {
     47 	if err := c.ensureParent(c.Path(path), c.root); err != nil {
     48 		return err
     49 	}
     50 	if err := os.MkdirAll(c.Path(path), defaultDirPerm); err != nil {
     51 		return err
     52 	}
     53 	if err := c.copyIfNeeded(c.Path(path), filepath.Dir(c.Path(path))); err != nil {
     54 		return err
     55 	}
     56 	if resources.CPU != nil {
     57 		for _, t := range []struct {
     58 			name  string
     59 			value string
     60 		}{
     61 			{
     62 				name:  "cpus",
     63 				value: resources.CPU.Cpus,
     64 			},
     65 			{
     66 				name:  "mems",
     67 				value: resources.CPU.Mems,
     68 			},
     69 		} {
     70 			if t.value != "" {
     71 				if err := os.WriteFile(
     72 					filepath.Join(c.Path(path), "cpuset."+t.name),
     73 					[]byte(t.value),
     74 					defaultFilePerm,
     75 				); err != nil {
     76 					return err
     77 				}
     78 			}
     79 		}
     80 	}
     81 	return nil
     82 }
     83 
     84 func (c *cpusetController) Update(path string, resources *specs.LinuxResources) error {
     85 	return c.Create(path, resources)
     86 }
     87 
     88 func (c *cpusetController) getValues(path string) (cpus []byte, mems []byte, err error) {
     89 	if cpus, err = os.ReadFile(filepath.Join(path, "cpuset.cpus")); err != nil && !os.IsNotExist(err) {
     90 		return
     91 	}
     92 	if mems, err = os.ReadFile(filepath.Join(path, "cpuset.mems")); err != nil && !os.IsNotExist(err) {
     93 		return
     94 	}
     95 	return cpus, mems, nil
     96 }
     97 
     98 // ensureParent makes sure that the parent directory of current is created
     99 // and populated with the proper cpus and mems files copied from
    100 // it's parent.
    101 func (c *cpusetController) ensureParent(current, root string) error {
    102 	parent := filepath.Dir(current)
    103 	if _, err := filepath.Rel(root, parent); err != nil {
    104 		return nil
    105 	}
    106 	// Avoid infinite recursion.
    107 	if parent == current {
    108 		return fmt.Errorf("cpuset: cgroup parent path outside cgroup root")
    109 	}
    110 	if cleanPath(parent) != root {
    111 		if err := c.ensureParent(parent, root); err != nil {
    112 			return err
    113 		}
    114 	}
    115 	if err := os.MkdirAll(current, defaultDirPerm); err != nil {
    116 		return err
    117 	}
    118 	return c.copyIfNeeded(current, parent)
    119 }
    120 
    121 // copyIfNeeded copies the cpuset.cpus and cpuset.mems from the parent
    122 // directory to the current directory if the file's contents are 0
    123 func (c *cpusetController) copyIfNeeded(current, parent string) error {
    124 	var (
    125 		err                      error
    126 		currentCpus, currentMems []byte
    127 		parentCpus, parentMems   []byte
    128 	)
    129 	if currentCpus, currentMems, err = c.getValues(current); err != nil {
    130 		return err
    131 	}
    132 	if parentCpus, parentMems, err = c.getValues(parent); err != nil {
    133 		return err
    134 	}
    135 	if isEmpty(currentCpus) {
    136 		if err := os.WriteFile(
    137 			filepath.Join(current, "cpuset.cpus"),
    138 			parentCpus,
    139 			defaultFilePerm,
    140 		); err != nil {
    141 			return err
    142 		}
    143 	}
    144 	if isEmpty(currentMems) {
    145 		if err := os.WriteFile(
    146 			filepath.Join(current, "cpuset.mems"),
    147 			parentMems,
    148 			defaultFilePerm,
    149 		); err != nil {
    150 			return err
    151 		}
    152 	}
    153 	return nil
    154 }
    155 
    156 func isEmpty(b []byte) bool {
    157 	return len(bytes.Trim(b, "\n")) == 0
    158 }