Conky: Incorrect disk usage using fs_used_perc and fs_used_free

Created on 10 Jul 2016  路  16Comments  路  Source: brndnmtthws/conky

I am running debian Jessie and conky 1.9.0-6

I am trying to add some disk stats -
/Downloads is a local software raid 1TB volume
/Downloads2 is a NFS share - 2.7TB
/data is a cifs share - 1.9TB

I was just trying to display the %used with the free GB / total GB ...
${color1}Root ${fs_used_perc /}% $alignr${fs_used /} / ${fs_size /}${color}

When I noticed the numbers being reported were several percentage points off ...

Filesystem Size Used Avail Use% Mounted on
/dev/md0 917G 518G 353G 60% /Downloads
192.168.29.11:/nfs/Downloads2 2.7T 2.2T 408G 85% /Downloads2
//192.168.29.10/storage 1.9T 1.4T 442G 77% /data

Conky reports the following ... none of which total 100% ...
Downloads : 56% used / 38% free
Downloads2 : 80% used / 14% free
data 76% used / 23% free

see the below screen shot ...

screenshot - 07092016 - 10 36 25 pm

Any of this fixed in the latest and greatest?

Most helpful comment

thread is from 2 years ago - I'm no longer using conky on the machine in question - its been rebuilt a couple times since. it may be best to close this issue and re-spawn a new issue?

All 16 comments

I have 7 partitions / drives. All drives except the ext4 one for my linux root partition add up to 99% (not 100). The latter adds up to 94% (Commands fs_free_per <path>, fs_used_per):

a: ext4, used 74%, free 20%, capacity
b: ntfs, used 50%, free 49%, capacity
c: ntfs, used 91%, free  8%, capacity
d: ntfs, used 93%, free  6%, capacity
e: ntfs, used 99%, free  0%, capacity 
f: vfat, used 95%, free  4%, capacity 
g: vfat, used 65%, free 34%, capacity 

@geolaw What file system are your partitions?

df -h shows these usages:

a: ext4, used  79%
b: ntfs, used  51%
c: ntfs, used  92%
d: ntfs, used  94%
e: ntfs, used 100%
f: vfat, used  96%
g: vfat, used  66%

It seems kinda improbable, that all 6 partitions show exactly 1% higher usage, if the underlying problem was simply a rounding error. The probability for this to happen would be like 1.5%. SO maybe it's not just a rounding problem for the working partitions either.

As the the partition not adding up to 100%. It seems like the problem is fs_used_per not fs_free_per when comparing it with df -h. I find it weird in the first place, that conky seems to query these values independently instead of just calculating one from the other.

Note that the non-percent commands have the same problem of not adding up for ext4. It shows 70GiB used + 19.5GiB used = 94.4GiB total. For the other though there is no rounding problem anymore in the absolute values, e.g. 19.GiB used + 10.GiB free = 29.4GiB total. (Commands: fs_free <path>, fs_used <path>, fs_size <path>)

Hello,

