func (s *PerfEventGroup) Set(d *data) error {
	// we just want to join this group even though we don't set anything
	if _, err := d.join("perf_event"); err != nil && !cgroups.IsNotFound(err) {
		return err
	}
	return nil
}
func Apply(c *cgroups.Cgroup, pid int) (map[string]string, error) {
	d, err := getCgroupData(c, pid)
	if err != nil {
		return nil, err
	}

	paths := make(map[string]string)
	defer func() {
		if err != nil {
			cgroups.RemovePaths(paths)
		}
	}()
	for name, sys := range subsystems {
		if err := sys.Set(d); err != nil {
			return nil, err
		}
		// FIXME: Apply should, ideally, be reentrant or be broken up into a separate
		// create and join phase so that the cgroup hierarchy for a container can be
		// created then join consists of writing the process pids to cgroup.procs
		p, err := d.path(name)
		if err != nil {
			if cgroups.IsNotFound(err) {
				continue
			}
			return nil, err
		}
		paths[name] = p
	}
	return paths, nil
}
Example #3
0
func (s *BlkioGroup) Set(d *data) error {
	dir, err := d.join("blkio")
	if err != nil && !cgroups.IsNotFound(err) {
		return err
	}

	if d.c.BlkioWeight != 0 {
		if err := writeFile(dir, "blkio.weight", strconv.FormatInt(d.c.BlkioWeight, 10)); err != nil {
			return err
		}
	}

	return nil
}
func Apply(c *cgroups.Cgroup, pid int) (map[string]string, error) {
	var (
		unitName   = getUnitName(c)
		slice      = "system.slice"
		properties []systemd.Property
		res        = &systemdCgroup{}
	)

	res.cgroup = c

	if c.Slice != "" {
		slice = c.Slice
	}

	properties = append(properties,
		systemd.PropSlice(slice),
		systemd.PropDescription("docker container "+c.Name),
		newProp("PIDs", []uint32{uint32(pid)}),
	)

	// Always enable accounting, this gets us the same behaviour as the fs implementation,
	// plus the kernel has some problems with joining the memory cgroup at a later time.
	properties = append(properties,
		newProp("MemoryAccounting", true),
		newProp("CPUAccounting", true),
		newProp("BlockIOAccounting", true))

	if c.Memory != 0 {
		properties = append(properties,
			newProp("MemoryLimit", uint64(c.Memory)))
	}
	// TODO: MemoryReservation and MemorySwap not available in systemd

	if c.CpuShares != 0 {
		properties = append(properties,
			newProp("CPUShares", uint64(c.CpuShares)))
	}

	if c.BlkioWeight != 0 {
		properties = append(properties,
			newProp("BlockIOWeight", uint64(c.BlkioWeight)))
	}

	if _, err := theConn.StartTransientUnit(unitName, "replace", properties...); err != nil {
		return nil, err
	}

	if !c.AllowAllDevices {
		if err := joinDevices(c, pid); err != nil {
			return nil, err
		}
	}

	// -1 disables memorySwap
	if c.MemorySwap >= 0 && (c.Memory != 0 || c.MemorySwap > 0) {
		if err := joinMemory(c, pid); err != nil {
			return nil, err
		}

	}

	// we need to manually join the freezer and cpuset cgroup in systemd
	// because it does not currently support it via the dbus api.
	if err := joinFreezer(c, pid); err != nil {
		return nil, err
	}

	if err := joinCpuset(c, pid); err != nil {
		return nil, err
	}

	paths := make(map[string]string)
	for _, sysname := range []string{
		"devices",
		"memory",
		"cpu",
		"cpuset",
		"cpuacct",
		"blkio",
		"perf_event",
		"freezer",
	} {
		subsystemPath, err := getSubsystemPath(res.cgroup, sysname)
		if err != nil {
			// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
			if cgroups.IsNotFound(err) {
				continue
			}
			return nil, err
		}
		paths[sysname] = subsystemPath
	}
	return paths, nil
}