diff --git a/cg.go b/cg.go index 9b11afa..3f8d0aa 100644 --- a/cg.go +++ b/cg.go @@ -28,7 +28,7 @@ func NewCgroup(name string) Cgroup { cg := Cgroup{ C.cgroup_new_cgroup(C.CString(name)), } - runtime.SetFinalizer(cg, freeCgroupThings) + runtime.SetFinalizer(&cg, freeCgroupThings) return cg } @@ -43,9 +43,10 @@ func (cg Cgroup) GetController(name string) Controller { } } -func freeCgroupThings(cg Cgroup) { - freeCgroup(cg) - freeControllers(cg) +func freeCgroupThings(cg *Cgroup) { + + freeCgroup(*cg) + freeControllers(*cg) } func freeCgroup(cg Cgroup) { @@ -65,13 +66,202 @@ TODO correct docs for golang implementation All parameters set by cgroup_add_value_* functions are written. The created groups has owner which was set by cgroup_set_uid_gid() and permissions set by cgroup_set_permissions. + + foo = cgroup.NewCgroup("foo) + foo.Create() + */ -func CreateGroup(cg Cgroup, ignore_ownership bool) error { - var i int = 0 - if ignore_ownership == true { - i = 1 - } - return _err(C.cgroup_create_cgroup(cg.g, C.int(i))) +func (cg Cgroup) Create() error { + return _err(C.cgroup_create_cgroup(cg.g, C.int(0))) +} + +/* +Same as Create(), but all errors are ignored when setting +owner of the group and/or its tasks file. +*/ +func (cg Cgroup) CreateIgnoreOwnership() error { + return _err(C.cgroup_create_cgroup(cg.g, C.int(1))) +} + +/* +Physically create new control group in kernel, with all parameters and values +copied from its parent group. The group is created in all hierarchies, where +the parent group exists. I.e. following code creates subgroup in all +hierarchies, because all of them have root (=parent) group. + + foo = cgroup.NewCgroup("foo) + foo.CreateFromParent() + +*/ +func (cg Cgroup) CreateFromParent() error { + return _err(C.cgroup_create_cgroup_from_parent(cg.g, C.int(0))) +} + +/* +Same as CreateFromParent(), but all errors are ignored when setting +owner of the group and/or its tasks file. +*/ +func (cg Cgroup) CreateFromParentIgnoreOwnership() error { + return _err(C.cgroup_create_cgroup_from_parent(cg.g, C.int(1))) +} + +/* +Physically modify a control group in kernel. All parameters added by +cgroup_add_value_ or cgroup_set_value_ are written. +Currently it's not possible to change and owner of a group. + +TODO correct docs for golang implementation +*/ +func (cg Cgroup) Modify() error { + return _err(C.cgroup_modify_cgroup(cg.g)) +} + +/* +Physically remove a control group from kernel. The group is removed from +all hierarchies, which cover controllers added by Cgroup.AddController() +or GetCgroup(). All tasks inside the group are automatically moved +to parent group. + +The group being removed must be empty, i.e. without subgroups. Use +cgroup_delete_cgroup_ext() for recursive delete. + +TODO correct docs for golang implementation +*/ +func (cg Cgroup) Delete() error { + return _err(C.cgroup_delete_cgroup(cg.g, C.int(0))) +} + +/* +Same as Delete(), but ignores errors when migrating. +*/ +func (cg Cgroup) DeleteIgnoreMigration() error { + return _err(C.cgroup_delete_cgroup(cg.g, C.int(1))) +} + +/* +Physically remove a control group from kernel. +All tasks are automatically moved to parent group. +If DeleteIgnoreMigration flag is used, the errors that occurred +during the task movement are ignored. +DeleteRecursive flag specifies that all subgroups should be removed +too. If root group is being removed with this flag specified, all subgroups +are removed but the root group itself is left undeleted. +*/ +func (cg Cgroup) DeleteExt(flags DeleteFlag) error { + return _err(C.cgroup_delete_cgroup_ext(cg.g, C.int(flags))) +} + +/* +Read all information regarding the group from kernel. +Based on name of the group, list of controllers and all parameters and their +values are read from all hierarchies, where a group with given name exists. +All existing controllers are replaced. I.e. following code will fill root with +controllers from all hierarchies, because the root group is available in all of +them. + + root := cgroup.NewCgroup("/") + err := root.Get() + ... + +*/ +func (cg Cgroup) Get() error { + return _err(C.cgroup_get_cgroup(cg.g)) +} + +type UID C.uid_t +type GID C.gid_t + +/* +Set owner of the group control files and the @c tasks file. This function +modifies only libcgroup internal cgroup structure, use +Cgroup.Create() afterwards to create the group with given owners. + +@param cgroup +@param tasks_uid UID of the owner of group's @c tasks file. +@param tasks_gid GID of the owner of group's @c tasks file. +@param control_uid UID of the owner of group's control files (i.e. +parameters). +@param control_gid GID of the owner of group's control files (i.e. +parameters). +*/ +func (cg Cgroup) SetUidGid(tasks_uid UID, tasks_gid GID, + control_uid UID, control_gid GID) error { + return _err(C.cgroup_set_uid_gid(cg.g, + C.uid_t(tasks_uid), C.gid_t(tasks_gid), + C.uid_t(control_uid), C.gid_t(control_gid))) + +} + +/* +Return owners of the group's @c tasks file and control files. +The data is read from libcgroup internal cgroup structure, use +Cgroup.SetUidGid() or Cgroup.Get() to fill it. +*/ +func (cg Cgroup) GetUidGid() (tasks_uid UID, tasks_gid GID, control_uid UID, control_gid GID, err error) { + var ( + c_t_u C.uid_t + c_t_g C.gid_t + c_c_u C.uid_t + c_c_g C.gid_t + ) + err = _err(C.cgroup_set_uid_gid(cg.g, + c_t_u, + c_t_g, + c_c_u, + c_c_g)) + return UID(c_t_u), GID(c_t_g), UID(c_c_u), GID(c_c_g), err + +} + +const ( + // Uninitialized file/directory permissions used for task/control files. + NO_PERMS = C.NO_PERMS + + // Uninitialized UID/GID used for task/control files. + NO_UID_GID = C.NO_UID_GID +) + +type Mode C.mode_t + +/* +Stores given file permissions of the group's control and tasks files +into the cgroup data structure. Use NO_PERMS if permissions shouldn't +be changed or a value which applicable to chmod(2). Please note that +the given permissions are masked with the file owner's permissions. +For example if a control file has permissions 640 and control_fperm is +471 the result will be 460. + +control_dperm Directory permission for the group. +control_fperm File permission for the control files. +task_fperm File permissions for task file. + + g := cgroup.NewCgroup("foo") + g.SetPermissions(cgroup.Mode(0777), cgroup.Mode(0777), cgroup.Mode(0777)) +*/ +func (cg Cgroup) SetPermissions(control_dperm, control_fperm, task_fperm Mode) { + C.cgroup_set_permissions(cg.g, C.mode_t(control_dperm), + C.mode_t(control_fperm), C.mode_t(task_fperm)) +} + +/* +Copy all controllers, parameters and their values. All existing controllers +in the source group are discarded. +*/ +func CopyCgroup(src, dest Cgroup) error { + return _err(C.cgroup_copy_cgroup(src.g, dest.g)) +} + +/* +Compare names, owners, controllers, parameters and values of two groups. + +Return value of: + * nil - a and b are equal + * ECGROUPNOTEQUAL - groups are not equal + * ECGCONTROLLERNOTEQUAL - controllers are not equal + +*/ +func CompareCgroup(a, b Cgroup) error { + return _err(C.cgroup_compare_cgroup(a.g, b.g)) } /* @@ -83,6 +273,27 @@ type Controller struct { c *C.struct_cgroup_controller } +/* +Add parameter and its value to internal libcgroup structures. +Use Cgroup.Modify() or Cgroup.Create() to write it to kernel. + +Name of the parameter and its value +*/ +func (c Controller) AddValueString(name, value string) error { + return _err(C.cgroup_add_value_string(c.c, C.CString(name), C.CString(value))) +} + +/* +Compare names, parameters and values of two controllers. + +Return value of: + * nil - a and b are equal + * ECGCONTROLLERNOTEQUAL - controllers are not equal +*/ +func CompareControllers(a, b Controller) error { + return _err(C.cgroup_compare_controllers(a.c, b.c)) +} + /* Initialize libcgroup. Information about mounted hierarchies are examined and cached internally (just what's mounted where, not the groups themselves). @@ -154,7 +365,7 @@ New default permissions from this group are copied to libcgroup internal structures. */ func SetDefault(cg Cgroup) error { - return _err(C.cgroup_config_set_default(cg.g)) + return _err(C.cgroup_config_set_default(cg.g)) } type FileInfo struct { @@ -244,8 +455,10 @@ func GetSubSysMountPoint(controller string) (string, error) { var ( // End-of-file for iterators - ECGEOF = errors.New(C.GoString(C.cgroup_strerror(C.ECGEOF))) - ECGOTHER = errors.New(C.GoString(C.cgroup_strerror(C.ECGOTHER))) + ECGEOF = errors.New(C.GoString(C.cgroup_strerror(C.ECGEOF))) + ECGOTHER = errors.New(C.GoString(C.cgroup_strerror(C.ECGOTHER))) + ECGROUPNOTEQUAL = errors.New(C.GoString(C.cgroup_strerror(C.ECGROUPNOTEQUAL))) + ECGCONTROLLERNOTEQUAL = errors.New(C.GoString(C.cgroup_strerror(C.ECGCONTROLLERNOTEQUAL))) ) /* @@ -263,6 +476,10 @@ func _err(num C.int) error { return ECGEOF case C.ECGOTHER: return ECGOTHER + case C.ECGROUPNOTEQUAL: + return ECGROUPNOTEQUAL + case C.ECGCONTROLLERNOTEQUAL: + return ECGCONTROLLERNOTEQUAL } // There's a lot. We'll create them as they come return errors.New(C.GoString(C.cgroup_strerror(num)))