@cryptotaxi247 / netdata-1 / commits / fd7ed63cc

Fix code formatting for the mdstat collector (#9749)

Vladimir Kobal committed Aug 14, 2020 at 15:08 UTC fd7ed63cc697b42e64358c0a92e963073797e9b4
1 file changed +647 -641
collectors/proc.plugin/proc_mdstat.c
+647 -641
@@ -1,641 +1,647 @@
1 -// SPDX-License-Identifier: GPL-3.0-or-later
2 -
3 -#include "plugin_proc.h"
4 -
5 -#define PLUGIN_PROC_MODULE_MDSTAT_NAME "/proc/mdstat"
6 -
7 -struct raid {
8 - int redundant;
9 - char *name;
10 - uint32_t hash;
11 -
12 - RRDDIM *rd_health;
13 - unsigned long long failed_disks;
14 -
15 - RRDSET *st_disks;
16 - RRDDIM *rd_down;
17 - RRDDIM *rd_inuse;
18 - unsigned long long total_disks;
19 - unsigned long long inuse_disks;
20 -
21 - RRDSET *st_operation;
22 - RRDDIM *rd_check;
23 - RRDDIM *rd_resync;
24 - RRDDIM *rd_recovery;
25 - RRDDIM *rd_reshape;
26 - unsigned long long check;
27 - unsigned long long resync;
28 - unsigned long long recovery;
29 - unsigned long long reshape;
30 -
31 - RRDSET *st_finish;
32 - RRDDIM *rd_finish_in;
33 - unsigned long long finish_in;
34 -
35 - RRDSET *st_speed;
36 - RRDDIM *rd_speed;
37 - unsigned long long speed;
38 -
39 - char *mismatch_cnt_filename;
40 - RRDSET *st_mismatch_cnt;
41 - RRDDIM *rd_mismatch_cnt;
42 - unsigned long long mismatch_cnt;
43 -
44 - RRDSET *st_nonredundant;
45 - RRDDIM *rd_nonredundant;
46 -};
47 -
48 -struct old_raid {
49 - int redundant;
50 - char *name;
51 - uint32_t hash;
52 - int found;
53 -};
54 -
55 -static inline char *remove_trailing_chars(char *s, char c) {
56 - while(*s) {
57 - if(unlikely(*s == c)) {
58 - *s = '\0';
59 - }
60 - s++;
61 - }
62 - return s;
63 -}
64 -
65 -static inline void make_chart_obsolete(char *name, const char *id_modifier) {
66 - char id[50 + 1];
67 - RRDSET *st = NULL;
68 -
69 - if(likely(name && id_modifier)) {
70 - snprintfz(id, 50, "mdstat.%s_%s", name, id_modifier);
71 - st = rrdset_find_active_byname_localhost(id);
72 - if(likely(st)) rrdset_is_obsolete(st);
73 - }
74 -}
75 -
76 -int do_proc_mdstat(int update_every, usec_t dt) {
77 - (void)dt;
78 - static procfile *ff = NULL;
79 - static int do_health = -1, do_nonredundant = -1, do_disks = -1, do_operations = -1, do_mismatch = -1, do_mismatch_config = -1;
80 - static int make_charts_obsolete = -1;
81 - static char *mdstat_filename = NULL, *mismatch_cnt_filename = NULL;
82 - static struct raid *raids = NULL;
83 - static size_t raids_allocated = 0;
84 - size_t raids_num = 0, raid_idx = 0, redundant_num = 0;
85 - static struct old_raid *old_raids = NULL;
86 - static size_t old_raids_allocated = 0;
87 - size_t old_raid_idx = 0;
88 -
89 - if(unlikely(do_health == -1)){
90 - do_health = config_get_boolean("plugin:proc:/proc/mdstat", "faulty devices", CONFIG_BOOLEAN_YES);
91 - do_nonredundant = config_get_boolean("plugin:proc:/proc/mdstat", "nonredundant arrays availability", CONFIG_BOOLEAN_YES);
92 - do_mismatch_config = config_get_boolean_ondemand("plugin:proc:/proc/mdstat", "mismatch count", CONFIG_BOOLEAN_AUTO);
93 - do_disks = config_get_boolean("plugin:proc:/proc/mdstat", "disk stats", CONFIG_BOOLEAN_YES);
94 - do_operations = config_get_boolean("plugin:proc:/proc/mdstat", "operation status", CONFIG_BOOLEAN_YES);
95 -
96 - make_charts_obsolete = config_get_boolean("plugin:proc:/proc/mdstat", "make charts obsolete", CONFIG_BOOLEAN_YES);
97 -
98 - char filename[FILENAME_MAX + 1];
99 -
100 - snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/mdstat");
101 - mdstat_filename = config_get("plugin:proc:/proc/mdstat", "filename to monitor", filename);
102 -
103 - snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/md/mismatch_cnt");
104 - mismatch_cnt_filename = config_get("plugin:proc:/proc/mdstat", "mismatch_cnt filename to monitor", filename);
105 - }
106 -
107 - if(unlikely(!ff)) {
108 - ff = procfile_open(mdstat_filename, " \t:", PROCFILE_FLAG_DEFAULT);
109 - if(unlikely(!ff)) return 1;
110 - }
111 -
112 - ff = procfile_readall(ff);
113 - if(unlikely(!ff)) return 0; // we return 0, so that we will retry opening it next time
114 -
115 - size_t lines = procfile_lines(ff);
116 - size_t words = 0;
117 -
118 - if(unlikely(lines < 2)) {
119 - error("Cannot read /proc/mdstat. Expected 2 or more lines, read %zu.", lines);
120 - return 1;
121 - }
122 -
123 - // find how many raids are there
124 - size_t l;
125 - raids_num = 0;
126 - for(l = 1; l < lines - 2 ; l++) {
127 - if(unlikely(procfile_lineword(ff, l, 1)[0] == 'a')) // check if the raid is active
128 - raids_num++;
129 - }
130 -
131 - if(unlikely(!raids_num && !old_raids_allocated)) return 0; // we return 0, so that we will retry searching for raids next time
132 -
133 - // allocate the memory we need;
134 - if(unlikely(raids_num != raids_allocated)) {
135 - for(raid_idx = 0; raid_idx < raids_allocated; raid_idx++) {
136 - struct raid *raid = &raids[raid_idx];
137 - freez(raid->name);
138 - freez(raid->mismatch_cnt_filename);
139 - }
140 - if(raids_num) {
141 - raids = (struct raid *)reallocz(raids, raids_num * sizeof(struct raid));
142 - memset(raids, 0, raids_num * sizeof(struct raid));
143 - }
144 - else {
145 - freez(raids);
146 - raids = NULL;
147 - }
148 - raids_allocated = raids_num;
149 - }
150 -
151 - // loop through all lines except the first and the last ones
152 - for(l = 1, raid_idx = 0; l < (lines - 2) && raid_idx < raids_num; l++) {
153 - struct raid *raid = &raids[raid_idx];
154 - raid->redundant = 0;
155 -
156 - words = procfile_linewords(ff, l);
157 - if(unlikely(words < 2)) continue;
158 -
159 - if(unlikely(procfile_lineword(ff, l, 1)[0] != 'a')) continue;
160 - if(unlikely(!raid->name)) {
161 - raid->name = strdupz(procfile_lineword(ff, l, 0));
162 - raid->hash = simple_hash(raid->name);
163 - }
164 - else if(unlikely(strcmp(raid->name, procfile_lineword(ff, l, 0)))) {
165 - freez(raid->name);
166 - freez(raid->mismatch_cnt_filename);
167 - memset(raid, 0, sizeof(struct raid));
168 - raid->name = strdupz(procfile_lineword(ff, l, 0));
169 - raid->hash = simple_hash(raid->name);
170 - }
171 - if(unlikely(!raid->name || !raid->name[0])) continue;
172 - raid_idx++;
173 -
174 - // check if raid has disk status
175 - l++;
176 - words = procfile_linewords(ff, l);
177 - if(words < 2 || procfile_lineword(ff, l, words - 1)[0] != '[') continue;
178 -
179 - // split inuse and total number of disks
180 - if(likely(do_health || do_disks)) {
181 - char *s = NULL, *str_total = NULL, *str_inuse = NULL;
182 -
183 - s = procfile_lineword(ff, l, words - 2);
184 - if(unlikely(s[0] != '[')) {
185 - error("Cannot read /proc/mdstat raid health status. Unexpected format: missing opening bracket.");
186 - continue;
187 - }
188 - str_total = ++s;
189 - while(*s) {
190 - if(unlikely(*s == '/')) {
191 - *s = '\0';
192 - str_inuse = s + 1;
193 - }
194 - else if(unlikely(*s == ']')) {
195 - *s = '\0';
196 - break;
197 - }
198 - s++;
199 - }
200 - if(unlikely(str_total[0] == '\0' || !str_inuse || str_inuse[0] == '\0')) {
201 - error("Cannot read /proc/mdstat raid health status. Unexpected format.");
202 - continue;
203 - }
204 -
205 - raid->inuse_disks = str2ull(str_inuse);
206 - raid->total_disks = str2ull(str_total);
207 - raid->failed_disks = raid->total_disks - raid->inuse_disks;
208 - }
209 -
210 - raid->redundant = 1;
211 - redundant_num++;
212 - l++;
213 -
214 - // check if any operation is performed on the raid
215 - if(likely(do_operations)) {
216 - char *s = NULL;
217 -
218 - raid->check = 0;
219 - raid->resync = 0;
220 - raid->recovery = 0;
221 - raid->reshape = 0;
222 - raid->finish_in = 0;
223 - raid->speed = 0;
224 -
225 - words = procfile_linewords(ff, l);
226 - if(likely(words < 2)) continue;
227 - if(unlikely(procfile_lineword(ff, l, 0)[0] != '[')) continue;
228 - if(unlikely(words < 7)) {
229 - error("Cannot read /proc/mdstat line. Expected 7 params, read %zu.", words);
230 - continue;
231 - }
232 -
233 - char *word;
234 - word = procfile_lineword(ff, l, 3);
235 - remove_trailing_chars(word, '%');
236 -
237 - unsigned long long percentage = (unsigned long long)(str2ld(word, NULL) * 100);
238 - // possible operations: check, resync, recovery, reshape
239 - // 4-th character is unique for each operation so it is checked
240 - switch(procfile_lineword(ff, l, 1)[3]) {
241 - case 'c': // check
242 - raid->check = percentage;
243 - break;
244 - case 'y': // resync
245 - raid->resync = percentage;
246 - break;
247 - case 'o': // recovery
248 - raid->recovery = percentage;
249 - break;
250 - case 'h': // reshape
251 - raid->reshape = percentage;
252 - break;
253 - }
254 -
255 - word = procfile_lineword(ff, l, 5);
256 - s = remove_trailing_chars(word, 'm'); // remove trailing "min"
257 -
258 - word += 7; // skip leading "finish="
259 -
260 - if(likely(s > word))
261 - raid->finish_in = (unsigned long long)(str2ld(word, NULL) * 60);
262 -
263 - word = procfile_lineword(ff, l, 6);
264 - s = remove_trailing_chars(word, 'K'); // remove trailing "K/sec"
265 -
266 - word += 6; // skip leading "speed="
267 -
268 - if(likely(s > word))
269 - raid->speed = str2ull(word);
270 - }
271 - }
272 -
273 - // read mismatch_cnt files
274 - if(do_mismatch == -1) {
275 - if(do_mismatch_config == CONFIG_BOOLEAN_AUTO) {
276 - if(raids_num > 50)
277 - do_mismatch = CONFIG_BOOLEAN_NO;
278 - else
279 - do_mismatch = CONFIG_BOOLEAN_YES;
280 - }
281 - else
282 - do_mismatch = do_mismatch_config;
283 - }
284 -
285 - if(likely(do_mismatch)) {
286 - for(raid_idx = 0; raid_idx < raids_num ; raid_idx++) {
287 - char filename[FILENAME_MAX + 1];
288 - struct raid *raid = &raids[raid_idx];
289 -
290 - if(likely(raid->redundant)) {
291 - if(unlikely(!raid->mismatch_cnt_filename)) {
292 - snprintfz(filename, FILENAME_MAX, mismatch_cnt_filename, raid->name);
293 - raid->mismatch_cnt_filename = strdupz(filename);
294 - }
295 - if(unlikely(read_single_number_file(raid->mismatch_cnt_filename, &raid->mismatch_cnt))) {
296 - error("Cannot read file '%s'", raid->mismatch_cnt_filename);
297 - do_mismatch = CONFIG_BOOLEAN_NO;
298 - error("Monitoring for mismatch count has been disabled");
299 - break;
300 - }
301 - }
302 - }
303 - }
304 -
305 - // check for disappeared raids
306 - for(old_raid_idx = 0; old_raid_idx < old_raids_allocated; old_raid_idx++) {
307 - struct old_raid *old_raid = &old_raids[old_raid_idx];
308 - int found = 0;
309 -
310 - for(raid_idx = 0; raid_idx < raids_num ; raid_idx++) {
311 - struct raid *raid = &raids[raid_idx];
312 -
313 - if(unlikely(raid->hash == old_raid->hash
314 - && !strcmp(raid->name, old_raid->name)
315 - && raid->redundant == old_raid->redundant)) found = 1;
316 - }
317 -
318 - old_raid->found = found;
319 - }
320 -
321 - int raid_disappeared = 0;
322 - for(old_raid_idx = 0; old_raid_idx < old_raids_allocated; old_raid_idx++) {
323 - struct old_raid *old_raid = &old_raids[old_raid_idx];
324 -
325 - if(unlikely(!old_raid->found)) {
326 - if(likely(make_charts_obsolete)) {
327 - make_chart_obsolete(old_raid->name, "disks");
328 - make_chart_obsolete(old_raid->name, "mismatch");
329 - make_chart_obsolete(old_raid->name, "operation");
330 - make_chart_obsolete(old_raid->name, "finish");
331 - make_chart_obsolete(old_raid->name, "speed");
332 - make_chart_obsolete(old_raid->name, "availability");
333 - }
334 - raid_disappeared = 1;
335 - }
336 - }
337 -
338 - // allocate memory for nonredundant arrays
339 - if(unlikely(raid_disappeared || old_raids_allocated != raids_num)) {
340 - for(old_raid_idx = 0; old_raid_idx < old_raids_allocated; old_raid_idx++) {
341 - freez(old_raids[old_raid_idx].name);
342 - }
343 - if(likely(raids_num)) {
344 - old_raids = reallocz(old_raids, sizeof(struct old_raid) * raids_num);
345 - memset(old_raids, 0, sizeof(struct old_raid) * raids_num);
346 - }
347 - else {
348 - freez(old_raids);
349 - old_raids = NULL;
350 - }
351 - old_raids_allocated = raids_num;
352 - for(old_raid_idx = 0; old_raid_idx < old_raids_allocated; old_raid_idx++) {
353 - struct old_raid *old_raid = &old_raids[old_raid_idx];
354 - struct raid *raid = &raids[old_raid_idx];
355 -
356 - old_raid->name = strdupz(raid->name);
357 - old_raid->hash = raid->hash;
358 - old_raid->redundant = raid->redundant;
359 - }
360 - }
361 -
362 - // --------------------------------------------------------------------
363 -
364 - if(likely(do_health && redundant_num)) {
365 - static RRDSET *st_mdstat_health = NULL;
366 - if(unlikely(!st_mdstat_health)) {
367 - st_mdstat_health = rrdset_create_localhost(
368 - "mdstat"
369 - , "mdstat_health"
370 - , NULL
371 - , "health"
372 - , "md.health"
373 - , "Faulty Devices In MD"
374 - , "failed disks"
375 - , PLUGIN_PROC_NAME
376 - , PLUGIN_PROC_MODULE_MDSTAT_NAME
377 - , NETDATA_CHART_PRIO_MDSTAT_HEALTH
378 - , update_every
379 - , RRDSET_TYPE_LINE
380 - );
381 -
382 - rrdset_isnot_obsolete(st_mdstat_health);
383 - }
384 - else
385 - rrdset_next(st_mdstat_health);
386 -
387 - if(!redundant_num) {
388 - if(likely(make_charts_obsolete)) make_chart_obsolete("mdstat", "health");
389 - }
390 - else {
391 - for(raid_idx = 0; raid_idx < raids_num; raid_idx++) {
392 - struct raid *raid = &raids[raid_idx];
393 -
394 - if(likely(raid->redundant)) {
395 - if(unlikely(!raid->rd_health && !(raid->rd_health = rrddim_find_active(st_mdstat_health, raid->name))))
396 - raid->rd_health = rrddim_add(st_mdstat_health, raid->name, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
397 -
398 - rrddim_set_by_pointer(st_mdstat_health, raid->rd_health, raid->failed_disks);
399 - }
400 - }
401 -
402 - rrdset_done(st_mdstat_health);
403 - }
404 - }
405 -
406 - // --------------------------------------------------------------------
407 -
408 - for(raid_idx = 0; raid_idx < raids_num ; raid_idx++) {
409 - struct raid *raid = &raids[raid_idx];
410 - char id[50 + 1];
411 - char family[50 + 1];
412 -
413 - if(likely(raid->redundant)) {
414 - if(likely(do_disks)) {
415 - snprintfz(id, 50, "%s_disks", raid->name);
416 -
417 - if(unlikely(!raid->st_disks && !(raid->st_disks = rrdset_find_active_byname_localhost(id)))) {
418 - snprintfz(family, 50, "%s", raid->name);
419 -
420 - raid->st_disks = rrdset_create_localhost(
421 - "mdstat"
422 - , id
423 - , NULL
424 - , family
425 - , "md.disks"
426 - , "Disks Stats"
427 - , "disks"
428 - , PLUGIN_PROC_NAME
429 - , PLUGIN_PROC_MODULE_MDSTAT_NAME
430 - , NETDATA_CHART_PRIO_MDSTAT_DISKS + raid_idx * 10
431 - , update_every
432 - , RRDSET_TYPE_STACKED
433 - );
434 -
435 - rrdset_isnot_obsolete(raid->st_disks);
436 - }
437 - else
438 - rrdset_next(raid->st_disks);
439 -
440 - if(unlikely(!raid->rd_inuse && !(raid->rd_inuse = rrddim_find_active(raid->st_disks, "inuse"))))
441 - raid->rd_inuse = rrddim_add(raid->st_disks, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
442 - if(unlikely(!raid->rd_down && !(raid->rd_down = rrddim_find_active(raid->st_disks, "down"))))
443 - raid->rd_down = rrddim_add(raid->st_disks, "down", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
444 -
445 - rrddim_set_by_pointer(raid->st_disks, raid->rd_inuse, raid->inuse_disks);
446 - rrddim_set_by_pointer(raid->st_disks, raid->rd_down, raid->failed_disks);
447 -
448 - rrdset_done(raid->st_disks);
449 - }
450 -
451 - // --------------------------------------------------------------------
452 -
453 - if(likely(do_mismatch)) {
454 - snprintfz(id, 50, "%s_mismatch", raid->name);
455 -
456 - if(unlikely(!raid->st_mismatch_cnt && !(raid->st_mismatch_cnt = rrdset_find_active_byname_localhost(id)))) {
457 - snprintfz(family, 50, "%s", raid->name);
458 -
459 - raid->st_mismatch_cnt = rrdset_create_localhost(
460 - "mdstat"
461 - , id
462 - , NULL
463 - , family
464 - , "md.mismatch_cnt"
465 - , "Mismatch Count"
466 - , "unsynchronized blocks"
467 - , PLUGIN_PROC_NAME
468 - , PLUGIN_PROC_MODULE_MDSTAT_NAME
469 - , NETDATA_CHART_PRIO_MDSTAT_MISMATCH + raid_idx * 10
470 - , update_every
471 - , RRDSET_TYPE_LINE
472 - );
473 -
474 - rrdset_isnot_obsolete(raid->st_mismatch_cnt);
475 - }
476 - else
477 - rrdset_next(raid->st_mismatch_cnt);
478 -
479 - if(unlikely(!raid->rd_mismatch_cnt && !(raid->rd_mismatch_cnt = rrddim_find_active(raid->st_mismatch_cnt, "count"))))
480 - raid->rd_mismatch_cnt = rrddim_add(raid->st_mismatch_cnt, "count", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
481 -
482 - rrddim_set_by_pointer(raid->st_mismatch_cnt, raid->rd_mismatch_cnt, raid->mismatch_cnt);
483 -
484 - rrdset_done(raid->st_mismatch_cnt);
485 - }
486 -
487 - // --------------------------------------------------------------------
488 -
489 - if(likely(do_operations)) {
490 - snprintfz(id, 50, "%s_operation", raid->name);
491 -
492 - if(unlikely(!raid->st_operation && !(raid->st_operation = rrdset_find_active_byname_localhost(id)))) {
493 - snprintfz(family, 50, "%s", raid->name);
494 -
495 - raid->st_operation = rrdset_create_localhost(
496 - "mdstat"
497 - , id
498 - , NULL
499 - , family
500 - , "md.status"
501 - , "Current Status"
502 - , "percent"
503 - , PLUGIN_PROC_NAME
504 - , PLUGIN_PROC_MODULE_MDSTAT_NAME
505 - , NETDATA_CHART_PRIO_MDSTAT_OPERATION + raid_idx * 10
506 - , update_every
507 - , RRDSET_TYPE_LINE
508 - );
509 -
510 - rrdset_isnot_obsolete(raid->st_operation);
511 - }
512 - else
513 - rrdset_next(raid->st_operation);
514 -
515 - if(unlikely(!raid->rd_check && !(raid->rd_check = rrddim_find_active(raid->st_operation, "check"))))
516 - raid->rd_check = rrddim_add(raid->st_operation, "check", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE);
517 - if(unlikely(!raid->rd_resync && !(raid->rd_resync = rrddim_find_active(raid->st_operation, "resync"))))
518 - raid->rd_resync = rrddim_add(raid->st_operation, "resync", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE);
519 - if(unlikely(!raid->rd_recovery && !(raid->rd_recovery = rrddim_find_active(raid->st_operation, "recovery"))))
520 - raid->rd_recovery = rrddim_add(raid->st_operation, "recovery", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE);
521 - if(unlikely(!raid->rd_reshape && !(raid->rd_reshape = rrddim_find_active(raid->st_operation, "reshape"))))
522 - raid->rd_reshape = rrddim_add(raid->st_operation, "reshape", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE);
523 -
524 - rrddim_set_by_pointer(raid->st_operation, raid->rd_check, raid->check);
525 - rrddim_set_by_pointer(raid->st_operation, raid->rd_resync, raid->resync);
526 - rrddim_set_by_pointer(raid->st_operation, raid->rd_recovery, raid->recovery);
527 - rrddim_set_by_pointer(raid->st_operation, raid->rd_reshape, raid->reshape);
528 -
529 - rrdset_done(raid->st_operation);
530 -
531 - // --------------------------------------------------------------------
532 -
533 - snprintfz(id, 50, "%s_finish", raid->name);
534 -
535 - if(unlikely(!raid->st_finish && !(raid->st_finish = rrdset_find_active_byname_localhost(id)))) {
536 - snprintfz(family, 50, "%s", raid->name);
537 -
538 - raid->st_finish = rrdset_create_localhost(
539 - "mdstat"
540 - , id
541 - , NULL
542 - , family
543 - , "md.rate"
544 - , "Approximate Time Unit Finish"
545 - , "seconds"
546 - , PLUGIN_PROC_NAME
547 - , PLUGIN_PROC_MODULE_MDSTAT_NAME
548 - , NETDATA_CHART_PRIO_MDSTAT_FINISH + raid_idx * 10
549 - , update_every
550 - , RRDSET_TYPE_LINE
551 - );
552 -
553 - rrdset_isnot_obsolete(raid->st_finish);
554 - }
555 - else
556 - rrdset_next(raid->st_finish);
557 -
558 - if(unlikely(!raid->rd_finish_in && !(raid->rd_finish_in = rrddim_find_active(raid->st_finish, "finish_in"))))
559 - raid->rd_finish_in = rrddim_add(raid->st_finish, "finish_in", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
560 -
561 - rrddim_set_by_pointer(raid->st_finish, raid->rd_finish_in, raid->finish_in);
562 -
563 - rrdset_done(raid->st_finish);
564 -
565 - // --------------------------------------------------------------------
566 -
567 - snprintfz(id, 50, "%s_speed", raid->name);
568 -
569 - if(unlikely(!raid->st_speed && !(raid->st_speed = rrdset_find_active_byname_localhost(id)))) {
570 - snprintfz(family, 50, "%s", raid->name);
571 -
572 - raid->st_speed = rrdset_create_localhost(
573 - "mdstat"
574 - , id
575 - , NULL
576 - , family
577 - , "md.rate"
578 - , "Operation Speed"
579 - , "KiB/s"
580 - , PLUGIN_PROC_NAME
581 - , PLUGIN_PROC_MODULE_MDSTAT_NAME
582 - , NETDATA_CHART_PRIO_MDSTAT_SPEED + raid_idx * 10
583 - , update_every
584 - , RRDSET_TYPE_LINE
585 - );
586 -
587 - rrdset_isnot_obsolete(raid->st_speed);
588 - }
589 - else
590 - rrdset_next(raid->st_speed);
591 -
592 - if(unlikely(!raid->rd_speed && !(raid->rd_speed = rrddim_find_active(raid->st_speed, "speed"))))
593 - raid->rd_speed = rrddim_add(raid->st_speed, "speed", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
594 -
595 - rrddim_set_by_pointer(raid->st_speed, raid->rd_speed, raid->speed);
596 -
597 - rrdset_done(raid->st_speed);
598 - }
599 - }
600 - else {
601 -
602 - // --------------------------------------------------------------------
603 -
604 - if(likely(do_nonredundant)) {
605 - snprintfz(id, 50, "%s_availability", raid->name);
606 -
607 - if(unlikely(!raid->st_nonredundant && !(raid->st_nonredundant = rrdset_find_active_localhost(id)))) {
608 - snprintfz(family, 50, "%s", raid->name);
609 -
610 - raid->st_nonredundant = rrdset_create_localhost(
611 - "mdstat"
612 - , id
613 - , NULL
614 - , family
615 - , "md.nonredundant"
616 - , "Nonredundant Array Availability"
617 - , "boolean"
618 - , PLUGIN_PROC_NAME
619 - , PLUGIN_PROC_MODULE_MDSTAT_NAME
620 - , NETDATA_CHART_PRIO_MDSTAT_NONREDUNDANT + raid_idx * 10
621 - , update_every
622 - , RRDSET_TYPE_LINE
623 - );
624 -
625 - rrdset_isnot_obsolete(raid->st_nonredundant);
626 - }
627 - else
628 - rrdset_next(raid->st_nonredundant);
629 -
630 - if(unlikely(!raid->rd_nonredundant && !(raid->rd_nonredundant = rrddim_find_active(raid->st_nonredundant, "available"))))
631 - raid->rd_nonredundant = rrddim_add(raid->st_nonredundant, "available", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
632 -
633 - rrddim_set_by_pointer(raid->st_nonredundant, raid->rd_nonredundant, 1);
634 -
635 - rrdset_done(raid->st_nonredundant);
636 - }
637 - }
638 - }
639 -
640 - return 0;
641 -}
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "plugin_proc.h"
4 +
5 +#define PLUGIN_PROC_MODULE_MDSTAT_NAME "/proc/mdstat"
6 +
7 +struct raid {
8 + int redundant;
9 + char *name;
10 + uint32_t hash;
11 +
12 + RRDDIM *rd_health;
13 + unsigned long long failed_disks;
14 +
15 + RRDSET *st_disks;
16 + RRDDIM *rd_down;
17 + RRDDIM *rd_inuse;
18 + unsigned long long total_disks;
19 + unsigned long long inuse_disks;
20 +
21 + RRDSET *st_operation;
22 + RRDDIM *rd_check;
23 + RRDDIM *rd_resync;
24 + RRDDIM *rd_recovery;
25 + RRDDIM *rd_reshape;
26 + unsigned long long check;
27 + unsigned long long resync;
28 + unsigned long long recovery;
29 + unsigned long long reshape;
30 +
31 + RRDSET *st_finish;
32 + RRDDIM *rd_finish_in;
33 + unsigned long long finish_in;
34 +
35 + RRDSET *st_speed;
36 + RRDDIM *rd_speed;
37 + unsigned long long speed;
38 +
39 + char *mismatch_cnt_filename;
40 + RRDSET *st_mismatch_cnt;
41 + RRDDIM *rd_mismatch_cnt;
42 + unsigned long long mismatch_cnt;
43 +
44 + RRDSET *st_nonredundant;
45 + RRDDIM *rd_nonredundant;
46 +};
47 +
48 +struct old_raid {
49 + int redundant;
50 + char *name;
51 + uint32_t hash;
52 + int found;
53 +};
54 +
55 +static inline char *remove_trailing_chars(char *s, char c)
56 +{
57 + while (*s) {
58 + if (unlikely(*s == c)) {
59 + *s = '\0';
60 + }
61 + s++;
62 + }
63 + return s;
64 +}
65 +
66 +static inline void make_chart_obsolete(char *name, const char *id_modifier)
67 +{
68 + char id[50 + 1];
69 + RRDSET *st = NULL;
70 +
71 + if (likely(name && id_modifier)) {
72 + snprintfz(id, 50, "mdstat.%s_%s", name, id_modifier);
73 + st = rrdset_find_active_byname_localhost(id);
74 + if (likely(st))
75 + rrdset_is_obsolete(st);
76 + }
77 +}
78 +
79 +int do_proc_mdstat(int update_every, usec_t dt)
80 +{
81 + (void)dt;
82 + static procfile *ff = NULL;
83 + static int do_health = -1, do_nonredundant = -1, do_disks = -1, do_operations = -1, do_mismatch = -1,
84 + do_mismatch_config = -1;
85 + static int make_charts_obsolete = -1;
86 + static char *mdstat_filename = NULL, *mismatch_cnt_filename = NULL;
87 + static struct raid *raids = NULL;
88 + static size_t raids_allocated = 0;
89 + size_t raids_num = 0, raid_idx = 0, redundant_num = 0;
90 + static struct old_raid *old_raids = NULL;
91 + static size_t old_raids_allocated = 0;
92 + size_t old_raid_idx = 0;
93 +
94 + if (unlikely(do_health == -1)) {
95 + do_health =
96 + config_get_boolean("plugin:proc:/proc/mdstat", "faulty devices", CONFIG_BOOLEAN_YES);
97 + do_nonredundant =
98 + config_get_boolean("plugin:proc:/proc/mdstat", "nonredundant arrays availability", CONFIG_BOOLEAN_YES);
99 + do_mismatch_config =
100 + config_get_boolean_ondemand("plugin:proc:/proc/mdstat", "mismatch count", CONFIG_BOOLEAN_AUTO);
101 + do_disks =
102 + config_get_boolean("plugin:proc:/proc/mdstat", "disk stats", CONFIG_BOOLEAN_YES);
103 + do_operations =
104 + config_get_boolean("plugin:proc:/proc/mdstat", "operation status", CONFIG_BOOLEAN_YES);
105 +
106 + make_charts_obsolete =
107 + config_get_boolean("plugin:proc:/proc/mdstat", "make charts obsolete", CONFIG_BOOLEAN_YES);
108 +
109 + char filename[FILENAME_MAX + 1];
110 +
111 + snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/mdstat");
112 + mdstat_filename = config_get("plugin:proc:/proc/mdstat", "filename to monitor", filename);
113 +
114 + snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/md/mismatch_cnt");
115 + mismatch_cnt_filename = config_get("plugin:proc:/proc/mdstat", "mismatch_cnt filename to monitor", filename);
116 + }
117 +
118 + if (unlikely(!ff)) {
119 + ff = procfile_open(mdstat_filename, " \t:", PROCFILE_FLAG_DEFAULT);
120 + if (unlikely(!ff))
121 + return 1;
122 + }
123 +
124 + ff = procfile_readall(ff);
125 + if (unlikely(!ff))
126 + return 0; // we return 0, so that we will retry opening it next time
127 +
128 + size_t lines = procfile_lines(ff);
129 + size_t words = 0;
130 +
131 + if (unlikely(lines < 2)) {
132 + error("Cannot read /proc/mdstat. Expected 2 or more lines, read %zu.", lines);
133 + return 1;
134 + }
135 +
136 + // find how many raids are there
137 + size_t l;
138 + raids_num = 0;
139 + for (l = 1; l < lines - 2; l++) {
140 + if (unlikely(procfile_lineword(ff, l, 1)[0] == 'a')) // check if the raid is active
141 + raids_num++;
142 + }
143 +
144 + if (unlikely(!raids_num && !old_raids_allocated))
145 + return 0; // we return 0, so that we will retry searching for raids next time
146 +
147 + // allocate the memory we need;
148 + if (unlikely(raids_num != raids_allocated)) {
149 + for (raid_idx = 0; raid_idx < raids_allocated; raid_idx++) {
150 + struct raid *raid = &raids[raid_idx];
151 + freez(raid->name);
152 + freez(raid->mismatch_cnt_filename);
153 + }
154 + if (raids_num) {
155 + raids = (struct raid *)reallocz(raids, raids_num * sizeof(struct raid));
156 + memset(raids, 0, raids_num * sizeof(struct raid));
157 + } else {
158 + freez(raids);
159 + raids = NULL;
160 + }
161 + raids_allocated = raids_num;
162 + }
163 +
164 + // loop through all lines except the first and the last ones
165 + for (l = 1, raid_idx = 0; l < (lines - 2) && raid_idx < raids_num; l++) {
166 + struct raid *raid = &raids[raid_idx];
167 + raid->redundant = 0;
168 +
169 + words = procfile_linewords(ff, l);
170 +
171 + if (unlikely(words < 2))
172 + continue;
173 +
174 + if (unlikely(procfile_lineword(ff, l, 1)[0] != 'a'))
175 + continue;
176 +
177 + if (unlikely(!raid->name)) {
178 + raid->name = strdupz(procfile_lineword(ff, l, 0));
179 + raid->hash = simple_hash(raid->name);
180 + } else if (unlikely(strcmp(raid->name, procfile_lineword(ff, l, 0)))) {
181 + freez(raid->name);
182 + freez(raid->mismatch_cnt_filename);
183 + memset(raid, 0, sizeof(struct raid));
184 + raid->name = strdupz(procfile_lineword(ff, l, 0));
185 + raid->hash = simple_hash(raid->name);
186 + }
187 +
188 + if (unlikely(!raid->name || !raid->name[0]))
189 + continue;
190 +
191 + raid_idx++;
192 +
193 + // check if raid has disk status
194 + l++;
195 + words = procfile_linewords(ff, l);
196 + if (words < 2 || procfile_lineword(ff, l, words - 1)[0] != '[')
197 + continue;
198 +
199 + // split inuse and total number of disks
200 + if (likely(do_health || do_disks)) {
201 + char *s = NULL, *str_total = NULL, *str_inuse = NULL;
202 +
203 + s = procfile_lineword(ff, l, words - 2);
204 + if (unlikely(s[0] != '[')) {
205 + error("Cannot read /proc/mdstat raid health status. Unexpected format: missing opening bracket.");
206 + continue;
207 + }
208 + str_total = ++s;
209 + while (*s) {
210 + if (unlikely(*s == '/')) {
211 + *s = '\0';
212 + str_inuse = s + 1;
213 + } else if (unlikely(*s == ']')) {
214 + *s = '\0';
215 + break;
216 + }
217 + s++;
218 + }
219 + if (unlikely(str_total[0] == '\0' || !str_inuse || str_inuse[0] == '\0')) {
220 + error("Cannot read /proc/mdstat raid health status. Unexpected format.");
221 + continue;
222 + }
223 +
224 + raid->inuse_disks = str2ull(str_inuse);
225 + raid->total_disks = str2ull(str_total);
226 + raid->failed_disks = raid->total_disks - raid->inuse_disks;
227 + }
228 +
229 + raid->redundant = 1;
230 + redundant_num++;
231 + l++;
232 +
233 + // check if any operation is performed on the raid
234 + if (likely(do_operations)) {
235 + char *s = NULL;
236 +
237 + raid->check = 0;
238 + raid->resync = 0;
239 + raid->recovery = 0;
240 + raid->reshape = 0;
241 + raid->finish_in = 0;
242 + raid->speed = 0;
243 +
244 + words = procfile_linewords(ff, l);
245 +
246 + if (likely(words < 2))
247 + continue;
248 +
249 + if (unlikely(procfile_lineword(ff, l, 0)[0] != '['))
250 + continue;
251 +
252 + if (unlikely(words < 7)) {
253 + error("Cannot read /proc/mdstat line. Expected 7 params, read %zu.", words);
254 + continue;
255 + }
256 +
257 + char *word;
258 + word = procfile_lineword(ff, l, 3);
259 + remove_trailing_chars(word, '%');
260 +
261 + unsigned long long percentage = (unsigned long long)(str2ld(word, NULL) * 100);
262 + // possible operations: check, resync, recovery, reshape
263 + // 4-th character is unique for each operation so it is checked
264 + switch (procfile_lineword(ff, l, 1)[3]) {
265 + case 'c': // check
266 + raid->check = percentage;
267 + break;
268 + case 'y': // resync
269 + raid->resync = percentage;
270 + break;
271 + case 'o': // recovery
272 + raid->recovery = percentage;
273 + break;
274 + case 'h': // reshape
275 + raid->reshape = percentage;
276 + break;
277 + }
278 +
279 + word = procfile_lineword(ff, l, 5);
280 + s = remove_trailing_chars(word, 'm'); // remove trailing "min"
281 +
282 + word += 7; // skip leading "finish="
283 +
284 + if (likely(s > word))
285 + raid->finish_in = (unsigned long long)(str2ld(word, NULL) * 60);
286 +
287 + word = procfile_lineword(ff, l, 6);
288 + s = remove_trailing_chars(word, 'K'); // remove trailing "K/sec"
289 +
290 + word += 6; // skip leading "speed="
291 +
292 + if (likely(s > word))
293 + raid->speed = str2ull(word);
294 + }
295 + }
296 +
297 + // read mismatch_cnt files
298 + if (do_mismatch == -1) {
299 + if (do_mismatch_config == CONFIG_BOOLEAN_AUTO) {
300 + if (raids_num > 50)
301 + do_mismatch = CONFIG_BOOLEAN_NO;
302 + else
303 + do_mismatch = CONFIG_BOOLEAN_YES;
304 + } else
305 + do_mismatch = do_mismatch_config;
306 + }
307 +
308 + if (likely(do_mismatch)) {
309 + for (raid_idx = 0; raid_idx < raids_num; raid_idx++) {
310 + char filename[FILENAME_MAX + 1];
311 + struct raid *raid = &raids[raid_idx];
312 +
313 + if (likely(raid->redundant)) {
314 + if (unlikely(!raid->mismatch_cnt_filename)) {
315 + snprintfz(filename, FILENAME_MAX, mismatch_cnt_filename, raid->name);
316 + raid->mismatch_cnt_filename = strdupz(filename);
317 + }
318 + if (unlikely(read_single_number_file(raid->mismatch_cnt_filename, &raid->mismatch_cnt))) {
319 + error("Cannot read file '%s'", raid->mismatch_cnt_filename);
320 + do_mismatch = CONFIG_BOOLEAN_NO;
321 + error("Monitoring for mismatch count has been disabled");
322 + break;
323 + }
324 + }
325 + }
326 + }
327 +
328 + // check for disappeared raids
329 + for (old_raid_idx = 0; old_raid_idx < old_raids_allocated; old_raid_idx++) {
330 + struct old_raid *old_raid = &old_raids[old_raid_idx];
331 + int found = 0;
332 +
333 + for (raid_idx = 0; raid_idx < raids_num; raid_idx++) {
334 + struct raid *raid = &raids[raid_idx];
335 +
336 + if (unlikely(
337 + raid->hash == old_raid->hash && !strcmp(raid->name, old_raid->name) &&
338 + raid->redundant == old_raid->redundant))
339 + found = 1;
340 + }
341 +
342 + old_raid->found = found;
343 + }
344 +
345 + int raid_disappeared = 0;
346 + for (old_raid_idx = 0; old_raid_idx < old_raids_allocated; old_raid_idx++) {
347 + struct old_raid *old_raid = &old_raids[old_raid_idx];
348 +
349 + if (unlikely(!old_raid->found)) {
350 + if (likely(make_charts_obsolete)) {
351 + make_chart_obsolete(old_raid->name, "disks");
352 + make_chart_obsolete(old_raid->name, "mismatch");
353 + make_chart_obsolete(old_raid->name, "operation");
354 + make_chart_obsolete(old_raid->name, "finish");
355 + make_chart_obsolete(old_raid->name, "speed");
356 + make_chart_obsolete(old_raid->name, "availability");
357 + }
358 + raid_disappeared = 1;
359 + }
360 + }
361 +
362 + // allocate memory for nonredundant arrays
363 + if (unlikely(raid_disappeared || old_raids_allocated != raids_num)) {
364 + for (old_raid_idx = 0; old_raid_idx < old_raids_allocated; old_raid_idx++) {
365 + freez(old_raids[old_raid_idx].name);
366 + }
367 + if (likely(raids_num)) {
368 + old_raids = reallocz(old_raids, sizeof(struct old_raid) * raids_num);
369 + memset(old_raids, 0, sizeof(struct old_raid) * raids_num);
370 + } else {
371 + freez(old_raids);
372 + old_raids = NULL;
373 + }
374 + old_raids_allocated = raids_num;
375 + for (old_raid_idx = 0; old_raid_idx < old_raids_allocated; old_raid_idx++) {
376 + struct old_raid *old_raid = &old_raids[old_raid_idx];
377 + struct raid *raid = &raids[old_raid_idx];
378 +
379 + old_raid->name = strdupz(raid->name);
380 + old_raid->hash = raid->hash;
381 + old_raid->redundant = raid->redundant;
382 + }
383 + }
384 +
385 + // --------------------------------------------------------------------
386 +
387 + if (likely(do_health && redundant_num)) {
388 + static RRDSET *st_mdstat_health = NULL;
389 + if (unlikely(!st_mdstat_health)) {
390 + st_mdstat_health = rrdset_create_localhost(
391 + "mdstat",
392 + "mdstat_health",
393 + NULL,
394 + "health",
395 + "md.health",
396 + "Faulty Devices In MD",
397 + "failed disks",
398 + PLUGIN_PROC_NAME,
399 + PLUGIN_PROC_MODULE_MDSTAT_NAME,
400 + NETDATA_CHART_PRIO_MDSTAT_HEALTH,
401 + update_every,
402 + RRDSET_TYPE_LINE);
403 +
404 + rrdset_isnot_obsolete(st_mdstat_health);
405 + } else
406 + rrdset_next(st_mdstat_health);
407 +
408 + if (!redundant_num) {
409 + if (likely(make_charts_obsolete))
410 + make_chart_obsolete("mdstat", "health");
411 + } else {
412 + for (raid_idx = 0; raid_idx < raids_num; raid_idx++) {
413 + struct raid *raid = &raids[raid_idx];
414 +
415 + if (likely(raid->redundant)) {
416 + if (unlikely(!raid->rd_health && !(raid->rd_health = rrddim_find_active(st_mdstat_health, raid->name))))
417 + raid->rd_health = rrddim_add(st_mdstat_health, raid->name, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
418 +
419 + rrddim_set_by_pointer(st_mdstat_health, raid->rd_health, raid->failed_disks);
420 + }
421 + }
422 +
423 + rrdset_done(st_mdstat_health);
424 + }
425 + }
426 +
427 + // --------------------------------------------------------------------
428 +
429 + for (raid_idx = 0; raid_idx < raids_num; raid_idx++) {
430 + struct raid *raid = &raids[raid_idx];
431 + char id[50 + 1];
432 + char family[50 + 1];
433 +
434 + if (likely(raid->redundant)) {
435 + if (likely(do_disks)) {
436 + snprintfz(id, 50, "%s_disks", raid->name);
437 +
438 + if (unlikely(!raid->st_disks && !(raid->st_disks = rrdset_find_active_byname_localhost(id)))) {
439 + snprintfz(family, 50, "%s", raid->name);
440 +
441 + raid->st_disks = rrdset_create_localhost(
442 + "mdstat",
443 + id,
444 + NULL,
445 + family,
446 + "md.disks",
447 + "Disks Stats",
448 + "disks",
449 + PLUGIN_PROC_NAME,
450 + PLUGIN_PROC_MODULE_MDSTAT_NAME,
451 + NETDATA_CHART_PRIO_MDSTAT_DISKS + raid_idx * 10,
452 + update_every,
453 + RRDSET_TYPE_STACKED);
454 +
455 + rrdset_isnot_obsolete(raid->st_disks);
456 + } else
457 + rrdset_next(raid->st_disks);
458 +
459 + if (unlikely(!raid->rd_inuse && !(raid->rd_inuse = rrddim_find_active(raid->st_disks, "inuse"))))
460 + raid->rd_inuse = rrddim_add(raid->st_disks, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
461 + if (unlikely(!raid->rd_down && !(raid->rd_down = rrddim_find_active(raid->st_disks, "down"))))
462 + raid->rd_down = rrddim_add(raid->st_disks, "down", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
463 +
464 + rrddim_set_by_pointer(raid->st_disks, raid->rd_inuse, raid->inuse_disks);
465 + rrddim_set_by_pointer(raid->st_disks, raid->rd_down, raid->failed_disks);
466 +
467 + rrdset_done(raid->st_disks);
468 + }
469 +
470 + // --------------------------------------------------------------------
471 +
472 + if (likely(do_mismatch)) {
473 + snprintfz(id, 50, "%s_mismatch", raid->name);
474 +
475 + if (unlikely(!raid->st_mismatch_cnt && !(raid->st_mismatch_cnt = rrdset_find_active_byname_localhost(id)))) {
476 + snprintfz(family, 50, "%s", raid->name);
477 +
478 + raid->st_mismatch_cnt = rrdset_create_localhost(
479 + "mdstat",
480 + id,
481 + NULL,
482 + family,
483 + "md.mismatch_cnt",
484 + "Mismatch Count",
485 + "unsynchronized blocks",
486 + PLUGIN_PROC_NAME,
487 + PLUGIN_PROC_MODULE_MDSTAT_NAME,
488 + NETDATA_CHART_PRIO_MDSTAT_MISMATCH + raid_idx * 10,
489 + update_every,
490 + RRDSET_TYPE_LINE);
491 +
492 + rrdset_isnot_obsolete(raid->st_mismatch_cnt);
493 + } else
494 + rrdset_next(raid->st_mismatch_cnt);
495 +
496 + if (unlikely(!raid->rd_mismatch_cnt && !(raid->rd_mismatch_cnt = rrddim_find_active(raid->st_mismatch_cnt, "count"))))
497 + raid->rd_mismatch_cnt = rrddim_add(raid->st_mismatch_cnt, "count", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
498 +
499 + rrddim_set_by_pointer(raid->st_mismatch_cnt, raid->rd_mismatch_cnt, raid->mismatch_cnt);
500 +
501 + rrdset_done(raid->st_mismatch_cnt);
502 + }
503 +
504 + // --------------------------------------------------------------------
505 +
506 + if (likely(do_operations)) {
507 + snprintfz(id, 50, "%s_operation", raid->name);
508 +
509 + if (unlikely(!raid->st_operation && !(raid->st_operation = rrdset_find_active_byname_localhost(id)))) {
510 + snprintfz(family, 50, "%s", raid->name);
511 +
512 + raid->st_operation = rrdset_create_localhost(
513 + "mdstat",
514 + id,
515 + NULL,
516 + family,
517 + "md.status",
518 + "Current Status",
519 + "percent",
520 + PLUGIN_PROC_NAME,
521 + PLUGIN_PROC_MODULE_MDSTAT_NAME,
522 + NETDATA_CHART_PRIO_MDSTAT_OPERATION + raid_idx * 10,
523 + update_every,
524 + RRDSET_TYPE_LINE);
525 +
526 + rrdset_isnot_obsolete(raid->st_operation);
527 + } else
528 + rrdset_next(raid->st_operation);
529 +
530 + if(unlikely(!raid->rd_check && !(raid->rd_check = rrddim_find_active(raid->st_operation, "check"))))
531 + raid->rd_check = rrddim_add(raid->st_operation, "check", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE);
532 + if(unlikely(!raid->rd_resync && !(raid->rd_resync = rrddim_find_active(raid->st_operation, "resync"))))
533 + raid->rd_resync = rrddim_add(raid->st_operation, "resync", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE);
534 + if(unlikely(!raid->rd_recovery && !(raid->rd_recovery = rrddim_find_active(raid->st_operation, "recovery"))))
535 + raid->rd_recovery = rrddim_add(raid->st_operation, "recovery", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE);
536 + if(unlikely(!raid->rd_reshape && !(raid->rd_reshape = rrddim_find_active(raid->st_operation, "reshape"))))
537 + raid->rd_reshape = rrddim_add(raid->st_operation, "reshape", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE);
538 +
539 + rrddim_set_by_pointer(raid->st_operation, raid->rd_check, raid->check);
540 + rrddim_set_by_pointer(raid->st_operation, raid->rd_resync, raid->resync);
541 + rrddim_set_by_pointer(raid->st_operation, raid->rd_recovery, raid->recovery);
542 + rrddim_set_by_pointer(raid->st_operation, raid->rd_reshape, raid->reshape);
543 +
544 + rrdset_done(raid->st_operation);
545 +
546 + // --------------------------------------------------------------------
547 +
548 + snprintfz(id, 50, "%s_finish", raid->name);
549 +
550 + if (unlikely(!raid->st_finish && !(raid->st_finish = rrdset_find_active_byname_localhost(id)))) {
551 + snprintfz(family, 50, "%s", raid->name);
552 +
553 + raid->st_finish = rrdset_create_localhost(
554 + "mdstat",
555 + id,
556 + NULL,
557 + family,
558 + "md.rate",
559 + "Approximate Time Unit Finish",
560 + "seconds",
561 + PLUGIN_PROC_NAME,
562 + PLUGIN_PROC_MODULE_MDSTAT_NAME,
563 + NETDATA_CHART_PRIO_MDSTAT_FINISH + raid_idx * 10,
564 + update_every, RRDSET_TYPE_LINE);
565 +
566 + rrdset_isnot_obsolete(raid->st_finish);
567 + } else
568 + rrdset_next(raid->st_finish);
569 +
570 + if(unlikely(!raid->rd_finish_in && !(raid->rd_finish_in = rrddim_find_active(raid->st_finish, "finish_in"))))
571 + raid->rd_finish_in = rrddim_add(raid->st_finish, "finish_in", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
572 +
573 + rrddim_set_by_pointer(raid->st_finish, raid->rd_finish_in, raid->finish_in);
574 +
575 + rrdset_done(raid->st_finish);
576 +
577 + // --------------------------------------------------------------------
578 +
579 + snprintfz(id, 50, "%s_speed", raid->name);
580 +
581 + if (unlikely(!raid->st_speed && !(raid->st_speed = rrdset_find_active_byname_localhost(id)))) {
582 + snprintfz(family, 50, "%s", raid->name);
583 +
584 + raid->st_speed = rrdset_create_localhost(
585 + "mdstat",
586 + id,
587 + NULL,
588 + family,
589 + "md.rate",
590 + "Operation Speed",
591 + "KiB/s",
592 + PLUGIN_PROC_NAME,
593 + PLUGIN_PROC_MODULE_MDSTAT_NAME,
594 + NETDATA_CHART_PRIO_MDSTAT_SPEED + raid_idx * 10,
595 + update_every,
596 + RRDSET_TYPE_LINE);
597 +
598 + rrdset_isnot_obsolete(raid->st_speed);
599 + } else
600 + rrdset_next(raid->st_speed);
601 +
602 + if (unlikely(!raid->rd_speed && !(raid->rd_speed = rrddim_find_active(raid->st_speed, "speed"))))
603 + raid->rd_speed = rrddim_add(raid->st_speed, "speed", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
604 +
605 + rrddim_set_by_pointer(raid->st_speed, raid->rd_speed, raid->speed);
606 +
607 + rrdset_done(raid->st_speed);
608 + }
609 + } else {
610 + // --------------------------------------------------------------------
611 +
612 + if (likely(do_nonredundant)) {
613 + snprintfz(id, 50, "%s_availability", raid->name);
614 +
615 + if (unlikely(!raid->st_nonredundant && !(raid->st_nonredundant = rrdset_find_active_localhost(id)))) {
616 + snprintfz(family, 50, "%s", raid->name);
617 +
618 + raid->st_nonredundant = rrdset_create_localhost(
619 + "mdstat",
620 + id,
621 + NULL,
622 + family,
623 + "md.nonredundant",
624 + "Nonredundant Array Availability",
625 + "boolean",
626 + PLUGIN_PROC_NAME,
627 + PLUGIN_PROC_MODULE_MDSTAT_NAME,
628 + NETDATA_CHART_PRIO_MDSTAT_NONREDUNDANT + raid_idx * 10,
629 + update_every,
630 + RRDSET_TYPE_LINE);
631 +
632 + rrdset_isnot_obsolete(raid->st_nonredundant);
633 + } else
634 + rrdset_next(raid->st_nonredundant);
635 +
636 + if (unlikely(!raid->rd_nonredundant && !(raid->rd_nonredundant = rrddim_find_active(raid->st_nonredundant, "available"))))
637 + raid->rd_nonredundant = rrddim_add(raid->st_nonredundant, "available", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
638 +
639 + rrddim_set_by_pointer(raid->st_nonredundant, raid->rd_nonredundant, 1);
640 +
641 + rrdset_done(raid->st_nonredundant);
642 + }
643 + }
644 + }
645 +
646 + return 0;
647 +}