[Devel] [PATCH RFC] vz extension: vzlist, ctid, vzps commands

Vasily Averin vvs at odin.com
Thu Apr 30 07:46:40 PDT 2015


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 <vvs at 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




More information about the Devel mailing list