@cryptotaxi247 / netdata-1 / commits / f8350a705

fix diskspace plugin in Docker (#18035)

* fix diskspace in Docker * freez mount_point_stat_path

Ilya Mashchenko committed Jun 29, 2024 at 11:36 UTC f8350a705cdb9d8b1744cd6071825d7dddd69241
4 files changed +49 -19
packaging/docker/README.md
+8
@@ -50,6 +50,7 @@ along with their descriptions.
50 | Component | Mounts | Description |
51 |:----------------------:|:--------------------------:|--------------------------------------------------------------------------------------------------------------------------------------------|
52 | netdata | /etc/os-release | Host info detection. |
53 +| diskspace.plugin | / | Host mount points monitoring. |
54 | cgroups.plugin | /sys, /var/run/docker.sock | Docker containers monitoring and name resolution. |
55 | go.d.plugin | /var/run/docker.sock | Docker Engine and containers monitoring. See [docker](https://github.com/netdata/go.d.plugin/tree/master/modules/docker#readme) collector. |
56 | go.d.plugin | /var/log | Web servers logs tailing. See [weblog](https://github.com/netdata/go.d.plugin/tree/master/modules/weblog#readme) collector. |
@@ -80,6 +81,7 @@ docker run -d --name=netdata \
81 -v netdataconfig:/etc/netdata \
82 -v netdatalib:/var/lib/netdata \
83 -v netdatacache:/var/cache/netdata \
84 + -v /:/host/root:ro,rslave \
85 -v /etc/passwd:/host/etc/passwd:ro \
86 -v /etc/group:/host/etc/group:ro \
87 -v /etc/localtime:/etc/localtime:ro \
@@ -121,6 +123,7 @@ services:
123 - netdataconfig:/etc/netdata
124 - netdatalib:/var/lib/netdata
125 - netdatacache:/var/cache/netdata
126 + - /:/host/root:ro,rslave
127 - /etc/passwd:/host/etc/passwd:ro
128 - /etc/group:/host/etc/group:ro
129 - /etc/localtime:/etc/localtime:ro
@@ -233,6 +236,7 @@ docker run -d --name=netdata \
236 -v $(pwd)/netdataconfig/netdata:/etc/netdata \
237 -v netdatalib:/var/lib/netdata \
238 -v netdatacache:/var/cache/netdata \
239 + -v /:/host/root:ro,rslave \
240 -v /etc/passwd:/host/etc/passwd:ro \
241 -v /etc/group:/host/etc/group:ro \
242 -v /etc/localtime:/etc/localtime:ro \
@@ -274,6 +278,7 @@ services:
278 - ./netdataconfig/netdata:/etc/netdata
279 - netdatalib:/var/lib/netdata
280 - netdatacache:/var/cache/netdata
281 + - /:/host/root:ro,rslave
282 - /etc/passwd:/host/etc/passwd:ro
283 - /etc/group:/host/etc/group:ro
284 - /etc/localtime:/etc/localtime:ro
@@ -349,6 +354,7 @@ services:
354 - netdataconfig:/etc/netdata
355 - netdatalib:/var/lib/netdata
356 - netdatacache:/var/cache/netdata
357 + - /:/host/root:ro,rslave
358 - /etc/passwd:/host/etc/passwd:ro
359 - /etc/group:/host/etc/group:ro
360 - /etc/localtime:/etc/localtime:ro
@@ -402,6 +408,7 @@ services:
408 - netdataconfig:/etc/netdata
409 - netdatalib:/var/lib/netdata
410 - netdatacache:/var/cache/netdata
411 + - /:/host/root:ro,rslave
412 - /etc/passwd:/host/etc/passwd:ro
413 - /etc/group:/host/etc/group:ro
414 - /etc/localtime:/etc/localtime:ro
@@ -449,6 +456,7 @@ services:
456 - netdataconfig:/etc/netdata
457 - netdatalib:/var/lib/netdata
458 - netdatacache:/var/cache/netdata
459 + - /:/host/root:ro,rslave
460 - /etc/passwd:/host/etc/passwd:ro
461 - /etc/group:/host/etc/group:ro
462 - /etc/localtime:/etc/localtime:ro
src/collectors/diskspace.plugin/plugin_diskspace.c
+14 -11
@@ -111,6 +111,7 @@ void mountpoint_delete_cb(const DICTIONARY_ITEM *item __maybe_unused, void *entr
111 struct basic_mountinfo {
112 char *persistent_id;
113 char *root;
114 + char *mount_point_stat_path;
115 char *mount_point;
116 char *filesystem;
117
@@ -123,12 +124,13 @@ static netdata_mutex_t slow_mountinfo_mutex;
124 static struct basic_mountinfo *basic_mountinfo_create_and_copy(struct mountinfo* mi)
125 {
126 struct basic_mountinfo *bmi = callocz(1, sizeof(struct basic_mountinfo));
126 -
127 +
128 if (mi) {
129 bmi->persistent_id = strdupz(mi->persistent_id);
129 - bmi->root = strdupz(mi->root);
130 - bmi->mount_point = strdupz(mi->mount_point);
131 - bmi->filesystem = strdupz(mi->filesystem);
130 + bmi->root = strdupz(mi->root);
131 + bmi->mount_point_stat_path = strdupz(mi->mount_point_stat_path);
132 + bmi->mount_point = strdupz(mi->mount_point);
133 + bmi->filesystem = strdupz(mi->filesystem);
134 }
135
136 return bmi;
@@ -150,6 +152,7 @@ static void free_basic_mountinfo(struct basic_mountinfo *bmi)
152 if (bmi) {
153 freez(bmi->persistent_id);
154 freez(bmi->root);
155 + freez(bmi->mount_point_stat_path);
156 freez(bmi->mount_point);
157 freez(bmi->filesystem);
158
@@ -359,9 +362,9 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
362 usec_t start_time = now_monotonic_high_precision_usec();
363 struct stat bs;
364
362 - if(stat(mi->mount_point, &bs) == -1) {
365 + if(stat(mi->mount_point_stat_path, &bs) == -1) {
366 collector_error("DISKSPACE: Cannot stat() mount point '%s' (disk '%s', filesystem '%s', root '%s')."
364 - , mi->mount_point
367 + , mi->mount_point_stat_path
368 , disk
369 , mi->filesystem?mi->filesystem:""
370 , mi->root?mi->root:""
@@ -372,7 +375,7 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
375 else {
376 if((bs.st_mode & S_IFMT) != S_IFDIR) {
377 collector_error("DISKSPACE: Mount point '%s' (disk '%s', filesystem '%s', root '%s') is not a directory."
375 - , mi->mount_point
378 + , mi->mount_point_stat_path
379 , disk
380 , mi->filesystem?mi->filesystem:""
381 , mi->root?mi->root:""
@@ -451,10 +454,10 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
454 usec_t start_time = now_monotonic_high_precision_usec();
455 struct statvfs buff_statvfs;
456
454 - if (statvfs(mi->mount_point, &buff_statvfs) < 0) {
457 + if (statvfs(mi->mount_point_stat_path, &buff_statvfs) < 0) {
458 if(!m->shown_error) {
459 collector_error("DISKSPACE: failed to statvfs() mount point '%s' (disk '%s', filesystem '%s', root '%s')"
457 - , mi->mount_point
460 + , mi->mount_point_stat_path
461 , disk
462 , mi->filesystem?mi->filesystem:""
463 , mi->root?mi->root:""
@@ -489,10 +492,10 @@ static inline void do_slow_disk_space_stats(struct basic_mountinfo *mi, int upda
492 m->updated = true;
493
494 struct statvfs buff_statvfs;
492 - if (statvfs(mi->mount_point, &buff_statvfs) < 0) {
495 + if (statvfs(mi->mount_point_stat_path, &buff_statvfs) < 0) {
496 if(!m->shown_error) {
497 collector_error("DISKSPACE: failed to statvfs() mount point '%s' (disk '%s', filesystem '%s', root '%s')"
495 - , mi->mount_point
498 + , mi->mount_point_stat_path
499 , mi->persistent_id
500 , mi->filesystem?mi->filesystem:""
501 , mi->root?mi->root:""
src/collectors/proc.plugin/proc_self_mountinfo.c
+25 -7
@@ -113,6 +113,7 @@ struct mountinfo *mountinfo_find_by_filesystem_super_option(struct mountinfo *ro
113
114 static void mountinfo_free(struct mountinfo *mi) {
115 freez(mi->root);
116 + freez(mi->mount_point_stat_path);
117 freez(mi->mount_point);
118 freez(mi->mount_options);
119 freez(mi->persistent_id);
@@ -212,13 +213,23 @@ static inline int mount_point_is_protected(char *mount_point)
213 // read the whole mountinfo into a linked list
214 struct mountinfo *mountinfo_read(int do_statvfs) {
215 char filename[FILENAME_MAX + 1];
215 - snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", netdata_configured_host_prefix);
216 - procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
217 - if(unlikely(!ff)) {
216 +
217 + snprintfz(filename, FILENAME_MAX, "%s/root/proc/1/mountinfo", netdata_configured_host_prefix);
218 + procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
219 +
220 + // Inside docker with '-v "/:/host/root:ro'
221 + bool host_root_prefix = ff != NULL;
222 +
223 + if (!ff) {
224 + snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", netdata_configured_host_prefix);
225 + ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
226 + }
227 + if (!ff) {
228 snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", netdata_configured_host_prefix);
229 ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
220 - if(unlikely(!ff)) return NULL;
230 }
231 + if (!ff)
232 + return NULL;
233
234 ff = procfile_readall(ff);
235 if(unlikely(!ff))
@@ -269,9 +280,16 @@ struct mountinfo *mountinfo_read(int do_statvfs) {
280 mi->root = strdupz(procfile_lineword(ff, l, w)); w++;
281 mi->root_hash = simple_hash(mi->root);
282
272 - mi->mount_point = strdupz_decoding_octal(procfile_lineword(ff, l, w)); w++;
283 + mi->mount_point = strdupz_decoding_octal(procfile_lineword(ff, l, w));w++;
284 mi->mount_point_hash = simple_hash(mi->mount_point);
285
286 + if (host_root_prefix) {
287 + snprintfz(filename, FILENAME_MAX, "%s/root%s", netdata_configured_host_prefix, mi->mount_point);
288 + mi->mount_point_stat_path = strdupz(filename);
289 + } else {
290 + mi->mount_point_stat_path = strdupz(mi->mount_point);
291 + }
292 +
293 mi->persistent_id = strdupz(mi->mount_point);
294 netdata_fix_chart_id(mi->persistent_id);
295 mi->persistent_id_hash = simple_hash(mi->persistent_id);
@@ -339,7 +357,7 @@ struct mountinfo *mountinfo_read(int do_statvfs) {
357 // mark as BIND the duplicates (i.e. same filesystem + same source)
358 if(do_statvfs) {
359 struct stat buf;
342 - if(unlikely(stat(mi->mount_point, &buf) == -1)) {
360 + if(unlikely(stat(mi->mount_point_stat_path, &buf) == -1)) {
361 mi->st_dev = 0;
362 mi->flags |= MOUNTINFO_NO_STAT;
363 }
@@ -391,7 +409,7 @@ struct mountinfo *mountinfo_read(int do_statvfs) {
409 // check if it has size
410 if(do_statvfs && !(mi->flags & MOUNTINFO_IS_DUMMY)) {
411 struct statvfs buff_statvfs;
394 - if(unlikely(statvfs(mi->mount_point, &buff_statvfs) < 0)) {
412 + if(unlikely(statvfs(mi->mount_point_stat_path, &buff_statvfs) < 0)) {
413 mi->flags |= MOUNTINFO_NO_STAT;
414 }
415 else if(unlikely(!buff_statvfs.f_blocks /* || !buff_statvfs.f_files */)) {
src/collectors/proc.plugin/proc_self_mountinfo.h
+2 -1
@@ -24,7 +24,8 @@ struct mountinfo {
24 char *root; // root: root of the mount within the filesystem.
25 uint32_t root_hash;
26
27 - char *mount_point; // mount point: mount point relative to the process's root.
27 + char *mount_point_stat_path; // the actual pathname of the mount point (may differ in Docker)
28 + char *mount_point; // mount point: mount point relative to the process's root.
29 uint32_t mount_point_hash;
30
31 char *mount_options; // mount options: per-mount options.