Blob Blame History Raw
commit d1576f88dcc7008bcd3448172caff1b928be1254
Author: Aravinda Prasad <aravinda@linux.vnet.ibm.com>
Date:   Thu Sep 6 15:01:04 2018 +0530

    lparstat: Show available physical processors in the shared pool
    
    This patch adds the "app" field that displays the available
    processors in the shared pool.
    
    The platform provides the summation of the physical processor
    pool idle cycles through H_PIC hypercall. This data is updated
    in the "pool_idle_time" field of the /proc/ppc64/lparcfg file.
    This patch derives the "app" from the "pool_idle_time" field.
    
    v2: Handle fgets() errors
    
    Signed-off-by: Aravinda Prasad <aravinda@linux.vnet.ibm.com>
    Signed-off-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>

diff --git a/man/lparstat.8 b/man/lparstat.8
index 6d94486..4872a37 100644
--- a/man/lparstat.8
+++ b/man/lparstat.8
@@ -77,6 +77,9 @@ Shows the percentage of the entitled capacity consumed. Because the time base ov
 lbusy
 Shows the percentage of logical processor(s) utilization that occurred while executing at the user and system level. 
 .TP
+app
+Shows the available physical processors in the shared pool.
+.TP
 phint
 Shows the number of phantom (targeted to another shared partition in this pool) interruptions received. 
 .SH OPTIONS
diff --git a/src/lparstat.c b/src/lparstat.c
index 6c54c7e..23e45f7 100644
--- a/src/lparstat.c
+++ b/src/lparstat.c
@@ -123,6 +123,32 @@ int get_time_base()
 	return 0;
 }
 
+void get_sys_uptime(struct sysentry *unused_se, char *uptime)
+{
+	FILE *f;
+	char buf[80];
+
+	f = fopen("/proc/uptime", "r");
+	if (!f) {
+		fprintf(stderr, "Could not open /proc/uptime\n");
+		sprintf(uptime, SE_NOT_VALID);
+		return;
+	}
+
+	if ((fgets(buf, 80, f)) != NULL) {
+		char *value;
+
+		value = strchr(buf, ' ');
+		*value = '\0';
+		sprintf(uptime, "%s", buf);
+	} else {
+		sprintf(uptime, SE_NOT_VALID);
+	}
+
+	fclose(f);
+}
+
+
 void get_cpu_physc(struct sysentry *unused_se, char *buf)
 {
 	struct sysentry *se;
@@ -155,6 +181,44 @@ void get_per_entc(struct sysentry *unused_se, char *buf)
 	sprintf(buf, "%.6f", atof(physc) / atof(entc) * 100.0);
 }
 
+void get_cpu_app(struct sysentry *unused_se, char *buf)
+{
+	struct sysentry *se;
+	float timebase, app, elapsed_time;
+	long long new_app, old_app, newtime, oldtime;
+	char *descr, uptime[32];
+
+	se = get_sysentry("time");
+	if (se->old_value[0] == '\0') {
+		/* Single report since boot */
+		get_sysdata("uptime", &descr, uptime);
+
+		if (!strcmp(uptime, SE_NOT_VALID)) {
+			sprintf(buf, "-");
+			return;
+		}
+		elapsed_time = atof(uptime);
+	} else {
+		newtime = strtoll(se->value, NULL, 0);
+		oldtime = strtoll(se->old_value, NULL, 0);
+		elapsed_time = (newtime - oldtime) / 1000000.0;
+	}
+
+	se = get_sysentry("timebase");
+	timebase = atof(se->value);
+
+	se = get_sysentry("pool_idle_time");
+	new_app = strtoll(se->value, NULL, 0);
+	if (se->old_value[0] == '\0') {
+		old_app = 0;
+	} else {
+		old_app = strtoll(se->old_value, NULL, 0);
+	}
+
+	app = (new_app - old_app)/timebase/elapsed_time;
+	sprintf(buf, "%.2f", app);
+}
+
 int parse_lparcfg()
 {
 	FILE *f;
@@ -527,13 +591,13 @@ int print_iflag_data()
 
 void print_default_output(int interval, int count)
 {
-	char *fmt = "%5s %5s %5s %8s %8s %5s %5s %5s %5s\n";
+	char *fmt = "%5s %5s %5s %8s %8s %5s %5s %5s %5s %5s\n";
 	char *descr;
 	char buf[128];
 	int offset;
 	char value[32];
 	char user[32], sys[32], wait[32], idle[32], physc[32], entc[32];
-	char lbusy[32], vcsw[32], phint[32];
+	char lbusy[32], app[32], vcsw[32], phint[32];
 
 	memset(buf, 0, 128);
 	get_sysdata("shared_processor_mode", &descr, value);
@@ -554,9 +618,9 @@ void print_default_output(int interval, int count)
 	fprintf(stdout, "\nSystem Configuration\n%s\n\n", buf);
 
 	fprintf(stdout, fmt, "\%user", "\%sys", "\%wait", "\%idle", "physc",
-		"\%entc", "lbusy", "vcsw", "phint");
+		"\%entc", "lbusy", "app", "vcsw", "phint");
 	fprintf(stdout, fmt, "-----", "-----", "-----", "-----", "-----",
-		"-----", "-----", "-----", "-----");
+		"-----", "-----", "-----", "-----", "-----");
 
 	do {
 		if (interval) {
@@ -573,9 +637,10 @@ void print_default_output(int interval, int count)
 		get_sysdata("physc", &descr, physc);
 		get_sysdata("per_entc", &descr, entc);
 		get_sysdata("phint", &descr, phint);
+		get_sysdata("app", &descr, app);
 
 		fprintf(stdout, fmt, user, sys, wait, idle, physc, entc,
-			lbusy, vcsw, phint);
+			lbusy, app, vcsw, phint);
 		fflush(stdout);
 	} while (--count > 0);
 }
diff --git a/src/lparstat.h b/src/lparstat.h
index 5412edc..20bb939 100644
--- a/src/lparstat.h
+++ b/src/lparstat.h
@@ -46,6 +46,8 @@ extern void get_smt_mode(struct sysentry *, char *);
 extern void get_cpu_stat(struct sysentry *, char *);
 extern void get_cpu_physc(struct sysentry *, char *);
 extern void get_per_entc(struct sysentry *, char *);
+extern void get_cpu_app(struct sysentry *, char *);
+extern void get_sys_uptime(struct sysentry *, char *);
 
 struct sysentry system_data[] = {
 	/* System Names */
@@ -221,6 +223,9 @@ struct sysentry system_data[] = {
 	{.name = "per_entc",
 	 .descr = "Entitled CPU Consumed",
 	 .get = &get_per_entc},
+	{.name = "app",
+	 .descr = "Available physical CPUs in pool",
+	 .get = &get_cpu_app},
 
 	/* Time */
 	{.name = "time",
@@ -234,6 +239,11 @@ struct sysentry system_data[] = {
 	{.name = "phint",
 	 .descr = "Phantom Interrupts"},
 
+	/* /proc/uptime */
+	{.name = "uptime",
+	 .descr = "System Uptime",
+	 .get = &get_sys_uptime},
+
 	{.name[0] = '\0'},
 };