From: Daniel Hokka Zakrisson Date: Wed, 10 Jan 2007 18:53:07 +0000 (+0000) Subject: Add vc_sched_info API. X-Git-Tag: release-0.30.214~156 X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fc84d2d3d5179f3bbbcee0f7e8d8cb155239edfd;p=util-vserver.git Add vc_sched_info API. Make vserver-stat use the various APIs instead of parsing per-process /proc entries. vc_virt_stat.uptime is a uint64_t. vc_get_dlimit can handle a NULL limits argument. git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@2449 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- diff --git a/kernel/sched_cmd.h b/kernel/sched_cmd.h index 27b98d6..c18fb9e 100644 --- a/kernel/sched_cmd.h +++ b/kernel/sched_cmd.h @@ -6,7 +6,7 @@ #define VCMD_set_sched_v2 VC_CMD(SCHED, 1, 2) #define VCMD_set_sched_v3 VC_CMD(SCHED, 1, 3) -#define VCMD_set_sched VC_CMD(SCHED, 1, 4) +#define VCMD_set_sched_v4 VC_CMD(SCHED, 1, 4) struct vcmd_set_sched_v2 { int32_t fill_rate; @@ -39,6 +39,20 @@ struct vcmd_set_sched_v4 { int32_t bucket_id; }; +#define VCMD_set_sched VC_CMD(SCHED, 1, 5) +#define VCMD_get_sched VC_CMD(SCHED, 2, 5) + +struct vcmd_sched_v5 { + uint32_t mask; + int32_t cpu_id; + int32_t bucket_id; + int32_t fill_rate[2]; + int32_t interval[2]; + int32_t tokens; + int32_t tokens_min; + int32_t tokens_max; + int32_t prio_bias; +}; #define VXSM_FILL_RATE 0x0001 #define VXSM_INTERVAL 0x0002 @@ -58,6 +72,21 @@ struct vcmd_set_sched_v4 { #define VXSM_CPU_ID 0x1000 #define VXSM_BUCKET_ID 0x2000 +#define VXSM_MSEC 0x4000 + #define SCHED_KEEP (-2) /* only for v2 */ + +#define VCMD_sched_info VC_CMD(SCHED, 3, 0) + +struct vcmd_sched_info { + int32_t cpu_id; + int32_t bucket_id; + uint64_t user_msec; + uint64_t sys_msec; + uint64_t hold_msec; + uint32_t token_usec; + int32_t vavavoom; +}; + #endif /* _VX_SCHED_CMD_H */ diff --git a/lib/Makefile-files b/lib/Makefile-files index fab3875..66b4d95 100644 --- a/lib/Makefile-files +++ b/lib/Makefile-files @@ -128,7 +128,9 @@ lib_v21_SRCS = lib/syscall_setccaps-v21.hc \ lib/syscall_setnamespace-v21.hc \ lib/syscall_ctxmigrate-v21.hc \ lib/syscall_setmapping.c \ - lib/syscall_setmapping-v21.hc + lib/syscall_setmapping-v21.hc \ + lib/syscall_schedinfo.c \ + lib/syscall_schedinfo-v21.hc if ENSC_HAVE_C99_COMPILER lib_v13_SRCS += lib/syscall_adddlimit-v13.hc \ diff --git a/lib/issupported.c b/lib/issupported.c index 30b6fb3..73bf813 100644 --- a/lib/issupported.c +++ b/lib/issupported.c @@ -43,6 +43,7 @@ vc_isSupported(vcFeatureSet feature) case vcFEATURE_VWAIT : return ver >= 0x00010025; case vcFEATURE_SCHED : return ver >= 0x00020000; // todo case vcFEATURE_VNET : return ver >= 0x00020001; + case vcFEATURE_VSTAT : return ver >= 0x00020103; default : assert(false); } diff --git a/lib/issupportedstring.c b/lib/issupportedstring.c index ef47cd7..a4ef2f9 100644 --- a/lib/issupportedstring.c +++ b/lib/issupportedstring.c @@ -34,7 +34,7 @@ static struct { DECL(VKILL), DECL(IATTR), DECL(RLIMIT), DECL(COMPAT), DECL(MIGRATE), DECL(NAMESPACE), DECL(SCHED), DECL(VINFO), DECL(VHI), DECL(VSHELPER0), DECL(VSHELPER), DECL(VWAIT), - DECL(VNET) + DECL(VNET), DECL(VSTAT), }; bool diff --git a/lib/syscall_schedinfo-v21.hc b/lib/syscall_schedinfo-v21.hc new file mode 100644 index 0000000..9c8595a --- /dev/null +++ b/lib/syscall_schedinfo-v21.hc @@ -0,0 +1,41 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2007 Daniel Hokka Zakrisson +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +static inline ALWAYSINLINE int +vc_sched_info_v21(xid_t ctx, struct vc_sched_info *info) +{ + int ret; + struct vcmd_sched_info param = { .cpu_id = info->cpu_id, .bucket_id = info->bucket_id }; + + ret = vserver(VCMD_sched_info, CTX_USER2KERNEL(ctx), ¶m); + if (ret) + return ret; + +#define G(ATTR) info->ATTR = param.ATTR + G(user_msec); + G(sys_msec); + G(hold_msec); + G(token_usec); + G(vavavoom); + + return 0; +} diff --git a/lib/syscall_schedinfo.c b/lib/syscall_schedinfo.c new file mode 100644 index 0000000..8c01f2a --- /dev/null +++ b/lib/syscall_schedinfo.c @@ -0,0 +1,39 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2007 Daniel Hokka Zakrisson +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "vserver.h" +#include "vserver-internal.h" +#include "virtual.h" + +#if defined(VC_ENABLE_API_V21) +# include "syscall_schedinfo-v21.hc" +#endif + +#if defined(VC_ENABLE_API_V21) + +int +vc_sched_info(xid_t ctx, struct vc_sched_info *info) +{ + CALL_VC(CALL_VC_V21(vc_sched_info, ctx, info)); +} + +#endif diff --git a/lib/vserver.h b/lib/vserver.h index a6708a7..20122c5 100644 --- a/lib/vserver.h +++ b/lib/vserver.h @@ -414,7 +414,7 @@ extern "C" { /** \brief Contains further statistics about a context. */ struct vc_virt_stat { uint_least64_t offset; - uint_least32_t uptime; + uint_least64_t uptime; uint_least32_t nr_threads; uint_least32_t nr_running; uint_least32_t nr_uninterruptible; @@ -720,9 +720,9 @@ extern "C" { /** Get a disk limit. */ int vc_get_dlimit(char const *filename, xid_t xid, uint_least32_t flags, - struct vc_ctx_dlimit *limits) VC_ATTR_NONNULL((1,4)); + struct vc_ctx_dlimit *limits) VC_ATTR_NONNULL((1)); - /* misc. syscalls */ + /* scheduler related syscalls */ struct vc_set_sched { uint_least32_t set_mask; int_least32_t fill_rate; @@ -739,6 +739,19 @@ extern "C" { int vc_set_sched(xid_t xid, struct vc_set_sched const *) VC_ATTR_NONNULL((2)); + struct vc_sched_info { + int_least32_t cpu_id; + int_least32_t bucket_id; + uint_least64_t user_msec; + uint_least64_t sys_msec; + uint_least64_t hold_msec; + uint_least32_t token_usec; + int_least32_t vavavoom; + }; + + int vc_sched_info(xid_t xid, struct vc_sched_info *info) VC_ATTR_NONNULL((2)); + + /* misc. syscalls */ int vc_set_mapping(xid_t xid, const char *device, const char *target, uint32_t flags); @@ -870,7 +883,7 @@ extern "C" { vcFEATURE_COMPAT, vcFEATURE_MIGRATE, vcFEATURE_NAMESPACE, vcFEATURE_SCHED, vcFEATURE_VINFO, vcFEATURE_VHI, vcFEATURE_VSHELPER0, vcFEATURE_VSHELPER, vcFEATURE_VWAIT, - vcFEATURE_VNET } + vcFEATURE_VNET, vcFEATURE_VSTAT } vcFeatureSet; bool vc_isSupported(vcFeatureSet) VC_ATTR_CONST; diff --git a/src/vserver-stat.c b/src/vserver-stat.c index d3e1741..efb8706 100644 --- a/src/vserver-stat.c +++ b/src/vserver-stat.c @@ -42,6 +42,7 @@ #include #include #include +#include #define ENSC_WRAPPERS_DIRENT 1 #define ENSC_WRAPPERS_VSERVER 1 @@ -50,6 +51,7 @@ #include "wrappers.h" #define PROC_DIR_NAME "/proc" +#define PROC_VIRT_DIR_NAME "/proc/virtual" #define CTX_DIR_NAME "/var/run/vservers/" #define CTX_NAME_MAX_LEN 50 @@ -223,6 +225,60 @@ registerXid(struct Vector *vec, struct process_info *process) res->start_time_oldest = MIN(res->start_time_oldest, process->start_time); } +static void +registerXidVstat(struct Vector *vec, unsigned long xid_l) +{ + xid_t xid = (xid_t) xid_l; + struct XidData *res; + struct vc_rlimit_stat limit[3]; + struct vc_virt_stat vstat; + struct vc_sched_info sched; + int cpu; + + res = Vector_search(vec, &xid, cmpData); + if (res!=0) { + WRITE_MSG(2, "Duplicate xid found?!\n"); + return; + } + if (vc_virt_stat(xid, &vstat) == -1) { + perror("vc_virt_stat()"); + return; + } + if (vc_rlimit_stat(xid, RLIMIT_NPROC, &limit[0]) == -1) { + perror("vc_rlimit_stat(RLIMIT_NRPOC)"); + return; + } + if (vc_rlimit_stat(xid, RLIMIT_AS, &limit[1]) == -1) { + perror("vc_rlimit_stat(RLIMIT_AS)"); + return; + } + if (vc_rlimit_stat(xid, RLIMIT_RSS, &limit[2]) == -1) { + perror("vc_rlimit_stat(RLIMIT_RSS)"); + return; + } + + res = Vector_insert(vec, &xid, cmpData); + res->xid = xid; + + res->process_count = limit[0].value; + res->VmSize_total = limit[1].value * pagesize; + res->VmRSS_total = limit[2].value; + res->start_time_oldest= getUptime() - vstat.uptime/1000000; + + res->utime_total = 0; + res->stime_total = 0; + // XXX: arbitrary CPU limit. + for (cpu = 0; cpu < 1024; cpu++) { + sched.cpu_id = cpu; + sched.bucket_id = 0; + if (vc_sched_info(xid, &sched) == -1) + break; + + res->utime_total += sched.user_msec; + res->stime_total += sched.sys_msec; + } +} + static inline uint64_t toMsec(uint64_t v) { @@ -572,21 +628,35 @@ int main(int argc, char **argv) Vector_init(&xid_data, sizeof(struct XidData)); - Echdir(PROC_DIR_NAME); - proc_dir = Eopendir("."); - while ((dir_entry = readdir(proc_dir)) != NULL) - { + if (vc_isSupported(vcFEATURE_VSTAT)) { + unsigned long xid; + Echdir(PROC_VIRT_DIR_NAME); + proc_dir = Eopendir("."); + while ((dir_entry = readdir(proc_dir)) != NULL) { + if (!isNumberUnsigned(dir_entry->d_name, &xid, false)) + continue; + + registerXidVstat(&xid_data, xid); + } + closedir(proc_dir); + } + else { + Echdir(PROC_DIR_NAME); + proc_dir = Eopendir("."); + while ((dir_entry = readdir(proc_dir)) != NULL) + { // select only process file - if (!isdigit(*dir_entry->d_name)) - continue; + if (!isdigit(*dir_entry->d_name)) + continue; - if (atoi(dir_entry->d_name) != my_pid) { - struct process_info * info = get_process_info(dir_entry->d_name); - if (info) - registerXid(&xid_data, info); + if (atoi(dir_entry->d_name) != my_pid) { + struct process_info * info = get_process_info(dir_entry->d_name); + if (info) + registerXid(&xid_data, info); + } } + closedir(proc_dir); } - closedir(proc_dir); Vector_foreach(&xid_data, fillName, 0);