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
+}