From c43167cca3d27940e81bfed06f6645a864d00216 Mon Sep 17 00:00:00 2001
From: Sebastien GODARD <sysstat@users.noreply.github.com>
Date: Sun, 7 May 2023 10:16:40 +0200
Subject: [PATCH] iostat: Try to avoid negative values (#355)

Check for negative values to avoir displaying large numbers.

Signed-off-by: Sebastien GODARD <sysstat@users.noreply.github.com>

Reference:https://github.com/sysstat/sysstat/commit/c43167cca3d27940e81bfed06f6645a864d00216
Conflict:NA

---
 iostat.c   | 32 ++++++++++++++++++++++++--------
 rd_stats.c |  4 +++-
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/iostat.c b/iostat.c
index 8174a93..bd21eb4 100644
--- a/iostat.c
+++ b/iostat.c
@@ -1189,6 +1189,7 @@ void write_plain_ext_stat(unsigned long long itv, int fctr, int hpart,
 		if ((hpart == 1) || !hpart) {
 			/* r/s */
 			cprintf_f(NO_UNIT, 1, 7, 2,
+				  ioi->rd_ios < ioj->rd_ios ? 0.0 :
 				  S_VALUE(ioj->rd_ios, ioi->rd_ios, itv));
 			/* rkB/s */
 			if (!DISPLAY_UNIT(flags)) {
@@ -1212,6 +1213,7 @@ void write_plain_ext_stat(unsigned long long itv, int fctr, int hpart,
 		if ((hpart == 2) || !hpart) {
 			/* w/s */
 			cprintf_f(NO_UNIT, 1, 7, 2,
+				  ioi->wr_ios < ioj->wr_ios ? 0.0 :
 				  S_VALUE(ioj->wr_ios, ioi->wr_ios, itv));
 			/* wkB/s */
 			if (!DISPLAY_UNIT(flags)) {
@@ -1235,6 +1237,7 @@ void write_plain_ext_stat(unsigned long long itv, int fctr, int hpart,
 		if ((hpart == 3) || !hpart) {
 			/* d/s */
 			cprintf_f(NO_UNIT, 1, 7, 2,
+				  ioi->dc_ios < ioj->dc_ios ? 0.0 :
 				  S_VALUE(ioj->dc_ios, ioi->dc_ios, itv));
 			/* dkB/s */
 			if (!DISPLAY_UNIT(flags)) {
@@ -1258,6 +1261,7 @@ void write_plain_ext_stat(unsigned long long itv, int fctr, int hpart,
 		if ((hpart == 4) || !hpart) {
 			/* f/s */
 			cprintf_f(NO_UNIT, 1, 7, 2,
+				  ioi->fl_ios < ioj->fl_ios ? 0.0 :
 				  S_VALUE(ioj->fl_ios, ioi->fl_ios, itv));
 			/* f_await */
 			cprintf_f(NO_UNIT, 1, 7, 2,
@@ -1343,10 +1347,14 @@ void write_json_ext_stat(int tab, unsigned long long itv, int fctr,
 	}
 	else {
 		printf("\"r/s\": %.2f, \"w/s\": %.2f, \"d/s\": %.2f, \"f/s\": %.2f, ",
-		       S_VALUE(ioj->rd_ios, ioi->rd_ios, itv),
-		       S_VALUE(ioj->wr_ios, ioi->wr_ios, itv),
-		       S_VALUE(ioj->dc_ios, ioi->dc_ios, itv),
-		       S_VALUE(ioj->fl_ios, ioi->fl_ios, itv));
+		       ioi->rd_ios < ioj->rd_ios ? 0.0
+						 : S_VALUE(ioj->rd_ios, ioi->rd_ios, itv),
+		       ioi->wr_ios < ioj->wr_ios ? 0.0
+						 : S_VALUE(ioj->wr_ios, ioi->wr_ios, itv),
+		       ioi->dc_ios < ioj->dc_ios ? 0.0
+						 : S_VALUE(ioj->dc_ios, ioi->dc_ios, itv),
+		       ioi->fl_ios < ioj->fl_ios ? 0.0
+						 : S_VALUE(ioj->fl_ios, ioi->fl_ios, itv));
 		if (DISPLAY_MEGABYTES(flags)) {
 			sprintf(line, "\"rMB/s\": %%.2f, \"wMB/s\": %%.2f, \"dMB/s\": %%.2f, ");
 		}
@@ -1454,10 +1462,18 @@ void write_ext_stat(unsigned long long itv, int fctr, int hpart,
 		compute_ext_disk_stats(&sdc, &sdp, itv, &xds);
 	}
 
-	/* rkB/s  wkB/s dkB/s */
-	xios.rsectors = S_VALUE(ioj->rd_sectors, ioi->rd_sectors, itv);
-	xios.wsectors = S_VALUE(ioj->wr_sectors, ioi->wr_sectors, itv);
-	xios.dsectors = S_VALUE(ioj->dc_sectors, ioi->dc_sectors, itv);
+	/*
+	 * rkB/s  wkB/s dkB/s
+	 * Note: We've already tried to determine if a device had been
+	 * removed then added again (see write_stats() function).
+	 * Anyway we need to check again for possible negative values.
+	 */
+	xios.rsectors = ioi->rd_sectors < ioj->rd_sectors ? 0.0 :
+			S_VALUE(ioj->rd_sectors, ioi->rd_sectors, itv);
+	xios.wsectors = ioi->wr_sectors < ioj->wr_sectors ? 0.0 :
+			S_VALUE(ioj->wr_sectors, ioi->wr_sectors, itv);
+	xios.dsectors = ioi->dc_sectors < ioj->dc_sectors ? 0.0 :
+			S_VALUE(ioj->dc_sectors, ioi->dc_sectors, itv);
 
 	if (DISPLAY_SHORT_OUTPUT(flags)) {
 		xios.sectors  = xios.rsectors + xios.wsectors + xios.dsectors;
diff --git a/rd_stats.c b/rd_stats.c
index 245dc74..9c91dac 100644
--- a/rd_stats.c
+++ b/rd_stats.c
@@ -377,7 +377,9 @@ void read_uptime(unsigned long long *uptime)
 void compute_ext_disk_stats(struct stats_disk *sdc, struct stats_disk *sdp,
 			    unsigned long long itv, struct ext_disk_stats *xds)
 {
-	xds->util  = S_VALUE(sdp->tot_ticks, sdc->tot_ticks, itv);
+	xds->util  = sdc->tot_ticks < sdp->tot_ticks ?
+		     0.0 :
+		     S_VALUE(sdp->tot_ticks, sdc->tot_ticks, itv);
 	/*
 	 * Kernel gives ticks already in milliseconds for all platforms
 	 * => no need for further scaling.
-- 
2.33.0
