[lxc-devel] [libresource/master] Adding process related information

rahuyada on Github lxc-bot at linuxcontainers.org
Sat Jun 22 01:53:53 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 451 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190621/41fca4df/attachment-0001.bin>
-------------- next part --------------
From 659843a9e0679dfd0f56b936d6d970f3ff5548aa Mon Sep 17 00:00:00 2001
From: Rahul Yadav <rahul.x.yadav at oracle.com>
Date: Fri, 21 Jun 2019 17:24:29 -0700
Subject: [PATCH 1/5] Added resource to get process related info

Signed-off-by: Rahul Yadav <rahul.x.yadav at oracle.com>
---
 resproc.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 resproc.h |  31 +++++++++
 2 files changed, 231 insertions(+)
 create mode 100644 resproc.c
 create mode 100644 resproc.h

diff --git a/resproc.c b/resproc.c
new file mode 100644
index 0000000..6305dc0
--- /dev/null
+++ b/resproc.c
@@ -0,0 +1,200 @@
+/* Copyright (C) 2018, Oracle and/or its affiliates. All rights reserved
+ *
+ * This file is part of libresource.
+ *
+ * libresource is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libresource 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 Lesser General public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General public License
+ * along with libresource. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _RESOURCE_H
+#include "resource.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "resproc.h"
+#include "resource_impl.h"
+#include <errno.h>
+#include <libgen.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <pwd.h>
+
+/* Reading information from /proc/<pid>/statm */
+static void statm_to_proc(char* buf, res_proc_infoall_t *p) {
+	sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld",
+		&p->size, &p->resident, &p->share,
+		&p->text, &p->lib, &p->data, &p->dt);
+}
+
+/* Reading information from /proc/<pid>/stat */
+static void stat_to_proc(char* buf, res_proc_infoall_t *p) {
+	unsigned int num;
+	char* tmp;
+
+	/* fill in default values for older kernels */
+	p->processor = 0;
+	p->rtprio = -1;
+	p->policy = -1;
+	p->nlwp = 0;
+
+	/* Fill the command to run process */
+	buf = strchr(buf, '(') + 1;
+	tmp = strrchr(buf, ')');
+	num = tmp - buf;
+	if(num >= sizeof p->cmd)
+		num = sizeof p->cmd - 1;
+	memcpy(p->cmd, buf, num);
+	p->cmd[num] = '\0';
+	buf = tmp + 2;
+
+	/* Now we are just after command in the string starting from status
+	 * of the process.
+	 */
+	sscanf(buf,
+		"%c "
+		"%d %d %d %d %d "
+		"%lu %lu %lu %lu %lu "
+		 /* utime stime cutime cstime */
+		"%Lu %Lu %Lu %Lu "
+		"%ld %ld "
+		"%d "
+		"%ld "
+		/* start_time */
+		"%Lu "
+		"%lu "
+		"%ld "
+		"%lu "
+		/* start_code, end_code, start_stack */
+		"%Lu %Lu %Lu "
+		"%Lu %Lu "
+		/* discard, no RT signals & Linux 2.1 used hex */
+		"%*s %*s %*s %*s "
+		"%Lu "
+		"%*s %*s "
+		"%d %d "
+		"%lu %lu",
+		&p->state,
+		&p->ppid, &p->pgrp, &p->session, &p->tty, &p->tpgid,
+		&p->flags, &p->min_flt, &p->cmin_flt, &p->maj_flt, &p->cmaj_flt,
+		&p->utime, &p->stime, &p->cutime, &p->cstime,
+		&p->priority, &p->nice,
+		&p->nlwp,
+		&p->alarm,
+		&p->start_time,
+		&p->vsize,
+		&p->rss,
+		&p->rss_rlim,
+		&p->start_code, &p->end_code, &p->start_stack,
+		&p->kstk_esp, &p->kstk_eip,
+		/* p->signal, p->blocked, p->sigignore, p->sigcatch, can't use */
+		&p->wchan,
+		/* &p->nswap, &p->cnswap,  nswap and cnswap dead for 2.4.xx and up */
+		/* -- Linux 2.0.35 ends here -- */
+		&p->exit_signal, &p->processor,
+		/* -- Linux 2.2.8 to 2.5.17 end here -- */
+		&p->rtprio, &p->policy
+	);
+
+	if(!p->nlwp){
+		p->nlwp = 1;
+	}
+}
+
+static void get_user_info(char *path, res_proc_infoall_t *p) {
+	static struct stat sb;
+	struct passwd *pw = NULL;
+
+
+	/* Get user id and use that to get useranme */
+	if (stat(path, &sb) == -1) {
+		eprintf("Error in reading stat");
+	}
+
+	p->euid = sb.st_uid;
+	pw = getpwuid(p->euid);
+	if(!pw || strlen(pw->pw_name) >= RES_USR_NAME_SZ) {
+		sprintf(p->euser, "%u", p->euid);
+	} else {
+		strcpy(p->euser, pw->pw_name);
+	}
+}
+
+/* Read resource information corresponding to res_id */
+int getprocinfo(int res_id, void *out, size_t sz, void *hint, int pid, int flags)
+{
+	char fstat[FNAMELEN];
+	char fstatm[FNAMELEN];
+	res_proc_infoall_t *p;
+	char buf[PROCBUF_1024];
+
+#define CHECK_SIZE(sz, req_sz)						\
+	if (sz < req_sz) {						\
+		eprintf("memory (%ld) is not enough to hold data (%ld)",\
+		sz, req_sz);						\
+		errno = ENOMEM;						\
+		return -1;						\
+	}
+
+
+	switch (res_id) {
+	case RES_PROC_INFOALL:
+		CHECK_SIZE(sz, sizeof(res_proc_infoall_t));
+
+		p = (res_proc_infoall_t *)out;
+
+		if (pid) {
+			p->pid = pid;
+			snprintf(fstat, FNAMELEN, "/proc/%d/stat", pid);
+			snprintf(fstatm, FNAMELEN, "/proc/%d/statm", pid);
+        	} else {
+			p->pid = getpid();
+			snprintf(fstat, FNAMELEN, "/proc/self/stat");
+			snprintf(fstatm, FNAMELEN, "/proc/self/statm");
+        	}
+
+		get_user_info(fstat, p);
+		file_to_buf(fstat, buf, PROCBUF_1024);
+		stat_to_proc(buf, p);
+		file_to_buf(fstatm, buf, PROCBUF_1024);
+		statm_to_proc(buf, p);
+
+		break;
+
+	default:
+		eprintf("Resource Id is invalid");
+		errno = EINVAL;
+		return -1;
+	}
+
+#undef CHECK_SIZE
+
+	return 0;
+}
+
+int populate_procinfo(res_blk_t *res, int pid, int flags)
+{
+        for (int i = 0; i < res->res_count; i++) {
+                switch (res->res_unit[i]->res_id) {
+                case RES_PROC_INFOALL:
+			getprocinfo(RES_PROC_INFOALL,
+				(res->res_unit[i]->data).ptr,
+				res->res_unit[i]->data_sz,
+				NULL, pid, flags);
+			res->res_unit[i]->status = RES_STATUS_FILLED;
+		}
+	}
+	return 0;
+}
diff --git a/resproc.h b/resproc.h
new file mode 100644
index 0000000..6d01e2c
--- /dev/null
+++ b/resproc.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 2018, Oracle and/or its affiliates. All rights reserved
+ *
+ * This file is part of libresource.
+ *
+ * libresource is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libresource 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libresource. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _RESPROC_H
+#define _RESPROC_H
+
+#define MEMINFO_FILE "/proc/meminfo"
+#define VMINFO_FILE "/proc/vmstat"
+
+#define PROCBUF_1024	1024
+#define PROCBUF_2048	2048
+
+extern int getprocinfo(int res_id, void *out, size_t sz,
+		void *hint, int pid, int flags);
+
+#endif /* _RESPROC_H */

