disk: in linux, reset the disk when it disappear from diskstats
authorNikita Kozlov <nikita@elyzion.net>
Tue, 14 Nov 2017 20:48:53 +0000 (21:48 +0100)
committerPavel Rochnyack <pavel2000@ngs.ru>
Tue, 30 Oct 2018 16:59:49 +0000 (23:59 +0700)
If you don't reset the diskstats_t for a given diskname when it
disappear and the disk name is reused later (for exemple an iSCSI disk)
The "disk" plugin detect an int overflow because linux /proc/diskstats are
reseted to 0 for that diskname and the plugin send incorrect stats for
the new disk.

src/disk.c

index b2285c1..6675534 100644 (file)
@@ -662,6 +662,7 @@ static int disk_read(void) {
   char buffer[1024];
 
   char *fields[32];
+  static unsigned int local_poll_count = 0;
 
   derive_t read_sectors = 0;
   derive_t write_sectors = 0;
@@ -714,6 +715,7 @@ static int disk_read(void) {
         disklist = ds;
       else
         pre_ds->next = ds;
+      ds->poll_count = local_poll_count;
     }
 
     is_disk = 0;
@@ -875,6 +877,27 @@ static int disk_read(void) {
 #endif
   } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
 
+  local_poll_count++;
+  for (ds = disklist, pre_ds = disklist; ds != NULL;) {
+      /* test if we have seen the disk in diskstats */
+      if (ds->poll_count != local_poll_count) {
+        diskstats_t *old_ds = ds;
+        /* free the ds */
+        if (pre_ds == disklist) {
+            /* first element */
+            disklist = ds->next;
+            ds = disklist;
+            pre_ds = ds;
+        } else {
+            pre_ds->next = ds->next;
+            ds = ds->next;
+        }
+        free(old_ds);
+      } else {
+        pre_ds = ds;
+        ds = ds->next;
+      }
+  }
   fclose(fh);
 /* #endif defined(KERNEL_LINUX) */