@cryptotaxi247 / netdata-1 / commits / b507120a9

calculate disk space statistics much like df does; fixes #1148

Costa Tsaousis (ktsaou) committed Oct 22, 2016 at 13:15 UTC b507120a95d168f1a334d2510324bbcb86663a84
1 file changed +109 -74
src/proc_diskstats.c
+109 -74
@@ -29,6 +29,107 @@ static struct disk {
29 struct disk *next;
30 } *disk_root = NULL;
31
32 +/* Return true if N is a known integer value. On many file systems,
33 + UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1
34 + represents unknown. Use a rule that works on AIX file systems, and
35 + that almost-always works on other types. */
36 +static inline int known_value (uintmax_t n) { return n < UINTMAX_MAX - 1; }
37 +
38 +static inline void disk_space_stats(struct disk *d, const char *disk, const char *family, int update_every, unsigned long long dt) {
39 + struct statvfs buff_statvfs;
40 + RRDSET *st;
41 +
42 + if (statvfs(d->mount_point, &buff_statvfs) < 0)
43 + error("Failed statvfs() for '%s' (disk '%s')", d->mount_point, d->disk);
44 + else {
45 + struct stat buff_stat;
46 +
47 + // verify we collected the metrics for the right disk.
48 + // if not the mountpoint has changed.
49 +
50 + if(stat(d->mount_point, &buff_stat) == -1)
51 + error("Failed to stat() for '%s' (disk '%s')", d->mount_point, d->disk);
52 + else {
53 + if(major(buff_stat.st_dev) == d->major && minor(buff_stat.st_dev) == d->minor) {
54 +
55 + // http://stackoverflow.com/a/4965511
56 + // taken from get_fs_usage() found in coreutils
57 + unsigned long bsize = (buff_statvfs.f_frsize) ? buff_statvfs.f_frsize : buff_statvfs.f_bsize;
58 +
59 + fsblkcnt_t bavail = buff_statvfs.f_bavail;
60 + fsblkcnt_t btotal = buff_statvfs.f_blocks;
61 + fsblkcnt_t bavail_root = buff_statvfs.f_bfree;
62 + fsblkcnt_t breserved_root = bavail_root - bavail;
63 + fsblkcnt_t bused;
64 + if(likely(btotal >= bavail_root))
65 + bused = btotal - bavail_root;
66 + else
67 + bused = bavail_root - btotal;
68 +
69 +#ifdef NETDATA_INTERNAL_CHECKS
70 + if(unlikely(btotal != bavail + breserved_root + bused))
71 + error("Disk block statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", d->mount_point, d->disk, (unsigned long long)btotal, (unsigned long long)bavail, (unsigned long long)breserved_root, (unsigned long long)bused);
72 +#endif
73 +
74 + // --------------------------------------------------------------------------
75 +
76 + fsfilcnt_t favail = buff_statvfs.f_favail;
77 + fsfilcnt_t ftotal = buff_statvfs.f_files;
78 + fsfilcnt_t favail_root = buff_statvfs.f_ffree;
79 + fsfilcnt_t freserved_root = favail_root - favail;
80 + fsfilcnt_t fused = ftotal - favail_root;
81 +
82 +#ifdef NETDATA_INTERNAL_CHECKS
83 + if(unlikely(btotal != bavail + breserved_root + bused))
84 + error("Disk inode statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", d->mount_point, d->disk, (unsigned long long)ftotal, (unsigned long long)favail, (unsigned long long)freserved_root, (unsigned long long)fused);
85 +#endif
86 +
87 + // --------------------------------------------------------------------------
88 +
89 + if(d->do_space == CONFIG_ONDEMAND_YES || (d->do_space == CONFIG_ONDEMAND_ONDEMAND && (bavail || breserved_root || bused))) {
90 + d->do_space = CONFIG_ONDEMAND_YES;
91 +
92 + st = rrdset_find_bytype("disk_space", disk);
93 + if(!st) {
94 + st = rrdset_create("disk_space", disk, NULL, family, "disk.space", "Disk Space Usage", "GB", 2023, update_every, RRDSET_TYPE_STACKED);
95 + st->isdetail = 1;
96 +
97 + rrddim_add(st, "avail", NULL, bsize, 1024*1024*1024, RRDDIM_ABSOLUTE);
98 + rrddim_add(st, "used" , NULL, bsize, 1024*1024*1024, RRDDIM_ABSOLUTE);
99 + rrddim_add(st, "reserved_for_root", "reserved for root", bsize, 1024*1024*1024, RRDDIM_ABSOLUTE);
100 + }
101 + else rrdset_next_usec(st, dt);
102 +
103 + rrddim_set(st, "avail", bavail);
104 + rrddim_set(st, "used", bused);
105 + rrddim_set(st, "reserved_for_root", breserved_root);
106 + rrdset_done(st);
107 + }
108 +
109 + // --------------------------------------------------------------------------
110 +
111 + if(d->do_inodes == CONFIG_ONDEMAND_YES || (d->do_inodes == CONFIG_ONDEMAND_ONDEMAND && (favail || freserved_root || fused))) {
112 + st = rrdset_find_bytype("disk_inodes", disk);
113 + if(!st) {
114 + st = rrdset_create("disk_inodes", disk, NULL, family, "disk.inodes", "Disk Inodes Usage", "Inodes", 2024, update_every, RRDSET_TYPE_STACKED);
115 + st->isdetail = 1;
116 +
117 + rrddim_add(st, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE);
118 + rrddim_add(st, "used" , NULL, 1, 1, RRDDIM_ABSOLUTE);
119 + rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRDDIM_ABSOLUTE);
120 + }
121 + else rrdset_next_usec(st, dt);
122 +
123 + rrddim_set(st, "avail", favail);
124 + rrddim_set(st, "used", fused);
125 + rrddim_set(st, "reserved_for_root", freserved_root);
126 + rrdset_done(st);
127 + }
128 + }
129 + }
130 + }
131 +}
132 +
133 static struct mountinfo *disk_mountinfo_root = NULL;
134
135 static struct disk *get_disk(unsigned long major, unsigned long minor, char *disk) {
@@ -189,8 +290,6 @@ static inline int select_positive_option(int option1, int option2) {
290
291 int do_proc_diskstats(int update_every, unsigned long long dt) {
292 static procfile *ff = NULL;
192 - static struct statvfs buff_statvfs;
193 - static struct stat buff_stat;
293 static int global_enable_new_disks_detected_at_runtime = CONFIG_ONDEMAND_YES,
294 global_enable_performance_for_physical_disks = CONFIG_ONDEMAND_ONDEMAND,
295 global_enable_performance_for_virtual_disks = CONFIG_ONDEMAND_NO,
@@ -250,22 +349,21 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
349 // Read parameters
350
351 char *disk;
253 - unsigned long long major = 0, minor = 0,
254 - reads = 0, mreads = 0, readsectors = 0, readms = 0,
352 + unsigned long major = 0, minor = 0;
353 +
354 + collected_number reads = 0, mreads = 0, readsectors = 0, readms = 0,
355 writes = 0, mwrites = 0, writesectors = 0, writems = 0,
256 - queued_ios = 0, busy_ms = 0, backlog_ms = 0,
257 - space_avail = 0, space_avail_root = 0, space_used = 0,
258 - inodes_avail = 0, inodes_avail_root = 0, inodes_used = 0;
356 + queued_ios = 0, busy_ms = 0, backlog_ms = 0;
357
260 - unsigned long long last_reads = 0, last_readsectors = 0, last_readms = 0,
358 + collected_number last_reads = 0, last_readsectors = 0, last_readms = 0,
359 last_writes = 0, last_writesectors = 0, last_writems = 0,
360 last_busy_ms = 0;
361
362 words = procfile_linewords(ff, l);
363 if(words < 14) continue;
364
267 - major = strtoull(procfile_lineword(ff, l, 0), NULL, 10);
268 - minor = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
365 + major = strtoul(procfile_lineword(ff, l, 0), NULL, 10);
366 + minor = strtoul(procfile_lineword(ff, l, 1), NULL, 10);
367 disk = procfile_lineword(ff, l, 2);
368
369 // # of reads completed # of writes completed
@@ -372,7 +470,6 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
470
471 if(d->mount_point)
472 def_performance = select_positive_option(def_performance, global_enable_performance_for_virtual_mountpoints);
375 -
473 break;
474 }
475
@@ -630,69 +727,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
727 // space metrics
728
729 if(d->mount_point && (d->do_space || d->do_inodes) ) {
633 - // collect space metrics using statvfs
634 -
635 - if (statvfs(d->mount_point, &buff_statvfs) < 0)
636 - error("Failed statvfs() for '%s' (disk '%s')", d->mount_point, d->disk);
637 - else {
638 - space_avail = buff_statvfs.f_bavail * buff_statvfs.f_bsize;
639 - space_avail_root = (buff_statvfs.f_bfree - buff_statvfs.f_bavail) * buff_statvfs.f_bsize;
640 - space_used = (buff_statvfs.f_blocks - buff_statvfs.f_bfree) * buff_statvfs.f_bsize;
641 -
642 - inodes_avail = buff_statvfs.f_favail;
643 - inodes_avail_root = buff_statvfs.f_ffree - buff_statvfs.f_favail;
644 - inodes_used = buff_statvfs.f_files - buff_statvfs.f_ffree;
645 -
646 - // verify we collected the metrics for the right disk.
647 - // if not the mountpoint has changed.
648 -
649 - if(stat(d->mount_point, &buff_stat) == -1)
650 - error("Failed to stat() for '%s' (disk '%s')", d->mount_point, d->disk);
651 - else {
652 - if(major(buff_stat.st_dev) == major && minor(buff_stat.st_dev) == minor) {
653 -
654 - // --------------------------------------------------------------------------
655 -
656 - if(d->do_space == CONFIG_ONDEMAND_YES || (d->do_space == CONFIG_ONDEMAND_ONDEMAND && (space_avail || space_avail_root || space_used))) {
657 - st = rrdset_find_bytype("disk_space", disk);
658 - if(!st) {
659 - st = rrdset_create("disk_space", disk, NULL, family, "disk.space", "Disk Space Usage", "GB", 2023, update_every, RRDSET_TYPE_STACKED);
660 - st->isdetail = 1;
661 -
662 - rrddim_add(st, "avail", NULL, 1, 1024*1024*1024, RRDDIM_ABSOLUTE);
663 - rrddim_add(st, "used" , NULL, 1, 1024*1024*1024, RRDDIM_ABSOLUTE);
664 - rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1024*1024*1024, RRDDIM_ABSOLUTE);
665 - }
666 - else rrdset_next_usec(st, dt);
667 -
668 - rrddim_set(st, "avail", space_avail);
669 - rrddim_set(st, "used", space_used);
670 - rrddim_set(st, "reserved_for_root", space_avail_root);
671 - rrdset_done(st);
672 - }
673 -
674 - // --------------------------------------------------------------------------
675 -
676 - if(d->do_inodes == CONFIG_ONDEMAND_YES || (d->do_inodes == CONFIG_ONDEMAND_ONDEMAND && (inodes_avail || inodes_avail_root || inodes_used))) {
677 - st = rrdset_find_bytype("disk_inodes", disk);
678 - if(!st) {
679 - st = rrdset_create("disk_inodes", disk, NULL, family, "disk.inodes", "Disk Inodes Usage", "Inodes", 2024, update_every, RRDSET_TYPE_STACKED);
680 - st->isdetail = 1;
681 -
682 - rrddim_add(st, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE);
683 - rrddim_add(st, "used" , NULL, 1, 1, RRDDIM_ABSOLUTE);
684 - rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRDDIM_ABSOLUTE);
685 - }
686 - else rrdset_next_usec(st, dt);
687 -
688 - rrddim_set(st, "avail", inodes_avail);
689 - rrddim_set(st, "used", inodes_used);
690 - rrddim_set(st, "reserved_for_root", inodes_avail_root);
691 - rrdset_done(st);
692 - }
693 - }
694 - }
695 - }
730 + disk_space_stats(d, disk, family, update_every, dt);
731 }
732 }
733