2012-02-28 22:23:56 +04:00
/*
* Copyright ( C ) 2012 Red Hat , Inc .
*
* 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 ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
2012-02-23 17:11:07 +04:00
# include "lib.h"
# include "toolcontext.h"
# include "metadata.h"
# include "device.h"
# include "lvmetad.h"
# include "lvmcache.h"
# include "lvmetad-client.h"
# include "format-text.h" // TODO for disk_locn, used as a DA representation
2012-08-13 21:44:10 +04:00
# include "filter.h"
# include "assert.h"
# include "crc.h"
2012-02-23 17:11:07 +04:00
static daemon_handle _lvmetad ;
2012-08-13 21:44:10 +04:00
static int _lvmetad_use = 0 ;
static int _lvmetad_connected = 0 ;
2012-02-23 17:11:07 +04:00
2012-08-13 21:44:10 +04:00
static char * _lvmetad_token = NULL ;
static const char * _lvmetad_socket = NULL ;
static struct cmd_context * _lvmetad_cmd = NULL ;
void lvmetad_disconnect ( void )
{
daemon_close ( _lvmetad ) ;
_lvmetad_connected = 0 ;
_lvmetad_cmd = NULL ;
}
void lvmetad_init ( struct cmd_context * cmd )
2012-02-23 17:11:07 +04:00
{
2012-10-10 14:33:48 +04:00
if ( ! _lvmetad_use & & ! access ( LVMETAD_PIDFILE , F_OK ) )
log_warn ( " WARNING: lvmetad is running but disabled. Restart lvmetad before enabling it! " ) ;
2012-08-13 21:44:10 +04:00
if ( _lvmetad_use & & _lvmetad_socket & & ! _lvmetad_connected ) {
assert ( _lvmetad_socket ) ;
_lvmetad = lvmetad_open ( _lvmetad_socket ) ;
if ( _lvmetad . socket_fd > = 0 & & ! _lvmetad . error ) {
_lvmetad_connected = 1 ;
_lvmetad_cmd = cmd ;
2012-10-12 04:48:39 +04:00
}
2012-02-23 17:11:07 +04:00
}
}
2012-10-12 04:48:39 +04:00
void lvmetad_warning ( )
{
log_warn ( " WARNING: Failed to connect to lvmetad: %s. Falling back to internal scanning. " ,
strerror ( _lvmetad . error ) ) ;
}
2012-08-13 21:44:10 +04:00
int lvmetad_active ( void )
{
return _lvmetad_use & & _lvmetad_connected ;
}
void lvmetad_set_active ( int active )
{
_lvmetad_use = active ;
}
void lvmetad_set_token ( const struct dm_config_value * filter )
{
2012-10-12 12:15:30 +04:00
int ft = 0 ;
2012-08-13 21:44:10 +04:00
if ( _lvmetad_token )
dm_free ( _lvmetad_token ) ;
2012-10-12 12:15:30 +04:00
2012-08-13 21:44:10 +04:00
while ( filter & & filter - > type = = DM_CFG_STRING ) {
ft = calc_crc ( ft , ( const uint8_t * ) filter - > v . str , strlen ( filter - > v . str ) ) ;
filter = filter - > next ;
}
2012-10-12 12:15:30 +04:00
2012-08-13 21:44:10 +04:00
if ( ! dm_asprintf ( & _lvmetad_token , " filter:%u " , ft ) )
log_warn ( " WARNING: Failed to set lvmetad token. Out of memory? " ) ;
}
void lvmetad_set_socket ( const char * sock )
{
_lvmetad_socket = sock ;
}
static daemon_reply _lvmetad_send ( const char * id , . . . ) ;
2012-10-12 12:15:30 +04:00
static int _token_update ( void )
2012-08-13 21:44:10 +04:00
{
daemon_reply repl = _lvmetad_send ( " token_update " , NULL ) ;
2012-09-20 01:30:16 +04:00
if ( repl . error | | strcmp ( daemon_reply_str ( repl , " response " , " " ) , " OK " ) ) {
2012-08-13 21:44:10 +04:00
daemon_reply_destroy ( repl ) ;
return 0 ;
}
daemon_reply_destroy ( repl ) ;
return 1 ;
}
2012-08-11 12:37:28 +04:00
static daemon_reply _lvmetad_send ( const char * id , . . . )
{
va_list ap ;
2012-10-12 12:15:30 +04:00
daemon_reply repl ;
2012-08-13 21:44:10 +04:00
daemon_request req ;
int try = 0 ;
2012-08-11 12:37:28 +04:00
2012-08-13 21:44:10 +04:00
retry :
req = daemon_request_make ( id ) ;
if ( _lvmetad_token )
daemon_request_extend ( req , " token = %s " , _lvmetad_token , NULL ) ;
va_start ( ap , id ) ;
2012-08-11 12:37:28 +04:00
daemon_request_extend_v ( req , ap ) ;
2012-08-13 21:44:10 +04:00
va_end ( ap ) ;
2012-08-11 12:37:28 +04:00
repl = daemon_send ( _lvmetad , req ) ;
daemon_request_destroy ( req ) ;
2012-10-08 14:21:36 +04:00
if ( ! repl . error & & ! strcmp ( daemon_reply_str ( repl , " response " , " " ) , " token_mismatch " ) & &
try < 2 & & ! test_mode ( ) ) {
2012-09-10 00:05:59 +04:00
if ( lvmetad_pvscan_all_devs ( _lvmetad_cmd , NULL ) ) {
2012-10-08 14:21:36 +04:00
+ + try ;
daemon_reply_destroy ( repl ) ;
goto retry ;
2012-08-13 21:44:10 +04:00
}
}
2012-08-11 12:37:28 +04:00
return repl ;
}
2012-02-23 17:11:07 +04:00
/*
* Helper ; evaluate the reply from lvmetad , check for errors , print diagnostics
2012-03-03 00:46:36 +04:00
* and return a summary success / failure exit code .
*
* If found is set , * found indicates whether or not device exists ,
* and missing device is not treated as an error .
2012-02-23 17:11:07 +04:00
*/
2012-03-03 00:46:36 +04:00
static int _lvmetad_handle_reply ( daemon_reply reply , const char * action , const char * object ,
int * found )
{
if ( reply . error ) {
log_error ( " Request to %s %s%sin lvmetad gave response %s. " ,
action , object , * object ? " " : " " , strerror ( reply . error ) ) ;
2012-02-23 17:11:07 +04:00
return 0 ;
}
2012-03-03 00:46:36 +04:00
/* All OK? */
if ( ! strcmp ( daemon_reply_str ( reply , " response " , " " ) , " OK " ) ) {
if ( found )
* found = 1 ;
return 1 ;
}
/* Unknown device permitted? */
if ( found & & ! strcmp ( daemon_reply_str ( reply , " response " , " " ) , " unknown " ) ) {
log_very_verbose ( " Request to %s %s%sin lvmetad did not find object. " ,
action , object , * object ? " " : " " ) ;
* found = 0 ;
return 1 ;
}
log_error ( " Request to %s %s%sin lvmetad gave response %s. Reason: %s " ,
action , object , * object ? " " : " " ,
daemon_reply_str ( reply , " response " , " <missing> " ) ,
daemon_reply_str ( reply , " reason " , " <missing> " ) ) ;
return 0 ;
2012-02-23 17:11:07 +04:00
}
static int _read_mda ( struct lvmcache_info * info ,
struct format_type * fmt ,
const struct dm_config_node * cn )
{
struct metadata_area_ops * ops ;
2012-02-23 21:59:32 +04:00
dm_list_iterate_items ( ops , & fmt - > mda_ops )
2012-02-23 17:11:07 +04:00
if ( ops - > mda_import_text & & ops - > mda_import_text ( info , cn ) )
return 1 ;
2012-02-23 21:59:32 +04:00
2012-02-23 17:11:07 +04:00
return 0 ;
}
static struct lvmcache_info * _pv_populate_lvmcache (
struct cmd_context * cmd , struct dm_config_node * cn , dev_t fallback )
{
2012-02-23 21:59:32 +04:00
struct device * device ;
struct id pvid , vgid ;
char mda_id [ 32 ] ;
char da_id [ 32 ] ;
int i = 0 ;
struct dm_config_node * mda = NULL ;
struct dm_config_node * da = NULL ;
uint64_t offset , size ;
struct lvmcache_info * info ;
2012-02-23 17:11:07 +04:00
const char * pvid_txt = dm_config_find_str ( cn - > child , " id " , NULL ) ,
* vgid_txt = dm_config_find_str ( cn - > child , " vgid " , NULL ) ,
* vgname = dm_config_find_str ( cn - > child , " vgname " , NULL ) ,
* fmt_name = dm_config_find_str ( cn - > child , " format " , NULL ) ;
dev_t devt = dm_config_find_int ( cn - > child , " device " , 0 ) ;
2012-03-02 00:04:44 +04:00
uint64_t devsize = dm_config_find_int64 ( cn - > child , " dev_size " , 0 ) ,
label_sector = dm_config_find_int64 ( cn - > child , " label_sector " , 0 ) ;
2012-02-23 17:11:07 +04:00
struct format_type * fmt = fmt_name ? get_format_by_name ( cmd , fmt_name ) : NULL ;
if ( ! fmt ) {
2012-03-02 20:58:41 +04:00
log_error ( " PV %s not recognised. Is the device missing? " , pvid_txt ) ;
2012-02-23 21:59:32 +04:00
return NULL ;
2012-02-23 17:11:07 +04:00
}
2012-02-23 21:59:32 +04:00
device = dev_cache_get_by_devt ( devt , cmd - > filter ) ;
2012-02-23 17:11:07 +04:00
if ( ! device & & fallback )
device = dev_cache_get_by_devt ( fallback , cmd - > filter ) ;
if ( ! device ) {
2012-03-02 20:58:41 +04:00
log_error ( " No device found for PV %s. " , pvid_txt ) ;
2012-02-23 21:59:32 +04:00
return NULL ;
2012-02-23 17:11:07 +04:00
}
if ( ! pvid_txt | | ! id_read_format ( & pvid , pvid_txt ) ) {
2012-03-02 20:58:41 +04:00
log_error ( " Missing or ill-formatted PVID for PV: %s. " , pvid_txt ) ;
2012-02-23 21:59:32 +04:00
return NULL ;
2012-02-23 17:11:07 +04:00
}
if ( vgid_txt )
id_read_format ( & vgid , vgid_txt ) ;
else
strcpy ( ( char * ) & vgid , fmt - > orphan_vg_name ) ;
if ( ! vgname )
vgname = fmt - > orphan_vg_name ;
2012-04-10 16:26:27 +04:00
if ( ! ( info = lvmcache_add ( fmt - > labeller , ( const char * ) & pvid , device ,
vgname , ( const char * ) & vgid , 0 ) ) )
return_NULL ;
2012-02-23 17:11:07 +04:00
lvmcache_get_label ( info ) - > sector = label_sector ;
lvmcache_set_device_size ( info , devsize ) ;
lvmcache_del_das ( info ) ;
lvmcache_del_mdas ( info ) ;
do {
sprintf ( mda_id , " mda%d " , i ) ;
mda = dm_config_find_node ( cn - > child , mda_id ) ;
if ( mda )
_read_mda ( info , fmt , mda ) ;
+ + i ;
} while ( mda ) ;
i = 0 ;
do {
sprintf ( da_id , " da%d " , i ) ;
da = dm_config_find_node ( cn - > child , da_id ) ;
if ( da ) {
if ( ! dm_config_get_uint64 ( da - > child , " offset " , & offset ) ) return_0 ;
if ( ! dm_config_get_uint64 ( da - > child , " size " , & size ) ) return_0 ;
lvmcache_add_da ( info , offset , size ) ;
}
+ + i ;
} while ( da ) ;
return info ;
}
struct volume_group * lvmetad_vg_lookup ( struct cmd_context * cmd , const char * vgname , const char * vgid )
{
2012-02-23 21:59:32 +04:00
struct volume_group * vg = NULL ;
daemon_reply reply ;
char uuid [ 64 ] ;
struct format_instance * fid ;
struct format_instance_ctx fic ;
struct dm_config_node * top ;
const char * name ;
const char * fmt_name ;
struct format_type * fmt ;
struct dm_config_node * pvcn ;
struct pv_list * pvl ;
struct lvmcache_info * info ;
2012-08-13 21:44:10 +04:00
if ( ! lvmetad_active ( ) )
2012-02-23 17:11:07 +04:00
return NULL ;
if ( vgid ) {
2012-02-27 15:32:48 +04:00
if ( ! id_write_format ( ( const struct id * ) vgid , uuid , sizeof ( uuid ) ) )
2012-08-17 14:04:52 +04:00
return_NULL ;
2012-08-11 12:37:28 +04:00
reply = _lvmetad_send ( " vg_lookup " , " uuid = %s " , uuid , NULL ) ;
2012-02-23 17:11:07 +04:00
} else {
if ( ! vgname )
log_error ( INTERNAL_ERROR " VG name required (VGID not available) " ) ;
2012-08-11 12:37:28 +04:00
reply = _lvmetad_send ( " vg_lookup " , " name = %s " , vgname , NULL ) ;
2012-02-23 17:11:07 +04:00
}
2012-09-20 01:30:16 +04:00
if ( ! reply . error & & ! strcmp ( daemon_reply_str ( reply , " response " , " " ) , " OK " ) ) {
2012-02-23 17:11:07 +04:00
2012-06-21 14:43:31 +04:00
if ( ! ( top = dm_config_find_node ( reply . cft - > root , " metadata " ) ) ) {
log_error ( INTERNAL_ERROR " metadata config node not found. " ) ;
goto out ;
}
2012-02-23 21:59:32 +04:00
name = daemon_reply_str ( reply , " name " , NULL ) ;
2012-02-23 17:11:07 +04:00
/* fall back to lvm2 if we don't know better */
2012-02-23 21:59:32 +04:00
fmt_name = dm_config_find_str ( top , " metadata/format " , " lvm2 " ) ;
if ( ! ( fmt = get_format_by_name ( cmd , fmt_name ) ) ) {
2012-02-23 17:11:07 +04:00
log_error ( INTERNAL_ERROR
" We do not know the format (%s) reported by lvmetad. " ,
fmt_name ) ;
2012-03-03 01:24:37 +04:00
goto out ;
2012-02-23 17:11:07 +04:00
}
fic . type = FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS ;
fic . context . vg_ref . vg_name = name ;
fic . context . vg_ref . vg_id = vgid ;
if ( ! ( fid = fmt - > ops - > create_instance ( fmt , & fic ) ) )
2012-03-03 01:24:37 +04:00
goto_out ;
2012-02-23 17:11:07 +04:00
2012-03-02 02:52:59 +04:00
if ( ( pvcn = dm_config_find_node ( top , " metadata/physical_volumes " ) ) )
for ( pvcn = pvcn - > child ; pvcn ; pvcn = pvcn - > sib )
_pv_populate_lvmcache ( cmd , pvcn , 0 ) ;
2012-02-23 17:11:07 +04:00
top - > key = name ;
2012-03-02 02:52:59 +04:00
if ( ! ( vg = import_vg_from_config_tree ( reply . cft , fid ) ) )
2012-03-03 01:24:37 +04:00
goto_out ;
2012-02-23 17:11:07 +04:00
dm_list_iterate_items ( pvl , & vg - > pvs ) {
2012-02-23 21:59:32 +04:00
if ( ( info = lvmcache_info_from_pvid ( ( const char * ) & pvl - > pv - > id , 0 ) ) ) {
2012-02-23 17:11:07 +04:00
pvl - > pv - > label_sector = lvmcache_get_label ( info ) - > sector ;
pvl - > pv - > dev = lvmcache_device ( info ) ;
2012-03-03 01:24:37 +04:00
if ( ! lvmcache_fid_add_mdas_pv ( info , fid ) ) {
vg = NULL ;
goto_out ; /* FIXME error path */
}
2012-02-23 17:11:07 +04:00
} /* else probably missing */
}
lvmcache_update_vg ( vg , 0 ) ;
}
2012-03-03 01:24:37 +04:00
out :
2012-02-23 17:11:07 +04:00
daemon_reply_destroy ( reply ) ;
2012-03-03 01:24:37 +04:00
2012-02-23 17:11:07 +04:00
return vg ;
}
struct _fixup_baton {
int i ;
int find ;
int ignore ;
} ;
static int _fixup_ignored ( struct metadata_area * mda , void * baton ) {
struct _fixup_baton * b = baton ;
if ( b - > i = = b - > find )
mda_set_ignored ( mda , b - > ignore ) ;
b - > i + + ;
return 1 ;
}
2012-08-11 12:37:28 +04:00
static struct dm_config_tree * _export_vg_to_config_tree ( struct volume_group * vg )
2012-02-23 17:11:07 +04:00
{
char * buf = NULL ;
2012-08-11 12:37:28 +04:00
struct dm_config_tree * vgmeta ;
if ( ! export_vg_to_buffer ( vg , & buf ) ) {
log_error ( " Could not format VG metadata. " ) ;
return 0 ;
}
if ( ! ( vgmeta = dm_config_from_string ( buf ) ) ) {
log_error ( " Error parsing VG metadata. " ) ;
dm_free ( buf ) ;
return 0 ;
}
dm_free ( buf ) ;
return vgmeta ;
}
int lvmetad_vg_update ( struct volume_group * vg )
{
2012-02-23 21:59:32 +04:00
daemon_reply reply ;
struct dm_hash_node * n ;
struct metadata_area * mda ;
char mda_id [ 128 ] , * num ;
struct pv_list * pvl ;
struct lvmcache_info * info ;
2012-02-23 23:03:48 +04:00
struct _fixup_baton baton ;
2012-08-11 12:37:28 +04:00
struct dm_config_tree * vgmeta ;
2012-02-23 21:59:32 +04:00
2012-02-23 17:11:07 +04:00
if ( ! vg )
return 0 ;
2012-02-23 21:59:32 +04:00
2012-08-13 21:44:10 +04:00
if ( ! lvmetad_active ( ) | | test_mode ( ) )
2012-02-23 17:11:07 +04:00
return 1 ; /* fake it */
2012-08-11 12:37:28 +04:00
if ( ! ( vgmeta = _export_vg_to_config_tree ( vg ) ) )
return_0 ;
2012-02-23 17:11:07 +04:00
2012-08-11 12:37:28 +04:00
reply = _lvmetad_send ( " vg_update " , " vgname = %s " , vg - > name ,
" metadata = %t " , vgmeta , NULL ) ;
dm_config_destroy ( vgmeta ) ;
2012-02-23 17:11:07 +04:00
2012-03-03 00:46:36 +04:00
if ( ! _lvmetad_handle_reply ( reply , " update VG " , vg - > name , NULL ) ) {
daemon_reply_destroy ( reply ) ;
2012-02-23 17:11:07 +04:00
return 0 ;
2012-03-03 00:46:36 +04:00
}
2012-02-23 17:11:07 +04:00
2012-03-03 01:24:37 +04:00
daemon_reply_destroy ( reply ) ;
2012-02-23 21:59:32 +04:00
n = ( vg - > fid & & vg - > fid - > metadata_areas_index ) ?
2012-02-23 17:11:07 +04:00
dm_hash_get_first ( vg - > fid - > metadata_areas_index ) : NULL ;
while ( n ) {
2012-02-23 21:59:32 +04:00
mda = dm_hash_get_data ( vg - > fid - > metadata_areas_index , n ) ;
2012-02-23 17:11:07 +04:00
strcpy ( mda_id , dm_hash_get_key ( vg - > fid - > metadata_areas_index , n ) ) ;
if ( ( num = strchr ( mda_id , ' _ ' ) ) ) {
* num = 0 ;
+ + num ;
2012-02-23 21:59:32 +04:00
if ( ( info = lvmcache_info_from_pvid ( mda_id , 0 ) ) ) {
2012-02-23 23:03:48 +04:00
memset ( & baton , 0 , sizeof ( baton ) ) ;
2012-02-23 21:59:32 +04:00
baton . find = atoi ( num ) ;
baton . ignore = mda_is_ignored ( mda ) ;
2012-02-23 17:11:07 +04:00
lvmcache_foreach_mda ( info , _fixup_ignored , & baton ) ;
2012-02-23 21:59:32 +04:00
}
2012-02-23 17:11:07 +04:00
}
n = dm_hash_get_next ( vg - > fid - > metadata_areas_index , n ) ;
}
dm_list_iterate_items ( pvl , & vg - > pvs ) {
/* NB. the PV fmt pointer is sometimes wrong during vgconvert */
if ( pvl - > pv - > dev & & ! lvmetad_pv_found ( pvl - > pv - > id , pvl - > pv - > dev ,
vg - > fid ? vg - > fid - > fmt : pvl - > pv - > fmt ,
2012-06-27 16:59:34 +04:00
pvl - > pv - > label_sector , NULL , NULL ) )
2012-02-23 17:11:07 +04:00
return 0 ;
}
return 1 ;
}
int lvmetad_vg_remove ( struct volume_group * vg )
{
2012-02-23 21:59:32 +04:00
char uuid [ 64 ] ;
daemon_reply reply ;
2012-03-03 00:46:36 +04:00
int result ;
2012-02-23 21:59:32 +04:00
2012-08-13 21:44:10 +04:00
if ( ! lvmetad_active ( ) | | test_mode ( ) )
2012-02-23 17:11:07 +04:00
return 1 ; /* just fake it */
2012-02-23 21:59:32 +04:00
2012-02-27 15:32:48 +04:00
if ( ! id_write_format ( & vg - > id , uuid , sizeof ( uuid ) ) )
return_0 ;
2012-08-11 12:37:28 +04:00
reply = _lvmetad_send ( " vg_remove " , " uuid = %s " , uuid , NULL ) ;
2012-03-03 00:46:36 +04:00
result = _lvmetad_handle_reply ( reply , " remove VG " , vg - > name , NULL ) ;
daemon_reply_destroy ( reply ) ;
return result ;
2012-02-23 17:11:07 +04:00
}
2012-03-03 00:46:36 +04:00
int lvmetad_pv_lookup ( struct cmd_context * cmd , struct id pvid , int * found )
2012-02-23 17:11:07 +04:00
{
2012-02-23 21:59:32 +04:00
char uuid [ 64 ] ;
daemon_reply reply ;
2012-03-03 00:46:36 +04:00
int result = 0 ;
2012-02-23 21:59:32 +04:00
struct dm_config_node * cn ;
2012-08-13 21:44:10 +04:00
if ( ! lvmetad_active ( ) )
2012-02-23 17:11:07 +04:00
return_0 ;
2012-02-27 15:32:48 +04:00
if ( ! id_write_format ( & pvid , uuid , sizeof ( uuid ) ) )
return_0 ;
2012-02-23 17:11:07 +04:00
2012-08-11 12:37:28 +04:00
reply = _lvmetad_send ( " pv_lookup " , " uuid = %s " , uuid , NULL ) ;
2012-03-03 00:46:36 +04:00
if ( ! _lvmetad_handle_reply ( reply , " lookup PV " , " " , found ) )
goto_out ;
if ( found & & ! * found )
goto out_success ;
2012-02-23 17:11:07 +04:00
2012-03-02 02:52:59 +04:00
if ( ! ( cn = dm_config_find_node ( reply . cft - > root , " physical_volume " ) ) )
2012-03-03 00:46:36 +04:00
goto_out ;
2012-03-02 02:52:59 +04:00
else if ( ! _pv_populate_lvmcache ( cmd , cn , 0 ) )
2012-03-03 00:46:36 +04:00
goto_out ;
2012-02-23 17:11:07 +04:00
2012-03-03 00:46:36 +04:00
out_success :
result = 1 ;
out :
2012-02-23 17:11:07 +04:00
daemon_reply_destroy ( reply ) ;
2012-03-03 00:46:36 +04:00
2012-02-23 17:11:07 +04:00
return result ;
}
2012-03-03 00:46:36 +04:00
int lvmetad_pv_lookup_by_dev ( struct cmd_context * cmd , struct device * dev , int * found )
2012-02-23 17:11:07 +04:00
{
2012-03-03 00:46:36 +04:00
int result = 0 ;
2012-02-23 21:59:32 +04:00
daemon_reply reply ;
struct dm_config_node * cn ;
2012-08-13 21:44:10 +04:00
if ( ! lvmetad_active ( ) )
2012-02-23 17:11:07 +04:00
return_0 ;
2012-09-09 23:57:59 +04:00
reply = _lvmetad_send ( " pv_lookup " , " device = % " PRId64 , ( int64_t ) dev - > dev , NULL ) ;
2012-03-03 00:46:36 +04:00
if ( ! _lvmetad_handle_reply ( reply , " lookup PV " , dev_name ( dev ) , found ) )
goto_out ;
if ( found & & ! * found )
goto out_success ;
2012-02-23 17:11:07 +04:00
2012-02-23 21:59:32 +04:00
cn = dm_config_find_node ( reply . cft - > root , " physical_volume " ) ;
2012-03-03 00:46:36 +04:00
if ( ! cn | | ! _pv_populate_lvmcache ( cmd , cn , dev - > dev ) )
goto_out ;
2012-02-23 17:11:07 +04:00
2012-03-03 00:46:36 +04:00
out_success :
result = 1 ;
out :
2012-02-23 17:11:07 +04:00
daemon_reply_destroy ( reply ) ;
return result ;
}
int lvmetad_pv_list_to_lvmcache ( struct cmd_context * cmd )
{
2012-02-23 21:59:32 +04:00
daemon_reply reply ;
struct dm_config_node * cn ;
2012-08-13 21:44:10 +04:00
if ( ! lvmetad_active ( ) )
2012-02-28 22:23:56 +04:00
return 1 ;
2012-02-23 17:11:07 +04:00
2012-08-11 12:37:28 +04:00
reply = _lvmetad_send ( " pv_list " , NULL ) ;
2012-03-03 00:46:36 +04:00
if ( ! _lvmetad_handle_reply ( reply , " list PVs " , " " , NULL ) ) {
daemon_reply_destroy ( reply ) ;
2012-02-23 17:11:07 +04:00
return_0 ;
}
2012-03-02 02:52:59 +04:00
if ( ( cn = dm_config_find_node ( reply . cft - > root , " physical_volumes " ) ) )
for ( cn = cn - > child ; cn ; cn = cn - > sib )
_pv_populate_lvmcache ( cmd , cn , 0 ) ;
2012-02-23 17:11:07 +04:00
daemon_reply_destroy ( reply ) ;
2012-03-03 00:46:36 +04:00
2012-02-23 17:11:07 +04:00
return 1 ;
}
int lvmetad_vg_list_to_lvmcache ( struct cmd_context * cmd )
{
2012-02-23 21:59:32 +04:00
struct volume_group * tmp ;
struct id vgid ;
const char * vgid_txt ;
daemon_reply reply ;
struct dm_config_node * cn ;
2012-08-13 21:44:10 +04:00
if ( ! lvmetad_active ( ) )
2012-02-28 22:23:56 +04:00
return 1 ;
2012-02-23 17:11:07 +04:00
2012-08-11 12:37:28 +04:00
reply = _lvmetad_send ( " vg_list " , NULL ) ;
2012-03-03 00:46:36 +04:00
if ( ! _lvmetad_handle_reply ( reply , " list VGs " , " " , NULL ) ) {
daemon_reply_destroy ( reply ) ;
2012-02-23 17:11:07 +04:00
return_0 ;
}
2012-03-02 02:52:59 +04:00
if ( ( cn = dm_config_find_node ( reply . cft - > root , " volume_groups " ) ) )
for ( cn = cn - > child ; cn ; cn = cn - > sib ) {
vgid_txt = cn - > key ;
if ( ! id_read_format ( & vgid , vgid_txt ) ) {
stack ;
continue ;
}
2012-02-23 17:11:07 +04:00
2012-03-02 02:52:59 +04:00
/* the call to lvmetad_vg_lookup will poke the VG into lvmcache */
tmp = lvmetad_vg_lookup ( cmd , NULL , ( const char * ) & vgid ) ;
release_vg ( tmp ) ;
}
2012-02-23 17:11:07 +04:00
daemon_reply_destroy ( reply ) ;
return 1 ;
}
2012-08-11 12:37:28 +04:00
struct _extract_mda_baton {
2012-02-23 17:11:07 +04:00
int i ;
2012-08-11 12:37:28 +04:00
struct dm_config_tree * cft ;
struct dm_config_node * pre_sib ;
2012-02-23 17:11:07 +04:00
} ;
2012-08-11 12:37:28 +04:00
static int _extract_mda ( struct metadata_area * mda , void * baton )
2012-02-23 17:11:07 +04:00
{
2012-08-11 12:37:28 +04:00
struct _extract_mda_baton * b = baton ;
struct dm_config_node * cn ;
char id [ 32 ] ;
2012-02-23 17:11:07 +04:00
if ( ! mda - > ops - > mda_export_text ) /* do nothing */
return 1 ;
2012-08-11 12:37:28 +04:00
dm_snprintf ( id , 32 , " mda%d " , b - > i ) ;
if ( ! ( cn = make_config_node ( b - > cft , id , b - > cft - > root , b - > pre_sib ) ) )
return 0 ;
if ( ! mda - > ops - > mda_export_text ( mda , b - > cft , cn ) )
return 0 ;
2012-02-23 17:11:07 +04:00
b - > i + + ;
2012-08-11 12:37:28 +04:00
b - > pre_sib = cn ; /* for efficiency */
return 1 ;
2012-02-23 17:11:07 +04:00
}
2012-08-11 12:37:28 +04:00
static int _extract_da ( struct disk_locn * da , void * baton )
2012-02-23 17:11:07 +04:00
{
2012-08-11 12:37:28 +04:00
struct _extract_mda_baton * b = baton ;
struct dm_config_node * cn ;
char id [ 32 ] ;
2012-02-23 21:59:32 +04:00
2012-02-23 17:11:07 +04:00
if ( ! da )
return 1 ;
2012-08-11 12:37:28 +04:00
dm_snprintf ( id , 32 , " da%d " , b - > i ) ;
if ( ! ( cn = make_config_node ( b - > cft , id , b - > cft - > root , b - > pre_sib ) ) )
return 0 ;
2012-09-09 23:57:59 +04:00
if ( ! config_make_nodes ( b - > cft , cn , NULL ,
" offset = % " PRId64 , ( int64_t ) da - > offset ,
" size = % " PRId64 , ( int64_t ) da - > size ,
NULL ) )
2012-08-11 12:37:28 +04:00
return 0 ;
2012-02-23 17:11:07 +04:00
b - > i + + ;
2012-08-11 12:37:28 +04:00
b - > pre_sib = cn ; /* for efficiency */
2012-02-23 21:59:32 +04:00
2012-02-23 17:11:07 +04:00
return 1 ;
}
2012-08-11 12:37:28 +04:00
static int _extract_mdas ( struct lvmcache_info * info , struct dm_config_tree * cft ,
struct dm_config_node * pre_sib )
2012-02-23 17:11:07 +04:00
{
2012-08-11 12:37:28 +04:00
struct _extract_mda_baton baton = { . i = 0 , . cft = cft , . pre_sib = NULL } ;
2012-02-23 21:59:32 +04:00
2012-08-11 12:37:28 +04:00
if ( ! lvmcache_foreach_mda ( info , & _extract_mda , & baton ) )
return 0 ;
2012-02-23 17:11:07 +04:00
baton . i = 0 ;
2012-08-11 12:37:28 +04:00
if ( ! lvmcache_foreach_da ( info , & _extract_da , & baton ) )
return 0 ;
2012-02-23 21:59:32 +04:00
2012-08-11 12:37:28 +04:00
return 1 ;
2012-02-23 17:11:07 +04:00
}
int lvmetad_pv_found ( struct id pvid , struct device * device , const struct format_type * fmt ,
2012-06-27 16:59:34 +04:00
uint64_t label_sector , struct volume_group * vg , activation_handler handler )
2012-02-23 17:11:07 +04:00
{
2012-02-23 21:59:32 +04:00
char uuid [ 64 ] ;
daemon_reply reply ;
struct lvmcache_info * info ;
2012-08-11 12:37:28 +04:00
struct dm_config_tree * pvmeta , * vgmeta ;
2012-06-27 16:59:34 +04:00
const char * status ;
2012-03-03 00:46:36 +04:00
int result ;
2012-02-23 21:59:32 +04:00
2012-08-13 21:44:10 +04:00
if ( ! lvmetad_active ( ) | | test_mode ( ) )
2012-02-23 17:11:07 +04:00
return 1 ;
2012-02-27 15:32:48 +04:00
if ( ! id_write_format ( & pvid , uuid , sizeof ( uuid ) ) )
return_0 ;
2012-02-23 17:11:07 +04:00
2012-08-11 12:37:28 +04:00
pvmeta = dm_config_create ( ) ;
if ( ! pvmeta )
return_0 ;
info = lvmcache_info_from_pvid ( ( const char * ) & pvid , 0 ) ;
if ( ! ( pvmeta - > root = make_config_node ( pvmeta , " pv " , NULL , NULL ) ) ) {
dm_config_destroy ( pvmeta ) ;
return_0 ;
}
if ( ! config_make_nodes ( pvmeta , pvmeta - > root , NULL ,
2012-09-09 23:57:59 +04:00
" device = % " PRId64 , ( int64_t ) device - > dev ,
" dev_size = % " PRId64 , ( int64_t ) ( info ? lvmcache_device_size ( info ) : 0 ) ,
2012-08-11 12:37:28 +04:00
" format = %s " , fmt - > name ,
2012-09-09 23:57:59 +04:00
" label_sector = % " PRId64 , ( int64_t ) label_sector ,
2012-08-11 12:37:28 +04:00
" id = %s " , uuid ,
NULL ) )
{
dm_config_destroy ( pvmeta ) ;
2012-02-23 17:11:07 +04:00
return_0 ;
2012-02-26 12:49:40 +04:00
}
2012-08-11 12:37:28 +04:00
if ( info )
/* FIXME A more direct route would be much preferable. */
_extract_mdas ( info , pvmeta , pvmeta - > root ) ;
2012-02-23 17:11:07 +04:00
if ( vg ) {
2012-08-11 12:37:28 +04:00
if ( ! ( vgmeta = _export_vg_to_config_tree ( vg ) ) ) {
dm_config_destroy ( pvmeta ) ;
2012-02-28 15:09:06 +04:00
return_0 ;
}
2012-08-11 12:37:28 +04:00
reply = _lvmetad_send ( " pv_found " ,
" pvmeta = %t " , pvmeta ,
" vgname = %s " , vg - > name ,
" metadata = %t " , vgmeta ,
NULL ) ;
dm_config_destroy ( vgmeta ) ;
2012-02-23 17:11:07 +04:00
} else {
2012-06-21 14:43:31 +04:00
if ( handler ) {
log_error ( INTERNAL_ERROR " Handler needs existing VG. " ) ;
dm_free ( pvmeta ) ;
return 0 ;
}
2012-02-23 17:11:07 +04:00
/* There are no MDAs on this PV. */
2012-08-11 12:37:28 +04:00
reply = _lvmetad_send ( " pv_found " , " pvmeta = %t " , pvmeta , NULL ) ;
2012-02-23 17:11:07 +04:00
}
2012-08-11 12:37:28 +04:00
dm_config_destroy ( pvmeta ) ;
2012-03-03 00:46:36 +04:00
result = _lvmetad_handle_reply ( reply , " update PV " , uuid , NULL ) ;
2012-06-27 16:59:34 +04:00
2012-09-20 01:45:51 +04:00
if ( vg & & result & &
( daemon_reply_int ( reply , " seqno_after " , - 1 ) ! = vg - > seqno | |
daemon_reply_int ( reply , " seqno_after " , - 1 ) ! = daemon_reply_int ( reply , " seqno_before " , - 1 ) ) )
log_warn ( " WARNING: Inconsistent metadata found for VG %s " , vg - > name ) ;
2012-06-27 16:59:34 +04:00
if ( result & & handler ) {
status = daemon_reply_str ( reply , " status " , " <missing> " ) ;
if ( ! strcmp ( status , " partial " ) )
handler ( vg , 1 , CHANGE_AAY ) ;
else if ( ! strcmp ( status , " complete " ) )
handler ( vg , 0 , CHANGE_AAY ) ;
else if ( ! strcmp ( status , " orphan " ) )
;
else
log_error ( " Request to %s %s in lvmetad gave status %s. " ,
" update PV " , uuid , status ) ;
}
2012-03-03 00:46:36 +04:00
daemon_reply_destroy ( reply ) ;
return result ;
2012-02-23 17:11:07 +04:00
}
2012-06-27 16:59:34 +04:00
int lvmetad_pv_gone ( dev_t device , const char * pv_name , activation_handler handler )
2012-02-23 17:11:07 +04:00
{
2012-03-14 21:15:22 +04:00
daemon_reply reply ;
2012-03-03 00:46:36 +04:00
int result ;
int found ;
2012-08-13 21:44:10 +04:00
if ( ! lvmetad_active ( ) | | test_mode ( ) )
2012-02-26 12:49:40 +04:00
return 1 ;
2012-06-27 16:59:34 +04:00
/*
* TODO : automatic volume deactivation takes place here * before *
* all cached info is gone - call handler . Also , consider
* integrating existing deactivation script that deactivates
* the whole stack from top to bottom ( not yet upstream ) .
*/
2012-09-09 23:57:59 +04:00
reply = _lvmetad_send ( " pv_gone " , " device = % " PRId64 , ( int64_t ) device , NULL ) ;
2012-03-03 00:46:36 +04:00
result = _lvmetad_handle_reply ( reply , " drop PV " , pv_name , & found ) ;
/* We don't care whether or not the daemon had the PV cached. */
2012-02-23 17:11:07 +04:00
2012-03-03 00:46:36 +04:00
daemon_reply_destroy ( reply ) ;
return result ;
2012-03-02 20:58:41 +04:00
}
2012-06-27 16:59:34 +04:00
int lvmetad_pv_gone_by_dev ( struct device * dev , activation_handler handler )
2012-03-02 20:58:41 +04:00
{
2012-06-27 16:59:34 +04:00
return lvmetad_pv_gone ( dev - > dev , dev_name ( dev ) , handler ) ;
2012-02-23 17:11:07 +04:00
}
/*
2012-03-02 22:09:46 +04:00
* The following code implements pvscan - - cache .
2012-02-23 17:11:07 +04:00
*/
2012-09-10 00:05:59 +04:00
struct _lvmetad_pvscan_baton {
2012-02-23 17:11:07 +04:00
struct volume_group * vg ;
struct format_instance * fid ;
} ;
2012-09-10 00:05:59 +04:00
static int _lvmetad_pvscan_single ( struct metadata_area * mda , void * baton )
2012-02-23 17:11:07 +04:00
{
2012-09-10 00:05:59 +04:00
struct _lvmetad_pvscan_baton * b = baton ;
2012-02-29 06:35:35 +04:00
struct volume_group * this = mda - > ops - > vg_read ( b - > fid , " " , mda , 1 ) ;
2012-03-03 02:44:31 +04:00
/* FIXME Also ensure contents match etc. */
2012-02-26 17:42:50 +04:00
if ( ! b - > vg | | this - > seqno > b - > vg - > seqno )
2012-02-23 17:11:07 +04:00
b - > vg = this ;
2012-02-26 17:42:50 +04:00
else if ( b - > vg )
release_vg ( this ) ;
2012-02-29 06:35:35 +04:00
2012-02-23 17:11:07 +04:00
return 1 ;
}
2012-09-10 00:05:59 +04:00
int lvmetad_pvscan_single ( struct cmd_context * cmd , struct device * dev ,
2012-06-27 16:59:34 +04:00
activation_handler handler )
2012-02-23 17:11:07 +04:00
{
2012-02-23 21:59:32 +04:00
struct label * label ;
struct lvmcache_info * info ;
2012-09-10 00:05:59 +04:00
struct _lvmetad_pvscan_baton baton ;
2012-02-23 21:59:32 +04:00
/* Create a dummy instance. */
struct format_instance_ctx fic = { . type = 0 } ;
2012-02-23 17:11:07 +04:00
if ( ! lvmetad_active ( ) ) {
log_error ( " Cannot proceed since lvmetad is not active. " ) ;
return 0 ;
}
if ( ! label_read ( dev , & label , 0 ) ) {
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
log_print_unless_silent ( " No PV label found on %s. " , dev_name ( dev ) ) ;
2012-06-27 16:59:34 +04:00
if ( ! lvmetad_pv_gone_by_dev ( dev , handler ) )
2012-03-02 20:58:41 +04:00
goto_bad ;
2012-02-23 17:11:07 +04:00
return 1 ;
}
2012-02-23 21:59:32 +04:00
info = ( struct lvmcache_info * ) label - > info ;
2012-02-23 17:11:07 +04:00
baton . vg = NULL ;
2012-02-23 21:59:32 +04:00
baton . fid = lvmcache_fmt ( info ) - > ops - > create_instance ( lvmcache_fmt ( info ) ,
& fic ) ;
2012-02-23 17:11:07 +04:00
2012-06-21 15:43:55 +04:00
if ( ! baton . fid )
goto_bad ;
2012-09-10 00:05:59 +04:00
lvmcache_foreach_mda ( info , _lvmetad_pvscan_single , & baton ) ;
2012-10-10 23:49:40 +04:00
/* LVM1 VGs have no MDAs. */
if ( ! baton . vg & & lvmcache_fmt ( info ) = = get_format_by_name ( cmd , " lvm1 " ) )
baton . vg = ( ( struct metadata_area * ) dm_list_first ( & baton . fid - > metadata_areas_in_use ) ) - >
ops - > vg_read ( baton . fid , lvmcache_vgname_from_info ( info ) , NULL , 0 ) ;
2012-02-26 17:42:50 +04:00
if ( ! baton . vg )
lvmcache_fmt ( info ) - > ops - > destroy_instance ( baton . fid ) ;
2012-02-23 17:11:07 +04:00
/*
* NB . If this command failed and we are relying on lvmetad to have an
* * exact * image of the system , the lvmetad instance that went out of
* sync needs to be killed .
*/
if ( ! lvmetad_pv_found ( * ( struct id * ) dev - > pvid , dev , lvmcache_fmt ( info ) ,
2012-06-27 16:59:34 +04:00
label - > sector , baton . vg , handler ) ) {
2012-03-02 20:58:41 +04:00
release_vg ( baton . vg ) ;
goto_bad ;
}
2012-02-23 17:11:07 +04:00
release_vg ( baton . vg ) ;
return 1 ;
2012-03-02 20:58:41 +04:00
bad :
2012-02-23 17:11:07 +04:00
/* FIXME kill lvmetad automatically if we can */
log_error ( " Update of lvmetad failed. This is a serious problem. \n "
" It is strongly recommended that you restart lvmetad immediately. " ) ;
return 0 ;
}
2012-08-13 21:44:10 +04:00
2012-09-10 00:05:59 +04:00
int lvmetad_pvscan_all_devs ( struct cmd_context * cmd , activation_handler handler )
2012-08-13 21:44:10 +04:00
{
struct dev_iter * iter ;
struct device * dev ;
2012-09-20 01:18:28 +04:00
daemon_reply reply ;
2012-08-13 21:44:10 +04:00
int r = 1 ;
2012-10-08 14:21:36 +04:00
char * future_token ;
2012-08-13 21:44:10 +04:00
if ( ! ( iter = dev_iter_create ( cmd - > lvmetad_filter , 1 ) ) ) {
log_error ( " dev_iter creation failed " ) ;
return 0 ;
}
2012-10-08 14:21:36 +04:00
future_token = _lvmetad_token ;
_lvmetad_token = ( char * ) " update in progress " ;
if ( ! _token_update ( ) ) {
_lvmetad_token = future_token ;
return 0 ;
}
2012-09-20 01:18:28 +04:00
reply = _lvmetad_send ( " pv_clear_all " , NULL ) ;
if ( ! _lvmetad_handle_reply ( reply , " clear status on all PVs " , " " , NULL ) )
r = 0 ;
daemon_reply_destroy ( reply ) ;
2012-08-13 21:44:10 +04:00
while ( ( dev = dev_iter_get ( iter ) ) ) {
2012-10-08 14:21:36 +04:00
if ( ! lvmetad_pvscan_single ( cmd , dev , handler ) )
2012-08-13 21:44:10 +04:00
r = 0 ;
if ( sigint_caught ( ) )
break ;
}
dev_iter_destroy ( iter ) ;
2012-10-08 14:21:36 +04:00
_lvmetad_token = future_token ;
if ( ! _token_update ( ) )
return 0 ;
2012-08-13 21:44:10 +04:00
return r ;
}