lib: Memory reporting fails over 2GB

Ticket: CM-8015
Reviewed by: CCR-3717
Testing: See bug

The old style mallinfo() function uses an 'int' to
report memory usage data to the program.  Unfortunately
modern architectures can chew through 2gb of memory like a
buzz saw hitting some warm butter, especially in the case
of a memory leak or memory fragmentation.

When a daemon uses more than 2gb of memory, just indicate it's
gotten large and we don't know anymore.

Pre-change behavior:
Robot-1# show memory
System allocator statistics:
Total heap allocated: 16777216 TiB
Holding block headers: 1288 KiB
Used small blocks: 0 bytes
Used ordinary blocks: 535 MiB
Free small blocks: 768 bytes
Free ordinary blocks: 16777216 TiB
Ordinary blocks: 266107
Small blocks: 24
Holding blocks: 2

Post-change behavior:
Robot-1# show memory
System allocator statistics:
  Total heap allocated:  1572 KiB
  Holding block headers: > 2GB
  Used small blocks:     0 bytes
  Used ordinary blocks:  1443 KiB
  Free small blocks:     32 bytes
  Free ordinary blocks:  129 KiB
  Ordinary blocks:       2
  Small blocks:          1
  Holding blocks:        2

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2015-10-28 19:59:30 -04:00
parent a6e0d253a2
commit 6896f65018

View File

@ -437,7 +437,7 @@ memory_init (void)
const char *
mtype_memstr (char *buf, size_t len, unsigned long bytes)
{
unsigned int t, g, m, k;
unsigned int m, k;
/* easy cases */
if (!bytes)
@ -445,33 +445,20 @@ mtype_memstr (char *buf, size_t len, unsigned long bytes)
if (bytes == 1)
return "1 byte";
if (sizeof (unsigned long) >= 8)
/* Hacked to make it not warn on ILP32 machines
* Shift will always be 40 at runtime. See below too */
t = bytes >> (sizeof (unsigned long) >= 8 ? 40 : 0);
else
t = 0;
g = bytes >> 30;
/*
* When we pass the 2gb barrier mallinfo() can no longer report
* correct data so it just does something odd...
* Reporting like Terrabytes of data. Which makes users...
* edgy.. yes edgy that's the term for it.
* So let's just give up gracefully
*/
if (bytes > 0x7fffffff)
return "> 2GB";
m = bytes >> 20;
k = bytes >> 10;
if (t > 10)
{
/* The shift will always be 39 at runtime.
* Just hacked to make it not warn on 'smaller' machines.
* Static compiler analysis should mean no extra code
*/
if (bytes & (1UL << (sizeof (unsigned long) >= 8 ? 39 : 0)))
t++;
snprintf (buf, len, "%4d TiB", t);
}
else if (g > 10)
{
if (bytes & (1 << 29))
g++;
snprintf (buf, len, "%d GiB", g);
}
else if (m > 10)
if (m > 10)
{
if (bytes & (1 << 19))
m++;