1/*
2 KSysGuard, the KDE System Guard
3
4 Copyright (c) 2007 Greg Martyn <greg.martyn@gmail.com>, John Tapsell <tapsell@kde.org>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of version 2 or later of the GNU General Public
8 License as published by the Free Software Foundation.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18*/
19
20#include "Command.h"
21#include "ksysguardd.h"
22#include "softraid.h"
23
24#include <string.h> /* for strlen, strcat and strcmp */
25#include <stdio.h> /* for sprintf */
26#include <sys/types.h> /* for open */
27#include <sys/stat.h> /* for open */
28#include <fcntl.h> /* for open */
29#include <unistd.h> /* for read, close, exec, fork */
30#include <stdlib.h> /* for exit */
31#include <sys/wait.h> /* for wait :) */
32#include <stdbool.h> /* for bool */
33#include "ccont.h" /* for CONTAINER */
34
35#define MDSTATBUFSIZE (1 * 1024)
36#define MDADMSTATBUFSIZE (2 * 1024)
37#define ARRAYNAMELEN 32
38#define ARRAYNAMELENSTRING "32"
39
40static struct SensorModul* StatSM;
41
42static CONTAINER ArrayInfos = 0;
43char mdstatBuf[ MDSTATBUFSIZE ]; /* Buffer for /proc/mdstat */
44
45typedef struct Disks {
46 char *name; /* e.g. hda1 */
47 char status; /* e.g. F for failed, S for spare. U for fully synced, _ for syncing */
48 int index; /* number in the array */
49 struct Disks *next; /* A pointer to the next disk in this array. NULL if no next */
50} Disks;
51
52typedef struct {
53 bool Alive;
54
55
56 /* from /sbin/mdadm --detail /dev/ArrayName */
57 bool ArraySizeIsAlive;
58 bool ArraySizeIsRegistered;
59 int ArraySizeKB;
60
61 bool UsedDeviceSizeIsAlive;
62 bool UsedDeviceSizeIsRegistered;
63 int UsedDeviceSizeKB;
64
65 bool PreferredMinorIsAlive;
66 bool PreferredMinorIsRegistered;
67 int PreferredMinor;
68
69 /* from /proc/mdstat */
70 char ArrayName[ ARRAYNAMELEN +1];
71 int NumBlocks;
72
73 int NumRaidDevices; /* Number of 'useful' disks. Included working and spare disks, but not failed. */
74
75 int TotalDevices; /* Total number of devices, including failed and spare disks */
76
77 int ActiveDevices; /* Active means it's fully synced, and working, so not a spare or failed */
78
79 int WorkingDevices; /* Working means it's in the raid (not a spare or failed) but it may or may not be fully synced. Active - Working = number being synced */
80
81 int FailedDevices; /* Number of failed devices */
82
83 int SpareDevices; /* Number of spare devices, WE DO NOT Include Failed devices here, unlike mdadm. */
84
85 int devnum; /* Raid array number. e.g. if ArrayName is "md0", then devnum=0 */
86 bool ArrayActive; /* Whether this raid is active */
87 char *level; /* Raid1, Raid2, etc */
88 char *pattern; /* U for up, _ for down */
89 int ResyncingPercent; /* -1 if not resyncing, otherwise between 0 to 100 */
90 bool IsCurrentlyReSyncing; /* True if currently resyncing - */
91 Disks *first_disk; /* A linked list of hard disks */
92} ArrayInfo;
93
94static int ArrayInfoEqual( void* s1, void* s2 )
95{
96 /* Returns 0 if both ArrayInfos have the same name. */
97 return strncmp( ((ArrayInfo*)s1)->ArrayName, ((ArrayInfo*)s2)->ArrayName,ARRAYNAMELEN );
98}
99
100void printArrayAttribute( const char* cmd ) {
101 INDEX idx;
102 ArrayInfo key;
103 ArrayInfo* foundArray;
104 char attribute[40];
105
106 if ( sscanf(cmd, "SoftRaid/%[^/]/%39s", key.ArrayName, attribute) == 2 ) {
107 if ( ( idx = search_ctnr( ArrayInfos, ArrayInfoEqual, &key ) ) == 0 ) {
108 foundArray = get_ctnr( ArrayInfos, idx );
109
110 if ( strcmp( attribute, "NumBlocks" ) == 0 )
111 output( "%d\n", foundArray->NumBlocks );
112 else if ( strcmp( attribute, "ArraySizeKB" ) == 0 )
113 output( "%d\n", foundArray->ArraySizeKB );
114 else if ( strcmp( attribute, "UsedDeviceSizeKB" ) == 0 )
115 output( "%d\n", foundArray->UsedDeviceSizeKB );
116 else if ( strcmp( attribute, "NumRaidDevices" ) == 0 )
117 output( "%d\n", foundArray->NumRaidDevices );
118 else if ( strcmp( attribute, "TotalDevices" ) == 0 )
119 output( "%d\n", foundArray->TotalDevices );
120 else if ( strcmp( attribute, "PreferredMinor" ) == 0 )
121 output( "%d\n", foundArray->PreferredMinor );
122 else if ( strcmp( attribute, "ActiveDevices" ) == 0 )
123 output( "%d\n", foundArray->ActiveDevices );
124 else if ( strcmp( attribute, "WorkingDevices" ) == 0 )
125 output( "%d\n", foundArray->WorkingDevices );
126 else if ( strcmp( attribute, "FailedDevices" ) == 0 )
127 output( "%d\n", foundArray->FailedDevices );
128 else if ( strcmp( attribute, "SpareDevices" ) == 0 )
129 output( "%d\n", foundArray->SpareDevices );
130 else if( strcmp( attribute, "DeviceNumber" ) == 0 )
131 output( "%d\n", foundArray->devnum);
132 else if( strcmp( attribute, "ResyncingPercent" ) == 0 )
133 output( "%d\n", foundArray->ResyncingPercent);
134 else if( strcmp( attribute, "RaidType" ) == 0 )
135 output( "%s\n", foundArray->level);
136 else if( strcmp( attribute, "DiskInfo" ) == 0 ) {
137 Disks *disk = foundArray->first_disk;
138 while(disk) {
139 output( "%s\t%d\t%c\n", disk->name, disk->index, disk->status);
140 disk = disk->next;
141 }
142 output( "\n");
143 }
144 }
145 else {
146 output( "\n");
147 }
148 } else {
149 output( "\n");
150 }
151
152
153}
154
155void printArrayAttributeInfo( const char* cmd ) {
156 INDEX idx;
157 ArrayInfo key;
158 ArrayInfo* foundArray;
159 char attribute[40];
160
161 if ( sscanf(cmd, "SoftRaid/%[^/]/%39s", key.ArrayName, attribute) == 2 ) {
162 if ( ( idx = search_ctnr( ArrayInfos, ArrayInfoEqual, &key ) ) == 0 ) {
163 foundArray = get_ctnr( ArrayInfos, idx );
164
165 if ( strcmp( attribute, "NumBlocks?" ) == 0 )
166 output( "Num blocks\t0\t0\t\n" );
167 else if ( strcmp( attribute, "ArraySizeKB?" ) == 0 )
168 output( "Array size\t0\t0\tKB\n" );
169 else if ( strcmp( attribute, "UsedDeviceSizeKB?" ) == 0 )
170 output( "Used Device Size\t0\t0\tKB\n" );
171 else if ( strcmp( attribute, "NumRaidDevices?" ) == 0 )
172 output( "Total number of raid devices\t0\t0\t\n" );
173 else if ( strcmp( attribute, "TotalDevices?" ) == 0 )
174 output( "Total number of devices\t0\t0\t\n" );
175 else if ( strcmp( attribute, "PreferredMinor?" ) == 0 )
176 output( "The preferred minor\t0\t0\t\n" );
177 else if ( strcmp( attribute, "ActiveDevices?" ) == 0 )
178 output( "Number of active devices\t0\t%d\t\n", foundArray->TotalDevices );
179 else if ( strcmp( attribute, "WorkingDevices?" ) == 0 )
180 output( "Number of working devices\t0\t%d\t\n", foundArray->TotalDevices );
181 else if ( strcmp( attribute, "FailedDevices?" ) == 0 )
182 output( "Number of failed devices\t0\t%d\t\n", foundArray->TotalDevices );
183 else if ( strcmp( attribute, "SpareDevices?" ) == 0 )
184 output( "Number of spare devices\t0\t%d\t\n", foundArray->TotalDevices );
185 else if( strcmp( attribute, "DeviceNumber?" ) == 0 )
186 output( "Raid Device Number\t0\t0\t\n");
187 else if( strcmp( attribute, "ResyncingPercent?" ) == 0 )
188 output( "Resyncing Percentage Done. -1 if not resyncing\t-1\t100\t%%\n");
189 else if( strcmp( attribute, "RaidType?" ) == 0 )
190 output( "Type of RAID array\n");
191 else if( strcmp( attribute, "DiskInfo?") == 0 )
192 output( "Disk Name\tIndex\tStatus\ns\td\tS\n");
193 }
194 else {
195 output( "\n");
196 }
197 } else {
198 output( "\n");
199 }
200}
201
202
203
204void getMdadmDetail( ArrayInfo* MyArray ) {
205 int fd[2];
206 pid_t ChildPID;
207 ssize_t nbytes;
208
209 char sensorName[128];
210 char arrayDevice[ARRAYNAMELEN + 5];
211 char format[ 32 ];
212 char lineBuf[ 1024 ];
213 char mdadmStatBuf[ MDADMSTATBUFSIZE ]; /* Buffer for mdadm --detail */
214 char* mdadmStatBufP;
215
216 /* Create a pipe */
217 if(pipe(fd) == -1)
218 {
219 perror("Could not create a pipe to launch mdadm.");
220 exit(1);
221 }
222
223 /* Fork */
224 if((ChildPID = fork()) == -1)
225 {
226 perror("Could not fork to launch mdadm.");
227 exit(1);
228 }
229
230 /* Child will execute the program, parent will listen. */
231
232 if (ChildPID == 0) {
233 /* Child process */
234
235 /* Child will execute the program, parent will listen. */
236 /* Close stdout, duplicate the input side of pipe to stdout */
237 dup2(fd[1], 1);
238 /* Close output side of pipe */
239 close(fd[0]);
240 close(2);
241
242 snprintf( arrayDevice, sizeof( arrayDevice ), "/dev/%s", MyArray->ArrayName );
243 execl ("/sbin/mdadm", "mdadm", "--detail", arrayDevice, (char *)0);
244 exit(0); /* In case /sbin/mdadm isn't found */
245 /* Child is now dead, as per our request */
246 }
247
248 /* Parent process */
249
250 /* Close input side of pipe */
251 close(fd[1]);
252
253 waitpid( ChildPID, 0, 0);
254
255 /* Fill mdadmStatBuf with pipe's output */
256 nbytes = read( fd[0], mdadmStatBuf, MDADMSTATBUFSIZE-1 );
257 if (nbytes >= 0)
258 mdadmStatBuf[nbytes] = '\0';
259
260 /* Now, go through mdadmStatBuf line by line. Register monitors along the way */
261 sprintf( format, "%%%d[^\n]\n", (int)sizeof( lineBuf ) - 1 );
262 mdadmStatBufP = mdadmStatBuf;
263 while (sscanf(mdadmStatBufP, format, lineBuf) != EOF) {
264 lineBuf[sizeof(lineBuf) - 1] = '\0';
265 mdadmStatBufP += strlen(lineBuf) + 1; /* move mdadmStatBufP to next line */
266
267 if ( sscanf(lineBuf, " Array Size : %d", &MyArray->ArraySizeKB) == 1 ) {
268 MyArray->ArraySizeIsAlive = true;
269 if ( !MyArray->ArraySizeIsRegistered ) {
270 sprintf(sensorName, "SoftRaid/%s/ArraySizeKB", MyArray->ArrayName);
271 registerMonitor(sensorName, "integer", printArrayAttribute, printArrayAttributeInfo, StatSM );
272
273 MyArray->ArraySizeIsRegistered = true;
274 }
275 }
276
277 /* Versions of mdadm prior to 2.6 used "Device Size" instead of "Used Dev Size"
278 */
279 else if ( ( sscanf(lineBuf, " Device Size : %d", &MyArray->UsedDeviceSizeKB) == 1 ) ||
280 ( sscanf(lineBuf, " Used Dev Size : %d", &MyArray->UsedDeviceSizeKB) == 1 ) ) {
281 MyArray->UsedDeviceSizeIsAlive = true;
282 if ( !MyArray->UsedDeviceSizeIsRegistered ) {
283 sprintf(sensorName, "SoftRaid/%s/UsedDeviceSizeKB", MyArray->ArrayName);
284 registerMonitor(sensorName, "integer", printArrayAttribute, printArrayAttributeInfo, StatSM );
285 MyArray->UsedDeviceSizeIsRegistered = true;
286 }
287 }
288
289 else if ( sscanf(lineBuf, "Preferred Minor : %d", &MyArray->PreferredMinor) == 1 ) {
290 MyArray->PreferredMinorIsAlive = true;
291 if ( !MyArray->PreferredMinorIsRegistered ) {
292 sprintf(sensorName, "SoftRaid/%s/PreferredMinor", MyArray->ArrayName);
293 registerMonitor(sensorName, "integer", printArrayAttribute, printArrayAttributeInfo, StatSM );
294 MyArray->PreferredMinorIsRegistered = true;
295 }
296 }
297 }
298
299 /* Note: Don't test NumBlocksIsAlive, because it hasn't been set yet */
300 if ( (!MyArray->ArraySizeIsAlive && MyArray->ArraySizeIsRegistered ) ||
301 (!MyArray->UsedDeviceSizeIsAlive && MyArray->UsedDeviceSizeIsRegistered ) ||
302 (!MyArray->PreferredMinorIsAlive && MyArray->PreferredMinorIsRegistered )
303 ) {
304 print_error( "RECONFIGURE" );
305 log_error( "Soft raid device disappeared" );
306 return;
307 }
308}
309
310void openMdstatFile() {
311 ssize_t n;
312 int fd;
313
314 mdstatBuf[ 0 ] = '\0';
315 if ( ( fd = open( "/proc/mdstat", O_RDONLY ) ) < 0 )
316 return; /* couldn't open /proc/mdstat */
317
318 n = read( fd, mdstatBuf, MDSTATBUFSIZE - 1 );
319 close( fd );
320
321 if ( n == MDSTATBUFSIZE - 1 || n <= 0 ) {
322 log_error( "Internal buffer too small to read \'/proc/mdstat\'" );
323
324 return;
325 }
326
327 mdstatBuf[ n ] = '\0';
328}
329
330ArrayInfo *getOrCreateArrayInfo(char *array_name, int array_name_length) {
331 ArrayInfo key;
332 INDEX idx;
333 ArrayInfo* MyArray;
334 /*We have the array name. see if we already have a record for it*/
335 strncpy(key.ArrayName, array_name, array_name_length);
336 key.ArrayName[array_name_length]='\0';
337 if ( ( idx = search_ctnr( ArrayInfos, ArrayInfoEqual, &key ) ) == 0 ) {
338 /* Found an existing array device */
339 MyArray = get_ctnr( ArrayInfos, idx );
340 }
341 else {
342 /* Found a new array device. Create a data structure for it. */
343 MyArray = calloc(1,sizeof (ArrayInfo));
344 if (MyArray == NULL) {
345 /* Memory could not be allocated, so print an error and exit. */
346 fprintf(stderr, "Could not allocate memory\n");
347 exit(EXIT_FAILURE);
348 }
349 strcpy( MyArray->ArrayName, key.ArrayName );
350 /* Add this array to our list of array devices */
351 push_ctnr(ArrayInfos, MyArray);
352 char sensorName[128];
353 sprintf(sensorName, "SoftRaid/%s/NumBlocks", MyArray->ArrayName);
354 registerMonitor(sensorName, "integer", printArrayAttribute, printArrayAttributeInfo, StatSM );
355
356 sprintf(sensorName, "SoftRaid/%s/TotalDevices", MyArray->ArrayName);
357 registerMonitor(sensorName, "integer", printArrayAttribute, printArrayAttributeInfo, StatSM );
358
359 sprintf(sensorName, "SoftRaid/%s/FailedDevices", MyArray->ArrayName);
360 registerMonitor(sensorName, "integer", printArrayAttribute, printArrayAttributeInfo, StatSM );
361
362 sprintf(sensorName, "SoftRaid/%s/SpareDevices", MyArray->ArrayName);
363 registerMonitor(sensorName, "integer", printArrayAttribute, printArrayAttributeInfo, StatSM );
364
365 sprintf(sensorName, "SoftRaid/%s/NumRaidDevices", MyArray->ArrayName);
366 registerMonitor(sensorName, "integer", printArrayAttribute, printArrayAttributeInfo, StatSM );
367
368 sprintf(sensorName, "SoftRaid/%s/WorkingDevices", MyArray->ArrayName);
369 registerMonitor(sensorName, "integer", printArrayAttribute, printArrayAttributeInfo, StatSM );
370
371 sprintf(sensorName, "SoftRaid/%s/ActiveDevices", MyArray->ArrayName);
372 registerMonitor(sensorName, "integer", printArrayAttribute, printArrayAttributeInfo, StatSM );
373
374 sprintf(sensorName, "SoftRaid/%s/RaidType", MyArray->ArrayName);
375 registerMonitor(sensorName, "string", printArrayAttribute, printArrayAttributeInfo, StatSM );
376
377 sprintf(sensorName, "SoftRaid/%s/DeviceNumber", MyArray->ArrayName);
378 registerMonitor(sensorName, "integer", printArrayAttribute, printArrayAttributeInfo, StatSM );
379
380 sprintf(sensorName, "SoftRaid/%s/ResyncingPercent", MyArray->ArrayName);
381 registerMonitor(sensorName, "integer", printArrayAttribute, printArrayAttributeInfo, StatSM );
382
383 sprintf(sensorName, "SoftRaid/%s/DiskInfo", MyArray->ArrayName);
384 registerMonitor(sensorName, "listview", printArrayAttribute, printArrayAttributeInfo, StatSM );
385
386 }
387 return MyArray;
388}
389
390bool scanForArrays() {
391 char* mdstatBufP;
392 char* current_word;
393 int current_word_length = 0;
394
395 ArrayInfo* MyArray;
396
397 /* Mark all data as dead. As we find data, we'll mark it alive. */
398 for ( MyArray = first_ctnr( ArrayInfos ); MyArray; MyArray = next_ctnr( ArrayInfos ) ) {
399 MyArray->Alive = false;
400 }
401 MyArray = NULL;
402
403 openMdstatFile();
404
405 current_word = mdstatBufP = mdstatBuf;
406
407 /* Process values from /proc/mdstat */
408
409 bool start = true;
410 while(mdstatBufP[0] != '\0') {
411
412 if(!start) {
413 /*advanced one line at a time*/
414 while( mdstatBufP[0] != '\0' && mdstatBufP[0] != '\n') mdstatBufP++;
415 mdstatBufP++;
416 }
417 start = false;
418
419 if( mdstatBufP[0] == '\0') break;
420 current_word_length = 0;
421 current_word = mdstatBufP;
422
423
424 if(mdstatBufP[0]=='\n')
425 continue;
426
427 if(mdstatBufP[0]=='#') /*skip comments */
428 continue;
429 if (strncmp(current_word, "Personalities", sizeof("Personalities")-1)==0)
430 continue;
431 if (strncmp(current_word, "read_ahead", sizeof("read_ahead")-1)==0)
432 continue;
433 if (strncmp(current_word, "unused", sizeof("unused")-1)==0)
434 continue;
435 /* Better be an md line.. */
436 if (strncmp(current_word, "md", 2)!= 0)
437 continue;
438 int devnum;
439 if (strncmp(current_word, "md_d", 4) == 0)
440 devnum = -1-strtoul(current_word+4, NULL, 10);
441 else /* it's md0 etc */
442 devnum = strtoul(current_word+2, NULL, 10);
443 while( mdstatBufP[0] != '\0' &&mdstatBufP[0] != '\n' && mdstatBufP[0] != ' ' && mdstatBufP[0] != '\t') {
444 /*find the end of the word*/
445 mdstatBufP++;
446 current_word_length++;
447 }
448
449 MyArray = getOrCreateArrayInfo(current_word, current_word_length);
450 MyArray->Alive = true;
451 getMdadmDetail ( MyArray );
452 MyArray->level = MyArray->pattern= NULL;
453 MyArray->ResyncingPercent = -1;
454 MyArray->IsCurrentlyReSyncing = false;
455 MyArray->devnum = devnum;
456 MyArray->ArrayActive = false;
457 MyArray->TotalDevices = MyArray->SpareDevices = MyArray->FailedDevices = 0;
458 MyArray->NumBlocks = 0;
459
460 Disks *disk = MyArray->first_disk;
461 MyArray->first_disk = NULL;
462 Disks *next;
463 while(disk) {
464 next = disk->next;
465 free(disk);
466 disk = next;
467 }
468
469
470 /* In mdstat, we have something that looks like:
471
472md0 : active raid1 sda1[0] sdb1[1]
473 312568576 blocks [2/2] [UU]
474md1 : active raid1 sda2[0] sdb2[1]
475 452568576 blocks [2/2] [UU]
476
477 We have so far read in the "md0" bit, and now want to continue reading the details for this raid group until
478 we reach the next raid group which we note as starting with a non whitespace.
479 */
480 char buffer[100];
481 char status[100];
482 status[0] = 0;
483 int harddisk_index;
484 for(;;) {
485
486 while( mdstatBufP[0] != '\0' && ( (mdstatBufP[0] == '\n' && (mdstatBufP[1] == ' ' || mdstatBufP[1] == '\t')) || mdstatBufP[0] == ' ' || mdstatBufP[0] == '\t')) {
487 mdstatBufP++; /*Remove any whitespace first*/
488 }
489 if( mdstatBufP[0] == '\0' || mdstatBufP[0] == '\n') {
490 break; /*we are now at the end of the file or line. Break this for loop*/
491 }
492
493 current_word=mdstatBufP; /*we are now pointing to the first non-whitespace of a word*/
494 current_word_length=0;
495 while( mdstatBufP[0] != '\0' && mdstatBufP[0] != '\n' && mdstatBufP[0] != ' ' && mdstatBufP[0] != '\t') {
496 /*find the end of the word. We do this now so that we know the length of the word*/
497 mdstatBufP++;
498 current_word_length++;
499 }
500
501 char *eq;
502 int in_devs = 0;
503 int temp_int =0;
504
505
506 if (strncmp(current_word, "active", sizeof("active")-1)==0)
507 MyArray->ArrayActive = true;
508 else if (strncmp(current_word, "inactive", sizeof("inactive")-1)==0)
509 MyArray->ArrayActive = false;
510 else if (MyArray->ArrayActive >=0 && MyArray->level == NULL && current_word[0] != '(' && current_word[0] != ':' /*readonly*/) {
511 MyArray->level = strndup(current_word, current_word_length);
512 in_devs = 1;
513
514 } else if (sscanf(current_word, "%d blocks ", &temp_int) == 1 ) {
515 MyArray->NumBlocks = temp_int; /* We have to do it via a temp_int variable otherwise we'll end up with nonsence if it's not found */
516 } else if (in_devs && strncmp(current_word, "blocks", sizeof("blocks")-1)==0)
517 in_devs = 0;
518#ifdef __GNUC__
519#warning in_devs cannot be != 0!! (CID 3228)
520#endif
521 else if (in_devs && strncmp(current_word, "md", 2)==0) {
522 /* This has an md device as a component. Maybe we should note this or something*/
523 } else if(sscanf(current_word, "%[^[ ][%d]%[^ ]", buffer, &harddisk_index, status) >= 2) {
524 /*Each device in the raid has an index. We can find the total number of devices in the raid by
525 simply finding the device with the highest index + 1. */
526 if(harddisk_index >= MyArray->TotalDevices) MyArray->TotalDevices = harddisk_index+1;
527 Disks *new_disk = malloc(sizeof(Disks));
528 new_disk->name = strdup(buffer);
529 new_disk->index = harddisk_index;
530
531
532 if(status[0] == '(') {
533 new_disk->status = status[1];
534 if(status[1] == 'S') /*Spare hard disk*/
535 MyArray->SpareDevices++;
536 else if(status[1] == 'F')
537 MyArray->FailedDevices++;
538 } else
539 new_disk->status = 'U';
540
541 /* insert the new disk into the linked list of disks*/
542 new_disk->next = MyArray->first_disk;
543 MyArray->first_disk = new_disk;
544
545 MyArray->NumRaidDevices = MyArray->TotalDevices - MyArray->FailedDevices;
546 status[0]=0; /*make sure we zero it again for next time*/
547 } else if (!MyArray->pattern &&
548 current_word[0] == '[' &&
549 (current_word[1] == 'U' || current_word[1] == '_')) {
550 MyArray->pattern = strndup(current_word+1, current_word_length-1);
551
552 if (MyArray->pattern[current_word_length-2]==']')
553 MyArray->pattern[current_word_length-2] = '\0';
554 MyArray->ActiveDevices = MyArray->TotalDevices - MyArray->SpareDevices - MyArray->FailedDevices;
555
556 MyArray->WorkingDevices=0;
557 int index=0;
558 for(;;) {
559 current_word++;
560
561 if(current_word[0] == 'U')
562 MyArray->WorkingDevices++;
563 else if(current_word[0] == '_') {
564 Disks *disk = MyArray->first_disk;
565 while(disk) {
566 if(disk->index == index) {
567 if(disk->status == 'U')
568 disk->status = '_'; /* The disk hasn't failed, but is syncing */
569 break;
570 }
571 disk = disk->next;
572 }
573 } else
574 break;
575 index++;
576 }
577 } else if (MyArray->ResyncingPercent == -1 &&
578 strncmp(current_word, "re", 2)== 0 &&
579 current_word[current_word_length-1] == '%' &&
580 (eq=strchr(current_word, '=')) != NULL ) {
581 MyArray->ResyncingPercent = atoi(eq+1);
582 if (strncmp(current_word,"resync", 4)==0)
583 MyArray->IsCurrentlyReSyncing = true;
584 } else if (MyArray->ResyncingPercent == -1 &&
585 strncmp(current_word, "resync", 4)==0) {
586 MyArray->IsCurrentlyReSyncing = true;
587 } else if (MyArray->ResyncingPercent == -1 &&
588 current_word[0] >= '0' &&
589 current_word[0] <= '9' &&
590 current_word[current_word_length-1] == '%') {
591 MyArray->ResyncingPercent = atoi(current_word);
592 }
593 /*ignore anything not understood*/
594 }
595 }
596
597 /* Look for dead arrays, and for NumBlocksIsRegistered */
598 for ( MyArray = first_ctnr( ArrayInfos ); MyArray; MyArray = next_ctnr( ArrayInfos ) ) {
599 if ( MyArray->Alive == false ) {
600 print_error( "RECONFIGURE" );
601
602 log_error( "Soft raid device disappeared" );
603 return false;
604 }
605 }
606 return true;
607}
608
609/* =========== Public part =========== */
610
611void initSoftRaid( struct SensorModul* sm ) {
612 StatSM = sm;
613
614 ArrayInfos = new_ctnr();
615 updateSoftRaid();
616}
617
618void exitSoftRaid( void ) {
619 destr_ctnr( ArrayInfos, free );
620}
621
622int updateSoftRaid( void ) {
623 scanForArrays();
624 return 0;
625}
626