2005-12-02 22:52:06 +03:00
/*
2015-10-10 17:58:31 +03:00
* Copyright ( C ) 2005 - 2015 Red Hat , Inc . All rights reserved .
2005-12-02 22:52:06 +03: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
2005-12-02 22:52:06 +03:00
*/
2010-01-22 01:15:45 +03:00
# include "lib.h"
# include "libdevmapper-event.h"
# include "dmeventd_lvm.h"
2005-12-02 22:52:06 +03:00
2009-11-25 18:59:07 +03:00
/* FIXME Reformat to 80 char lines. */
2005-12-02 22:52:06 +03:00
# define ME_IGNORE 0
# define ME_INSYNC 1
# define ME_FAILURE 2
2015-10-13 12:28:57 +03:00
struct dso_state {
struct dm_pool * mem ;
char cmd_lvscan [ 512 ] ;
char cmd_lvconvert [ 512 ] ;
} ;
2015-10-10 17:58:31 +03:00
DM_EVENT_LOG_FN ( " mirr " )
2015-11-30 23:17:25 +03:00
static void _process_status_code ( dm_status_mirror_health_t health ,
uint32_t major , uint32_t minor ,
const char * dev_type , int * r )
2009-11-25 18:59:07 +03:00
{
/*
* A = > Alive - No failures
* D = > Dead - A write failure occurred leaving mirror out - of - sync
* F = > Flush failed .
* S = > Sync - A sychronization failure occurred , mirror out - of - sync
* R = > Read - A read failure occurred , mirror data unaffected
* U = > Unclassified failure ( bug )
*/
2015-11-30 23:17:25 +03:00
switch ( health ) {
case DM_STATUS_MIRROR_ALIVE :
return ;
case DM_STATUS_MIRROR_FLUSH_FAILED :
log_error ( " %s device %u:%u flush failed. " ,
dev_type , major , minor ) ;
* r = ME_FAILURE ;
break ;
case DM_STATUS_MIRROR_SYNC_FAILED :
log_error ( " %s device %u:%u sync failed. " ,
dev_type , major , minor ) ;
break ;
case DM_STATUS_MIRROR_READ_FAILED :
log_error ( " %s device %u:%u read failed. " ,
dev_type , major , minor ) ;
break ;
default :
log_error ( " %s device %u:%u has failed (%c). " ,
dev_type , major , minor , ( char ) health ) ;
* r = ME_FAILURE ;
break ;
2009-11-25 18:59:07 +03:00
}
}
2015-11-30 23:17:25 +03:00
static int _get_mirror_event ( struct dso_state * state , char * params )
2005-12-02 22:52:06 +03:00
{
2015-11-30 23:17:25 +03:00
int r = ME_INSYNC ;
unsigned i ;
struct dm_status_mirror * ms ;
2005-12-02 22:52:06 +03:00
2015-12-01 15:59:20 +03:00
if ( ! dm_get_status_mirror ( state - > mem , params , & ms ) )
2015-11-30 23:17:25 +03:00
goto_out ;
2005-12-02 22:52:06 +03:00
/* Check for bad mirror devices */
2015-11-30 23:17:25 +03:00
for ( i = 0 ; i < ms - > dev_count ; + + i )
_process_status_code ( ms - > devs [ i ] . health ,
ms - > devs [ i ] . major , ms - > devs [ i ] . minor ,
i ? " Secondary mirror " : " Primary mirror " , & r ) ;
2005-12-02 22:52:06 +03:00
2007-01-11 22:52:06 +03:00
/* Check for bad disk log device */
2015-11-30 23:17:25 +03:00
for ( i = 0 ; i < ms - > log_count ; + + i )
_process_status_code ( ms - > logs [ i ] . health ,
ms - > logs [ i ] . major , ms - > logs [ i ] . minor ,
" Log " , & r ) ;
/* Ignore if not in-sync */
if ( ( r = = ME_INSYNC ) & & ( ms - > insync_regions ! = ms - > total_regions ) )
r = ME_IGNORE ;
dm_pool_free ( state - > mem , ms ) ;
2007-01-11 22:52:06 +03:00
2006-12-20 17:35:02 +03:00
return r ;
2012-03-10 13:32:46 +04:00
2015-11-30 23:17:25 +03:00
out :
2015-10-09 22:57:48 +03:00
log_error ( " Unable to parse mirror status string. " ) ;
2007-01-11 22:52:06 +03:00
return ME_IGNORE ;
2005-12-02 22:52:06 +03:00
}
2015-10-13 12:35:44 +03:00
static int _remove_failed_devices ( const char * cmd_lvscan , const char * cmd_lvconvert )
2005-12-02 22:52:06 +03:00
{
int r ;
2015-10-13 12:35:44 +03:00
if ( ! dmeventd_lvm2_run_with_lock ( cmd_lvscan ) )
log_info ( " Re-scan of mirrored device failed. " ) ;
2005-12-02 22:52:06 +03:00
2015-01-14 20:04:46 +03:00
/* if repair goes OK, report success even if lvscan has failed */
2015-10-13 12:35:44 +03:00
r = dmeventd_lvm2_run_with_lock ( cmd_lvconvert ) ;
2005-12-02 22:52:06 +03:00
2015-10-13 12:35:44 +03:00
log_info ( " Repair of mirrored device %s. " ,
2015-10-09 22:57:48 +03:00
( r ) ? " finished successfully " : " failed " ) ;
2009-06-15 18:47:39 +04:00
2015-10-13 12:35:44 +03:00
return r ;
2005-12-02 22:52:06 +03:00
}
2008-01-31 15:19:36 +03:00
void process_event ( struct dm_task * dmt ,
2010-07-09 19:34:40 +04:00
enum dm_event_mask event __attribute__ ( ( unused ) ) ,
2015-10-12 12:40:51 +03:00
void * * user )
2005-12-02 22:52:06 +03:00
{
2015-10-13 12:35:44 +03:00
struct dso_state * state = * user ;
2005-12-02 22:52:06 +03:00
void * next = NULL ;
uint64_t start , length ;
char * target_type = NULL ;
char * params ;
2007-01-12 01:24:32 +03:00
const char * device = dm_task_get_name ( dmt ) ;
2005-12-02 22:52:06 +03:00
do {
next = dm_get_next_target ( dmt , next , & start , & length ,
& target_type , & params ) ;
2007-01-08 17:24:20 +03:00
if ( ! target_type ) {
2015-10-09 22:57:48 +03:00
log_info ( " %s mapping lost. " , device ) ;
2006-12-20 17:35:02 +03:00
continue ;
2007-01-08 17:24:20 +03:00
}
2006-12-20 17:35:02 +03:00
2005-12-02 22:52:06 +03:00
if ( strcmp ( target_type , " mirror " ) ) {
2015-10-09 22:57:48 +03:00
log_info ( " %s has unmirrored portion. " , device ) ;
2005-12-02 22:52:06 +03:00
continue ;
}
2015-11-30 23:17:25 +03:00
switch ( _get_mirror_event ( state , params ) ) {
2005-12-02 22:52:06 +03:00
case ME_INSYNC :
/* FIXME: all we really know is that this
_part_ of the device is in sync
Also , this is not an error
*/
2015-10-09 22:57:48 +03:00
log_notice ( " %s is now in-sync. " , device ) ;
2005-12-02 22:52:06 +03:00
break ;
case ME_FAILURE :
2015-10-09 22:57:48 +03:00
log_error ( " Device failure in %s. " , device ) ;
2015-10-13 12:35:44 +03:00
if ( ! _remove_failed_devices ( state - > cmd_lvscan ,
state - > cmd_lvconvert ) )
2006-12-20 17:35:02 +03:00
/* FIXME Why are all the error return codes unused? Get rid of them? */
2015-10-09 22:57:48 +03:00
log_error ( " Failed to remove faulty devices in %s. " ,
device ) ;
2006-01-27 23:48:19 +03:00
/* Should check before warning user that device is now linear
2005-12-02 22:52:06 +03:00
else
2015-10-09 22:57:48 +03:00
log_notice ( " %s is now a linear device. " ,
device ) ;
2006-01-27 23:48:19 +03:00
*/
2005-12-02 22:52:06 +03:00
break ;
case ME_IGNORE :
break ;
default :
2007-01-12 01:24:32 +03:00
/* FIXME Provide value then! */
2015-10-09 22:57:48 +03:00
log_info ( " Unknown event received. " ) ;
2005-12-02 22:52:06 +03:00
}
} while ( next ) ;
}
2008-01-31 15:19:36 +03:00
int register_device ( const char * device ,
2010-07-09 19:34:40 +04:00
const char * uuid __attribute__ ( ( unused ) ) ,
int major __attribute__ ( ( unused ) ) ,
int minor __attribute__ ( ( unused ) ) ,
2015-10-12 12:40:51 +03:00
void * * user )
2005-12-02 22:52:06 +03:00
{
2015-10-13 12:28:57 +03:00
struct dso_state * state ;
if ( ! dmeventd_lvm2_init_with_pool ( " mirror_state " , state ) )
goto_bad ;
if ( ! dmeventd_lvm2_command ( state - > mem , state - > cmd_lvscan , sizeof ( state - > cmd_lvscan ) ,
" lvscan --cache " , device ) ) {
dmeventd_lvm2_exit_with_pool ( state ) ;
goto_bad ;
}
if ( ! dmeventd_lvm2_command ( state - > mem , state - > cmd_lvconvert , sizeof ( state - > cmd_lvconvert ) ,
2015-10-22 18:09:43 +03:00
" lvconvert --repair --use-policies " , device ) ) {
2015-10-13 12:28:57 +03:00
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 mirror 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 mirror %s. " , device ) ;
return 0 ;
2005-12-02 22:52:06 +03:00
}
2008-01-31 15:19:36 +03:00
int unregister_device ( const char * device ,
2010-07-09 19:34:40 +04:00
const char * uuid __attribute__ ( ( unused ) ) ,
int major __attribute__ ( ( unused ) ) ,
int minor __attribute__ ( ( unused ) ) ,
2015-10-12 12:40:51 +03:00
void * * user )
2005-12-02 22:52:06 +03: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 mirror device %s for events. " ,
device ) ;
2011-12-22 20:37:01 +04:00
2007-01-08 17:24:20 +03:00
return 1 ;
2005-12-02 22:52:06 +03:00
}