vz extension contains OpenVZ specific commands:
  vzlist        shows list of OpenVZ containers,
  vzps          shows all tasks executed inside of specified container,
  ctid          shows ContainerID of given task.

Signed-off-by: Vasily Averin <v...@parallels.com>
---
 extensions/vz.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 345 insertions(+)
 create mode 100644 extensions/vz.c

diff --git a/extensions/vz.c b/extensions/vz.c
new file mode 100644
index 0000000..f48d428
--- /dev/null
+++ b/extensions/vz.c
@@ -0,0 +1,345 @@
+/* vz.c - crash extension for OpenVZ containers
+ *
+ * Copyright (C) 2015 Vasily Averin
+ * Copyright (C) 2015 Parallels IP Holdings GmbH.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include "defs.h"
+
+#define VZ_MEMBER_OFFSET_INIT(X,Y,Z) (vz_offset_table.X=MEMBER_OFFSET(Y,Z))
+#define VZ_OFFSET(X)   (OFFSET_verify(vz_offset_table.X, (char *)__FUNCTION__, 
__FILE__, __LINE__, #X))
+#define VZ_INIT 0x1
+
+struct vz_offset_table {
+       long task_veinfo;
+       long veinfo_ve;
+       long ve_veid;
+       long ve_nsproxy;
+       long nsproxy_pidns;
+       long pidns_init;
+};
+
+static struct vz_offset_table vz_offset_table = { 0 };
+static int init_flags = 0;
+static int id_size;
+
+void vz_init(void);
+void vz_fini(void);
+
+static ulong
+ve_to_task(ulong ve)
+{
+       ulong ns, pidns, task;
+
+       readmem(ve + VZ_OFFSET(ve_nsproxy), KVADDR, &ns,
+               sizeof(ulong), "ve_struct.ve_ns", FAULT_ON_ERROR);
+       readmem(ns + VZ_OFFSET(nsproxy_pidns), KVADDR, &pidns,
+               sizeof(ulong), "nsproxy.ve_pidns", FAULT_ON_ERROR);
+       readmem(pidns + VZ_OFFSET(pidns_init), KVADDR, &task,
+               sizeof(ulong), "pid_namespace.child_reaper", FAULT_ON_ERROR);
+
+       return task;
+}
+
+#define VZLIST_HEADER \
+"     CTID     VE_STRUCT            TASK          PID  COMM\n"
+
+static void
+show_container(ulong ve, ulong ctid, ulong flag)
+{
+       ulong task;
+       struct task_context *tc;
+
+       task = ve_to_task(ve);
+       tc = task_to_context(task);
+
+       if (!(flag & PS_NO_HEADER))
+               fprintf(fp, VZLIST_HEADER);
+
+       fprintf(fp, "%9ld  %16lx  %16lx  %6ld  %s\n",
+               ctid, ve, tc->task, tc->pid, tc->comm);
+       return;
+}
+
+static void
+show_containers(ulong ctid)
+{
+       struct list_data list_data, *ld;
+       ulong ve, id, flag = 0;
+       int i, cnt;
+
+       ld = &list_data;
+       BZERO(ld, sizeof(struct list_data));
+       ld->flags |= LIST_ALLOCATE;
+
+       ld->start = ld->end = symbol_value("ve_list_head");
+       ld->list_head_offset = 0;
+
+       cnt = do_list(ld);
+
+       for (i = 1; i < cnt; i++) {
+               id = 0;
+               ve = ld->list_ptr[i];
+               readmem(ve + VZ_OFFSET(ve_veid), KVADDR, &id,
+                       id_size, "ve_struct.veid", FAULT_ON_ERROR);
+               if ((ctid == -1) || ctid == id) {
+                       show_container(ve, id, flag);
+                       flag = PS_NO_HEADER;
+               }
+       }
+       return;
+}
+
+void
+cmd_vzlist(void)
+{
+       int c;
+       ulong ctid = -1;
+
+       while ((c = getopt(argcnt, args, "E:")) != EOF) {
+               switch(c)
+               {
+               case 'E':
+                       ctid = stol(optarg, FAULT_ON_ERROR, NULL);
+                       break;
+               default:
+                       argerrs++;
+                       break;
+               }
+       }
+       if (argerrs) {
+               cmd_usage(pc->curcmd, SYNOPSIS);
+               return;
+       }
+
+       show_containers(ctid);
+       return;
+}
+
+char *help_vzlist[] = {
+"vzlist",
+"shows list of runnig OpenVZ containers",
+"[-E CTID]",
+"If no argument is entered, command shows IDs of all running containers\n",
+"  -E  Container ID",
+"\nEXAMPLES",
+"%s> vzlist",
+"     CTID     VE_STRUCT            TASK          PID  COMM",
+"      121  ffff8801491e7000  ffff8801493d0ff0   95990  init",
+"      123  ffff880135a37000  ffff8803fb0a3470   95924  init",
+"      321  ffff88045a778000  ffff880400616300   95923  init",
+"      700  ffff88019ddae000  ffff88019ddd4fb0   95882  init",
+"      503  ffff88045a84e800  ffff8803c3c782c0   95902  init",
+"      122  ffff8804004ea000  ffff88045612afb0   95886  init",
+"      600  ffff88016e467000  ffff880459d653f0   95885  init",
+"        0  ffffffff81aaa220  ffff88045e530b30       1  init",
+NULL
+};
+
+static ulong
+task_to_ctid(ulong task)
+{
+       ulong veinfo, ve, ctid = 0;
+
+       veinfo = task + VZ_OFFSET(task_veinfo);
+       readmem(veinfo + VZ_OFFSET(veinfo_ve), KVADDR, &ve,
+               sizeof(ulong), "ve_task_info.exec_env", FAULT_ON_ERROR);
+       readmem(ve + VZ_OFFSET(ve_veid), KVADDR, &ctid,
+               id_size, "ve_struct.veid", FAULT_ON_ERROR);
+
+       return ctid;
+}
+
+static void
+show_ctid(struct task_context *tc, ulong flag)
+{
+       ulong ctid;
+
+       ctid = task_to_ctid(tc->task);
+       if (!(flag & PS_NO_HEADER))
+               fprintf(fp, "     CTID    PID         TASK        COMM\n");
+
+       fprintf(fp, "%9ld  %6ld  %16lx  %s\n",
+               ctid, tc->pid, tc->task, tc->comm);
+       return;
+}
+
+void
+cmd_ctid(void)
+{
+       ulong value, flag = 0;
+       struct task_context *tc;
+       int c;
+
+       while ((c = getopt(argcnt, args, "")) != EOF) {
+               switch(c)
+               {
+               default:
+                       cmd_usage(pc->curcmd, SYNOPSIS);
+                       return;
+               }
+       }
+
+       if (!args[optind]) {
+               tc = task_to_context(CURRENT_TASK());
+               show_ctid(tc, flag);
+       }
+       while (args[optind]) {
+               switch (str_to_context(args[optind], &value, &tc))
+               {
+               case STR_PID:
+               case STR_TASK:
+                       break;
+               case STR_INVALID:
+                       error(INFO, "invalid task or pid value: %s\n",
+                                  args[optind]);
+               default:
+                       argerrs++;
+                        break;
+               }
+               if (argerrs)
+                       break;
+               show_ctid(tc, flag);
+               flag = PS_NO_HEADER;
+               optind++;
+       }
+       if (argerrs)
+               cmd_usage(pc->curcmd, SYNOPSIS);
+
+       return;
+}
+
+char *help_ctid[] = {
+"ctid",
+"shows Container ID of given tasks",
+"[task|pid]",
+"     If no argument is entered, command shows CTID of current task",
+"\nEXAMPLES",
+"%s> ctid 99583",
+"     CTID    PID         TASK        COMM",
+"      121   99583  ffff880203e56f30  httpd",
+NULL
+};
+
+static void
+show_vzps(ulong ctid)
+{
+       struct task_context *tc;
+       ulong flag;
+       int i;
+
+       tc = FIRST_CONTEXT();
+       for (i = 0; i < RUNNING_TASKS(); i++, tc++) {
+               ulong id = task_to_ctid(tc->task);
+               if ((ctid == -1) || (ctid == id)) {
+                       show_ctid(tc, flag);
+                       flag = PS_NO_HEADER;
+               }
+       }
+       return;
+}
+
+void
+cmd_vzps(void)
+{
+       ulong ctid = -1;
+       int c;
+
+       while ((c = getopt(argcnt, args, "E:")) != EOF) {
+               switch(c)
+               {
+               case 'E':
+                       ctid = stol(optarg, FAULT_ON_ERROR, NULL);
+                       break;
+               default:
+                       argerrs++;
+                       break;
+               }
+       }
+       if (argerrs)
+               cmd_usage(pc->curcmd, SYNOPSIS);
+
+       show_vzps(ctid);
+       return;
+}
+
+char *help_vzps[] = {
+"vzps",
+"shows list of tasks related to specified CTID",
+" [ -E CTID]",
+"     If no argument is entered, command shows CTID for all processes\n",
+"\nEXAMPLES",
+"%s> vzps -E 121",
+"     CTID    PID         TASK        COMM",
+"      121   95990  ffff8801493d0ff0  init",
+"      121   95996  ffff8803c3e3b0f0  kthreadd/121",
+"      121   95997  ffff8803cd3aacb0  khelper/121",
+"      121   97267  ffff880405e4b2f0  udevd",
+"      121   99341  ffff8803c3fd2440  syslogd",
+"      121   99404  ffff880405e0c2c0  klogd",
+"      121   99424  ffff8803fb0f68c0  sshd",
+"      121   99445  ffff8801493d0500  xinetd",
+"      121   99557  ffff8804599f9230  sendmail",
+"      121   99568  ffff8804591b00c0  sendmail",
+"      121   99583  ffff880203e56f30  httpd",
+"      121   99594  ffff88016e4e01c0  crond",
+"      121   99614  ffff8803fb26cf70  xfs",
+"      121   99624  ffff88045a6ce2c0  saslauthd",
+"      121   99625  ffff8801ce134ff0  saslauthd",
+"      121  248691  ffff88040e2ee9c0  httpd",
+NULL
+};
+
+static struct command_table_entry command_table[] = {
+       { "vzlist", cmd_vzlist, help_vzlist, 0},
+       { "ctid", cmd_ctid, help_ctid, 0},
+       { "vzps", cmd_vzps, help_vzps, 0},
+       { NULL },
+};
+
+void __attribute__((constructor))
+vz_init(void)
+{
+       if (init_flags & VZ_INIT)
+               return;
+
+       if (!symbol_exists("ve_list_head")) {
+               fprintf(fp, "vz commands only work on OpenVZ kernels\n");
+               return;
+       }
+       init_flags |= VZ_INIT;
+
+       BNEG(&vz_offset_table, sizeof(vz_offset_table));
+
+       if (STRUCT_EXISTS("ve_task_info")) {
+               VZ_MEMBER_OFFSET_INIT(task_veinfo,
+                                        "task_struct", "ve_task_info");
+               VZ_MEMBER_OFFSET_INIT(veinfo_ve, "ve_task_info", "exec_env");
+       }
+       if (STRUCT_EXISTS("ve_struct")) {
+               VZ_MEMBER_OFFSET_INIT(ve_veid, "ve_struct", "veid");
+               VZ_MEMBER_OFFSET_INIT(ve_nsproxy, "ve_struct", "ve_ns");
+               id_size = MEMBER_SIZE("ve_struct", "veid");
+       }
+       if (STRUCT_EXISTS("nsproxy")) {
+               VZ_MEMBER_OFFSET_INIT(nsproxy_pidns, "nsproxy", "pid_ns");
+       }
+       if (STRUCT_EXISTS("pid_namespace"))
+               VZ_MEMBER_OFFSET_INIT(pidns_init,
+                                       "pid_namespace", "child_reaper");
+
+       register_extension(command_table);
+}
+
+void __attribute__((destructor))
+vz_fini(void) { }
-- 
1.7.12.4

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to