From 6366143f9bacf4142f581dde0615a97723001e65 Mon Sep 17 00:00:00 2001
From: Rahul Yadav <rahul.x.yadav at oracle.com>
Date: Fri, 21 Jun 2019 17:53:49 -0700
Subject: [PATCH 2/5] Added proc info

Signed-off-by: Rahul Yadav <rahul.x.yadav at oracle.com>
---
 resproc.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/resproc.h b/resproc.h
index 6d01e2c..5559fdd 100644
--- a/resproc.h
+++ b/resproc.h
@@ -25,6 +25,7 @@
 #define PROCBUF_1024	1024
 #define PROCBUF_2048	2048
 
+extern int populate_procinfo(struct res_blk *res, int pid, int flags);
 extern int getprocinfo(int res_id, void *out, size_t sz,
 		void *hint, int pid, int flags);
 

From d74b8fd28641205f90935527710f2f78e802dfac Mon Sep 17 00:00:00 2001
From: Rahul Yadav <rahul.x.yadav at oracle.com>
Date: Fri, 21 Jun 2019 17:58:35 -0700
Subject: [PATCH 3/5] Adding proc info

Signed-off-by: Rahul Yadav <rahul.x.yadav at oracle.com>
---
 Makefile   |  4 ++--
 resource.c | 22 +++++++++++++++++++++
 resource.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 2c71328..dcfd226 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 CC = gcc
 CFLAGS = -g -Wall -Werror -fPIC
