2014-11-13 19:30:51 +02:00
/*
KSysGuard , the KDE System Guard
Copyright ( c ) 2007 Greg Martyn < greg . martyn @ gmail . com > , John Tapsell < tapsell @ kde . org >
This program is free software ; you can redistribute it and / or
modify it under the terms of version 2 or later of the GNU General Public
License as published by the Free Software Foundation .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
# include "Command.h"
# include "ksysguardd.h"
# include "softraid.h"
# include <string.h> /* for strlen, strcat and strcmp */
# include <stdio.h> /* for sprintf */
# include <sys/types.h> /* for open */
# include <sys/stat.h> /* for open */
# include <fcntl.h> /* for open */
# include <unistd.h> /* for read, close, exec, fork */
# include <stdlib.h> /* for exit */
# include <sys/wait.h> /* for wait :) */
# include <stdbool.h> /* for bool */
# include "ccont.h" /* for CONTAINER */
# define MDSTATBUFSIZE (1 * 1024)
# define MDADMSTATBUFSIZE (2 * 1024)
# define ARRAYNAMELEN 32
# define ARRAYNAMELENSTRING "32"
static struct SensorModul * StatSM ;
static CONTAINER ArrayInfos = 0 ;
char mdstatBuf [ MDSTATBUFSIZE ] ; /* Buffer for /proc/mdstat */
typedef struct Disks {
char * name ; /* e.g. hda1 */
char status ; /* e.g. F for failed, S for spare. U for fully synced, _ for syncing */
int index ; /* number in the array */
struct Disks * next ; /* A pointer to the next disk in this array. NULL if no next */
} Disks ;
typedef struct {
bool Alive ;
/* from /sbin/mdadm --detail /dev/ArrayName */
bool ArraySizeIsAlive ;
bool ArraySizeIsRegistered ;
int ArraySizeKB ;
bool UsedDeviceSizeIsAlive ;
bool UsedDeviceSizeIsRegistered ;
int UsedDeviceSizeKB ;
bool PreferredMinorIsAlive ;
bool PreferredMinorIsRegistered ;
int PreferredMinor ;
/* from /proc/mdstat */
char ArrayName [ ARRAYNAMELEN + 1 ] ;
int NumBlocks ;
int NumRaidDevices ; /* Number of 'useful' disks. Included working and spare disks, but not failed. */
int TotalDevices ; /* Total number of devices, including failed and spare disks */
int ActiveDevices ; /* Active means it's fully synced, and working, so not a spare or failed */
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 */
int FailedDevices ; /* Number of failed devices */
int SpareDevices ; /* Number of spare devices, WE DO NOT Include Failed devices here, unlike mdadm. */
int devnum ; /* Raid array number. e.g. if ArrayName is "md0", then devnum=0 */
bool ArrayActive ; /* Whether this raid is active */
char * level ; /* Raid1, Raid2, etc */
char * pattern ; /* U for up, _ for down */
int ResyncingPercent ; /* -1 if not resyncing, otherwise between 0 to 100 */
bool IsCurrentlyReSyncing ; /* True if currently resyncing - */
Disks * first_disk ; /* A linked list of hard disks */
} ArrayInfo ;
static int ArrayInfoEqual ( void * s1 , void * s2 )
{
/* Returns 0 if both ArrayInfos have the same name. */
return strncmp ( ( ( ArrayInfo * ) s1 ) - > ArrayName , ( ( ArrayInfo * ) s2 ) - > ArrayName , ARRAYNAMELEN ) ;
}
void printArrayAttribute ( const char * cmd ) {
INDEX idx ;
ArrayInfo key ;
ArrayInfo * foundArray ;
char attribute [ 40 ] ;
if ( sscanf ( cmd , " SoftRaid/%[^/]/%39s " , key . ArrayName , attribute ) = = 2 ) {
if ( ( idx = search_ctnr ( ArrayInfos , ArrayInfoEqual , & key ) ) = = 0 ) {
foundArray = get_ctnr ( ArrayInfos , idx ) ;
if ( strcmp ( attribute , " NumBlocks " ) = = 0 )
output ( " %d \n " , foundArray - > NumBlocks ) ;
else if ( strcmp ( attribute , " ArraySizeKB " ) = = 0 )
output ( " %d \n " , foundArray - > ArraySizeKB ) ;
else if ( strcmp ( attribute , " UsedDeviceSizeKB " ) = = 0 )
output ( " %d \n " , foundArray - > UsedDeviceSizeKB ) ;
else if ( strcmp ( attribute , " NumRaidDevices " ) = = 0 )
output ( " %d \n " , foundArray - > NumRaidDevices ) ;
else if ( strcmp ( attribute , " TotalDevices " ) = = 0 )
output ( " %d \n " , foundArray - > TotalDevices ) ;
else if ( strcmp ( attribute , " PreferredMinor " ) = = 0 )
output ( " %d \n " , foundArray - > PreferredMinor ) ;
else if ( strcmp ( attribute , " ActiveDevices " ) = = 0 )
output ( " %d \n " , foundArray - > ActiveDevices ) ;
else if ( strcmp ( attribute , " WorkingDevices " ) = = 0 )
output ( " %d \n " , foundArray - > WorkingDevices ) ;
else if ( strcmp ( attribute , " FailedDevices " ) = = 0 )
output ( " %d \n " , foundArray - > FailedDevices ) ;
else if ( strcmp ( attribute , " SpareDevices " ) = = 0 )
output ( " %d \n " , foundArray - > SpareDevices ) ;
else if ( strcmp ( attribute , " DeviceNumber " ) = = 0 )
output ( " %d \n " , foundArray - > devnum ) ;
else if ( strcmp ( attribute , " ResyncingPercent " ) = = 0 )
output ( " %d \n " , foundArray - > ResyncingPercent ) ;
else if ( strcmp ( attribute , " RaidType " ) = = 0 )
output ( " %s \n " , foundArray - > level ) ;
else if ( strcmp ( attribute , " DiskInfo " ) = = 0 ) {
Disks * disk = foundArray - > first_disk ;
while ( disk ) {
output ( " %s \t %d \t %c \n " , disk - > name , disk - > index , disk - > status ) ;
disk = disk - > next ;
}
output ( " \n " ) ;
}
}
else {
output ( " \n " ) ;
}
} else {
output ( " \n " ) ;
}
}
void printArrayAttributeInfo ( const char * cmd ) {
INDEX idx ;
ArrayInfo key ;
ArrayInfo * foundArray ;
char attribute [ 40 ] ;
if ( sscanf ( cmd , " SoftRaid/%[^/]/%39s " , key . ArrayName , attribute ) = = 2 ) {
if ( ( idx = search_ctnr ( ArrayInfos , ArrayInfoEqual , & key ) ) = = 0 ) {
foundArray = get_ctnr ( ArrayInfos , idx ) ;
if ( strcmp ( attribute , " NumBlocks? " ) = = 0 )
output ( " Num blocks \t 0 \t 0 \t \n " ) ;
else if ( strcmp ( attribute , " ArraySizeKB? " ) = = 0 )
output ( " Array size \t 0 \t 0 \t KB \n " ) ;
else if ( strcmp ( attribute , " UsedDeviceSizeKB? " ) = = 0 )
output ( " Used Device Size \t 0 \t 0 \t KB \n " ) ;
else if ( strcmp ( attribute , " NumRaidDevices? " ) = = 0 )
output ( " Total number of raid devices \t 0 \t 0 \t \n " ) ;
else if ( strcmp ( attribute , " TotalDevices? " ) = = 0 )
output ( " Total number of devices \t 0 \t 0 \t \n " ) ;
else if ( strcmp ( attribute , " PreferredMinor? " ) = = 0 )
output ( " The preferred minor \t 0 \t 0 \t \n " ) ;
else if ( strcmp ( attribute , " ActiveDevices? " ) = = 0 )
output ( " Number of active devices \t 0 \t %d \t \n " , foundArray - > TotalDevices ) ;
else if ( strcmp ( attribute , " WorkingDevices? " ) = = 0 )
output ( " Number of working devices \t 0 \t %d \t \n " , foundArray - > TotalDevices ) ;
else if ( strcmp ( attribute , " FailedDevices? " ) = = 0 )
output ( " Number of failed devices \t 0 \t %d \t \n " , foundArray - > TotalDevices ) ;
else if ( strcmp ( attribute , " SpareDevices? " ) = = 0 )
output ( " Number of spare devices \t 0 \t %d \t \n " , foundArray - > TotalDevices ) ;
else if ( strcmp ( attribute , " DeviceNumber? " ) = = 0 )
output ( " Raid Device Number \t 0 \t 0 \t \n " ) ;
else if ( strcmp ( attribute , " ResyncingPercent? " ) = = 0 )
output ( " Resyncing Percentage Done. -1 if not resyncing \t -1 \t 100 \t %% \n " ) ;
else if ( strcmp ( attribute , " RaidType? " ) = = 0 )
output ( " Type of RAID array \n " ) ;
else if ( strcmp ( attribute , " DiskInfo? " ) = = 0 )
output ( " Disk Name \t Index \t Status \n s \t d \t S \n " ) ;
}
else {
output ( " \n " ) ;
}
} else {
output ( " \n " ) ;
}
}
void getMdadmDetail ( ArrayInfo * MyArray ) {
int fd [ 2 ] ;
pid_t ChildPID ;
ssize_t nbytes ;
char sensorName [ 128 ] ;
2019-05-08 14:52:16 +00:00
char arrayDevice [ ARRAYNAMELEN + 5 + 1 ] ;
2014-11-13 19:30:51 +02:00
char format [ 32 ] ;
char lineBuf [ 1024 ] ;
char mdadmStatBuf [ MDADMSTATBUFSIZE ] ; /* Buffer for mdadm --detail */
char * mdadmStatBufP ;
/* Create a pipe */
if ( pipe ( fd ) = = - 1 )
{
perror ( " Could not create a pipe to launch mdadm. " ) ;
exit ( 1 ) ;
}
/* Fork */
if ( ( ChildPID = fork ( ) ) = = - 1 )
{
perror ( " Could not fork to launch mdadm. " ) ;
exit ( 1 ) ;
}
/* Child will execute the program, parent will listen. */
if ( ChildPID = = 0 ) {
/* Child process */
/* Child will execute the program, parent will listen. */
/* Close stdout, duplicate the input side of pipe to stdout */
dup2 ( fd [ 1 ] , 1 ) ;
/* Close output side of pipe */
close ( fd [ 0 ] ) ;
close ( 2 ) ;
snprintf ( arrayDevice , sizeof ( arrayDevice ) , " /dev/%s " , MyArray - > ArrayName ) ;
execl ( " /sbin/mdadm " , " mdadm " , " --detail " , arrayDevice , ( char * ) 0 ) ;
exit ( 0 ) ; /* In case /sbin/mdadm isn't found */
/* Child is now dead, as per our request */
}
/* Parent process */
/* Close input side of pipe */
close ( fd [ 1 ] ) ;
waitpid ( ChildPID , 0 , 0 ) ;
/* Fill mdadmStatBuf with pipe's output */
nbytes = read ( fd [ 0 ] , mdadmStatBuf , MDADMSTATBUFSIZE - 1 ) ;
if ( nbytes > = 0 )
mdadmStatBuf [ nbytes ] = ' \0 ' ;
/* Now, go through mdadmStatBuf line by line. Register monitors along the way */
sprintf ( format , " %%%d[^ \n ] \n " , ( int ) sizeof ( lineBuf ) - 1 ) ;
mdadmStatBufP = mdadmStatBuf ;
while ( sscanf ( mdadmStatBufP , format , lineBuf ) ! = EOF ) {
lineBuf [ sizeof ( lineBuf ) - 1 ] = ' \0 ' ;
mdadmStatBufP + = strlen ( lineBuf ) + 1 ; /* move mdadmStatBufP to next line */
if ( sscanf ( lineBuf , " Array Size : %d " , & MyArray - > ArraySizeKB ) = = 1 ) {
MyArray - > ArraySizeIsAlive = true ;
if ( ! MyArray - > ArraySizeIsRegistered ) {
sprintf ( sensorName , " SoftRaid/%s/ArraySizeKB " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " integer " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
MyArray - > ArraySizeIsRegistered = true ;
}
}
/* Versions of mdadm prior to 2.6 used "Device Size" instead of "Used Dev Size"
*/
else if ( ( sscanf ( lineBuf , " Device Size : %d " , & MyArray - > UsedDeviceSizeKB ) = = 1 ) | |
( sscanf ( lineBuf , " Used Dev Size : %d " , & MyArray - > UsedDeviceSizeKB ) = = 1 ) ) {
MyArray - > UsedDeviceSizeIsAlive = true ;
if ( ! MyArray - > UsedDeviceSizeIsRegistered ) {
sprintf ( sensorName , " SoftRaid/%s/UsedDeviceSizeKB " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " integer " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
MyArray - > UsedDeviceSizeIsRegistered = true ;
}
}
else if ( sscanf ( lineBuf , " Preferred Minor : %d " , & MyArray - > PreferredMinor ) = = 1 ) {
MyArray - > PreferredMinorIsAlive = true ;
if ( ! MyArray - > PreferredMinorIsRegistered ) {
sprintf ( sensorName , " SoftRaid/%s/PreferredMinor " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " integer " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
MyArray - > PreferredMinorIsRegistered = true ;
}
}
}
/* Note: Don't test NumBlocksIsAlive, because it hasn't been set yet */
if ( ( ! MyArray - > ArraySizeIsAlive & & MyArray - > ArraySizeIsRegistered ) | |
( ! MyArray - > UsedDeviceSizeIsAlive & & MyArray - > UsedDeviceSizeIsRegistered ) | |
( ! MyArray - > PreferredMinorIsAlive & & MyArray - > PreferredMinorIsRegistered )
) {
print_error ( " RECONFIGURE " ) ;
log_error ( " Soft raid device disappeared " ) ;
return ;
}
}
void openMdstatFile ( ) {
ssize_t n ;
int fd ;
mdstatBuf [ 0 ] = ' \0 ' ;
if ( ( fd = open ( " /proc/mdstat " , O_RDONLY ) ) < 0 )
return ; /* couldn't open /proc/mdstat */
n = read ( fd , mdstatBuf , MDSTATBUFSIZE - 1 ) ;
close ( fd ) ;
if ( n = = MDSTATBUFSIZE - 1 | | n < = 0 ) {
log_error ( " Internal buffer too small to read \' /proc/mdstat \' " ) ;
return ;
}
mdstatBuf [ n ] = ' \0 ' ;
}
ArrayInfo * getOrCreateArrayInfo ( char * array_name , int array_name_length ) {
ArrayInfo key ;
INDEX idx ;
ArrayInfo * MyArray ;
/*We have the array name. see if we already have a record for it*/
strncpy ( key . ArrayName , array_name , array_name_length ) ;
key . ArrayName [ array_name_length ] = ' \0 ' ;
if ( ( idx = search_ctnr ( ArrayInfos , ArrayInfoEqual , & key ) ) = = 0 ) {
/* Found an existing array device */
MyArray = get_ctnr ( ArrayInfos , idx ) ;
}
else {
/* Found a new array device. Create a data structure for it. */
MyArray = calloc ( 1 , sizeof ( ArrayInfo ) ) ;
if ( MyArray = = NULL ) {
/* Memory could not be allocated, so print an error and exit. */
fprintf ( stderr , " Could not allocate memory \n " ) ;
exit ( EXIT_FAILURE ) ;
}
strcpy ( MyArray - > ArrayName , key . ArrayName ) ;
/* Add this array to our list of array devices */
push_ctnr ( ArrayInfos , MyArray ) ;
char sensorName [ 128 ] ;
sprintf ( sensorName , " SoftRaid/%s/NumBlocks " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " integer " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
sprintf ( sensorName , " SoftRaid/%s/TotalDevices " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " integer " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
sprintf ( sensorName , " SoftRaid/%s/FailedDevices " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " integer " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
sprintf ( sensorName , " SoftRaid/%s/SpareDevices " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " integer " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
sprintf ( sensorName , " SoftRaid/%s/NumRaidDevices " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " integer " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
sprintf ( sensorName , " SoftRaid/%s/WorkingDevices " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " integer " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
sprintf ( sensorName , " SoftRaid/%s/ActiveDevices " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " integer " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
sprintf ( sensorName , " SoftRaid/%s/RaidType " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " string " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
sprintf ( sensorName , " SoftRaid/%s/DeviceNumber " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " integer " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
sprintf ( sensorName , " SoftRaid/%s/ResyncingPercent " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " integer " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
sprintf ( sensorName , " SoftRaid/%s/DiskInfo " , MyArray - > ArrayName ) ;
registerMonitor ( sensorName , " listview " , printArrayAttribute , printArrayAttributeInfo , StatSM ) ;
}
return MyArray ;
}
bool scanForArrays ( ) {
char * mdstatBufP ;
char * current_word ;
int current_word_length = 0 ;
ArrayInfo * MyArray ;
/* Mark all data as dead. As we find data, we'll mark it alive. */
for ( MyArray = first_ctnr ( ArrayInfos ) ; MyArray ; MyArray = next_ctnr ( ArrayInfos ) ) {
MyArray - > Alive = false ;
}
MyArray = NULL ;
openMdstatFile ( ) ;
current_word = mdstatBufP = mdstatBuf ;
/* Process values from /proc/mdstat */
bool start = true ;
while ( mdstatBufP [ 0 ] ! = ' \0 ' ) {
if ( ! start ) {
/*advanced one line at a time*/
while ( mdstatBufP [ 0 ] ! = ' \0 ' & & mdstatBufP [ 0 ] ! = ' \n ' ) mdstatBufP + + ;
mdstatBufP + + ;
}
start = false ;
if ( mdstatBufP [ 0 ] = = ' \0 ' ) break ;
current_word_length = 0 ;
current_word = mdstatBufP ;
if ( mdstatBufP [ 0 ] = = ' \n ' )
continue ;
if ( mdstatBufP [ 0 ] = = ' # ' ) /*skip comments */
continue ;
if ( strncmp ( current_word , " Personalities " , sizeof ( " Personalities " ) - 1 ) = = 0 )
continue ;
if ( strncmp ( current_word , " read_ahead " , sizeof ( " read_ahead " ) - 1 ) = = 0 )
continue ;
if ( strncmp ( current_word , " unused " , sizeof ( " unused " ) - 1 ) = = 0 )
continue ;
/* Better be an md line.. */
if ( strncmp ( current_word , " md " , 2 ) ! = 0 )
continue ;
int devnum ;
if ( strncmp ( current_word , " md_d " , 4 ) = = 0 )
devnum = - 1 - strtoul ( current_word + 4 , NULL , 10 ) ;
else /* it's md0 etc */
devnum = strtoul ( current_word + 2 , NULL , 10 ) ;
while ( mdstatBufP [ 0 ] ! = ' \0 ' & & mdstatBufP [ 0 ] ! = ' \n ' & & mdstatBufP [ 0 ] ! = ' ' & & mdstatBufP [ 0 ] ! = ' \t ' ) {
/*find the end of the word*/
mdstatBufP + + ;
current_word_length + + ;
}
MyArray = getOrCreateArrayInfo ( current_word , current_word_length ) ;
MyArray - > Alive = true ;
getMdadmDetail ( MyArray ) ;
MyArray - > level = MyArray - > pattern = NULL ;
MyArray - > ResyncingPercent = - 1 ;
MyArray - > IsCurrentlyReSyncing = false ;
MyArray - > devnum = devnum ;
MyArray - > ArrayActive = false ;
MyArray - > TotalDevices = MyArray - > SpareDevices = MyArray - > FailedDevices = 0 ;
MyArray - > NumBlocks = 0 ;
Disks * disk = MyArray - > first_disk ;
MyArray - > first_disk = NULL ;
Disks * next ;
while ( disk ) {
next = disk - > next ;
free ( disk ) ;
disk = next ;
}
/* In mdstat, we have something that looks like:
md0 : active raid1 sda1 [ 0 ] sdb1 [ 1 ]
312568576 blocks [ 2 / 2 ] [ UU ]
md1 : active raid1 sda2 [ 0 ] sdb2 [ 1 ]
452568576 blocks [ 2 / 2 ] [ UU ]
We have so far read in the " md0 " bit , and now want to continue reading the details for this raid group until
we reach the next raid group which we note as starting with a non whitespace .
*/
char buffer [ 100 ] ;
char status [ 100 ] ;
status [ 0 ] = 0 ;
int harddisk_index ;
for ( ; ; ) {
while ( mdstatBufP [ 0 ] ! = ' \0 ' & & ( ( mdstatBufP [ 0 ] = = ' \n ' & & ( mdstatBufP [ 1 ] = = ' ' | | mdstatBufP [ 1 ] = = ' \t ' ) ) | | mdstatBufP [ 0 ] = = ' ' | | mdstatBufP [ 0 ] = = ' \t ' ) ) {
mdstatBufP + + ; /*Remove any whitespace first*/
}
if ( mdstatBufP [ 0 ] = = ' \0 ' | | mdstatBufP [ 0 ] = = ' \n ' ) {
break ; /*we are now at the end of the file or line. Break this for loop*/
}
current_word = mdstatBufP ; /*we are now pointing to the first non-whitespace of a word*/
current_word_length = 0 ;
while ( mdstatBufP [ 0 ] ! = ' \0 ' & & mdstatBufP [ 0 ] ! = ' \n ' & & mdstatBufP [ 0 ] ! = ' ' & & mdstatBufP [ 0 ] ! = ' \t ' ) {
/*find the end of the word. We do this now so that we know the length of the word*/
mdstatBufP + + ;
current_word_length + + ;
}
char * eq ;
int in_devs = 0 ;
int temp_int = 0 ;
if ( strncmp ( current_word , " active " , sizeof ( " active " ) - 1 ) = = 0 )
MyArray - > ArrayActive = true ;
else if ( strncmp ( current_word , " inactive " , sizeof ( " inactive " ) - 1 ) = = 0 )
MyArray - > ArrayActive = false ;
2021-02-15 15:44:53 +02:00
else if ( MyArray - > ArrayActive & & MyArray - > level = = NULL & & current_word [ 0 ] ! = ' ( ' & & current_word [ 0 ] ! = ' : ' /*readonly*/ ) {
2014-11-13 19:30:51 +02:00
MyArray - > level = strndup ( current_word , current_word_length ) ;
in_devs = 1 ;
} else if ( sscanf ( current_word , " %d blocks " , & temp_int ) = = 1 ) {
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 */
} else if ( in_devs & & strncmp ( current_word , " blocks " , sizeof ( " blocks " ) - 1 ) = = 0 )
in_devs = 0 ;
# ifdef __GNUC__
# warning in_devs cannot be != 0!! (CID 3228)
# endif
else if ( in_devs & & strncmp ( current_word , " md " , 2 ) = = 0 ) {
/* This has an md device as a component. Maybe we should note this or something*/
} else if ( sscanf ( current_word , " %[^[ ][%d]%[^ ] " , buffer , & harddisk_index , status ) > = 2 ) {
/*Each device in the raid has an index. We can find the total number of devices in the raid by
simply finding the device with the highest index + 1. */
if ( harddisk_index > = MyArray - > TotalDevices ) MyArray - > TotalDevices = harddisk_index + 1 ;
Disks * new_disk = malloc ( sizeof ( Disks ) ) ;
new_disk - > name = strdup ( buffer ) ;
new_disk - > index = harddisk_index ;
if ( status [ 0 ] = = ' ( ' ) {
new_disk - > status = status [ 1 ] ;
if ( status [ 1 ] = = ' S ' ) /*Spare hard disk*/
MyArray - > SpareDevices + + ;
else if ( status [ 1 ] = = ' F ' )
MyArray - > FailedDevices + + ;
} else
new_disk - > status = ' U ' ;
/* insert the new disk into the linked list of disks*/
new_disk - > next = MyArray - > first_disk ;
MyArray - > first_disk = new_disk ;
MyArray - > NumRaidDevices = MyArray - > TotalDevices - MyArray - > FailedDevices ;
status [ 0 ] = 0 ; /*make sure we zero it again for next time*/
} else if ( ! MyArray - > pattern & &
current_word [ 0 ] = = ' [ ' & &
( current_word [ 1 ] = = ' U ' | | current_word [ 1 ] = = ' _ ' ) ) {
MyArray - > pattern = strndup ( current_word + 1 , current_word_length - 1 ) ;
if ( MyArray - > pattern [ current_word_length - 2 ] = = ' ] ' )
MyArray - > pattern [ current_word_length - 2 ] = ' \0 ' ;
MyArray - > ActiveDevices = MyArray - > TotalDevices - MyArray - > SpareDevices - MyArray - > FailedDevices ;
MyArray - > WorkingDevices = 0 ;
int index = 0 ;
for ( ; ; ) {
current_word + + ;
if ( current_word [ 0 ] = = ' U ' )
MyArray - > WorkingDevices + + ;
else if ( current_word [ 0 ] = = ' _ ' ) {
Disks * disk = MyArray - > first_disk ;
while ( disk ) {
if ( disk - > index = = index ) {
if ( disk - > status = = ' U ' )
disk - > status = ' _ ' ; /* The disk hasn't failed, but is syncing */
break ;
}
disk = disk - > next ;
}
} else
break ;
index + + ;
}
} else if ( MyArray - > ResyncingPercent = = - 1 & &
strncmp ( current_word , " re " , 2 ) = = 0 & &
current_word [ current_word_length - 1 ] = = ' % ' & &
( eq = strchr ( current_word , ' = ' ) ) ! = NULL ) {
MyArray - > ResyncingPercent = atoi ( eq + 1 ) ;
if ( strncmp ( current_word , " resync " , 4 ) = = 0 )
MyArray - > IsCurrentlyReSyncing = true ;
} else if ( MyArray - > ResyncingPercent = = - 1 & &
strncmp ( current_word , " resync " , 4 ) = = 0 ) {
MyArray - > IsCurrentlyReSyncing = true ;
} else if ( MyArray - > ResyncingPercent = = - 1 & &
current_word [ 0 ] > = ' 0 ' & &
current_word [ 0 ] < = ' 9 ' & &
current_word [ current_word_length - 1 ] = = ' % ' ) {
MyArray - > ResyncingPercent = atoi ( current_word ) ;
}
/*ignore anything not understood*/
}
}
/* Look for dead arrays, and for NumBlocksIsRegistered */
for ( MyArray = first_ctnr ( ArrayInfos ) ; MyArray ; MyArray = next_ctnr ( ArrayInfos ) ) {
if ( MyArray - > Alive = = false ) {
print_error ( " RECONFIGURE " ) ;
log_error ( " Soft raid device disappeared " ) ;
return false ;
}
}
return true ;
}
/* =========== Public part =========== */
void initSoftRaid ( struct SensorModul * sm ) {
StatSM = sm ;
ArrayInfos = new_ctnr ( ) ;
updateSoftRaid ( ) ;
}
void exitSoftRaid ( void ) {
destr_ctnr ( ArrayInfos , free ) ;
}
int updateSoftRaid ( void ) {
scanForArrays ( ) ;
return 0 ;
}