Dirty code hacks: removing partitions from nmon

I’ll start with this: I really like the way nmon graphically shows disk activity on a per-disk basis.

One thing that’s always irked me a little is that partitions are also shown (on Linux), and they contribute to the totals displayed at the bottom. From what I can tell, this is simply because Linux lists all the partitions in /proc/diskstats .

This is what I’m talking about…

nmon showing partitions

You can see above the partitions ZFS was so kind to make, which:

  • take up screen real-estate
  • cause double-counting of the total writes

Since I was transitioning away from BTRFS (which was happy to use the entire drive), this was becoming a little more painful as I was running out of screen space if I had CPU + network + drives all displaying at once.

Onwards! (to the dirty code hacks)

I’ll forewarn you that this is quite a dirty way of doing things, but I was lazy and only parsed code until I found a spot where I could muck with things without having to read any more code. It’s also not terribly robust. But since my searches for a solution turned up empty, here’s hoping this clunky solution helps someone else…

Step 1: Grab the source code for nmon from http://nmon.sourceforge.net/pmwiki.php?n=Site.CompilingNmon . It’s 1 file. I saved it as matt-nmon.c .

Step 2: Jump to somewhere in the neighborhood of  line 2169, where you should hopefully see something like this:

} else if (ret == 14)
    p->dk[i].dk_partition = 0;
else
    fprintf(stderr,
    "disk sscanf wanted 14 but returned=%d line=%s\n", ret,
    buf);

(doing a search for “disk sscanf” will likely get you to the right spot – and yes, 2 s’s in sscanf)

Step 3: Add some code after the last line you see above. Here’s an example I used:

if (strlen(p->dk[i].dk_name) == 4) {
  p->dk[i].dk_major = 0;
  p->dk[i].dk_minor = 0;
  p->dk[i].dk_name[0] = 0;
  p->dk[i].dk_reads = 0;
  p->dk[i].dk_rmerge = 0;
  p->dk[i].dk_rkb = 0;
  p->dk[i].dk_rmsec = 0;
  p->dk[i].dk_writes = 0;
  p->dk[i].dk_wmerge = 0;
  p->dk[i].dk_wkb = 0;
  p->dk[i].dk_wmsec = 0;
  p->dk[i].dk_inflight = 0;
  p->dk[i].dk_time = 0;
  p->dk[i].dk_backlog = 0;
}

…so that section now looked like this once all was said and done…

} else if (ret == 14)
    p->dk[i].dk_partition = 0;
else
    fprintf(stderr,
    "disk sscanf wanted 14 but returned=%d line=%s\n", ret,
    buf);



if (strlen(p->dk[i].dk_name) == 4) {
  p->dk[i].dk_major = 0;
  p->dk[i].dk_minor = 0;
  p->dk[i].dk_name[0] = 0;
  p->dk[i].dk_reads = 0;
  p->dk[i].dk_rmerge = 0;
  p->dk[i].dk_rkb = 0;
  p->dk[i].dk_rmsec = 0;
  p->dk[i].dk_writes = 0;
  p->dk[i].dk_wmerge = 0;
  p->dk[i].dk_wkb = 0;
  p->dk[i].dk_wmsec = 0;
  p->dk[i].dk_inflight = 0;
  p->dk[i].dk_time = 0;
  p->dk[i].dk_backlog = 0;
}


p->dk[i].dk_rkb /= 2;/* sectors = 512 bytes */p->dk[i].dk_wkb /= 2;
p->dk[i].dk_xfers = p->dk[i].dk_reads + p->dk[i].dk_writes;

Step 4: Compile!

  • on Ubuntu 22.04 I installed build-essential, libncurses5-dev, and libncursesw5-dev before compiling.
  • compiled via: cc -g matt-nmon.c -o matt-nmon -lncurses -lm

Step 5: Run the new program!

nmon-sdx-partitions-removed
…and realize that while the sdX drives no longer list partitions, the nvme partitions are still showing up. But we’ll get to that.

What the code above did…

If you scroll back up to the 1st image, you’ll notice that all the partitions on the sdX drives are 4 characters long (sda1, sda9, sdb1, sdb9, etc).

The code added basically says “if the string length of the ‘drive’ is 4 characters, set everything to 0”. Setting everything to 0 gets nmon to treat all these 4-character “drives” the same way it treats other random stuff that it doesn’t display.

Obviously this has a few key issues:

  1. It will cause problems if you have more than 26 drives.
  2. It doesn’t work with NVME devices.
  3. There are likely other possible devices names that won’t work.

Other messy options…

We can mess with our if condition to get more desired behavior. For example if we use this instead…

if (isdigit(p->dk[i].dk_name[strlen(p->dk[i].dk_name)-1])) {

…we’ll drop any “drive” that ends in a digit. That’s perhaps a little better than just looking for 4-character “drives”, but since my NVME drive ends in a digit as well, this isn’t necessarily ideal.

nmon-modded-but-nvme-missing

To cure it on my system, this is what I ended up with for the if condition:

if (strlen(p->dk[i].dk_name) == 4 || strlen(p->dk[i].dk_name) > 7) {

Essentially, we look for a 4-character “drive” name (just like the first time), or a drive name that is more than 7-characters long. And we get this:

nmon no longer shows partitions!

Obviously, you could get a little creative and make changes that work best for your situation.

Finally, I should mention that if you don’t care for the long “bars”, you can use nmon disk groups instead by creating a little text file and passing it to nmon (or launch nmon -g auto and pressing the g key once it’s running – note that this will make a file called “auto” in your current directory). No coding required for this!

Leave a Comment

You can use an alias and fake email. However, if you choose to use a real email, "gravatars" are supported. You can check the privacy policy for more details.