#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;
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
#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 */
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 \
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);
}
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
--- /dev/null
+// $Id$ --*- c++ -*--
+
+// Copyright (C) 2007 Daniel Hokka Zakrisson <daniel@hozac.com>
+//
+// 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 <config.h>
+#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;
+}
--- /dev/null
+// $Id$ --*- c++ -*--
+
+// Copyright (C) 2007 Daniel Hokka Zakrisson <daniel@hozac.com>
+//
+// 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 <config.h>
+#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
/** \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;
/** 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;
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);
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;
#include <stdbool.h>
#include <getopt.h>
#include <sys/param.h>
+#include <sys/resource.h>
#define ENSC_WRAPPERS_DIRENT 1
#define ENSC_WRAPPERS_VSERVER 1
#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
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)
{
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);