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)