This patch introduces four APIs. Two APIs are used to modify the CPU subsystem shares (read as well as write). Two other APIs access the cpuacct subsystem and read te usage parameter. I did not have the latest kernel running on my development environment and so am missing the cpuacct.stat file. I hpoe to have assistance from Bharata for those API once a consensus is obtained on whether this approach will work or not.
There is still the question of handling multiple versions of kernel which was put up by Jan. That should be resolved once these patches are merged in. Signed-off-by: Dhaval Giani <[email protected]> Cc: Linus Walleij <[email protected]> --- include/libcgroup.h | 9 ++ src/Makefile.am | 2 src/api.c | 3 src/cpu.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/libcgroup.map | 4 5 files changed, 228 insertions(+), 2 deletions(-) Index: libcg/src/cpu.c =================================================================== --- /dev/null +++ libcg/src/cpu.c @@ -0,0 +1,212 @@ +/* + * Copyright IBM Corporation. 2009 + * + * Author: Dhaval Giani <[email protected]> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Code initiated and designed by Dhaval Giani. All faults are most likely + * his mistake. + * + */ +#include <errno.h> +#include <libcgroup.h> +#include <libcgroup-internal.h> + +/* + * We handle both the cpu as the cpuacct subsystem in this file itself. + * This is because they are closely related subsystems, even if they are + * mounted seperately. However we will follow the cgroup_<subsystem>_<action> + * naming scheme for them. + */ + +/* + * XX: Should these be moved to libcgroup.h + */ +#define CPU "cpu" +#define CPUACCT "cpuacct" + +extern int cgroup_initialized; + +/* + * TODO: + * 1. Test out these functions more. + * 2. Handle the situation when the cgroup does not exist already (?) + */ +int cgroup_cpu_set_shares(char *name, u_int64_t shares) +{ + struct cgroup *cgroup; + struct cgroup_controller *cgc; + int ret = 0; + + if (!cgroup_initialized) + return ECGROUPNOTINITIALIZED; + + cgroup = cgroup_new_cgroup(name); + + if (!cgroup) { + last_errno = errno; + return ECGOTHER; + } + + cgc = cgroup_add_controller(cgroup, CPU); + + if (!cgc) { + /* + * The only reason cgroup_add_controller can fail is due to + * calloc failing. There is no other reason for it to fail. + */ + last_errno = errno; + ret = ECGOTHER; + goto out; + } + + ret = cgroup_add_value_uint64(cgc, "cpu.shares", shares); + + if (ret) + goto out; + + ret = cgroup_modify_cgroup(cgroup); + +out: + cgroup_free(&cgroup); + return ret; +} + +/* + * Please note, the value stored at the locaton pointed by shares is + * undefined when this function fails. + */ +int cgroup_cpu_get_shares(char *name, u_int64_t *shares) +{ + struct cgroup *cgroup; + struct cgroup_controller *cgc; + int ret = 0; + + if (!cgroup_initialized) + return ECGROUPNOTINITIALIZED; + + if (!shares) + return ECGINVAL; + + cgroup = cgroup_new_cgroup(name); + + if (!cgroup) { + last_errno = errno; + return ECGOTHER; + } + + ret = cgroup_get_cgroup(cgroup); + + if (ret) + goto out; + + cgc = cgroup_get_controller(cgroup, CPU); + + /* Most likely if the controller does not exist. If controller does + * exist, then we are out of memory. Should not be an issue on Linux + * since we will OOM, so we will just return CPUNOTEXIST + */ + if (!cgc) + return ECGCPUNOTEXIST; + + + ret = cgroup_get_value_uint64(cgc, "cpu.shares", shares); + +out: + cgroup_free(&cgroup); + return ret; +} + +/* + * Please note, the value stored at the location pointed by usage is + * undefined when this function fails. + */ +int cgroup_cpuacct_get_usage(char *name, u_int64_t *usage) +{ + struct cgroup *cgroup; + struct cgroup_controller *cgc; + int ret = 0; + + if (!cgroup_initialized) + return ECGROUPNOTINITIALIZED; + + if (!usage) + return ECGINVAL; + + cgroup = cgroup_new_cgroup(name); + + if (!cgroup) { + last_errno = errno; + return ECGOTHER; + } + + cgc = cgroup_add_controller(cgroup, CPUACCT); + + if (!cgc) { + /* + * The only reason cgroup_add_controller can fail is due to + * calloc failing. There is no other reason for it to fail. + */ + last_errno = errno; + ret = ECGOTHER; + goto out; + } + + ret = cgroup_get_cgroup(cgroup); + + if (ret) + goto out; + + ret = cgroup_get_value_uint64(cgc, "cpuacct.usage", usage); + +out: + cgroup_free(&cgroup); + return ret; +} + +int cgroup_cpuacct_reset_usage(char *name) +{ + struct cgroup *cgroup; + struct cgroup_controller *cgc; + int ret = 0; + + if (!cgroup_initialized) + return ECGROUPNOTINITIALIZED; + + cgroup = cgroup_new_cgroup(name); + + if (!cgroup) { + last_errno = errno; + return ECGOTHER; + } + + cgc = cgroup_add_controller(cgroup, CPUACCT); + + if (!cgc) { + /* + * The only reason cgroup_add_controller can fail is due to + * calloc failing. There is no other reason for it to fail. + */ + last_errno = errno; + ret = ECGOTHER; + goto out; + } + + ret = cgroup_add_value_int64(cgc, "cpuacct.usage", 0); + + if (ret) + goto out; + + ret = cgroup_modify_cgroup(cgroup); + +out: + cgroup_free(&cgroup); + return ret; +} Index: libcg/include/libcgroup.h =================================================================== --- libcg.orig/include/libcgroup.h +++ libcg/include/libcgroup.h @@ -89,6 +89,7 @@ enum cgroup_errors { ECGSENTINEL, /* Please insert further error codes above this */ ECGEOF, /* End of file, iterator */ ECGCONFIGPARSEFAIL,/* Failed to parse config file (cgconfig.conf). */ + ECGCPUNOTEXIST, /* This group dos not have the CPU controller for it */ }; #define ECGRULESPARSEFAIL ECGROUPPARSEFAIL @@ -472,6 +473,14 @@ struct cgroup_controller *cgroup_get_con int cgroup_config_load_config(const char *pathname); int cgroup_unload_cgroups(void); +/* + * Controller specific APIs + */ +int cgroup_cpu_set_shares(char *name, u_int64_t shares); +int cgroup_cpu_get_shares(char *name, u_int64_t *shares); +int cgroup_cpuacct_get_usage(char *name, u_int64_t *usage); +int cgroup_cpuacct_reset_usage(char *name); + __END_DECLS #endif /* _LIBCG_H */ Index: libcg/src/Makefile.am =================================================================== --- libcg.orig/src/Makefile.am +++ libcg/src/Makefile.am @@ -5,7 +5,7 @@ AM_YFLAGS = -d INCLUDES = -I$(top_srcdir)/include lib_LTLIBRARIES = libcgroup.la -libcgroup_la_SOURCES = parse.y lex.l api.c config.c libcgroup-internal.h libcgroup.map wrapper.c +libcgroup_la_SOURCES = parse.y lex.l api.c config.c libcgroup-internal.h libcgroup.map wrapper.c cpu.c libcgroup_la_LIBADD = -lpthread libcgroup_la_LDFLAGS = -Wl,--version-script,$(srcdir)/libcgroup.map \ -version-number $(LIBRARY_VERSION_MAJOR):$(LIBRARY_VERSION_MINOR):$(LIBRARY_VERSION_RELEASE) Index: libcg/src/api.c =================================================================== --- libcg.orig/src/api.c +++ libcg/src/api.c @@ -68,7 +68,7 @@ struct cg_mount_table_s cg_mount_table[C static pthread_rwlock_t cg_mount_table_lock = PTHREAD_RWLOCK_INITIALIZER; /* Check if cgroup_init has been called or not. */ -static int cgroup_initialized; +int cgroup_initialized; /* Check if the rules cache has been loaded or not. */ static bool cgroup_rules_loaded; @@ -108,6 +108,7 @@ char *cgroup_strerror_codes[] = { "The config file can not be opened", "Sentinel" "End of File or iterator", + "Cgroup does not exist for the CPU controller", }; static int cg_chown_file(FTS *fts, FTSENT *ent, uid_t owner, gid_t group) Index: libcg/src/libcgroup.map =================================================================== --- libcg.orig/src/libcgroup.map +++ libcg/src/libcgroup.map @@ -82,4 +82,8 @@ global: cgroup_get_all_controller_begin; cgroup_get_all_controller_next; cgroup_get_all_controller_end; + cgroup_cpu_set_shares; + cgroup_cpu_get_shares; + cgroup_cpuacct_get_usage; + cgroup_cpuacct_reset_usage; } CGROUP_0.34; ------------------------------------------------------------------------------ This SF.Net email is sponsored by the Verizon Developer Community Take advantage of Verizon's best-in-class app development support A streamlined, 14 day to market process makes app distribution fast and easy Join now and get one step closer to millions of Verizon customers http://p.sf.net/sfu/verizon-dev2dev _______________________________________________ Libcg-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/libcg-devel
