2011-08-11 09:00:20 +04:00
/*
2016-09-21 01:38:38 +03:00
* Copyright ( C ) 2005 - 2016 Red Hat , Inc . All rights reserved .
2011-08-11 09:00:20 +04:00
*
* This file is part of LVM2 .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v .2 .1 .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program ; if not , write to the Free Software Foundation ,
2016-01-21 13:49:46 +03:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2011-08-11 09:00:20 +04:00
*/
# include "lib.h"
2016-09-21 01:38:38 +03:00
# include "defaults.h"
2011-08-11 09:00:20 +04:00
# include "dmeventd_lvm.h"
2015-10-10 17:58:31 +03:00
# include "libdevmapper-event.h"
2016-09-21 01:38:38 +03:00
/* Hold enough elements for the mximum number of RAID images */
# define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64)
2015-10-13 12:28:57 +03:00
struct dso_state {
struct dm_pool * mem ;
char cmd_lvscan [ 512 ] ;
char cmd_lvconvert [ 512 ] ;
2016-09-21 01:38:38 +03:00
uint64_t raid_devs [ RAID_DEVS_ELEMS ] ;
2015-10-13 12:28:57 +03:00
int failed ;
2016-09-21 01:38:38 +03:00
int warned ;
2015-10-13 12:28:57 +03:00
} ;
2015-10-10 17:58:31 +03:00
DM_EVENT_LOG_FN ( " raid " )
2011-08-11 09:00:20 +04:00
/* FIXME Reformat to 80 char lines. */
2015-10-13 12:37:14 +03:00
static int _process_raid_event ( struct dso_state * state , char * params , const char * device )
2011-12-06 23:30:15 +04:00
{
2015-10-13 12:37:14 +03:00
struct dm_status_raid * status ;
const char * d ;
2016-09-21 01:38:38 +03:00
int dead = 0 , r = 1 ;
2016-12-09 15:58:19 +03:00
uint32_t dev ;
2014-07-21 06:33:21 +04:00
2015-10-13 12:37:14 +03:00
if ( ! dm_get_status_raid ( state - > mem , params , & status ) ) {
2015-10-09 22:57:48 +03:00
log_error ( " Failed to process status line for %s. " , device ) ;
2015-10-13 12:37:14 +03:00
return 0 ;
2011-08-11 09:00:20 +04:00
}
2016-09-21 01:38:38 +03:00
d = status - > dev_health ;
while ( ( d = strchr ( d , ' D ' ) ) ) {
2016-12-09 15:58:19 +03:00
dev = ( uint32_t ) ( d - status - > dev_health ) ;
2016-09-21 01:38:38 +03:00
2016-12-09 15:58:19 +03:00
if ( ! ( state - > raid_devs [ dev / 64 ] & ( UINT64_C ( 1 ) < < ( dev % 64 ) ) ) ) {
state - > raid_devs [ dev / 64 ] | = ( UINT64_C ( 1 ) < < ( dev % 64 ) ) ;
log_warn ( " WARNING: Device #%u of %s array, %s, has failed. " ,
dev , status - > raid_type , device ) ;
}
2016-09-21 01:38:38 +03:00
d + + ;
dead = 1 ;
}
if ( dead ) {
if ( status - > insync_regions < status - > total_regions ) {
2016-12-09 15:58:19 +03:00
if ( ! state - > warned ) {
state - > warned = 1 ;
2016-09-21 01:38:38 +03:00
log_warn ( " WARNING: waiting for resynchronization to finish "
2016-11-16 17:11:07 +03:00
" before initiating repair on RAID device %s. " , device ) ;
2016-12-09 15:58:19 +03:00
}
2016-09-21 01:38:38 +03:00
goto out ; /* Not yet done syncing with accessible devices */
}
2015-10-22 11:38:40 +03:00
if ( state - > failed )
goto out ; /* already reported */
2015-10-13 12:37:14 +03:00
state - > failed = 1 ;
if ( ! dmeventd_lvm2_run_with_lock ( state - > cmd_lvscan ) )
2015-10-22 11:38:40 +03:00
log_warn ( " WARNING: Re-scan of RAID device %s failed. " , device ) ;
2015-10-13 12:37:14 +03:00
/* if repair goes OK, report success even if lvscan has failed */
if ( ! dmeventd_lvm2_run_with_lock ( state - > cmd_lvconvert ) ) {
2016-10-31 20:03:06 +03:00
log_error ( " Repair of RAID device %s failed. " , device ) ;
2016-09-21 01:38:38 +03:00
r = 0 ;
2011-08-11 09:00:20 +04:00
}
2015-10-13 12:37:14 +03:00
} else {
state - > failed = 0 ;
log_info ( " %s array, %s, is %s in-sync. " ,
status - > raid_type , device ,
( status - > insync_regions = = status - > total_regions ) ? " now " : " not " ) ;
2011-08-11 09:00:20 +04:00
}
2015-10-22 11:38:40 +03:00
out :
2015-10-13 12:37:14 +03:00
dm_pool_free ( state - > mem , status ) ;
2011-08-11 09:00:20 +04:00
2016-09-21 01:38:38 +03:00
return r ;
2011-08-11 09:00:20 +04:00
}
void process_event ( struct dm_task * dmt ,
enum dm_event_mask event __attribute__ ( ( unused ) ) ,
2015-10-12 12:40:51 +03:00
void * * user )
2011-08-11 09:00:20 +04:00
{
2015-10-13 12:37:14 +03:00
struct dso_state * state = * user ;
2011-08-11 09:00:20 +04:00
void * next = NULL ;
uint64_t start , length ;
char * target_type = NULL ;
char * params ;
const char * device = dm_task_get_name ( dmt ) ;
do {
next = dm_get_next_target ( dmt , next , & start , & length ,
& target_type , & params ) ;
if ( ! target_type ) {
2015-10-09 22:57:48 +03:00
log_info ( " %s mapping lost. " , device ) ;
2011-08-11 09:00:20 +04:00
continue ;
}
if ( strcmp ( target_type , " raid " ) ) {
2015-10-09 22:57:48 +03:00
log_info ( " %s has non-raid portion. " , device ) ;
2011-08-11 09:00:20 +04:00
continue ;
}
2015-10-13 12:37:14 +03:00
if ( ! _process_raid_event ( state , params , device ) )
2015-10-09 22:57:48 +03:00
log_error ( " Failed to process event for %s. " ,
device ) ;
2011-08-11 09:00:20 +04:00
} while ( next ) ;
}
int register_device ( const char * device ,
const char * uuid __attribute__ ( ( unused ) ) ,
int major __attribute__ ( ( unused ) ) ,
int minor __attribute__ ( ( unused ) ) ,
2015-10-12 12:40:51 +03:00
void * * user )
2011-08-11 09:00:20 +04:00
{
2015-10-13 12:28:57 +03:00
struct dso_state * state ;
if ( ! dmeventd_lvm2_init_with_pool ( " raid_state " , state ) )
goto_bad ;
if ( ! dmeventd_lvm2_command ( state - > mem , state - > cmd_lvscan , sizeof ( state - > cmd_lvscan ) ,
" lvscan --cache " , device ) | |
! dmeventd_lvm2_command ( state - > mem , state - > cmd_lvconvert , sizeof ( state - > cmd_lvconvert ) ,
" lvconvert --config devices{ignore_suspended_devices=1} "
" --repair --use-policies " , device ) ) {
dmeventd_lvm2_exit_with_pool ( state ) ;
goto_bad ;
}
* user = state ;
2011-12-22 20:37:01 +04:00
2015-10-09 22:57:48 +03:00
log_info ( " Monitoring RAID device %s for events. " , device ) ;
2011-12-22 20:37:01 +04:00
return 1 ;
2015-10-13 12:28:57 +03:00
bad :
log_error ( " Failed to monitor RAID %s. " , device ) ;
return 0 ;
2011-08-11 09:00:20 +04:00
}
int unregister_device ( const char * device ,
const char * uuid __attribute__ ( ( unused ) ) ,
int major __attribute__ ( ( unused ) ) ,
int minor __attribute__ ( ( unused ) ) ,
2015-10-12 12:40:51 +03:00
void * * user )
2011-08-11 09:00:20 +04:00
{
2015-10-13 12:28:57 +03:00
struct dso_state * state = * user ;
dmeventd_lvm2_exit_with_pool ( state ) ;
2015-10-09 22:57:48 +03:00
log_info ( " No longer monitoring RAID device %s for events. " ,
device ) ;
2011-12-22 20:37:01 +04:00
2011-08-11 09:00:20 +04:00
return 1 ;
}