mirror of
git://slackware.nl/current.git
synced 2024-12-30 10:24:23 +01:00
2c20c6847e
a/kernel-firmware-20180606_d114732-noarch-1.txz: Upgraded. a/kernel-generic-4.14.49-x86_64-1.txz: Upgraded. a/kernel-huge-4.14.49-x86_64-1.txz: Upgraded. a/kernel-modules-4.14.49-x86_64-1.txz: Upgraded. a/libcgroup-0.41-x86_64-4.txz: Rebuilt. Apply all post 0.41 patches from git, including one for an infinite loop bug that causes 100% CPU usage on one core. Thanks to chris.willing. a/pkgtools-15.0-noarch-17.txz: Rebuilt. installpkg: Use terse mode if TERSE=0 is set in the environment (this already works for removepkg and upgradepkg). This allows using terse mode in other tools that use the pkgtools (such as slackpkg with: TERSE=0 slackpkg). Thanks to Xsane. ap/hplip-3.18.6-x86_64-1.txz: Upgraded. d/kernel-headers-4.14.49-x86-1.txz: Upgraded. k/kernel-source-4.14.49-noarch-1.txz: Upgraded. GPIO_AMDPT n -> m (thanks to walecha) NFSD_V3_ACL n -> y (thanks to Jonathan Woithe) NFS_V3_ACL n -> y (thanks to Jonathan Woithe) NFS_V4_2 n -> y +NFSD_V2_ACL y +NFS_ACL_SUPPORT y +NFS_V4_SECURITY_LABEL y l/LibRaw-0.18.12-x86_64-1.txz: Upgraded. This update fixes bugs and security issues, including: parse_qt: possible integer overflow reject broken/crafted NOKIARAW files recover read position if TIFF/EXIF tag is too long possible infinite loop in parse_minolta() possible stack overrun in X3F parser out of bounds read in X3F parser For more information, see: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-13735 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-14265 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-10528 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-10529 (* Security fix *) l/dconf-0.26.1-x86_64-3.txz: Rebuilt. Eliminate install script noise. l/dconf-editor-3.26.2-x86_64-3.txz: Rebuilt. Eliminate install script noise. n/iproute2-4.17.0-x86_64-1.txz: Upgraded. x/wqy-zenhei-font-ttf-0.8.38_1-noarch-7.txz: Rebuilt. Try to avoid overriding other font choices unless lang = zh-cn or zh-sg. x/xkbcomp-1.4.2-x86_64-1.txz: Upgraded. isolinux/initrd.img: Rebuilt. kernels/*: Upgraded. usb-and-pxe-installers/usbboot.img: Rebuilt.
1595 lines
44 KiB
Diff
1595 lines
44 KiB
Diff
diff --git a/doc/man/cgclassify.1 b/doc/man/cgclassify.1
|
|
index db4e086..1facd2b 100644
|
|
--- a/doc/man/cgclassify.1
|
|
+++ b/doc/man/cgclassify.1
|
|
@@ -57,7 +57,25 @@ controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
|
|
.TP
|
|
.B /etc/cgrules.conf
|
|
default libcgroup configuration file
|
|
+.TP
|
|
+.B /etc/cgrules.d
|
|
+default libcgroup configuration files directory
|
|
+
|
|
+.SH EXAMPLES
|
|
+.TP
|
|
+.B cgclassify -g cpu:student 1234
|
|
+moves process with pid number 1234 to control group student in cpu hierarchy.
|
|
|
|
+.TP
|
|
+.B cgclassify 1234
|
|
+moves process with pid number 1234 to control groups based on
|
|
+\fB/etc/cgrules.conf\fR configuration file.
|
|
+
|
|
+.TP
|
|
+.B cgclassify --sticky -g cpu:/student 1234
|
|
+moves process with pid number 1234 to control group student in cpu hierarchy.
|
|
+The daemon of service cgred does not change cgroups of pid 1234 and its children
|
|
+(based on \fB/etc/cgrules.conf\fR).
|
|
|
|
.SH SEE ALSO
|
|
cgrules.conf (5), cgexec (1)
|
|
diff --git a/doc/man/cgclear.1 b/doc/man/cgclear.1
|
|
index 318c925..241a095 100644
|
|
--- a/doc/man/cgclear.1
|
|
+++ b/doc/man/cgclear.1
|
|
@@ -43,5 +43,24 @@ option works only with \fB-l\fR or \fB-L\fR options.
|
|
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
|
|
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
|
|
|
|
+.SH FILES
|
|
+.TP
|
|
+.B /etc/cgconfig.conf
|
|
+default templates file
|
|
+.TP
|
|
+.B /etc/cgconfig.d/
|
|
+default templates files directory
|
|
+.RE
|
|
+
|
|
+
|
|
+.SH EXAMPLES
|
|
+.TP
|
|
+.B cgclear
|
|
+unload the whole cgroup filesystem
|
|
+
|
|
+.TP
|
|
+.B cgclear -l /etc/cgconfig.conf
|
|
+unload a subsystem of cgroup filesystem based on \fB/etc/cgconfig.conf\fR definition.
|
|
+
|
|
.SH SEE ALSO
|
|
-cgconfigparser(1)
|
|
+cgconfigparser(1), cgconfig.conf(5)
|
|
diff --git a/doc/man/cgconfig.conf.5 b/doc/man/cgconfig.conf.5
|
|
index be80e4e..f3a4ba9 100644
|
|
--- a/doc/man/cgconfig.conf.5
|
|
+++ b/doc/man/cgconfig.conf.5
|
|
@@ -251,6 +251,9 @@ Templates does not use
|
|
.B default
|
|
section settings.
|
|
|
|
+.I /etc/cgconfig.d/
|
|
+directory can be used for additional configuration files. cgrulesengd searches this directory for additional templates.
|
|
+
|
|
.\"********************************************"
|
|
.SH EXAMPLES
|
|
.LP
|
|
@@ -781,13 +784,12 @@ better to explicitly specify all groups and all controllers
|
|
related to them.
|
|
|
|
.SH FILES
|
|
-.LP
|
|
-.PD .1v
|
|
-.TP 20
|
|
-.B /etc/cgconfig.conf
|
|
.TP
|
|
+.B /etc/cgconfig.conf
|
|
default libcgroup configuration file
|
|
-.PD
|
|
+.TP
|
|
+.B /etc/cgconfig.d/
|
|
+default libcgroup configuration files directory
|
|
|
|
.SH SEE ALSO
|
|
cgconfigparser (8)
|
|
diff --git a/doc/man/cgconfigparser.8 b/doc/man/cgconfigparser.8
|
|
index 0a20f95..8fff95f 100644
|
|
--- a/doc/man/cgconfigparser.8
|
|
+++ b/doc/man/cgconfigparser.8
|
|
@@ -74,5 +74,19 @@ of this group have write access to the file.
|
|
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
|
|
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
|
|
|
|
+.SH FILES
|
|
+.TP
|
|
+.B /etc/cgconfig.conf
|
|
+default libcgroup configuration file
|
|
+.TP
|
|
+.B /etc/cgconfig.d/
|
|
+default libcgroup configuration files directory
|
|
+
|
|
+.SH EXAMPLES
|
|
+.TP
|
|
+.B cgconfigparser -l /etc/cgconfig.conf
|
|
+setup control group file system based on \fB/etc/cgconfig.conf\fR configuration file
|
|
+
|
|
+
|
|
.SH SEE ALSO
|
|
cgconfig.conf (5)
|
|
diff --git a/doc/man/cgcreate.1 b/doc/man/cgcreate.1
|
|
index 7068073..6ec1b27 100644
|
|
--- a/doc/man/cgcreate.1
|
|
+++ b/doc/man/cgcreate.1
|
|
@@ -38,7 +38,8 @@ others permissions to the owners permissions).
|
|
.TP
|
|
.B -g <controllers>:<path>
|
|
defines control groups to be added.
|
|
-\fBcontrollers\fR is a list of controllers and
|
|
+\fBcontrollers\fR is a list of controllers. Character "*" can be used
|
|
+as a shortcut for "all mounted controllers".
|
|
\fBpath\fR is the relative path to control groups
|
|
in the given controllers list. This option can be specified
|
|
multiple times.
|
|
@@ -69,9 +70,16 @@ The default value is the same as has the parent cgroup.
|
|
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
|
|
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
|
|
|
|
-.SH FILES
|
|
+.SH EXAMPLES
|
|
+.TP
|
|
+.B cgcreate -g *:student devices:teacher
|
|
+create control group student in all mounted hierarchies and create
|
|
+control group teacher in hierarchy containing controller devices.
|
|
+
|
|
+
|
|
+
|
|
|
|
.SH SEE ALSO
|
|
cgrules.conf (5)
|
|
cgexec (1)
|
|
-cgclassify (1)
|
|
+cgclassify (1)
|
|
\ No newline at end of file
|
|
diff --git a/doc/man/cgdelete.1 b/doc/man/cgdelete.1
|
|
index 025a799..9572287 100644
|
|
--- a/doc/man/cgdelete.1
|
|
+++ b/doc/man/cgdelete.1
|
|
@@ -16,7 +16,7 @@ program removes all specified control groups.
|
|
|
|
.TP
|
|
.B [-g] <controllers>:<path>
|
|
-Defines the control group to delete. Multiple control groups nay be
|
|
+Defines the control group to delete. Multiple control groups may be
|
|
specified.
|
|
.B -g
|
|
is optional.
|
|
@@ -35,5 +35,11 @@ Recursively remove all subgroups.
|
|
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
|
|
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
|
|
|
|
+.SH EXAMPLES
|
|
+.TP
|
|
+.B cgdelete -g cpu,devices:/test
|
|
+remove control group test from hierarchies containing cpu and device controllers
|
|
+
|
|
+
|
|
.SH SEE ALSO
|
|
cgcreate (1), lscgroup (1), cgclear (1)
|
|
diff --git a/doc/man/cgred.conf.5 b/doc/man/cgred.conf.5
|
|
index 3fe760f..1c0922f 100644
|
|
--- a/doc/man/cgred.conf.5
|
|
+++ b/doc/man/cgred.conf.5
|
|
@@ -42,7 +42,7 @@ default libcgroup configuration file
|
|
|
|
.SH SEE ALSO
|
|
cgrules.conf (5),
|
|
-cgconfig.conf (5)
|
|
+cgconfig.conf (5), cgrules.d (5)
|
|
|
|
|
|
|
|
diff --git a/doc/man/cgrules.conf.5 b/doc/man/cgrules.conf.5
|
|
index 7a89fb5..2d434e7 100644
|
|
--- a/doc/man/cgrules.conf.5
|
|
+++ b/doc/man/cgrules.conf.5
|
|
@@ -85,7 +85,7 @@ configuration file. See (\fBcgconfig.conf\fR (5)).
|
|
If the template definition is not found there created group have default
|
|
kernel setting.
|
|
|
|
-
|
|
+To create a hierarchy of configuration files, use \fB/etc/cgrules.d\fR directory.
|
|
|
|
.SH EXAMPLES
|
|
.nf
|
|
@@ -136,13 +136,19 @@ process.
|
|
.PD .1v
|
|
.TP 20
|
|
.B /etc/cgrules.conf
|
|
-.TP
|
|
+.RS 6
|
|
default libcgroup configuration file
|
|
-.PD .
|
|
+.RE
|
|
+.TP 20
|
|
+.B /etc/cgrules.d
|
|
+.RS 6
|
|
+default libcgroup configuration files directory
|
|
+.RE
|
|
+.PD
|
|
|
|
|
|
.SH SEE ALSO
|
|
-cgconfig.conf (5), cgclassify (1), cgred.conf (5)
|
|
+cgconfig.conf (5), cgclassify (1), cgred.conf (5), cgrules.d (5)
|
|
|
|
.SH BUGS
|
|
|
|
diff --git a/doc/man/cgrules.d.5 b/doc/man/cgrules.d.5
|
|
new file mode 100644
|
|
index 0000000..37717de
|
|
--- /dev/null
|
|
+++ b/doc/man/cgrules.d.5
|
|
@@ -0,0 +1,50 @@
|
|
+.\" Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
|
|
+.\" Written by Jan Chaloupka <jchaloup@redhat.com>
|
|
+
|
|
+.TH CGRULES.D 5 2014-07-14 "Linux" "libcgroup Manual"
|
|
+.SH NAME
|
|
+cgrules.d \- libcgroup configuration files directory
|
|
+.SH DESCRIPTION
|
|
+.B "cgrules.d"
|
|
+configuration files directory is used by
|
|
+.B libcgroups
|
|
+and contains additional configuration files with the same syntax as
|
|
+\fBcgconfig.conf\fR (5).
|
|
+
|
|
+Files are parsed in an arbitrary order.
|
|
+If the cache is disabled, the searching algorithm of \fBcgrulesengd\fR (8)
|
|
+tries the first match.
|
|
+If there are two rules which match the criteria for a given process,
|
|
+and each rule is in a separate file, then there is no guarantee which one
|
|
+is chosen. If you want to control the given order of the rules, put them
|
|
+in one configuration file.
|
|
+
|
|
+
|
|
+\fB/etc/cgconfig.conf\fR is parsed as the first file. After success,
|
|
+all files from /etc/cgconfig.d are parsed as well (in an arbitrary order).
|
|
+If some file from the directory ends up with a parsing error,
|
|
+the process is stopped. With cache enabled, all successfully processed
|
|
+rules
|
|
+are kept in the cache. With cache disabled,
|
|
+matching is stopped and ends with a 'not found' result.
|
|
+
|
|
+If \fB/etc/cgrules.d\fR is empty, \fBcgrulesengd\fR (8) acts
|
|
+in a backwards compatibility mode.
|
|
+
|
|
+.SH FILES
|
|
+.LP
|
|
+.PD .1v
|
|
+.TP 20
|
|
+.B /etc/cgrules.d
|
|
+.RS 4
|
|
+default libcgroup configuration files directory
|
|
+.RE
|
|
+.B /etc/cgconfig.conf
|
|
+.RS 4
|
|
+default libcgroup configuration file
|
|
+.RE
|
|
+.PD .
|
|
+
|
|
+
|
|
+.SH SEE ALSO
|
|
+cgconfig.conf (5), cgrulesengd (8)
|
|
diff --git a/doc/man/cgrulesengd.8 b/doc/man/cgrulesengd.8
|
|
index 2e89c5b..cf45611 100644
|
|
--- a/doc/man/cgrulesengd.8
|
|
+++ b/doc/man/cgrulesengd.8
|
|
@@ -10,10 +10,11 @@ cgrulesengd \- control group rules daemon
|
|
.SH DESCRIPTION
|
|
\fBcgrulesengd\fR is a daemon, which distributes processes to control groups. When
|
|
any process changes its effective UID or GID, \fBcgrulesengd\fR inspects the list
|
|
-of rules loaded from the \fIcgrules.conf\fR file and moves the process to
|
|
-the appropriate control group.
|
|
+of rules loaded from the \fIcgrules.conf\fR file and files in \fIcgrules.d\fR
|
|
+(see \fBcgrules.d\fR (5) for potential conflicts) directory
|
|
+and moves the process to the appropriate control group.
|
|
|
|
-The list of rules is read during the daemon startup is are cached in the daemon's memory.
|
|
+The list of rules is read during the daemon startup and cached in the daemon's memory.
|
|
The daemon reloads the list of rules when it receives SIGUSR2 signal.
|
|
The daemon reloads the list of templates when it receives SIGUSR1 signal.
|
|
|
|
@@ -63,12 +64,21 @@ controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
|
|
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
|
|
|
|
.SH FILES
|
|
-.LP
|
|
-.PD .1v
|
|
-.TP 20
|
|
+.TP
|
|
.B /etc/cgrules.conf
|
|
+default libcgroup configuration file
|
|
+
|
|
+.TP
|
|
+.B /etc/cgrules.d
|
|
+default libcgroup configuration files directory
|
|
+
|
|
+.TP
|
|
+.B /etc/cgconfig.conf
|
|
+default templates file
|
|
+
|
|
.TP
|
|
-the default libcgroup configuration file
|
|
+.B /etc/cgconfig.d
|
|
+default templates directory
|
|
|
|
.SH SEE ALSO
|
|
-cgrules.conf (5)
|
|
+cgrules.conf (5), cgrules.d (5)
|
|
diff --git a/doc/man/cgset.1 b/doc/man/cgset.1
|
|
index be886c6..b05473f 100644
|
|
--- a/doc/man/cgset.1
|
|
+++ b/doc/man/cgset.1
|
|
@@ -36,5 +36,16 @@ copied to the input cgroup.
|
|
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
|
|
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
|
|
|
|
+.SH EXAMPLES
|
|
+.TP
|
|
+.B cgset -r cpuset.cpus=0-1 student
|
|
+set variable cpus in control group student (controller cpuset) to 0-1
|
|
+
|
|
+.TP
|
|
+.B cgset --copy-from group1/ group2/
|
|
+copy all parameters of group group1 to group group2
|
|
+(for all path where both cgroups are defined)
|
|
+
|
|
+
|
|
.SH SEE ALSO
|
|
cgrules.conf (1), cgcreate (1), cgget (1)
|
|
diff --git a/doc/man/cgsnapshot.1 b/doc/man/cgsnapshot.1
|
|
index 03c85f6..48a038e 100644
|
|
--- a/doc/man/cgsnapshot.1
|
|
+++ b/doc/man/cgsnapshot.1
|
|
@@ -8,7 +8,7 @@ cgsnapshot \- generate the configuration file for given controllers
|
|
|
|
.SH SYNOPSIS
|
|
\fBcgsnapshot\fR [\fB-h\fR] [\fB-s\fR] [\fB-t\fR] [\fB-b\fR \fIfile\fR]
|
|
-[\fB-w\fR \fIfile\fR] [\fB-f\fR \fIoutput_file\fR] [\fBcontroller\fR] [...]
|
|
+[\fB-w\fR \fIfile\fR] [\fB-f\fR \fIoutput_file\fR] [\fBcontroller\fR] [...]
|
|
|
|
.SH DESCRIPTION
|
|
\fBcgsnapshot\fR
|
|
@@ -96,5 +96,18 @@ default whitelist
|
|
.B /etc/cgconfig.conf
|
|
default libcgroup configuration file
|
|
|
|
+.SH EXAMPLES
|
|
+.TP
|
|
+.B cgsnapshot -s -f /etc/cgconfig.conf.cgsnapshot
|
|
+create configuration file which contains all mounted controllers and all
|
|
+control groups which are on the actual system
|
|
+
|
|
+.TP
|
|
+.B cgsnapshot -s -f /etc/cgconfig.conf.cgsnapshot cpu
|
|
+create configuration file which contains hierarchy containing cpu controller and all its
|
|
+control groups on the actual system
|
|
+
|
|
+
|
|
+
|
|
.SH SEE ALSO
|
|
cgconfig.conf (5)
|
|
diff --git a/doc/man/lscgroup.1 b/doc/man/lscgroup.1
|
|
index 693fbbc..124379e 100644
|
|
--- a/doc/man/lscgroup.1
|
|
+++ b/doc/man/lscgroup.1
|
|
@@ -26,6 +26,21 @@ list all existing cgroups.
|
|
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
|
|
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
|
|
|
|
+.SH EXAMPLES
|
|
+.TP
|
|
+.B lscgroup -g cpu:/
|
|
+list all cgroups which are in hierarchy containing cpu controller
|
|
+
|
|
+.TP
|
|
+.B lscgroup -g cpu:/student
|
|
+list all cgroups which are in hierarchy containing cpu controller
|
|
+in subgroup student
|
|
+
|
|
+.TP
|
|
+.B lscgroup
|
|
+list all cgroups which in all hierarchies
|
|
+
|
|
+
|
|
.SH SEE ALSO
|
|
lssubsys (1), cgcreate (1), cgdelete (1),
|
|
cgconfig.conf (5)
|
|
diff --git a/include/libcgroup/config.h b/include/libcgroup/config.h
|
|
index 43568e1..9aaa390 100644
|
|
--- a/include/libcgroup/config.h
|
|
+++ b/include/libcgroup/config.h
|
|
@@ -83,12 +83,33 @@ int cgroup_init_templates_cache(char *pathname);
|
|
*/
|
|
int cgroup_reload_cached_templates(char *pathname);
|
|
|
|
+/**
|
|
+ * Load the templates cache from files. Before calling this function,
|
|
+ * cgroup_templates_cache_set_source_files has to be called first.
|
|
+ * @param file_index index of file which was unable to be parsed
|
|
+ * @return 0 on success, > 0 on error
|
|
+ */
|
|
+int cgroup_load_templates_cache_from_files(int *file_index);
|
|
+
|
|
+/**
|
|
+ * Setting source files of templates. This function has to be called before
|
|
+ * any call of cgroup_load_templates_cache_from_files.
|
|
+ * @param tmpl_files
|
|
+ */
|
|
+struct cgroup_string_list;
|
|
+void cgroup_templates_cache_set_source_files(
|
|
+ struct cgroup_string_list *tmpl_files);
|
|
+
|
|
/**
|
|
* Physically create a new control group in kernel, based on given control
|
|
* group template and configuration file. If given template is not set in
|
|
* configuration file, then the procedure works create the control group
|
|
* using cgroup_create_cgroup() function
|
|
*
|
|
+ * Templates are loaded using cgroup_load_templates_cache_from_files
|
|
+ * function, which must be preceded by cgroup_templates_cache_set_source_files
|
|
+ * call.
|
|
+ *
|
|
* The flags can alter the behavior of this function:
|
|
* CGFLAG_USE_TEMPLATE_CACHE: Use cached templates instead of
|
|
* parsing the config file
|
|
diff --git a/include/libcgroup/groups.h b/include/libcgroup/groups.h
|
|
index d5c87aa..201558f 100644
|
|
--- a/include/libcgroup/groups.h
|
|
+++ b/include/libcgroup/groups.h
|
|
@@ -149,6 +149,16 @@ struct cgroup *cgroup_new_cgroup(const char *name);
|
|
struct cgroup_controller *cgroup_add_controller(struct cgroup *cgroup,
|
|
const char *name);
|
|
|
|
+/**
|
|
+ * Attach all mounted controllers to given cgroup. This function just modifies
|
|
+ * internal libcgroup structure, not the kernel control group.
|
|
+ *
|
|
+ * @param cgroup
|
|
+ * @return zero or error number
|
|
+ */
|
|
+int cgroup_add_all_controllers(struct cgroup *cgroup);
|
|
+
|
|
+
|
|
/**
|
|
* Return appropriate controller from given group.
|
|
* The controller must be added before using cgroup_add_controller() or loaded
|
|
diff --git a/src/api.c b/src/api.c
|
|
index bfd0177..0bf0615 100644
|
|
--- a/src/api.c
|
|
+++ b/src/api.c
|
|
@@ -473,17 +473,19 @@ static char *cg_skip_unused_charactors_in_rule(char *rule)
|
|
* The cache parameter alters the behavior of this function. If true, this
|
|
* function will read the entire configuration file and store the results in
|
|
* rl (global rules list). If false, this function will only parse until it
|
|
- * finds a rule matching the given UID or GID. It will store this rule in rl,
|
|
+ * finds a rule matching the given UID or GID. It will store this rule in trl,
|
|
* as well as any children rules (rules that begin with a %) that it has.
|
|
*
|
|
* This function is NOT thread safe!
|
|
+ * @param filename configuration file to parse
|
|
* @param cache True to cache rules, else false
|
|
* @param muid If cache is false, the UID to match against
|
|
* @param mgid If cache is false, the GID to match against
|
|
* @return 0 on success, -1 if no cache and match found, > 0 on error.
|
|
* TODO: Make this function thread safe!
|
|
+ *
|
|
*/
|
|
-static int cgroup_parse_rules(bool cache, uid_t muid,
|
|
+static int cgroup_parse_rules_file(char *filename, bool cache, uid_t muid,
|
|
gid_t mgid, const char *mprocname)
|
|
{
|
|
/* File descriptor for the configuration file */
|
|
@@ -544,21 +546,19 @@ static int cgroup_parse_rules(bool cache, uid_t muid,
|
|
else
|
|
lst = &trl;
|
|
|
|
- /* If our list already exists, clean it. */
|
|
- if (lst->head)
|
|
- cgroup_free_rule_list(lst);
|
|
-
|
|
/* Open the configuration file. */
|
|
- pthread_rwlock_wrlock(&rl_lock);
|
|
- fp = fopen(CGRULES_CONF_FILE, "re");
|
|
+ fp = fopen(filename, "re");
|
|
if (!fp) {
|
|
cgroup_warn("Warning: failed to open configuration file %s: %s\n",
|
|
- CGRULES_CONF_FILE, strerror(errno));
|
|
- goto unlock;
|
|
+ filename, strerror(errno));
|
|
+
|
|
+ ret = ECGRULESPARSEFAIL; /* originally ret = 0, but */
|
|
+ /* this is parse fail, not success */
|
|
+ goto finish;
|
|
}
|
|
|
|
/* Now, parse the configuration file one line at a time. */
|
|
- cgroup_dbg("Parsing configuration file.\n");
|
|
+ cgroup_dbg("Parsing configuration file %s.\n", filename);
|
|
while (fgets(buff, sizeof(buff), fp) != NULL) {
|
|
linenum++;
|
|
|
|
@@ -804,8 +804,143 @@ parsefail:
|
|
|
|
close:
|
|
fclose(fp);
|
|
-unlock:
|
|
+finish:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Parse CGRULES_CONF_FILE and all files in CGRULES_CONF_FILE_DIR.
|
|
+ * If CGRULES_CONF_FILE_DIR does not exists or can not be read,
|
|
+ * parse only CGRULES_CONF_FILE. This way we keep the back compatibility.
|
|
+ *
|
|
+ * Original description of this function moved to cgroup_parse_rules_file.
|
|
+ * Also cloned and all occurences of file changed to files.
|
|
+ *
|
|
+ * Parse the configuration files that maps UID/GIDs to cgroups. If ever the
|
|
+ * configuration files are modified, applications should call this function to
|
|
+ * load the new configuration rules. The function caller is responsible for
|
|
+ * calling free() on each rule in the list.
|
|
+ *
|
|
+ * The cache parameter alters the behavior of this function. If true, this
|
|
+ * function will read the entire content of all configuration files and store
|
|
+ * the results in rl (global rules list). If false, this function will only
|
|
+ * parse until it finds a file and a rule matching the given UID or GID.
|
|
+ * The remaining files are skipped. It will store this rule in trl,
|
|
+ * as well as any children rules (rules that begin with a %) that it has.
|
|
+ *
|
|
+ * Files can be read in an random order so the first match must not be
|
|
+ * dependent on it. Thus construct the rules the way not to break
|
|
+ * this assumption.
|
|
+ *
|
|
+ * This function is NOT thread safe!
|
|
+ * @param cache True to cache rules, else false
|
|
+ * @param muid If cache is false, the UID to match against
|
|
+ * @param mgid If cache is false, the GID to match against
|
|
+ * @return 0 on success, -1 if no cache and match found, > 0 on error.
|
|
+ * TODO: Make this function thread safe!
|
|
+ */
|
|
+static int cgroup_parse_rules(bool cache, uid_t muid,
|
|
+ gid_t mgid, const char *mprocname)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ /* Pointer to the list that we're using */
|
|
+ struct cgroup_rule_list *lst = NULL;
|
|
+
|
|
+ /* Directory variables */
|
|
+ DIR *d;
|
|
+ struct dirent *item;
|
|
+ const char *dirname = CGRULES_CONF_DIR;
|
|
+ char *tmp;
|
|
+ int sret;
|
|
+
|
|
+ /* Determine which list we're using. */
|
|
+ if (cache)
|
|
+ lst = &rl;
|
|
+ else
|
|
+ lst = &trl;
|
|
+
|
|
+ /* If our list already exists, clean it. */
|
|
+ if (lst->head)
|
|
+ cgroup_free_rule_list(lst);
|
|
+
|
|
+ pthread_rwlock_wrlock(&rl_lock);
|
|
+
|
|
+ /* Parse CGRULES_CONF_FILE configuration file (back compatibility). */
|
|
+ ret = cgroup_parse_rules_file(CGRULES_CONF_FILE,
|
|
+ cache, muid, mgid, mprocname);
|
|
+
|
|
+ /*
|
|
+ * if match (ret = -1), stop parsing other files, just return
|
|
+ * or ret > 0 => error
|
|
+ */
|
|
+ if (ret != 0) {
|
|
+ pthread_rwlock_unlock(&rl_lock);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /* Continue parsing */
|
|
+ d = opendir(dirname);
|
|
+ if (!d) {
|
|
+ cgroup_warn("Warning: Failed to open directory %s: %s\n",
|
|
+ dirname, strerror(errno));
|
|
+
|
|
+ /*
|
|
+ * Cannot read directory. However, CGRULES_CONF_FILE is
|
|
+ * succesfully parsed. Thus return as a success
|
|
+ * for back compatibility.
|
|
+ */
|
|
+ pthread_rwlock_unlock(&rl_lock);
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /* read all files from CGRULES_CONF_FILE_DIR */
|
|
+ do {
|
|
+ item = readdir(d);
|
|
+ if (item && (item->d_type == DT_REG
|
|
+ || item->d_type == DT_LNK)) {
|
|
+
|
|
+ sret = asprintf(&tmp, "%s/%s", dirname, item->d_name);
|
|
+ if (sret < 0) {
|
|
+ cgroup_err("Out of memory\n");
|
|
+
|
|
+ /*
|
|
+ * Cannot read directory. However, CGRULES_CONF_FILE is
|
|
+ * succesfully parsed. Thus return as a success
|
|
+ * for back compatibility.
|
|
+ */
|
|
+ ret = 0;
|
|
+ goto unlock_list;
|
|
+ }
|
|
+
|
|
+ cgroup_dbg("Parsing cgrules file: %s\n", tmp);
|
|
+ ret = cgroup_parse_rules_file(tmp,
|
|
+ cache, muid, mgid, mprocname);
|
|
+
|
|
+ free(tmp);
|
|
+
|
|
+ /* match with cache disabled? */
|
|
+ if (ret != 0)
|
|
+ goto unlock_list;
|
|
+ }
|
|
+ if (!item && errno) {
|
|
+ cgroup_warn("Warning: cannot read %s: %s\n",
|
|
+ dirname, strerror(errno));
|
|
+ /*
|
|
+ * Cannot read an item. But continue for
|
|
+ * back compatibility as a success.
|
|
+ */
|
|
+ ret = 0;
|
|
+ goto unlock_list;
|
|
+ }
|
|
+ } while (item != NULL);
|
|
+
|
|
+unlock_list:
|
|
+ closedir(d);
|
|
+
|
|
pthread_rwlock_unlock(&rl_lock);
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
@@ -1360,13 +1495,18 @@ static int cg_create_control_group(const char *path)
|
|
*/
|
|
static int cg_set_control_value(char *path, const char *val)
|
|
{
|
|
- FILE *control_file = NULL;
|
|
+ int ctl_file;
|
|
+ char *str_val;
|
|
+ char *str_val_start;
|
|
+ char *pos;
|
|
+ size_t len;
|
|
+
|
|
if (!cg_test_mounted_fs())
|
|
return ECGROUPNOTMOUNTED;
|
|
|
|
- control_file = fopen(path, "r+e");
|
|
+ ctl_file = open(path, O_RDWR | O_CLOEXEC);
|
|
|
|
- if (!control_file) {
|
|
+ if (ctl_file == -1) {
|
|
if (errno == EPERM) {
|
|
/*
|
|
* We need to set the correct error value, does the
|
|
@@ -1377,6 +1517,7 @@ static int cg_set_control_value(char *path, const char *val)
|
|
*/
|
|
char *path_dir_end;
|
|
char *tasks_path;
|
|
+ FILE *control_file;
|
|
|
|
path_dir_end = strrchr(path, '/');
|
|
if (path_dir_end == NULL)
|
|
@@ -1408,15 +1549,47 @@ static int cg_set_control_value(char *path, const char *val)
|
|
return ECGROUPVALUENOTEXIST;
|
|
}
|
|
|
|
- if (fprintf(control_file, "%s", val) < 0) {
|
|
+ /* Split the multiline value into lines. */
|
|
+ /* One line is a special case of multiline value. */
|
|
+ str_val = strdup(val);
|
|
+ if (str_val == NULL) {
|
|
last_errno = errno;
|
|
- fclose(control_file);
|
|
+ close(ctl_file);
|
|
return ECGOTHER;
|
|
}
|
|
- if (fclose(control_file) < 0) {
|
|
+
|
|
+ str_val_start = str_val;
|
|
+ pos = str_val;
|
|
+
|
|
+ do {
|
|
+ str_val = pos;
|
|
+ pos = strchr(str_val, '\n');
|
|
+
|
|
+ if (pos) {
|
|
+ *pos = '\0';
|
|
+ ++pos;
|
|
+ }
|
|
+
|
|
+ len = strlen(str_val);
|
|
+ if (len > 0) {
|
|
+ if (write(ctl_file, str_val, len) == -1) {
|
|
+ last_errno = errno;
|
|
+ free(str_val_start);
|
|
+ close(ctl_file);
|
|
+ return ECGOTHER;
|
|
+ }
|
|
+ } else
|
|
+ cgroup_warn("Warning: skipping empty line for %s\n",
|
|
+ path);
|
|
+ } while(pos);
|
|
+
|
|
+ if (close(ctl_file)) {
|
|
last_errno = errno;
|
|
+ free(str_val_start);
|
|
return ECGOTHER;
|
|
}
|
|
+
|
|
+ free(str_val_start);
|
|
return 0;
|
|
}
|
|
|
|
@@ -1897,15 +2070,23 @@ static int cg_move_task_files(FILE *input_tasks, FILE *output_tasks)
|
|
break;
|
|
|
|
ret = fprintf(output_tasks, "%d", tids);
|
|
- if (ret < 0)
|
|
- break;
|
|
+ if (ret < 0) {
|
|
+ if (errno == ESRCH)
|
|
+ ret = 0;
|
|
+ else
|
|
+ break;
|
|
+ }
|
|
|
|
/*
|
|
* Flush the file, we need only one process per write() call.
|
|
*/
|
|
ret = fflush(output_tasks);
|
|
- if (ret < 0)
|
|
- break;
|
|
+ if (ret < 0) {
|
|
+ if (errno == ESRCH)
|
|
+ ret = 0;
|
|
+ else
|
|
+ break;
|
|
+ }
|
|
}
|
|
|
|
if (ret < 0) {
|
|
@@ -2594,13 +2775,17 @@ static struct cgroup_rule *cgroup_find_matching_rule_uid_gid(uid_t uid,
|
|
/* Get the group data. */
|
|
sp = &(rule->username[1]);
|
|
grp = getgrnam(sp);
|
|
- if (!grp)
|
|
+ if (!grp) {
|
|
+ rule = rule->next;
|
|
continue;
|
|
+ }
|
|
|
|
/* Get the data for UID. */
|
|
usr = getpwuid(uid);
|
|
- if (!usr)
|
|
+ if (!usr) {
|
|
+ rule = rule->next;
|
|
continue;
|
|
+ }
|
|
|
|
/* If UID is a member of group, we matched. */
|
|
for (i = 0; grp->gr_mem[i]; i++) {
|
|
@@ -3108,10 +3293,13 @@ int cgroup_change_all_cgroups(void)
|
|
return -ECGOTHER;
|
|
|
|
while ((pid_dir = readdir(dir)) != NULL) {
|
|
- int err, pid;
|
|
+ int err, pid, tid;
|
|
uid_t euid;
|
|
gid_t egid;
|
|
char *procname = NULL;
|
|
+ DIR *tdir;
|
|
+ struct dirent *tid_dir = NULL;
|
|
+ char tpath[FILENAME_MAX] = { '\0' };
|
|
|
|
err = sscanf(pid_dir->d_name, "%i", &pid);
|
|
if (err < 1)
|
|
@@ -3125,11 +3313,24 @@ int cgroup_change_all_cgroups(void)
|
|
if (err)
|
|
continue;
|
|
|
|
- err = cgroup_change_cgroup_flags(euid,
|
|
- egid, procname, pid, CGFLAG_USECACHE);
|
|
- if (err)
|
|
- cgroup_dbg("cgroup change pid %i failed\n", pid);
|
|
+ snprintf(tpath, FILENAME_MAX, "%s%d/task/", path, pid);
|
|
+
|
|
+ tdir = opendir(tpath);
|
|
+ if (!tdir)
|
|
+ continue;
|
|
+
|
|
+ while ((tid_dir = readdir(tdir)) != NULL) {
|
|
+ err = sscanf(tid_dir->d_name, "%i", &tid);
|
|
+ if (err < 1)
|
|
+ continue;
|
|
+
|
|
+ err = cgroup_change_cgroup_flags(euid,
|
|
+ egid, procname, tid, CGFLAG_USECACHE);
|
|
+ if (err)
|
|
+ cgroup_dbg("cgroup change tid %i failed\n", tid);
|
|
+ }
|
|
|
|
+ closedir(tdir);
|
|
free(procname);
|
|
}
|
|
|
|
diff --git a/src/config.c b/src/config.c
|
|
index da2c0dd..090bea5 100644
|
|
--- a/src/config.c
|
|
+++ b/src/config.c
|
|
@@ -41,6 +41,8 @@
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
+#include "tools/tools-common.h"
|
|
+
|
|
unsigned int MAX_CGROUPS = 64; /* NOTE: This value changes dynamically */
|
|
unsigned int MAX_TEMPLATES = 64;
|
|
/* NOTE: This value changes dynamically */
|
|
@@ -89,6 +91,7 @@ static int config_template_table_index;
|
|
*/
|
|
static struct cgroup *template_table;
|
|
static int template_table_index;
|
|
+static struct cgroup_string_list *template_files;
|
|
|
|
|
|
/*
|
|
@@ -1572,6 +1575,161 @@ int cgroup_init_templates_cache(char *pathname)
|
|
|
|
}
|
|
|
|
+/**
|
|
+ * Setting source files of templates. This function has to be called before
|
|
+ * any call of cgroup_load_templates_cache_from_files.
|
|
+ * @param tmpl_files
|
|
+ */
|
|
+void cgroup_templates_cache_set_source_files(
|
|
+ struct cgroup_string_list *tmpl_files)
|
|
+{
|
|
+ template_files = tmpl_files;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Appending cgroup templates parsed by parser to template_table
|
|
+ * @param offset number of templates already in the table
|
|
+ */
|
|
+int cgroup_add_cgroup_templates(int offset)
|
|
+{
|
|
+ int i, ti, ret;
|
|
+
|
|
+ for (i = 0; i < config_template_table_index; i++) {
|
|
+ ti = i + offset;
|
|
+ ret = cgroup_copy_cgroup(&template_table[ti],
|
|
+ &config_template_table[i]);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ strcpy((template_table[ti]).name,
|
|
+ (config_template_table[i]).name);
|
|
+ template_table[ti].tasks_uid =
|
|
+ config_template_table[i].tasks_uid;
|
|
+ template_table[ti].tasks_gid =
|
|
+ config_template_table[i].tasks_gid;
|
|
+ template_table[ti].task_fperm =
|
|
+ config_template_table[i].task_fperm;
|
|
+ template_table[ti].control_uid =
|
|
+ config_template_table[i].control_uid;
|
|
+ template_table[ti].control_gid =
|
|
+ config_template_table[i].control_gid;
|
|
+ template_table[ti].control_fperm =
|
|
+ config_template_table[i].control_fperm;
|
|
+ template_table[ti].control_dperm =
|
|
+ config_template_table[i].control_dperm;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Expand template table based on new number of parsed templates, i.e.
|
|
+ * on value of config_template_table_index.
|
|
+ * Change value of template_table_index.
|
|
+ * @return 0 on success, < 0 on error
|
|
+ */
|
|
+int cgroup_expand_template_table(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ template_table = realloc(template_table,
|
|
+ (template_table_index + config_template_table_index)
|
|
+ *sizeof(struct cgroup));
|
|
+
|
|
+ if (template_table == NULL)
|
|
+ return -ECGOTHER;
|
|
+
|
|
+ for (i = 0; i < config_template_table_index; i++)
|
|
+ template_table[i + template_table_index].index = 0;
|
|
+
|
|
+ template_table_index += config_template_table_index;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Load the templates cache from files. Before calling this function,
|
|
+ * cgroup_templates_cache_set_source_files has to be called first.
|
|
+ * @param file_index index of file which was unable to be parsed
|
|
+ * @return 0 on success, > 0 on error
|
|
+ */
|
|
+int cgroup_load_templates_cache_from_files(int *file_index)
|
|
+{
|
|
+ int ret;
|
|
+ int i, j;
|
|
+ int template_table_last_index;
|
|
+ char *pathname;
|
|
+
|
|
+ if (!template_files) {
|
|
+ /* source files has not been set */
|
|
+ cgroup_dbg("Template source files have not been set. ");
|
|
+ cgroup_dbg("Using only %s\n", CGCONFIG_CONF_FILE);
|
|
+
|
|
+ if (template_table_index == 0)
|
|
+ /* the rules cache is empty */
|
|
+ return cgroup_init_templates_cache(
|
|
+ CGCONFIG_CONF_FILE);
|
|
+ else
|
|
+ /* cache is not empty */
|
|
+ return cgroup_reload_cached_templates(
|
|
+ CGCONFIG_CONF_FILE);
|
|
+ }
|
|
+
|
|
+ if (template_table) {
|
|
+ /* template structures have to be free */
|
|
+ for (i = 0; i < template_table_index; i++)
|
|
+ cgroup_free_controllers(&template_table[i]);
|
|
+ free(template_table);
|
|
+ template_table = NULL;
|
|
+ }
|
|
+ template_table_index = 0;
|
|
+
|
|
+ if ((config_template_table_index != 0) || (config_table_index != 0)) {
|
|
+ /* config structures have to be clean before parsing */
|
|
+ cgroup_free_config();
|
|
+ }
|
|
+
|
|
+ for (j = 0; j < template_files->count; j++) {
|
|
+ pathname = template_files->items[j];
|
|
+
|
|
+ cgroup_dbg("Parsing templates from %s.\n", pathname);
|
|
+ /* Attempt to read the configuration file
|
|
+ * and cache the rules. */
|
|
+ ret = cgroup_parse_config(pathname);
|
|
+ if (ret) {
|
|
+ cgroup_dbg("Could not initialize rule cache, ");
|
|
+ cgroup_dbg("error was: %d\n", ret);
|
|
+ *file_index = j;
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (config_template_table_index > 0) {
|
|
+ template_table_last_index = template_table_index;
|
|
+ ret = cgroup_expand_template_table();
|
|
+ if (ret) {
|
|
+ cgroup_dbg("Could not expand template table, ");
|
|
+ cgroup_dbg("error was: %d\n", -ret);
|
|
+ *file_index = j;
|
|
+ return -ret;
|
|
+ }
|
|
+
|
|
+ /* copy template data to templates cache structures */
|
|
+ cgroup_dbg("Copying templates to template table ");
|
|
+ cgroup_dbg("from %s.\n", pathname);
|
|
+ ret = cgroup_add_cgroup_templates(
|
|
+ template_table_last_index);
|
|
+ if (ret) {
|
|
+ cgroup_dbg("Unable to copy cgroup\n");
|
|
+ *file_index = j;
|
|
+ return ret;
|
|
+ }
|
|
+ cgroup_dbg("Templates to template table copied\n");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/*
|
|
* Create a given cgroup, based on template configuration if it is present
|
|
* if the template is not present cgroup is creted using cgroup_create_cgroup
|
|
@@ -1593,13 +1751,22 @@ int cgroup_config_create_template_group(struct cgroup *cgroup,
|
|
* use CGCONFIG_CONF_FILE by default
|
|
*/
|
|
if (!(flags & CGFLAG_USE_TEMPLATE_CACHE)) {
|
|
- if (template_table_index == 0)
|
|
- /* the rules cache is empty */
|
|
- ret = cgroup_init_templates_cache(CGCONFIG_CONF_FILE);
|
|
- else
|
|
- /* cache is not empty */
|
|
- ret = cgroup_reload_cached_templates(
|
|
- CGCONFIG_CONF_FILE);
|
|
+ int fileindex;
|
|
+
|
|
+ /* the rules cache is empty */
|
|
+ ret = cgroup_load_templates_cache_from_files(
|
|
+ &fileindex);
|
|
+ if (ret != 0) {
|
|
+ if (fileindex < 0) {
|
|
+ cgroup_dbg("Error: Template source files ");
|
|
+ cgroup_dbg("have not been set\n");
|
|
+ } else {
|
|
+ cgroup_dbg("Error: Failed to load template");
|
|
+ cgroup_dbg("rules from %s. ",
|
|
+ template_files->items[fileindex]);
|
|
+ }
|
|
+ }
|
|
+
|
|
if (ret != 0) {
|
|
cgroup_dbg("Failed initialize templates cache.\n");
|
|
return ret;
|
|
@@ -1659,7 +1826,7 @@ int cgroup_config_create_template_group(struct cgroup *cgroup,
|
|
/* no template is present for given name x controller pair
|
|
* add controller to result cgroup */
|
|
aux_cgroup = cgroup_new_cgroup(cgroup->name);
|
|
- if (aux_cgroup) {
|
|
+ if (!aux_cgroup) {
|
|
ret = ECGINVAL;
|
|
fprintf(stderr, "cgroup %s can't be created\n",
|
|
cgroup->name);
|
|
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
|
|
index f3100ed..abbbe30 100644
|
|
--- a/src/daemon/Makefile.am
|
|
+++ b/src/daemon/Makefile.am
|
|
@@ -1,9 +1,9 @@
|
|
-INCLUDES = -I $(top_srcdir)/include
|
|
+INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/include
|
|
|
|
if WITH_DAEMON
|
|
|
|
sbin_PROGRAMS = cgrulesengd
|
|
-cgrulesengd_SOURCES = cgrulesengd.c cgrulesengd.h
|
|
+cgrulesengd_SOURCES = cgrulesengd.c cgrulesengd.h ../tools/tools-common.h ../tools/tools-common.c
|
|
cgrulesengd_LDADD = $(top_builddir)/src/.libs/libcgroup.la -lrt
|
|
cgrulesengd_LDFLAGS = -L$(top_builddir)/src/.libs
|
|
|
|
diff --git a/src/daemon/cgrulesengd.c b/src/daemon/cgrulesengd.c
|
|
index 367b898..ea51f11 100644
|
|
--- a/src/daemon/cgrulesengd.c
|
|
+++ b/src/daemon/cgrulesengd.c
|
|
@@ -34,6 +34,7 @@
|
|
#include "libcgroup.h"
|
|
#include "cgrulesengd.h"
|
|
#include "../libcgroup-internal.h"
|
|
+#include "../tools/tools-common.h"
|
|
|
|
#include <errno.h>
|
|
#include <stdarg.h>
|
|
@@ -59,6 +60,9 @@
|
|
|
|
#define NUM_PER_REALLOCATIOM (100)
|
|
|
|
+/* list of config files from CGCONFIG_CONF_FILE and CGCONFIG_CONF_DIR */
|
|
+static struct cgroup_string_list template_files;
|
|
+
|
|
/* Log file, NULL if logging to file is disabled */
|
|
FILE* logfile;
|
|
|
|
@@ -936,6 +940,8 @@ void cgre_flash_rules(int signum)
|
|
/* Current time */
|
|
time_t tm = time(0);
|
|
|
|
+ int fileindex;
|
|
+
|
|
flog(LOG_INFO, "Reloading rules configuration\n");
|
|
flog(LOG_DEBUG, "Current time: %s\n", ctime(&tm));
|
|
|
|
@@ -949,7 +955,7 @@ void cgre_flash_rules(int signum)
|
|
}
|
|
|
|
/* Ask libcgroup to reload the template rules table. */
|
|
- cgroup_reload_cached_templates(CGCONFIG_CONF_FILE);
|
|
+ cgroup_load_templates_cache_from_files(&fileindex);
|
|
}
|
|
|
|
/**
|
|
@@ -962,11 +968,13 @@ void cgre_flash_templates(int signum)
|
|
/* Current time */
|
|
time_t tm = time(0);
|
|
|
|
+ int fileindex;
|
|
+
|
|
flog(LOG_INFO, "Reloading templates configuration.\n");
|
|
flog(LOG_DEBUG, "Current time: %s\n", ctime(&tm));
|
|
|
|
/* Ask libcgroup to reload the templates table. */
|
|
- cgroup_reload_cached_templates(CGCONFIG_CONF_FILE);
|
|
+ cgroup_load_templates_cache_from_files(&fileindex);
|
|
}
|
|
|
|
/**
|
|
@@ -1069,6 +1077,8 @@ int main(int argc, char *argv[])
|
|
{NULL, 0, NULL, 0}
|
|
};
|
|
|
|
+ int fileindex;
|
|
+
|
|
/* Make sure the user is root. */
|
|
if (getuid() != 0) {
|
|
fprintf(stderr, "Error: Only root can start/stop the control"
|
|
@@ -1180,6 +1190,25 @@ int main(int argc, char *argv[])
|
|
}
|
|
|
|
/* Ask libcgroup to load the configuration rules. */
|
|
+ ret = cgroup_string_list_init(&template_files,
|
|
+ CGCONFIG_CONF_FILES_LIST_MINIMUM_SIZE);
|
|
+ if (ret) {
|
|
+ fprintf(stderr, "%s: cannot init file list, out of memory?\n",
|
|
+ argv[0]);
|
|
+ goto finished_without_temp_files;
|
|
+ }
|
|
+ /* first add CGCONFIG_CONF_FILE into file list */
|
|
+ ret = cgroup_string_list_add_item(&template_files, CGCONFIG_CONF_FILE);
|
|
+ if (ret) {
|
|
+ fprintf(stderr, "%s: cannot add file to list, out of memory?\n"
|
|
+ , argv[0]);
|
|
+ goto finished;
|
|
+ }
|
|
+
|
|
+ /* then read CGCONFIG_CONF_DIR directory for additional config files */
|
|
+ cgroup_string_list_add_directory(&template_files, CGCONFIG_CONF_DIR,
|
|
+ argv[0]);
|
|
+
|
|
if ((ret = cgroup_init_rules_cache()) != 0) {
|
|
fprintf(stderr, "Error: libcgroup failed to initialize rules"
|
|
"cache from %s. %s\n", CGRULES_CONF_FILE,
|
|
@@ -1188,11 +1217,18 @@ int main(int argc, char *argv[])
|
|
}
|
|
|
|
/* ask libcgroup to load template rules as well */
|
|
- ret = cgroup_init_templates_cache(CGCONFIG_CONF_FILE);
|
|
+ cgroup_templates_cache_set_source_files(&template_files);
|
|
+ ret = cgroup_load_templates_cache_from_files(&fileindex);
|
|
if (ret != 0) {
|
|
- fprintf(stderr, "Error: libcgroup failed to initialize teplate"\
|
|
- "rules from %s. %s\n", CGCONFIG_CONF_FILE,
|
|
- cgroup_strerror(ret));
|
|
+ if (fileindex < 0) {
|
|
+ fprintf(stderr, "Error: Template source files ");
|
|
+ fprintf(stderr, "have not been set\n");
|
|
+ } else {
|
|
+ fprintf(stderr, "Error: Failed to initialize template");
|
|
+ fprintf(stderr, "rules from %s. ",
|
|
+ template_files.items[fileindex]);
|
|
+ fprintf(stderr, "%s\n", cgroup_strerror(-ret));
|
|
+ }
|
|
goto finished;
|
|
}
|
|
|
|
@@ -1259,6 +1295,9 @@ int main(int argc, char *argv[])
|
|
ret = cgre_create_netlink_socket_process_msg();
|
|
|
|
finished:
|
|
+ cgroup_string_list_free(&template_files);
|
|
+
|
|
+finished_without_temp_files:
|
|
if (logfile && logfile != stdout)
|
|
fclose(logfile);
|
|
|
|
diff --git a/src/lex.l b/src/lex.l
|
|
index 1b357db..ecd212c 100644
|
|
--- a/src/lex.l
|
|
+++ b/src/lex.l
|
|
@@ -42,8 +42,8 @@ jmp_buf parser_error_env;
|
|
"group" {return GROUP;}
|
|
"namespace" {return NAMESPACE;}
|
|
"template" {return TEMPLATE;}
|
|
-"default" {return DEFAULT;}
|
|
-[a-zA-Z0-9_\-\/\.\,\%\@]+ {yylval.name = strdup(yytext); return ID;}
|
|
+"default" {yylval.name = strdup(yytext); return DEFAULT;}
|
|
+[a-zA-Z0-9_\-\/\.\,\%\@\\]+ {yylval.name = strdup(yytext); return ID;}
|
|
\"[^"]*\" {yylval.name = strdup(yytext+1); yylval.name[strlen(yylval.name)-1] = '\0'; return ID; }
|
|
. {return yytext[0];}
|
|
%%
|
|
diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h
|
|
index 4c0f46c..9875dd9 100644
|
|
--- a/src/libcgroup-internal.h
|
|
+++ b/src/libcgroup-internal.h
|
|
@@ -48,8 +48,12 @@ __BEGIN_DECLS
|
|
|
|
|
|
#define CGCONFIG_CONF_FILE "/etc/cgconfig.conf"
|
|
+/* Minimum number of file in template file list for cgrulesengd */
|
|
+#define CGCONFIG_CONF_FILES_LIST_MINIMUM_SIZE 4
|
|
+#define CGCONFIG_CONF_DIR "/etc/cgconfig.d"
|
|
|
|
#define CGRULES_CONF_FILE "/etc/cgrules.conf"
|
|
+#define CGRULES_CONF_DIR "/etc/cgrules.d"
|
|
#define CGRULES_MAX_FIELDS_PER_LINE 3
|
|
|
|
#define CGROUP_BUFFER_LEN (5 * FILENAME_MAX)
|
|
diff --git a/src/libcgroup.map b/src/libcgroup.map
|
|
index b0c162c..8fe1990 100644
|
|
--- a/src/libcgroup.map
|
|
+++ b/src/libcgroup.map
|
|
@@ -117,3 +117,15 @@ CGROUP_0.39 {
|
|
cgroup_log;
|
|
cgroup_parse_log_level_str;
|
|
} CGROUP_0.38;
|
|
+
|
|
+CGROUP_0.40 {
|
|
+ cgroup_templates_cache_set_source_files;
|
|
+ cgroup_load_templates_cache_from_files;
|
|
+} CGROUP_0.39;
|
|
+
|
|
+CGROUP_0.41 {
|
|
+} CGROUP_0.40;
|
|
+
|
|
+CGROUP_0.42 {
|
|
+ cgroup_add_all_controllers;
|
|
+} CGROUP_0.41;
|
|
diff --git a/src/parse.y b/src/parse.y
|
|
index 9adbc0e..98f7699 100644
|
|
--- a/src/parse.y
|
|
+++ b/src/parse.y
|
|
@@ -45,9 +45,9 @@ int yywrap(void)
|
|
int val;
|
|
struct cgroup_dictionary *values;
|
|
}
|
|
-%type <name> ID
|
|
+%type <name> ID DEFAULT
|
|
%type <val> mountvalue_conf mount task_namevalue_conf admin_namevalue_conf
|
|
-%type <val> admin_conf task_conf task_or_admin group_conf group start
|
|
+%type <val> admin_conf task_conf task_or_admin group_conf group start group_name
|
|
%type <val> namespace namespace_conf default default_conf
|
|
%type <values> namevalue_conf
|
|
%type <val> template template_conf
|
|
@@ -99,7 +99,7 @@ default_conf
|
|
}
|
|
;
|
|
|
|
-group : GROUP ID '{' group_conf '}'
|
|
+group : GROUP group_name '{' group_conf '}'
|
|
{
|
|
$$ = $4;
|
|
if ($$) {
|
|
@@ -119,6 +119,16 @@ group : GROUP ID '{' group_conf '}'
|
|
}
|
|
;
|
|
|
|
+group_name
|
|
+ : ID
|
|
+ {
|
|
+ $$ = $1;
|
|
+ }
|
|
+ | DEFAULT
|
|
+ {
|
|
+ $$ = $1;
|
|
+ }
|
|
+
|
|
group_conf
|
|
: ID '{' namevalue_conf '}'
|
|
{
|
|
diff --git a/src/tools/cgcreate.c b/src/tools/cgcreate.c
|
|
index 73abd91..65b188a 100644
|
|
--- a/src/tools/cgcreate.c
|
|
+++ b/src/tools/cgcreate.c
|
|
@@ -54,7 +54,6 @@ static void usage(int status, const char *program_name)
|
|
printf(" -t <tuid>:<tgid> Owner of the tasks file\n");
|
|
}
|
|
|
|
-
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int ret = 0;
|
|
@@ -195,16 +194,29 @@ int main(int argc, char *argv[])
|
|
/* add controllers to the new cgroup */
|
|
j = 0;
|
|
while (cgroup_list[i]->controllers[j]) {
|
|
- cgc = cgroup_add_controller(cgroup,
|
|
- cgroup_list[i]->controllers[j]);
|
|
- if (!cgc) {
|
|
- ret = ECGINVAL;
|
|
- fprintf(stderr, "%s: "
|
|
- "controller %s can't be add\n",
|
|
- argv[0],
|
|
+ if (strcmp(cgroup_list[i]->controllers[j], "*") == 0) {
|
|
+ /* it is meta character, add all controllers */
|
|
+ ret = cgroup_add_all_controllers(cgroup);
|
|
+ if (ret != 0) {
|
|
+ ret = ECGINVAL;
|
|
+ fprintf(stderr, "%s: can't add ",
|
|
+ argv[0]);
|
|
+ fprintf(stderr, "all controllers\n");
|
|
+ cgroup_free(&cgroup);
|
|
+ goto err;
|
|
+ }
|
|
+ } else {
|
|
+ cgc = cgroup_add_controller(cgroup,
|
|
cgroup_list[i]->controllers[j]);
|
|
- cgroup_free(&cgroup);
|
|
- goto err;
|
|
+ if (!cgc) {
|
|
+ ret = ECGINVAL;
|
|
+ fprintf(stderr, "%s: ", argv[0]);
|
|
+ fprintf(stderr, "controller %s",
|
|
+ cgroup_list[i]->controllers[j]);
|
|
+ fprintf(stderr, "can't be add\n");
|
|
+ cgroup_free(&cgroup);
|
|
+ goto err;
|
|
+ }
|
|
}
|
|
j++;
|
|
}
|
|
diff --git a/src/tools/cgdelete.c b/src/tools/cgdelete.c
|
|
index 190310f..43cc47c 100644
|
|
--- a/src/tools/cgdelete.c
|
|
+++ b/src/tools/cgdelete.c
|
|
@@ -33,6 +33,13 @@ static struct option const long_options[] =
|
|
{NULL, 0, NULL, 0}
|
|
};
|
|
|
|
+struct ext_cgroup_record {
|
|
+ char name[FILENAME_MAX]; /* controller name */
|
|
+ char controller[FILENAME_MAX]; /* cgroup name */
|
|
+ int h_number; /* hierarchy number */
|
|
+};
|
|
+
|
|
+
|
|
static void usage(int status, const char *program_name)
|
|
{
|
|
if (status != 0) {
|
|
@@ -51,6 +58,69 @@ static void usage(int status, const char *program_name)
|
|
"all subgroups\n");
|
|
}
|
|
|
|
+/*
|
|
+ * Skip adding controller which points to the same cgroup when delete
|
|
+ * cgroup with specifying multi controllers. Just skip controller which
|
|
+ * cgroup and hierarchy number is same
|
|
+ */
|
|
+static int skip_add_controller(int counter, int *skip,
|
|
+ struct ext_cgroup_record *ecg_list)
|
|
+{
|
|
+ int k;
|
|
+ struct controller_data info;
|
|
+ void *handle;
|
|
+ int ret = 0;
|
|
+
|
|
+ /* find out hierarchy number of added cgroup */
|
|
+ ecg_list[counter].h_number = 0;
|
|
+ ret = cgroup_get_all_controller_begin(&handle, &info);
|
|
+ while (ret == 0) {
|
|
+ if (!strcmp(info.name, ecg_list[counter].name)) {
|
|
+ /* hierarchy number found out, set it */
|
|
+ ecg_list[counter].h_number = info.hierarchy;
|
|
+ break;
|
|
+ }
|
|
+ ret = cgroup_get_all_controller_next(&handle, &info);
|
|
+ }
|
|
+ cgroup_get_all_controller_end(&handle);
|
|
+
|
|
+ /* deal with cgroup_get_controller_begin/next ret values */
|
|
+ if (ret == ECGEOF)
|
|
+ ret = 0;
|
|
+ if (ret) {
|
|
+ fprintf(stderr, "cgroup_get_controller_begin/next failed(%s)\n",
|
|
+ cgroup_strerror(ret));
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /* found out whether the hierarchy should be skipped */
|
|
+ *skip = 0;
|
|
+ for (k = 0; k < counter; k++) {
|
|
+ if ((!strcmp(ecg_list[k].name, ecg_list[counter].name)) &&
|
|
+ (ecg_list[k].h_number == ecg_list[counter].h_number)) {
|
|
+ /* we found a control group in the same hierarchy */
|
|
+ if (strcmp(ecg_list[k].controller,
|
|
+ ecg_list[counter].controller)) {
|
|
+ /*
|
|
+ * it is a different controller ->
|
|
+ * if there is not one cgroup for the same
|
|
+ * controller, skip it
|
|
+ */
|
|
+ *skip = 1;
|
|
+ } else {
|
|
+ /*
|
|
+ * there is the identical group,controller pair
|
|
+ * don't skip it
|
|
+ */
|
|
+ *skip = 0;
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
@@ -60,6 +130,11 @@ int main(int argc, char *argv[])
|
|
int flags = 0;
|
|
int final_ret = 0;
|
|
|
|
+ int counter = 0;
|
|
+ int max = 0;
|
|
+ struct ext_cgroup_record *ecg_list = NULL;
|
|
+ int skip;
|
|
+
|
|
struct cgroup_group_spec **cgroup_list = NULL;
|
|
struct cgroup *cgroup;
|
|
struct cgroup_controller *cgc;
|
|
@@ -80,6 +155,13 @@ int main(int argc, char *argv[])
|
|
goto err;
|
|
}
|
|
|
|
+ ecg_list = calloc(argc, sizeof(struct ext_cgroup_record *));
|
|
+ if (cgroup_list == NULL) {
|
|
+ fprintf(stderr, "%s: out of memory\n", argv[0]);
|
|
+ ret = -1;
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
/*
|
|
* Parse arguments
|
|
*/
|
|
@@ -138,6 +220,44 @@ int main(int argc, char *argv[])
|
|
/* add controllers to the cgroup */
|
|
j = 0;
|
|
while (cgroup_list[i]->controllers[j]) {
|
|
+ skip = 0;
|
|
+ /*
|
|
+ * save controller name, cg name and hierarchy number
|
|
+ * to determine whether we should skip adding controller
|
|
+ */
|
|
+ if (counter == max) {
|
|
+ /*
|
|
+ * there is not enough space to store them,
|
|
+ * create it
|
|
+ */
|
|
+ max = max + argc;
|
|
+ ecg_list = (struct ext_cgroup_record *)
|
|
+ realloc(ecg_list,
|
|
+ max * sizeof(struct ext_cgroup_record));
|
|
+ if (!ecg_list) {
|
|
+ fprintf(stderr, "%s: ", argv[0]);
|
|
+ fprintf(stderr, "not enough memory\n");
|
|
+ final_ret = -1;
|
|
+ goto err;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ strncpy(ecg_list[counter].controller,
|
|
+ cgroup_list[i]->controllers[j], FILENAME_MAX);
|
|
+ ecg_list[counter].controller[FILENAME_MAX - 1] = '\0';
|
|
+ strncpy(ecg_list[counter].name,
|
|
+ cgroup_list[i]->path, FILENAME_MAX);
|
|
+ ecg_list[counter].name[FILENAME_MAX - 1] = '\0';
|
|
+
|
|
+ ret = skip_add_controller(counter, &skip, ecg_list);
|
|
+ if (ret)
|
|
+ goto err;
|
|
+
|
|
+ if (skip) {
|
|
+ /* don't add the controller, goto next one */
|
|
+ goto next;
|
|
+ }
|
|
+
|
|
cgc = cgroup_add_controller(cgroup,
|
|
cgroup_list[i]->controllers[j]);
|
|
if (!cgc) {
|
|
@@ -149,6 +269,8 @@ int main(int argc, char *argv[])
|
|
cgroup_free(&cgroup);
|
|
goto err;
|
|
}
|
|
+next:
|
|
+ counter++;
|
|
j++;
|
|
}
|
|
|
|
@@ -167,6 +289,9 @@ int main(int argc, char *argv[])
|
|
|
|
ret = final_ret;
|
|
err:
|
|
+ if (ecg_list)
|
|
+ free(ecg_list);
|
|
+
|
|
if (cgroup_list) {
|
|
for (i = 0; i < argc; i++) {
|
|
if (cgroup_list[i])
|
|
diff --git a/src/tools/tools-common.h b/src/tools/tools-common.h
|
|
index e05465f..c723eb4 100644
|
|
--- a/src/tools/tools-common.h
|
|
+++ b/src/tools/tools-common.h
|
|
@@ -20,7 +20,7 @@
|
|
|
|
#include "config.h"
|
|
#include <libcgroup.h>
|
|
-#include <libcgroup-internal.h>
|
|
+#include "../libcgroup-internal.h"
|
|
|
|
#define cgroup_err(x...) cgroup_log(CGROUP_LOG_ERROR, x)
|
|
#define cgroup_warn(x...) cgroup_log(CGROUP_LOG_WARNING, x)
|
|
diff --git a/src/wrapper.c b/src/wrapper.c
|
|
index c03472a..3a9331f 100644
|
|
--- a/src/wrapper.c
|
|
+++ b/src/wrapper.c
|
|
@@ -92,6 +92,56 @@ struct cgroup_controller *cgroup_add_controller(struct cgroup *cgroup,
|
|
return controller;
|
|
}
|
|
|
|
+int cgroup_add_all_controllers(struct cgroup *cgroup)
|
|
+{
|
|
+ int ret;
|
|
+ void *handle;
|
|
+ struct controller_data info;
|
|
+ struct cgroup_controller *cgc;
|
|
+
|
|
+ /* go through the controller list */
|
|
+ ret = cgroup_get_all_controller_begin(&handle, &info);
|
|
+ if ((ret != 0) && (ret != ECGEOF)) {
|
|
+ fprintf(stderr, "cannot read controller data: %s\n",
|
|
+ cgroup_strerror(ret));
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ while (ret == 0) {
|
|
+ if (info.hierarchy == 0) {
|
|
+ /* the controller is not attached to any hierarchy
|
|
+ skip it */
|
|
+ goto next;
|
|
+ }
|
|
+
|
|
+ /* add mounted controller to cgroup structure */
|
|
+ cgc = cgroup_add_controller(cgroup, info.name);
|
|
+ if (!cgc) {
|
|
+ ret = ECGINVAL;
|
|
+ fprintf(stderr, "controller %s can't be add\n",
|
|
+ info.name);
|
|
+ }
|
|
+
|
|
+next:
|
|
+ ret = cgroup_get_all_controller_next(&handle, &info);
|
|
+ if (ret && ret != ECGEOF)
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+end:
|
|
+ cgroup_get_all_controller_end(&handle);
|
|
+
|
|
+ if (ret == ECGEOF)
|
|
+ ret = 0;
|
|
+
|
|
+ if (ret)
|
|
+ fprintf(stderr,
|
|
+ "cgroup_get_controller_begin/next failed (%s)\n",
|
|
+ cgroup_strerror(ret));
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
void cgroup_free_controllers(struct cgroup *cgroup)
|
|
{
|
|
int i, j;
|