Add vc_sched_info API.
authorDaniel Hokka Zakrisson <daniel@hozac.com>
Wed, 10 Jan 2007 18:53:07 +0000 (18:53 +0000)
committerDaniel Hokka Zakrisson <daniel@hozac.com>
Wed, 10 Jan 2007 18:53:07 +0000 (18:53 +0000)
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

kernel/sched_cmd.h
lib/Makefile-files
lib/issupported.c
lib/issupportedstring.c
lib/syscall_schedinfo-v21.hc [new file with mode: 0644]
lib/syscall_schedinfo.c [new file with mode: 0644]
lib/vserver.h
src/vserver-stat.c

index 27b98d6..c18fb9e 100644 (file)
@@ -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 */
index fab3875..66b4d95 100644 (file)
@@ -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 \
index 30b6fb3..73bf813 100644 (file)
@@ -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); 
   }
 
index ef47cd7..a4ef2f9 100644 (file)
@@ -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 (file)
index 0000000..9c8595a
--- /dev/null
@@ -0,0 +1,41 @@
+// $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), &param);
+  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 (file)
index 0000000..8c01f2a
--- /dev/null
@@ -0,0 +1,39 @@
+// $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
index a6708a7..20122c5 100644 (file)
@@ -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;
index d3e1741..efb8706 100644 (file)
@@ -42,6 +42,7 @@
 #include <stdbool.h>
 #include <getopt.h>
 #include <sys/param.h>
+#include <sys/resource.h>
 
 #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);