]> granicus.if.org Git - sysstat/commitdiff
sar: Test for zero value when reallocating all the buffers
authorSebastien GODARD <sysstat@users.noreply.github.com>
Sun, 4 Mar 2018 09:02:52 +0000 (10:02 +0100)
committerSebastien GODARD <sysstat@users.noreply.github.com>
Sun, 4 Mar 2018 09:02:52 +0000 (10:02 +0100)
When sar reads the contents of a file and meets a LINUX RESTART, it
may have to reallocate the buffers used to save CPU statistics to match
the new number of CPU. If the number of CPU has increased it doubles the
size of its buffers.
There is a problem though if CPU activity was not included in file (or
if its format was unknown to current sysstat version). In this case the
buffer size was zero. So test this before reallocating buffers.

Below is a sample output before the patch was applied.
The file contains only A_PCSW activity then a LINUX RESTART message
(which cannot be displayed):

$ sar -f data0 -w

Linux 4.4.14-200.fc22.x86_64 (test.home)  03/04/18  _x86_64_
(8 CPU)

09:31:50       proc/s   cswch/s
09:31:51         0.00    402.00
09:31:52         0.00    356.00
Average:         0.00    379.00
srealloc <------------------------- Error!

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

index b274d32d7761c6dd773fed101736d808489cf994..a5579a8b9dc62ecd296d1148bd135f0100b2cda4 100644 (file)
@@ -437,7 +437,6 @@ void free_structures(struct activity *act[])
  ***************************************************************************
  * Reallocate all the buffers for given activity. The new size is the double
  * of the original one.
- * NB: nr_allocated is > 0.
  *
  * IN:
  * @a  Activity whose buffers need to be reallocated.
@@ -446,16 +445,26 @@ void free_structures(struct activity *act[])
 void reallocate_all_buffers(struct activity *a)
 {
        int j;
+       size_t nr_realloc;
+
+       if (!a->nr_allocated) {
+               nr_realloc = (a->nr_ini ? a->nr_ini : 1);
+       }
+       else {
+               nr_realloc = a->nr_allocated * 2;
+       }
 
        for (j = 0; j < 3; j++) {
                SREALLOC(a->buf[j], void,
-                       (size_t) a->msize * (size_t) a->nr_allocated * 2 * (size_t) a->nr2);
+                       (size_t) a->msize * nr_realloc * (size_t) a->nr2);
                /* Init additional space which has been allocated */
-               memset(a->buf[j] + a->msize * a->nr_allocated * a->nr2, 0,
-                      (size_t) a->msize * (size_t) a->nr_allocated * (size_t) a->nr2);
+               if (a->nr_allocated) {
+                       memset(a->buf[j] + a->msize * a->nr_allocated * a->nr2, 0,
+                              (size_t) a->msize * (size_t) a->nr_allocated * (size_t) a->nr2);
+               }
        }
 
-       a->nr_allocated *= 2;
+       a->nr_allocated = nr_realloc;
 }
 
 /*
@@ -2634,6 +2643,8 @@ int print_special_record(struct record_header *record_hdr, unsigned int l_flags,
                 * But if it is the case, @nr_ini will be used in the loop
                 * to display all processors. So update its value here and
                 * reallocate buffers if needed.
+                * NB: We may have nr_allocated=0 here if A_CPU activity has
+                * not been collected in file (or if it has an unknown format).
                 */
                p = get_activity_position(act, A_CPU, EXIT_IF_NOT_FOUND);
                act[p]->nr_ini = file_hdr->sa_cpu_nr;