-DEPS = resource.h res_impl.h resmem.h resnet.h
-OBJ = resource.o resmem.o resnet.o
+DEPS = resource.h res_impl.h resmem.h resnet.h resproc.h
+OBJ = resource.o resmem.o resnet.o resproc.o
 LIB = libresource.so
 TEST = test
 RM = rm -rf
diff --git a/resource.c b/resource.c
index ea8f64c..5da45be 100644
--- a/resource.c
+++ b/resource.c
@@ -28,6 +28,7 @@
 #include "resource_impl.h"
 #include "resmem.h"
 #include "resnet.h"
+#include "resproc.h"
 
 /* Allocate memory for bulk resource information and initiate it
  * properly.
@@ -108,6 +109,18 @@ res_blk_t *res_build_blk(int *res_ids, int res_count)
 			temp->data_sz = sizeof(res_mem_infoall_t);
 			break;
 
+		case RES_PROC_INFOALL:
+			temp->data.ptr = (res_proc_infoall_t *)
+				malloc(sizeof(res_proc_infoall_t));
+			if (temp->data.ptr == NULL) {
+				free(temp);
+				res_destroy_blk(res);
+				errno = ENOMEM;
+				return NULL;
+			}
+			temp->data_sz = sizeof(res_proc_infoall_t);
+			break;
+
 		default:
 			eprintf("Invalid resource ID: %d", res_ids[i]);
 			free(temp);
@@ -133,6 +146,7 @@ void res_destroy_blk(res_blk_t *res)
 		switch (res->res_unit[i]->res_id) {
 		case RES_NET_IFSTAT:
 		case RES_MEM_INFOALL:
+		case RES_PROC_INFOALL:
 			free((res->res_unit[i])->data.ptr);
 			(res->res_unit[i])->data.ptr = NULL;
 			break;
@@ -170,6 +184,9 @@ int res_read(int res_id, void *out, size_t out_sz, void *hint, int pid, int flag
 		}
 	}
 
+	if (res_id >= PROC_MIN && res_id < PROC_MAX)
+		return getprocinfo(res_id, out, out_sz, hint, pid, flags);
+
 	/* Check if memory proc file is needed to open */
 	if (res_id >= MEM_MIN && res_id < MEM_MAX)
 		return getmeminfo(res_id, out, out_sz, hint, pid, flags);
@@ -217,6 +234,7 @@ int res_read_blk(res_blk_t *res, int pid, int flags)
 {
 	int ismeminforeq = 0;
 	int isnetdevreq = 0;
+	int isprocreq = 0;
 	struct utsname t;
 	int ret;
 	char *out;
@@ -281,12 +299,16 @@ int res_read_blk(res_blk_t *res, int pid, int flags)
 		case RES_NET_ALLIFSTAT:
 			isnetdevreq = 1;
 			break;
+		case RES_PROC_INFOALL:
+			isprocreq = 1;
 
 		default:
 			res->res_unit[i]->status = RES_STATUS_NOTSUPPORTED;
 		}
 	}
 
+	if(isprocreq)
+		populate_procinfo(res, pid, flags);
 	if (ismeminforeq)
 		populate_meminfo(res, pid, flags);
 
diff --git a/resource.h b/resource.h
index 6ade910..ba11fc9 100644
--- a/resource.h
+++ b/resource.h
@@ -51,6 +51,9 @@
  */
 #define RES_UNIT_OUT_SIZE	256
 