That bothered me too, I looked in the code (of version 1.9, I can't build the master branch with nvidia support), and found where that behavior comes from:

In fs.h, the struct that holds the filesystem data stores the size, the available size and the free size:

struct fs_stat {
    char path[DEFAULT_TEXT_BUFFER_SIZE];
    char type[DEFAULT_TEXT_BUFFER_SIZE];
    long long size; 
    long long avail;
    long long free;
    char set;
}

In fs.c:

static double get_fs_perc(struct fs_stat *fs, int get_free)
{
    double ret = 0.0;

    if(fs && fs->size) {
        if(get_free)
            ret = fs->avail;
        else
            ret = fs->size - fs->free;
        ret /= fs->size;
    }   

    return ret;
}

And

HUMAN_PRINT_FS_GENERATOR(free, fs->avail)
HUMAN_PRINT_FS_GENERATOR(size, fs->size)
HUMAN_PRINT_FS_GENERATOR(used, fs->size - fs->free)

You'll see that the used size is calculated as fs->size - fs->free, while the free size is directly from fs->avail.

In the case of my ntfs filesystems, avail and free are identical. For my btfrs one, they are nearly the same. For my ext4 ones, they are quite different, the difference is 5% of the total size.

I think this isn't a bug. From what I've read there https://ubuntuforums.org/showthread.php?t=2180267, in ext4 filesystems, 5% are reserved for the superuser. So if you have 90% used, it's actually as if you had 95% used (I think nautilus and df report 95%, while conky reports 90%).

If you want to change the behavior, replace fs->size - fs->free by fs->size - fs->avail in those two blocks of code above and rebuild conky. That's what I did.

hi,

this is due to the space reserved to root (~10%)
if you use df, it shows the free space without the root space (free space minus root space)
if you use discus for instance, you'll get the exact free space
if you use discus -r, the result shall be the same of df, because the -r argument of discus means taking into account the root space

hope i'm clear enough !

@su8 Thoughts?

On my system df -h shows 71% usage, while ${fs_used_percent /} shows 67%. What shows on your systems @lasers with multiple drives ?

  • Drive 1... df -h 40% vs conky 37%.
  • Drive 2... df -h 13% vs conky 11%.

You can close this issue :money_mouth_face:

No config option to override fs_ style?

diff --git a/src/fs.cc b/src/fs.cc
index 463d650e..50a594c9 100644
--- a/src/fs.cc
+++ b/src/fs.cc
@@ -69,6 +69,7 @@ static struct fs_stat fs_stats_[MAX_FS_STATS];
 struct fs_stat *fs_stats = fs_stats_;

 static void update_fs_stat(struct fs_stat *fs);
+static unsigned int use_avail = 0U;

 void get_fs_type(const char *path, char *result);

@@ -95,11 +96,14 @@ void clear_fs_stats() {
 struct fs_stat *prepare_fs_stat(const char *s) {
   struct fs_stat *next = nullptr;
   unsigned i;
-
+  char buf[256];
+  if (sscanf(s, "%u %255s", &use_avail, buf) <= 1) {
+    snprintf(buf, 255, "%s", s);
+  }
   /* lookup existing or get new */
   for (i = 0; i < MAX_FS_STATS; ++i) {
     if (fs_stats[i].set != 0) {
-      if (strncmp(fs_stats[i].path, s, DEFAULT_TEXT_BUFFER_SIZE) == 0) {
+      if (strncmp(fs_stats[i].path, buf, DEFAULT_TEXT_BUFFER_SIZE) == 0) {
         return &fs_stats[i];
       }
     } else {
@@ -111,7 +115,7 @@ struct fs_stat *prepare_fs_stat(const char *s) {
     NORM_ERR("too many fs stats");
     return nullptr;
   }
-  strncpy(next->path, s, DEFAULT_TEXT_BUFFER_SIZE);
+  strncpy(next->path, buf, DEFAULT_TEXT_BUFFER_SIZE);
   next->set = 1;
   update_fs_stat(next);
   return next;
@@ -225,12 +229,14 @@ static double get_fs_perc(struct text_object *obj, bool get_free) {
   if ((fs != nullptr) && (fs->size != 0)) {
     if (get_free) {
       ret = fs->avail;
+    } else if (1 == use_avail) {
+      ret = fs->size - fs->avail;
     } else {
       ret = fs->size - fs->free;
     }
     ret /= fs->size;
   }
-
+  use_avail = 0;
   return ret;
 }

@@ -241,7 +247,7 @@ double fs_free_barval(struct text_object *obj) {
 }

 void init_fs(struct text_object *obj, const char *arg) {
-  obj->data.opaque = prepare_fs_stat(arg != nullptr ? arg : "/");
+  obj->data.opaque = prepare_fs_stat(arg != nullptr ? arg : "0 /");
 }

 uint8_t fs_free_percentage(struct text_object *obj) {

lone ${fs_used_perc 1 /} works fine, but when in combination with others, the code no longer works, as it's reset to 0.

    ${fs_used_perc 0 /}
    ${fs_used_perc 1 /}
    ${fs_used_perc 0 /}
    ${fs_used_perc 1 /}

What about config option inside conky.config?

conky.config = {
    out_to_true=false,
    out_to_console=false.
    fs_root=false,
}

I don't know if fs_root is a good name.

Edit, with this config option it work like a charm

diff --git a/src/common.cc b/src/common.cc
index d9e29114..0d71306c 100644
--- a/src/common.cc
+++ b/src/common.cc
@@ -273,6 +273,7 @@ void format_seconds_short(char *buf, unsigned int n, long seconds) {
 }

 conky::simple_config_setting<bool> no_buffers("no_buffers", true, true);
+conky::simple_config_setting<bool> fs_avail("fs_avail", true, true);

 void update_stuff() {
   /* clear speeds, addresses and up status in case device was removed and
diff --git a/src/common.h b/src/common.h
index 5b23e356..ba949d8f 100644
--- a/src/common.h
+++ b/src/common.h
@@ -74,6 +74,7 @@ int round_to_int_temp(float);
 unsigned int round_to_int(float);

 extern conky::simple_config_setting<bool> no_buffers;
+extern conky::simple_config_setting<bool> fs_avail;

 int open_acpi_temperature(const char *name);
 double get_acpi_temperature(int fd);
diff --git a/src/fs.cc b/src/fs.cc
index 463d650e..790330b0 100644
--- a/src/fs.cc
+++ b/src/fs.cc
@@ -37,6 +37,7 @@
 #include "logging.h"
 #include "specials.h"
 #include "text_object.h"
+#include "common.h"

 #ifdef HAVE_SYS_STATFS_H
 #include <sys/statfs.h>
@@ -225,6 +226,8 @@ static double get_fs_perc(struct text_object *obj, bool get_free) {
   if ((fs != nullptr) && (fs->size != 0)) {
     if (get_free) {
       ret = fs->avail;
+    } else if (fs_avail.get(*state)) {
+      ret = fs->size - fs->avail;
     } else {
       ret = fs->size - fs->free;
     }

conf

conky.config = {
    out_to_x=false,
    out_to_console=true,
    update_interval=1,
    default_bar_width=100,
    fs_avail=true,
}
conky.text = [[
    ${fs_used_perc /}
]]

Lol. Is this right? Now I'm over by 2% instead of under by 2%.

It's either under or over, there is no middle ground :smile_cat:

I can find tools that uses the same space numbers as master, but what tools to compare this new space numbers?

@geolaw @mxmlnkn @cyphaw @baobab33 Thoughts? The numbers are off too.

thread is from 2 years ago - I'm no longer using conky on the machine in question - its been rebuilt a couple times since. it may be best to close this issue and re-spawn a new issue?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Microcrap picture Microcrap  路  4Comments

Dimerbone picture Dimerbone  路  4Comments

bad-interpreter picture bad-interpreter  路  4Comments

mreinhardt picture mreinhardt  路  3Comments

ghost picture ghost  路  4Comments