@cryptotaxi247 / netdata-1 / commits / 00e6684d3

disk now get the mount point at the menu (only when they are not partitions) #295

Costa Tsaousis (ktsaou) committed Apr 29, 2016 at 02:16 UTC 00e6684d340c48618251cde845e61deff681e804
6 files changed +248 -16
.gitignore
+2
@@ -72,3 +72,5 @@ apps.plugin-profiler.sh
72 CMakeCache.txt
73 CMakeFiles/
74 cmake_install.cmake
75 +
76 +.jetbrains*
src/Makefile.am
+1
@@ -52,6 +52,7 @@ netdata_SOURCES = \
52 proc_net_stat_conntrack.c \
53 proc_net_stat_synproxy.c \
54 proc_stat.c \
55 + proc_self_mountinfo.c proc_self_mountinfo.h \
56 proc_sys_kernel_random_entropy_avail.c \
57 proc_vmstat.c \
58 sys_kernel_mm_ksm.c \
src/proc_diskstats.c
+39 -10
@@ -15,17 +15,21 @@
15 #include "rrd.h"
16 #include "plugin_proc.h"
17
18 +#include "proc_self_mountinfo.h"
19 +
20 #define RRD_TYPE_DISK "disk"
21
22 struct disk {
23 unsigned long major;
24 unsigned long minor;
25 int partition_id; // -1 = this is not a partition
26 + char *family;
27 struct disk *next;
28 } *disk_root = NULL;
29
30 struct disk *get_disk(unsigned long major, unsigned long minor) {
31 static char path_find_block_device_partition[FILENAME_MAX + 1] = "";
32 + static struct mountinfo *mountinfo_root = NULL;
33 struct disk *d;
34
35 // search for it in our RAM list.
@@ -81,6 +85,28 @@ struct disk *get_disk(unsigned long major, unsigned long minor) {
85 }
86 // if the /partition file does not exist, it is a disk, not a partition
87
88 + // ------------------------------------------------------------------------
89 + // check if we can find its mount point
90 +
91 + // mountinfo_find() can be called with NULL mountinfo_root
92 + struct mountinfo *mi = mountinfo_find(mountinfo_root, d->major, d->minor);
93 + if(unlikely(!mi)) {
94 + // mountinfo_free() can be called with NULL mountinfo_root
95 + mountinfo_free(mountinfo_root);
96 +
97 + // re-read mountinfo in case something changed
98 + mountinfo_root = mountinfo_read();
99 +
100 + // search again for this disk
101 + mi = mountinfo_find(mountinfo_root, d->major, d->minor);
102 + }
103 +
104 + if(mi)
105 + d->family = strdup(mi->mount_point);
106 + // no need to check for NULL
107 + else
108 + d->family = NULL;
109 +
110 return d;
111 }
112
@@ -189,6 +215,9 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
215 else
216 def_enabled = 0;
217
218 + char *family = d->family;
219 + if(!family) family = disk;
220 +
221 /*
222 switch(major) {
223 case 9: // MDs
@@ -379,7 +408,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
408 }
409 else error("Cannot read sector size for device %s from %s. Assuming 512.", disk, ssfilename);
410
382 - st = rrdset_create(RRD_TYPE_DISK, disk, NULL, disk, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
411 + st = rrdset_create(RRD_TYPE_DISK, disk, NULL, family, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
412
413 rrddim_add(st, "reads", NULL, sector_size, 1024, RRDDIM_INCREMENTAL);
414 rrddim_add(st, "writes", NULL, sector_size * -1, 1024, RRDDIM_INCREMENTAL);
@@ -396,7 +425,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
425 if(ddo_ops) {
426 st = rrdset_find_bytype("disk_ops", disk);
427 if(!st) {
399 - st = rrdset_create("disk_ops", disk, NULL, disk, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
428 + st = rrdset_create("disk_ops", disk, NULL, family, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
429 st->isdetail = 1;
430
431 rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
@@ -414,7 +443,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
443 if(ddo_qops) {
444 st = rrdset_find_bytype("disk_qops", disk);
445 if(!st) {
417 - st = rrdset_create("disk_qops", disk, NULL, disk, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE);
446 + st = rrdset_create("disk_qops", disk, NULL, family, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE);
447 st->isdetail = 1;
448
449 rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
@@ -430,7 +459,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
459 if(ddo_backlog) {
460 st = rrdset_find_bytype("disk_backlog", disk);
461 if(!st) {
433 - st = rrdset_create("disk_backlog", disk, NULL, disk, "disk.backlog", "Disk Backlog", "backlog (ms)", 2003, update_every, RRDSET_TYPE_AREA);
462 + st = rrdset_create("disk_backlog", disk, NULL, family, "disk.backlog", "Disk Backlog", "backlog (ms)", 2003, update_every, RRDSET_TYPE_AREA);
463 st->isdetail = 1;
464
465 rrddim_add(st, "backlog", NULL, 1, 10, RRDDIM_INCREMENTAL);
@@ -446,7 +475,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
475 if(ddo_util) {
476 st = rrdset_find_bytype("disk_util", disk);
477 if(!st) {
449 - st = rrdset_create("disk_util", disk, NULL, disk, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA);
478 + st = rrdset_create("disk_util", disk, NULL, family, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA);
479 st->isdetail = 1;
480
481 rrddim_add(st, "utilization", NULL, 1, 10, RRDDIM_INCREMENTAL);
@@ -462,7 +491,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
491 if(ddo_mops) {
492 st = rrdset_find_bytype("disk_mops", disk);
493 if(!st) {
465 - st = rrdset_create("disk_mops", disk, NULL, disk, "disk.mops", "Disk Merged Operations", "merged operations/s", 2021, update_every, RRDSET_TYPE_LINE);
494 + st = rrdset_create("disk_mops", disk, NULL, family, "disk.mops", "Disk Merged Operations", "merged operations/s", 2021, update_every, RRDSET_TYPE_LINE);
495 st->isdetail = 1;
496
497 rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
@@ -480,7 +509,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
509 if(ddo_iotime) {
510 st = rrdset_find_bytype("disk_iotime", disk);
511 if(!st) {
483 - st = rrdset_create("disk_iotime", disk, NULL, disk, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE);
512 + st = rrdset_create("disk_iotime", disk, NULL, family, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE);
513 st->isdetail = 1;
514
515 rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
@@ -501,7 +530,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
530 if(ddo_iotime && ddo_ops) {
531 st = rrdset_find_bytype("disk_await", disk);
532 if(!st) {
504 - st = rrdset_create("disk_await", disk, NULL, disk, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE);
533 + st = rrdset_create("disk_await", disk, NULL, family, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE);
534 st->isdetail = 1;
535
536 rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_ABSOLUTE);
@@ -517,7 +546,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
546 if(ddo_io && ddo_ops) {
547 st = rrdset_find_bytype("disk_avgsz", disk);
548 if(!st) {
520 - st = rrdset_create("disk_avgsz", disk, NULL, disk, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA);
549 + st = rrdset_create("disk_avgsz", disk, NULL, family, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA);
550 st->isdetail = 1;
551
552 rrddim_add(st, "reads", NULL, sector_size, 1024, RRDDIM_ABSOLUTE);
@@ -533,7 +562,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
562 if(ddo_util && ddo_ops) {
563 st = rrdset_find_bytype("disk_svctm", disk);
564 if(!st) {
536 - st = rrdset_create("disk_svctm", disk, NULL, disk, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE);
565 + st = rrdset_create("disk_svctm", disk, NULL, family, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE);
566 st->isdetail = 1;
567
568 rrddim_add(st, "svctm", NULL, 1, 1, RRDDIM_ABSOLUTE);
src/proc_self_mountinfo.c new
+170
@@ -0,0 +1,170 @@
1 +#ifdef HAVE_CONFIG_H
2 +#include <config.h>
3 +#endif
4 +#include <stdio.h>
5 +#include <stdlib.h>
6 +#include <string.h>
7 +#include <sys/types.h>
8 +#include <sys/stat.h>
9 +#include <fcntl.h>
10 +
11 +#include "common.h"
12 +#include "log.h"
13 +#include "appconfig.h"
14 +
15 +#include "proc_self_mountinfo.h"
16 +
17 +// find the mount info with the given major:minor
18 +// in the supplied linked list of mountinfo structures
19 +struct mountinfo *mountinfo_find(struct mountinfo *root, unsigned long major, unsigned long minor) {
20 + struct mountinfo *mi;
21 +
22 + for(mi = root; mi ; mi = mi->next)
23 + if(mi->major == major && mi->minor == minor)
24 + return mi;
25 +
26 + return NULL;
27 +}
28 +
29 +// free a linked list of mountinfo structures
30 +void mountinfo_free(struct mountinfo *mi) {
31 + if(unlikely(!mi))
32 + return;
33 +
34 + if(likely(mi->next))
35 + mountinfo_free(mi->next);
36 +
37 + free(mi->root);
38 + free(mi->mount_point);
39 + free(mi->mount_options);
40 +
41 + if(mi->optional_fields_count) {
42 + int i;
43 + for(i = 0; i < mi->optional_fields_count ; i++)
44 + free(mi->optional_fields[i]);
45 + }
46 + free(mi->optional_fields);
47 +
48 + free(mi->filesystem);
49 + free(mi->mount_source);
50 + free(mi->super_options);
51 + free(mi);
52 +}
53 +
54 +// read the whole mountinfo into a linked list
55 +struct mountinfo *mountinfo_read() {
56 + procfile *ff = NULL;
57 +
58 + char filename[FILENAME_MAX + 1];
59 + snprintf(filename, FILENAME_MAX, "%s/proc/self/mountinfo", global_host_prefix);
60 + ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
61 + if(!ff) {
62 + snprintf(filename, FILENAME_MAX, "%s/proc/1/mountinfo", global_host_prefix);
63 + ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
64 + if(!ff) return NULL;
65 + }
66 +
67 + ff = procfile_readall(ff);
68 + if(!ff) return NULL;
69 +
70 + struct mountinfo *root = NULL, *last = NULL, *mi = NULL;
71 +
72 + unsigned long l, lines = procfile_lines(ff);
73 + error("MOUNTINFO: file has %u lines", lines);
74 + for(l = 0; l < lines ;l++) {
75 + if(procfile_linewords(ff, l) < 5)
76 + continue;
77 +
78 + mi = malloc(sizeof(struct mountinfo));
79 + if(unlikely(!mi)) fatal("Cannot allocate memory for mountinfo");
80 +
81 + if(unlikely(!root))
82 + root = last = mi;
83 + else
84 + last->next = mi;
85 +
86 + last = mi;
87 + mi->next = NULL;
88 +
89 + unsigned long w = 0;
90 + mi->id = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++;
91 + mi->parentid = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++;
92 +
93 + char *major = procfile_lineword(ff, l, w), *minor; w++;
94 + for(minor = major; *minor && *minor != ':' ;minor++) ;
95 + *minor = '\0';
96 + minor++;
97 +
98 + mi->major = strtoul(major, NULL, 10);
99 + mi->minor = strtoul(minor, NULL, 10);
100 +
101 + mi->root = strdup(procfile_lineword(ff, l, w)); w++;
102 + if(unlikely(!mi->root)) fatal("Cannot allocate memory");
103 +
104 + mi->mount_point = strdup(procfile_lineword(ff, l, w)); w++;
105 + if(unlikely(!mi->mount_point)) fatal("Cannot allocate memory");
106 +
107 + mi->mount_options = strdup(procfile_lineword(ff, l, w)); w++;
108 + if(unlikely(!mi->mount_options)) fatal("Cannot allocate memory");
109 +
110 + // count the optional fields
111 + unsigned long wo = w;
112 + mi->optional_fields_count = 0;
113 + char *s = procfile_lineword(ff, l, w);
114 + while(*s && *s != '-') {
115 + w++;
116 + s = procfile_lineword(ff, l, w);
117 + mi->optional_fields_count++;
118 + }
119 +
120 + if(unlikely(mi->optional_fields_count)) {
121 + // we have some optional fields
122 + // read them into a new array of pointers;
123 +
124 + mi->optional_fields = malloc(mi->optional_fields_count * sizeof(char *));
125 + if(unlikely(!mi->optional_fields))
126 + fatal("Cannot allocate memory for %d mountinfo optional fields", mi->optional_fields_count);
127 +
128 + int i;
129 + for(i = 0; i < mi->optional_fields_count ; i++) {
130 + mi->optional_fields[wo] = strdup(procfile_lineword(ff, l, w));
131 + if(!mi->optional_fields[wo]) fatal("Cannot allocate memory");
132 + wo++;
133 + }
134 + }
135 + else
136 + mi->optional_fields = NULL;
137 +
138 + if(likely(*s == '-')) {
139 + mi->filesystem = strdup(procfile_lineword(ff, l, w)); w++;
140 + if(!mi->filesystem) fatal("Cannot allocate memory");
141 +
142 + mi->mount_source = strdup(procfile_lineword(ff, l, w)); w++;
143 + if(!mi->mount_source) fatal("Cannot allocate memory");
144 +
145 + mi->super_options = strdup(procfile_lineword(ff, l, w)); w++;
146 + if(!mi->super_options) fatal("Cannot allocate memory");
147 + }
148 + else {
149 + mi->filesystem = NULL;
150 + mi->mount_source = NULL;
151 + mi->super_options = NULL;
152 + }
153 +
154 + //info("MOUNTINFO: %u %u %u:%u root '%s', mount point '%s', mount options '%s', filesystem '%s', mount source '%s', super options '%s'",
155 + // mi->id,
156 + // mi->parentid,
157 + // mi->major,
158 + // mi->minor,
159 + // mi->root,
160 + // mi->mount_point,
161 + // mi->mount_options,
162 + // mi->filesystem,
163 + // mi->mount_source,
164 + // mi->super_options
165 + //);
166 + }
167 +
168 + procfile_close(ff);
169 + return root;
170 +}
src/proc_self_mountinfo.h new
+30
@@ -0,0 +1,30 @@
1 +#include "procfile.h"
2 +
3 +#ifndef NETDATA_PROC_SELF_MOUNTINFO_H
4 +#define NETDATA_PROC_SELF_MOUNTINFO_H 1
5 +
6 +struct mountinfo {
7 + long id; // mount ID: unique identifier of the mount (may be reused after umount(2)).
8 + long parentid; // parent ID: ID of parent mount (or of self for the top of the mount tree).
9 + unsigned long major; // major:minor: value of st_dev for files on filesystem (see stat(2)).
10 + unsigned long minor;
11 +
12 + char *root; // root: root of the mount within the filesystem.
13 + char *mount_point; // mount point: mount point relative to the process's root.
14 + char *mount_options; // mount options: per-mount options.
15 +
16 + int optional_fields_count;
17 + char **optional_fields; // optional fields: zero or more fields of the form "tag[:value]".
18 +
19 + char *filesystem; // filesystem type: name of filesystem in the form "type[.subtype]".
20 + char *mount_source; // mount source: filesystem-specific information or "none".
21 + char *super_options; // super options: per-superblock options.
22 +
23 + struct mountinfo *next;
24 +};
25 +
26 +extern struct mountinfo *mountinfo_find(struct mountinfo *root, unsigned long major, unsigned long minor);
27 +extern void mountinfo_free(struct mountinfo *mi);
28 +extern struct mountinfo *mountinfo_read();
29 +
30 +#endif /* NETDATA_PROC_SELF_MOUNTINFO_H */
\ No newline at end of file
web/index.html
+6 -6
@@ -1442,11 +1442,11 @@ function enrichChartData(chart) {
1442
1443 function name2id(s) {
1444 return s
1445 - .replace(' ', '_')
1446 - .replace('(', '_')
1447 - .replace(')', '_')
1448 - .replace('.', '_')
1449 - .replace('/', '_');
1445 + .replace(/ /g, '_')
1446 + .replace(/\(/g, '_')
1447 + .replace(/\)/g, '_')
1448 + .replace(/\./g, '_')
1449 + .replace(/\//g, '_');
1450 }
1451
1452 function headMain(charts, duration) {
@@ -1601,7 +1601,7 @@ function renderPage(menus, data) {
1601
1602 // generate an entry at the main menu
1603
1604 - sidebar += '<li class=""><a href="#' + menu + '">' + menus[menu].title + '</a><ul class="nav">';
1604 + sidebar += '<li class=""><a href="#' + name2id(menu) + '">' + menus[menu].title + '</a><ul class="nav">';
1605 html += '<div role="section"><div role="sectionhead"><h1 id="' + menu + '" role="heading">' + menus[menu].title + '</h1></div><div id="' + menu + '" role="document">';
1606
1607 if(menus[menu].info !== null)