+/* Size of user name length */
+#define RES_USR_NAME_SZ		32
+
 /* This union is used to return resource information of various types */
 union r_data {
 	int i;
@@ -111,6 +114,11 @@ typedef struct res_blk {
 #define RES_KERN_RELEASE		3074
 #define KERN_MAX			3075
 
+#define PROC_MIN			4096
+#define RES_PROC_PPID			4097
+#define RES_PROC_INFOALL		4098
+#define PROC_MAX			4099
+
 /* Structure to return RES_MEM_INFOALL resource information */
 typedef struct res_mem_infoall {
 	size_t memfree;
@@ -143,6 +151,55 @@ typedef struct res_net_ifstat {
 	unsigned long tx_compressed;
 } res_net_ifstat_t;
 
+typedef struct proc_info {
+	int pid;
+	char cmd[16];
+	char state;
+	int ppid;
+	int pgrp;
+	int session;
+	int tty;
+	int tpgid;
+	unsigned long flags;
+	unsigned long min_flt;
+	unsigned long cmin_flt;
+	unsigned long maj_flt;
+	unsigned long cmaj_flt;
+	unsigned long long utime;
+	unsigned long long stime;
+	unsigned long long cutime;
+	unsigned long long cstime;
+	unsigned long long start_time;
+	long priority;
+	long nice;
+	int nlwp;
+	long alarm;
+	unsigned long vsize;
+	long rss;
+	unsigned long rss_rlim;
+	unsigned long long start_code;
+	unsigned long long end_code;
+	unsigned long long start_stack;
+	unsigned long long kstk_esp;
+	unsigned long long kstk_eip;
+	unsigned long long wchan;
+	int exit_signal;
+	int processor;
+	unsigned long rtprio;
+	unsigned long policy;
+	int euid;
+	char euser[RES_USR_NAME_SZ];
+
+	/* Information from /prco/[pid]/statm */
+	unsigned long size;
+	unsigned long resident;
+	unsigned long share;
+	unsigned long text;
+	unsigned long lib;
+	unsigned long data;
+	unsigned long dt;
+} res_proc_infoall_t;
+
 /* Allocating memory and building a res_blk structure to return bulk
  * resource information.
  */

From aeb35ed2f5b6cac19b3fbcdd9cd1a64f3be5f9fe Mon Sep 17 00:00:00 2001
From: Rahul Yadav <rahul.x.yadav at oracle.com>
Date: Fri, 21 Jun 2019 18:40:13 -0700
Subject: [PATCH 4/5] Little change - remove unused resource id.

Signed-off-by: Rahul Yadav <rahul.x.yadav at oracle.com>
---
 resource.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/resource.h b/resource.h
index ba11fc9..2664de3 100644
--- a/resource.h
+++ b/resource.h
@@ -115,7 +115,6 @@ typedef struct res_blk {
 #define KERN_MAX			3075
 
 #define PROC_MIN			4096
-#define RES_PROC_PPID			4097
 #define RES_PROC_INFOALL		4098
 #define PROC_MAX			4099
 

From 016e2ea6535561b548aa17e16e5d4f63158ca3dd Mon Sep 17 00:00:00 2001
From: Rahul Yadav <rahul.x.yadav at oracle.com>
Date: Fri, 21 Jun 2019 18:49:01 -0700
Subject: [PATCH 5/5] Remove unused header

Signed-off-by: Rahul Yadav <rahul.x.yadav at oracle.com>
---
 resource.h | 4 ++--
 resproc.c  | 7 +------
 resproc.h  | 4 ----
 3 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/resource.h b/resource.h
index 2664de3..7828cdc 100644
--- a/resource.h
+++ b/resource.h
@@ -115,8 +115,8 @@ typedef struct res_blk {
 #define KERN_MAX			3075
 
 #define PROC_MIN			4096
-#define RES_PROC_INFOALL		4098
-#define PROC_MAX			4099
+#define RES_PROC_INFOALL		4097
+#define PROC_MAX			4098
 
 /* Structure to return RES_MEM_INFOALL resource information */
 typedef struct res_mem_infoall {
diff --git a/resproc.c b/resproc.c
index 6305dc0..3b25a4c 100644
--- a/resproc.c
+++ b/resproc.c
@@ -20,16 +20,11 @@
 #include "resource.h"
 #endif
 #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 #include <unistd.h>
+#include <string.h>
 #include "resproc.h"
 #include "resource_impl.h"
-#include <errno.h>
-#include <libgen.h>
-#include <sys/types.h>
 #include <sys/stat.h>
-#include <unistd.h>
 #include <pwd.h>
 
 /* Reading information from /proc/<pid>/statm */
diff --git a/resproc.h b/resproc.h
index 5559fdd..4ecbf18 100644
--- a/resproc.h
+++ b/resproc.h
@@ -19,11 +19,7 @@
 #ifndef _RESPROC_H
 #define _RESPROC_H
 
-#define MEMINFO_FILE "/proc/meminfo"
-#define VMINFO_FILE "/proc/vmstat"
-
 #define PROCBUF_1024	1024
-#define PROCBUF_2048	2048
 
 extern int populate_procinfo(struct res_blk *res, int pid, int flags);
 extern int getprocinfo(int res_id, void *out, size_t sz,


More information about the lxc-devel mailing list