2002-11-18 16:53:58 +03:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2011-08-11 21:24:23 +04:00
* Copyright ( C ) 2004 - 2011 Red Hat , Inc . All rights reserved .
2002-11-18 16:53:58 +03:00
*
2004-03-30 23:35:44 +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
2007-08-21 00:55:30 +04:00
* of the GNU Lesser General Public License v .2 .1 .
2004-03-30 23:35:44 +04:00
*
2007-08-21 00:55:30 +04:00
* You should have received a copy of the GNU Lesser General Public License
2004-03-30 23:35:44 +04:00
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
2002-11-18 16:53:58 +03:00
*/
# include "lib.h"
2003-07-05 02:34:56 +04:00
# include "lvmcache.h"
2002-11-18 16:53:58 +03:00
# include "toolcontext.h"
# include "dev-cache.h"
2008-04-03 22:56:40 +04:00
# include "locking.h"
2002-11-18 16:53:58 +03:00
# include "metadata.h"
2003-07-05 02:34:56 +04:00
# include "memlock.h"
2003-10-16 00:04:29 +04:00
# include "str_list.h"
2008-05-08 22:28:27 +04:00
# include "format-text.h"
# include "format_pool.h"
# include "format1.h"
2011-01-10 16:13:42 +03:00
# include "config.h"
2003-01-07 00:10:43 +03:00
2012-02-23 17:11:07 +04:00
# include "lvmetad.h"
2012-02-10 05:28:27 +04:00
# define CACHE_INVALID 0x00000001
# define CACHE_LOCKED 0x00000002
/* One per device */
struct lvmcache_info {
struct dm_list list ; /* Join VG members together */
struct dm_list mdas ; /* list head for metadata areas */
struct dm_list das ; /* list head for data areas */
2013-05-28 14:37:22 +04:00
struct dm_list bas ; /* list head for bootloader areas */
2012-02-10 05:28:27 +04:00
struct lvmcache_vginfo * vginfo ; /* NULL == unknown */
struct label * label ;
const struct format_type * fmt ;
struct device * dev ;
uint64_t device_size ; /* Bytes */
uint32_t status ;
} ;
/* One per VG */
struct lvmcache_vginfo {
struct dm_list list ; /* Join these vginfos together */
struct dm_list infos ; /* List head for lvmcache_infos */
const struct format_type * fmt ;
char * vgname ; /* "" == orphan */
uint32_t status ;
char vgid [ ID_LEN + 1 ] ;
char _padding [ 7 ] ;
struct lvmcache_vginfo * next ; /* Another VG with same name? */
char * creation_host ;
size_t vgmetadata_size ;
char * vgmetadata ; /* Copy of VG metadata as format_text string */
struct dm_config_tree * cft ; /* Config tree created from vgmetadata */
/* Lifetime is directly tied to vgmetadata */
struct volume_group * cached_vg ;
unsigned holders ;
unsigned vg_use_count ; /* Counter of vg reusage */
unsigned precommitted ; /* Is vgmetadata live or precommitted? */
} ;
2005-10-17 03:03:59 +04:00
static struct dm_hash_table * _pvid_hash = NULL ;
static struct dm_hash_table * _vgid_hash = NULL ;
static struct dm_hash_table * _vgname_hash = NULL ;
static struct dm_hash_table * _lock_hash = NULL ;
2010-04-30 16:54:31 +04:00
static DM_LIST_INIT ( _vginfos ) ;
2008-05-29 02:27:47 +04:00
static int _scanning_in_progress = 0 ;
2003-07-05 02:34:56 +04:00
static int _has_scanned = 0 ;
static int _vgs_locked = 0 ;
2008-04-03 22:56:40 +04:00
static int _vg_global_lock_held = 0 ; /* Global lock held when cache wiped? */
2002-11-18 16:53:58 +03:00
2003-07-05 02:34:56 +04:00
int lvmcache_init ( void )
2002-11-18 16:53:58 +03:00
{
2010-01-11 22:08:18 +03:00
/*
* FIXME add a proper lvmcache_locking_reset ( ) that
* resets the cache so no previous locks are locked
*/
_vgs_locked = 0 ;
2008-11-04 01:14:30 +03:00
dm_list_init ( & _vginfos ) ;
2002-11-18 16:53:58 +03:00
2005-10-17 03:03:59 +04:00
if ( ! ( _vgname_hash = dm_hash_create ( 128 ) ) )
2002-11-18 16:53:58 +03:00
return 0 ;
2005-10-17 03:03:59 +04:00
if ( ! ( _vgid_hash = dm_hash_create ( 128 ) ) )
2002-11-18 16:53:58 +03:00
return 0 ;
2005-10-17 03:03:59 +04:00
if ( ! ( _pvid_hash = dm_hash_create ( 128 ) ) )
2002-11-18 16:53:58 +03:00
return 0 ;
2005-10-17 03:03:59 +04:00
if ( ! ( _lock_hash = dm_hash_create ( 128 ) ) )
2003-07-05 02:34:56 +04:00
return 0 ;
2009-10-22 21:33:09 +04:00
/*
* Reinitialising the cache clears the internal record of
* which locks are held . The global lock can be held during
* this operation so its state must be restored afterwards .
*/
if ( _vg_global_lock_held ) {
2008-04-03 22:56:40 +04:00
lvmcache_lock_vgname ( VG_GLOBAL , 0 ) ;
2009-10-22 21:33:09 +04:00
_vg_global_lock_held = 0 ;
}
2008-04-03 22:56:40 +04:00
2002-11-18 16:53:58 +03:00
return 1 ;
}
2012-02-23 17:11:07 +04:00
void lvmcache_seed_infos_from_lvmetad ( struct cmd_context * cmd )
{
2012-02-28 22:20:17 +04:00
if ( ! lvmetad_active ( ) | | _has_scanned )
return ;
if ( ! lvmetad_pv_list_to_lvmcache ( cmd ) ) {
stack ;
return ;
2012-02-23 17:11:07 +04:00
}
2012-02-28 22:20:17 +04:00
_has_scanned = 1 ;
2012-03-28 15:11:25 +04:00
}
2012-02-23 17:11:07 +04:00
2008-04-02 02:40:13 +04:00
/* Volume Group metadata cache functions */
static void _free_cached_vgmetadata ( struct lvmcache_vginfo * vginfo )
{
if ( ! vginfo | | ! vginfo - > vgmetadata )
return ;
dm_free ( vginfo - > vgmetadata ) ;
vginfo - > vgmetadata = NULL ;
2011-01-10 16:15:57 +03:00
/* Release also cached config tree */
if ( vginfo - > cft ) {
2011-12-19 01:56:03 +04:00
dm_config_destroy ( vginfo - > cft ) ;
2011-01-10 16:15:57 +03:00
vginfo - > cft = NULL ;
}
2013-01-08 02:30:29 +04:00
log_debug_cache ( " Metadata cache: VG %s wiped. " , vginfo - > vgname ) ;
2011-08-11 21:24:23 +04:00
release_vg ( vginfo - > cached_vg ) ;
2008-04-02 02:40:13 +04:00
}
2009-02-17 21:56:41 +03:00
/*
* Cache VG metadata against the vginfo with matching vgid .
*/
static void _store_metadata ( struct volume_group * vg , unsigned precommitted )
2008-04-02 02:40:13 +04:00
{
2010-07-09 19:34:40 +04:00
char uuid [ 64 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2009-02-17 21:56:41 +03:00
struct lvmcache_vginfo * vginfo ;
2011-03-30 17:14:34 +04:00
char * data ;
2011-09-01 14:25:22 +04:00
size_t size ;
2008-04-02 02:40:13 +04:00
2012-02-10 05:28:27 +04:00
if ( ! ( vginfo = lvmcache_vginfo_from_vgid ( ( const char * ) & vg - > id ) ) ) {
2009-02-17 21:56:41 +03:00
stack ;
return ;
}
2011-03-30 17:14:34 +04:00
if ( ! ( size = export_vg_to_buffer ( vg , & data ) ) ) {
2008-04-02 02:40:13 +04:00
stack ;
2011-03-30 17:14:34 +04:00
_free_cached_vgmetadata ( vginfo ) ;
2008-04-02 02:40:13 +04:00
return ;
}
2011-03-30 17:14:34 +04:00
/* Avoid reparsing of the same data string */
if ( vginfo - > vgmetadata & & vginfo - > vgmetadata_size = = size & &
strcmp ( vginfo - > vgmetadata , data ) = = 0 )
dm_free ( data ) ;
else {
_free_cached_vgmetadata ( vginfo ) ;
vginfo - > vgmetadata_size = size ;
vginfo - > vgmetadata = data ;
}
2008-04-02 02:40:13 +04:00
vginfo - > precommitted = precommitted ;
2009-02-17 21:56:41 +03:00
if ( ! id_write_format ( ( const struct id * ) vginfo - > vgid , uuid , sizeof ( uuid ) ) ) {
stack ;
return ;
}
2013-01-08 02:30:29 +04:00
log_debug_cache ( " Metadata cache: VG %s (%s) stored (% " PRIsize_t " bytes%s). " ,
vginfo - > vgname , uuid , size ,
precommitted ? " , precommitted " : " " ) ;
2008-04-02 02:40:13 +04:00
}
static void _update_cache_info_lock_state ( struct lvmcache_info * info ,
int locked ,
int * cached_vgmetadata_valid )
2008-01-30 02:45:48 +03:00
{
int was_locked = ( info - > status & CACHE_LOCKED ) ? 1 : 0 ;
/*
2008-09-16 22:05:11 +04:00
* Cache becomes invalid whenever lock state changes unless
* exclusive VG_GLOBAL is held ( i . e . while scanning ) .
2008-01-30 02:45:48 +03:00
*/
2012-02-10 05:28:27 +04:00
if ( ! lvmcache_vgname_is_locked ( VG_GLOBAL ) & & ( was_locked ! = locked ) ) {
2008-01-30 02:45:48 +03:00
info - > status | = CACHE_INVALID ;
2008-04-02 02:40:13 +04:00
* cached_vgmetadata_valid = 0 ;
}
2008-01-30 02:45:48 +03:00
if ( locked )
info - > status | = CACHE_LOCKED ;
else
info - > status & = ~ CACHE_LOCKED ;
}
static void _update_cache_vginfo_lock_state ( struct lvmcache_vginfo * vginfo ,
int locked )
{
struct lvmcache_info * info ;
2008-04-02 02:40:13 +04:00
int cached_vgmetadata_valid = 1 ;
2008-01-30 02:45:48 +03:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( info , & vginfo - > infos )
2008-04-02 02:40:13 +04:00
_update_cache_info_lock_state ( info , locked ,
& cached_vgmetadata_valid ) ;
if ( ! cached_vgmetadata_valid )
_free_cached_vgmetadata ( vginfo ) ;
2008-01-30 02:45:48 +03:00
}
static void _update_cache_lock_state ( const char * vgname , int locked )
{
struct lvmcache_vginfo * vginfo ;
2012-02-10 05:28:27 +04:00
if ( ! ( vginfo = lvmcache_vginfo_from_vgname ( vgname , NULL ) ) )
2008-01-30 02:45:48 +03:00
return ;
_update_cache_vginfo_lock_state ( vginfo , locked ) ;
}
2010-01-05 19:06:42 +03:00
static void _drop_metadata ( const char * vgname , int drop_precommitted )
2008-04-15 18:46:19 +04:00
{
struct lvmcache_vginfo * vginfo ;
2008-05-08 22:28:27 +04:00
struct lvmcache_info * info ;
2008-04-15 18:46:19 +04:00
2012-02-10 05:28:27 +04:00
if ( ! ( vginfo = lvmcache_vginfo_from_vgname ( vgname , NULL ) ) )
2008-04-15 18:46:19 +04:00
return ;
2008-05-08 22:28:27 +04:00
/*
* Invalidate cached PV labels .
* If cached precommitted metadata exists that means we
* already invalidated the PV labels ( before caching it )
* and we must not do it again .
*/
2010-01-05 19:06:42 +03:00
if ( ! drop_precommitted & & vginfo - > precommitted & & ! vginfo - > vgmetadata )
log_error ( INTERNAL_ERROR " metadata commit (or revert) missing before "
" dropping metadata from cache. " ) ;
2008-05-08 22:28:27 +04:00
2010-01-05 19:06:42 +03:00
if ( drop_precommitted | | ! vginfo - > precommitted )
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( info , & vginfo - > infos )
2008-05-08 22:28:27 +04:00
info - > status | = CACHE_INVALID ;
2008-04-15 18:46:19 +04:00
_free_cached_vgmetadata ( vginfo ) ;
2011-12-09 03:18:00 +04:00
/* VG revert */
if ( drop_precommitted )
vginfo - > precommitted = 0 ;
2008-04-15 18:46:19 +04:00
}
2010-01-05 19:06:42 +03:00
/*
* Remote node uses this to upgrade precommited metadata to commited state
* when receives vg_commit notification .
* ( Note that devices can be suspended here , if so , precommited metadata are already read . )
*/
void lvmcache_commit_metadata ( const char * vgname )
{
struct lvmcache_vginfo * vginfo ;
2012-02-10 05:28:27 +04:00
if ( ! ( vginfo = lvmcache_vginfo_from_vgname ( vgname , NULL ) ) )
2010-01-05 19:06:42 +03:00
return ;
if ( vginfo - > precommitted ) {
2013-01-08 02:30:29 +04:00
log_debug_cache ( " Precommitted metadata cache: VG %s upgraded to committed. " ,
vginfo - > vgname ) ;
2010-01-05 19:06:42 +03:00
vginfo - > precommitted = 0 ;
}
}
void lvmcache_drop_metadata ( const char * vgname , int drop_precommitted )
2008-05-08 22:28:27 +04:00
{
/* For VG_ORPHANS, we need to invalidate all labels on orphan PVs. */
2008-05-09 19:13:20 +04:00
if ( ! strcmp ( vgname , VG_ORPHANS ) ) {
2010-01-05 19:06:42 +03:00
_drop_metadata ( FMT_TEXT_ORPHAN_VG_NAME , 0 ) ;
_drop_metadata ( FMT_LVM1_ORPHAN_VG_NAME , 0 ) ;
_drop_metadata ( FMT_POOL_ORPHAN_VG_NAME , 0 ) ;
2008-05-09 22:45:15 +04:00
/* Indicate that PVs could now be missing from the cache */
init_full_scan_done ( 0 ) ;
2012-02-10 05:28:27 +04:00
} else if ( ! lvmcache_vgname_is_locked ( VG_GLOBAL ) )
2010-01-05 19:06:42 +03:00
_drop_metadata ( vgname , drop_precommitted ) ;
2008-05-08 22:28:27 +04:00
}
2009-09-03 01:34:11 +04:00
/*
* Ensure vgname2 comes after vgname1 alphabetically .
2010-05-19 06:08:50 +04:00
* Orphan locks come last .
* VG_GLOBAL comes first .
2009-09-03 01:34:11 +04:00
*/
static int _vgname_order_correct ( const char * vgname1 , const char * vgname2 )
{
2010-05-19 06:08:50 +04:00
if ( is_global_vg ( vgname1 ) )
return 1 ;
if ( is_global_vg ( vgname2 ) )
return 0 ;
if ( is_orphan_vg ( vgname1 ) )
return 0 ;
if ( is_orphan_vg ( vgname2 ) )
2009-09-03 01:34:11 +04:00
return 1 ;
if ( strcmp ( vgname1 , vgname2 ) < 0 )
return 1 ;
2009-09-15 17:49:10 +04:00
2009-09-03 01:34:11 +04:00
return 0 ;
}
/*
* Ensure VG locks are acquired in alphabetical order .
*/
int lvmcache_verify_lock_order ( const char * vgname )
{
struct dm_hash_node * n ;
const char * vgname2 ;
if ( ! _lock_hash )
return_0 ;
dm_hash_iterate ( n , _lock_hash ) {
if ( ! dm_hash_get_data ( _lock_hash , n ) )
return_0 ;
2009-09-15 17:49:10 +04:00
2012-02-13 18:26:15 +04:00
if ( ! ( vgname2 = dm_hash_get_key ( _lock_hash , n ) ) ) {
log_error ( INTERNAL_ERROR " VG lock %s hits NULL. " ,
vgname ) ;
return 0 ;
}
2009-09-15 17:49:10 +04:00
2009-09-03 01:34:11 +04:00
if ( ! _vgname_order_correct ( vgname2 , vgname ) ) {
2009-12-16 22:22:11 +03:00
log_errno ( EDEADLK , INTERNAL_ERROR " VG lock %s must "
2009-09-03 01:34:11 +04:00
" be requested before %s, not after. " ,
vgname , vgname2 ) ;
2012-02-13 18:26:15 +04:00
return 0 ;
2009-09-03 01:34:11 +04:00
}
}
2009-09-15 17:49:10 +04:00
2009-09-03 01:34:11 +04:00
return 1 ;
}
2010-07-09 19:34:40 +04:00
void lvmcache_lock_vgname ( const char * vgname , int read_only __attribute__ ( ( unused ) ) )
2002-11-18 16:53:58 +03:00
{
2003-07-05 02:34:56 +04:00
if ( ! _lock_hash & & ! lvmcache_init ( ) ) {
log_error ( " Internal cache initialisation failed " ) ;
return ;
}
2008-04-03 22:56:40 +04:00
if ( dm_hash_lookup ( _lock_hash , vgname ) )
2009-12-16 22:22:11 +03:00
log_error ( INTERNAL_ERROR " Nested locking attempted on VG %s. " ,
2008-04-03 22:56:40 +04:00
vgname ) ;
2009-09-03 01:34:11 +04:00
2005-10-17 03:03:59 +04:00
if ( ! dm_hash_insert ( _lock_hash , vgname , ( void * ) 1 ) )
2003-07-05 02:34:56 +04:00
log_error ( " Cache locking failure for %s " , vgname ) ;
2008-01-30 02:45:48 +03:00
_update_cache_lock_state ( vgname , 1 ) ;
2008-04-24 06:22:07 +04:00
if ( strcmp ( vgname , VG_GLOBAL ) )
_vgs_locked + + ;
2003-07-05 02:34:56 +04:00
}
2012-02-10 05:28:27 +04:00
int lvmcache_vgname_is_locked ( const char * vgname )
2003-07-05 02:34:56 +04:00
{
if ( ! _lock_hash )
return 0 ;
2010-05-19 05:16:40 +04:00
return dm_hash_lookup ( _lock_hash , is_orphan_vg ( vgname ) ? VG_ORPHANS : vgname ) ? 1 : 0 ;
2003-07-05 02:34:56 +04:00
}
void lvmcache_unlock_vgname ( const char * vgname )
{
2008-04-03 22:56:40 +04:00
if ( ! dm_hash_lookup ( _lock_hash , vgname ) )
2009-12-16 22:22:11 +03:00
log_error ( INTERNAL_ERROR " Attempt to unlock unlocked VG %s. " ,
2008-04-03 22:56:40 +04:00
vgname ) ;
2008-01-30 02:45:48 +03:00
_update_cache_lock_state ( vgname , 0 ) ;
2005-10-17 03:03:59 +04:00
dm_hash_remove ( _lock_hash , vgname ) ;
2003-07-05 02:34:56 +04:00
/* FIXME Do this per-VG */
2008-04-24 06:22:07 +04:00
if ( strcmp ( vgname , VG_GLOBAL ) & & ! - - _vgs_locked )
2003-07-05 02:34:56 +04:00
dev_close_all ( ) ;
}
2012-02-10 05:28:27 +04:00
int lvmcache_vgs_locked ( void )
2003-07-05 02:34:56 +04:00
{
return _vgs_locked ;
}
2008-05-19 23:49:56 +04:00
static void _vginfo_attach_info ( struct lvmcache_vginfo * vginfo ,
struct lvmcache_info * info )
{
2008-05-29 02:27:47 +04:00
if ( ! vginfo )
return ;
2008-05-19 23:49:56 +04:00
info - > vginfo = vginfo ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & vginfo - > infos , & info - > list ) ;
2008-05-19 23:49:56 +04:00
}
static void _vginfo_detach_info ( struct lvmcache_info * info )
{
2008-11-04 01:14:30 +03:00
if ( ! dm_list_empty ( & info - > list ) ) {
dm_list_del ( & info - > list ) ;
dm_list_init ( & info - > list ) ;
2008-05-19 23:49:56 +04:00
}
info - > vginfo = NULL ;
}
2006-04-12 21:54:11 +04:00
/* If vgid supplied, require a match. */
2012-02-10 05:28:27 +04:00
struct lvmcache_vginfo * lvmcache_vginfo_from_vgname ( const char * vgname , const char * vgid )
2003-07-05 02:34:56 +04:00
{
struct lvmcache_vginfo * vginfo ;
2002-11-18 16:53:58 +03:00
2008-06-06 15:12:50 +04:00
if ( ! vgname )
2012-02-10 05:28:27 +04:00
return lvmcache_vginfo_from_vgid ( vgid ) ;
2008-06-06 15:12:50 +04:00
2002-11-18 16:53:58 +03:00
if ( ! _vgname_hash )
return NULL ;
2005-10-17 03:03:59 +04:00
if ( ! ( vginfo = dm_hash_lookup ( _vgname_hash , vgname ) ) )
2002-11-18 16:53:58 +03:00
return NULL ;
2006-04-12 21:54:11 +04:00
if ( vgid )
2008-01-30 17:00:02 +03:00
do
2006-04-21 18:44:33 +04:00
if ( ! strncmp ( vgid , vginfo - > vgid , ID_LEN ) )
2006-04-12 21:54:11 +04:00
return vginfo ;
while ( ( vginfo = vginfo - > next ) ) ;
2002-11-18 16:53:58 +03:00
return vginfo ;
}
2012-02-23 17:11:07 +04:00
const struct format_type * lvmcache_fmt_from_vgname ( struct cmd_context * cmd ,
const char * vgname , const char * vgid ,
unsigned revalidate_labels )
2002-11-18 16:53:58 +03:00
{
2003-07-05 02:34:56 +04:00
struct lvmcache_vginfo * vginfo ;
2005-06-01 20:51:55 +04:00
struct lvmcache_info * info ;
2005-03-22 01:40:35 +03:00
struct label * label ;
2008-11-04 01:14:30 +03:00
struct dm_list * devh , * tmp ;
struct dm_list devs ;
2005-03-22 01:40:35 +03:00
struct device_list * devl ;
2012-02-24 02:23:12 +04:00
struct volume_group * vg ;
const struct format_type * fmt ;
2010-07-09 19:34:40 +04:00
char vgid_found [ ID_LEN + 1 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2002-11-18 16:53:58 +03:00
2012-02-23 17:11:07 +04:00
if ( ! ( vginfo = lvmcache_vginfo_from_vgname ( vgname , vgid ) ) ) {
if ( ! lvmetad_active ( ) )
return NULL ; /* too bad */
/* If we don't have the info but we have lvmetad, we can ask
* there before failing . */
2012-02-24 02:23:12 +04:00
if ( ( vg = lvmetad_vg_lookup ( cmd , vgname , vgid ) ) ) {
fmt = vg - > fid - > fmt ;
2012-02-23 17:11:07 +04:00
release_vg ( vg ) ;
return fmt ;
}
2002-11-18 16:53:58 +03:00
return NULL ;
2012-02-23 17:11:07 +04:00
}
2002-11-18 16:53:58 +03:00
2010-12-11 01:39:52 +03:00
/*
* If this function is called repeatedly , only the first one needs to revalidate .
*/
if ( ! revalidate_labels )
goto out ;
/*
* This function is normally called before reading metadata so
* we check cached labels here . Unfortunately vginfo is volatile .
*/
2008-11-04 01:14:30 +03:00
dm_list_init ( & devs ) ;
dm_list_iterate_items ( info , & vginfo - > infos ) {
2006-05-10 21:49:25 +04:00
if ( ! ( devl = dm_malloc ( sizeof ( * devl ) ) ) ) {
log_error ( " device_list element allocation failed " ) ;
return NULL ;
}
2005-06-01 20:51:55 +04:00
devl - > dev = info - > dev ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & devs , & devl - > list ) ;
2005-03-22 01:40:35 +03:00
}
2006-04-13 01:23:04 +04:00
memcpy ( vgid_found , vginfo - > vgid , sizeof ( vgid_found ) ) ;
2006-04-12 21:54:11 +04:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_safe ( devh , tmp , & devs ) {
devl = dm_list_item ( devh , struct device_list ) ;
2012-03-02 01:57:43 +04:00
( void ) label_read ( devl - > dev , & label , UINT64_C ( 0 ) ) ;
2008-11-04 01:14:30 +03:00
dm_list_del ( & devl - > list ) ;
2005-10-17 03:03:59 +04:00
dm_free ( devl ) ;
2005-03-22 01:40:35 +03:00
}
2006-04-12 21:54:11 +04:00
/* If vginfo changed, caller needs to rescan */
2012-02-10 05:28:27 +04:00
if ( ! ( vginfo = lvmcache_vginfo_from_vgname ( vgname , vgid_found ) ) | |
2006-04-21 18:44:33 +04:00
strncmp ( vginfo - > vgid , vgid_found , ID_LEN ) )
2006-04-12 21:54:11 +04:00
return NULL ;
2010-12-11 01:39:52 +03:00
out :
2002-11-18 16:53:58 +03:00
return vginfo - > fmt ;
}
2012-02-10 05:28:27 +04:00
struct lvmcache_vginfo * lvmcache_vginfo_from_vgid ( const char * vgid )
2002-11-18 16:53:58 +03:00
{
2003-07-05 02:34:56 +04:00
struct lvmcache_vginfo * vginfo ;
2010-07-09 19:34:40 +04:00
char id [ ID_LEN + 1 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2002-11-18 16:53:58 +03:00
if ( ! _vgid_hash | | ! vgid )
return NULL ;
2003-01-10 22:14:01 +03:00
/* vgid not necessarily NULL-terminated */
strncpy ( & id [ 0 ] , vgid , ID_LEN ) ;
id [ ID_LEN ] = ' \0 ' ;
2005-10-17 03:03:59 +04:00
if ( ! ( vginfo = dm_hash_lookup ( _vgid_hash , id ) ) )
2002-11-18 16:53:58 +03:00
return NULL ;
return vginfo ;
}
2012-02-10 05:28:27 +04:00
const char * lvmcache_vgname_from_vgid ( struct dm_pool * mem , const char * vgid )
2006-04-13 01:23:04 +04:00
{
struct lvmcache_vginfo * vginfo ;
2006-06-15 00:11:22 +04:00
const char * vgname = NULL ;
2006-04-13 01:23:04 +04:00
2012-02-10 05:28:27 +04:00
if ( ( vginfo = lvmcache_vginfo_from_vgid ( vgid ) ) )
2006-06-15 00:11:22 +04:00
vgname = vginfo - > vgname ;
if ( mem & & vgname )
return dm_pool_strdup ( mem , vgname ) ;
2006-04-13 01:23:04 +04:00
2006-06-15 00:11:22 +04:00
return vgname ;
2006-04-13 01:23:04 +04:00
}
2008-01-30 02:45:48 +03:00
static int _info_is_valid ( struct lvmcache_info * info )
{
if ( info - > status & CACHE_INVALID )
return 0 ;
2008-01-30 19:18:37 +03:00
/*
* The caller must hold the VG lock to manipulate metadata .
* In a cluster , remote nodes sometimes read metadata in the
* knowledge that the controlling node is holding the lock .
* So if the VG appears to be unlocked here , it should be safe
* to use the cached value .
*/
2012-02-10 05:28:27 +04:00
if ( info - > vginfo & & ! lvmcache_vgname_is_locked ( info - > vginfo - > vgname ) )
2008-01-30 19:18:37 +03:00
return 1 ;
2008-01-30 02:45:48 +03:00
if ( ! ( info - > status & CACHE_LOCKED ) )
return 0 ;
return 1 ;
}
2008-04-02 02:40:13 +04:00
static int _vginfo_is_valid ( struct lvmcache_vginfo * vginfo )
{
struct lvmcache_info * info ;
2008-05-19 23:49:56 +04:00
/* Invalid if any info is invalid */
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( info , & vginfo - > infos )
2008-04-02 02:40:13 +04:00
if ( ! _info_is_valid ( info ) )
return 0 ;
return 1 ;
}
2008-05-29 02:27:47 +04:00
/* vginfo is invalid if it does not contain at least one valid info */
static int _vginfo_is_invalid ( struct lvmcache_vginfo * vginfo )
{
struct lvmcache_info * info ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( info , & vginfo - > infos )
2008-05-29 02:27:47 +04:00
if ( _info_is_valid ( info ) )
return 0 ;
return 1 ;
}
2008-01-30 02:45:48 +03:00
/*
* If valid_only is set , data will only be returned if the cached data is
* known still to be valid .
*/
2012-02-10 05:28:27 +04:00
struct lvmcache_info * lvmcache_info_from_pvid ( const char * pvid , int valid_only )
2002-11-18 16:53:58 +03:00
{
2003-07-05 02:34:56 +04:00
struct lvmcache_info * info ;
2010-07-09 19:34:40 +04:00
char id [ ID_LEN + 1 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2002-11-18 16:53:58 +03:00
if ( ! _pvid_hash | | ! pvid )
return NULL ;
2003-01-10 22:14:01 +03:00
strncpy ( & id [ 0 ] , pvid , ID_LEN ) ;
id [ ID_LEN ] = ' \0 ' ;
2005-10-17 03:03:59 +04:00
if ( ! ( info = dm_hash_lookup ( _pvid_hash , id ) ) )
2002-11-18 16:53:58 +03:00
return NULL ;
2008-01-30 02:45:48 +03:00
if ( valid_only & & ! _info_is_valid ( info ) )
return NULL ;
2002-11-18 16:53:58 +03:00
return info ;
}
2012-02-23 17:11:07 +04:00
const char * lvmcache_vgname_from_info ( struct lvmcache_info * info )
{
if ( info - > vginfo )
return info - > vginfo - > vgname ;
return NULL ;
}
2010-05-19 15:52:21 +04:00
char * lvmcache_vgname_from_pvid ( struct cmd_context * cmd , const char * pvid )
{
struct lvmcache_info * info ;
char * vgname ;
2012-02-10 05:28:27 +04:00
if ( ! lvmcache_device_from_pvid ( cmd , ( const struct id * ) pvid , NULL , NULL ) ) {
2010-05-19 15:52:21 +04:00
log_error ( " Couldn't find device with uuid %s. " , pvid ) ;
return NULL ;
}
2012-02-10 05:28:27 +04:00
info = lvmcache_info_from_pvid ( pvid , 0 ) ;
2010-05-19 15:52:21 +04:00
if ( ! info )
return_NULL ;
if ( ! ( vgname = dm_pool_strdup ( cmd - > mem , info - > vginfo - > vgname ) ) ) {
log_errno ( ENOMEM , " vgname allocation failed " ) ;
return NULL ;
}
return vgname ;
}
2003-07-05 02:34:56 +04:00
static void _rescan_entry ( struct lvmcache_info * info )
2002-11-18 16:53:58 +03:00
{
struct label * label ;
if ( info - > status & CACHE_INVALID )
2012-02-28 14:10:07 +04:00
( void ) label_read ( info - > dev , & label , UINT64_C ( 0 ) ) ;
2002-11-18 16:53:58 +03:00
}
2002-12-20 02:25:55 +03:00
static int _scan_invalid ( void )
2002-11-18 16:53:58 +03:00
{
2005-10-17 03:03:59 +04:00
dm_hash_iter ( _pvid_hash , ( dm_hash_iterate_fn ) _rescan_entry ) ;
2002-11-18 16:53:58 +03:00
return 1 ;
}
2003-07-05 02:34:56 +04:00
int lvmcache_label_scan ( struct cmd_context * cmd , int full_scan )
2002-11-18 16:53:58 +03:00
{
struct label * label ;
struct dev_iter * iter ;
struct device * dev ;
struct format_type * fmt ;
int r = 0 ;
2012-02-23 17:11:07 +04:00
if ( lvmetad_active ( ) )
return 1 ;
2002-11-18 16:53:58 +03:00
/* Avoid recursion when a PVID can't be found! */
if ( _scanning_in_progress )
return 0 ;
_scanning_in_progress = 1 ;
2003-07-05 02:34:56 +04:00
if ( ! _vgname_hash & & ! lvmcache_init ( ) ) {
2002-11-18 16:53:58 +03:00
log_error ( " Internal cache initialisation failed " ) ;
goto out ;
}
if ( _has_scanned & & ! full_scan ) {
2002-12-20 02:25:55 +03:00
r = _scan_invalid ( ) ;
2002-11-18 16:53:58 +03:00
goto out ;
}
2011-10-11 13:09:00 +04:00
if ( full_scan = = 2 & & ( cmd - > filter & & ! cmd - > filter - > use_count ) & & ! refresh_filters ( cmd ) )
goto_out ;
2009-11-24 19:10:25 +03:00
2011-10-11 13:09:00 +04:00
if ( ! cmd - > filter | | ! ( iter = dev_iter_create ( cmd - > filter , ( full_scan = = 2 ) ? 1 : 0 ) ) ) {
2002-11-18 16:53:58 +03:00
log_error ( " dev_iter creation failed " ) ;
goto out ;
}
while ( ( dev = dev_iter_get ( iter ) ) )
2012-02-28 14:10:07 +04:00
( void ) label_read ( dev , & label , UINT64_C ( 0 ) ) ;
2002-11-18 16:53:58 +03:00
dev_iter_destroy ( iter ) ;
_has_scanned = 1 ;
/* Perform any format-specific scanning e.g. text files */
2010-12-11 01:39:52 +03:00
if ( cmd - > independent_metadata_areas )
dm_list_iterate_items ( fmt , & cmd - > formats )
if ( fmt - > ops - > scan & & ! fmt - > ops - > scan ( fmt , NULL ) )
goto out ;
2002-11-18 16:53:58 +03:00
2009-11-24 19:11:37 +03:00
/*
* If we are a long - lived process , write out the updated persistent
* device cache for the benefit of short - lived processes .
*/
2013-06-02 23:59:57 +04:00
if ( full_scan = = 2 & & cmd - > is_long_lived & &
2013-06-03 01:27:34 +04:00
cmd - > dump_filter & & cmd - > filter & & cmd - > filter - > dump & &
! cmd - > filter - > dump ( cmd - > filter , 0 ) )
stack ;
2009-11-24 19:11:37 +03:00
2002-11-18 16:53:58 +03:00
r = 1 ;
out :
_scanning_in_progress = 0 ;
return r ;
}
2012-02-23 17:11:07 +04:00
struct volume_group * lvmcache_get_vg ( struct cmd_context * cmd , const char * vgname ,
const char * vgid , unsigned precommitted )
2008-04-02 02:40:13 +04:00
{
struct lvmcache_vginfo * vginfo ;
2011-03-11 18:08:31 +03:00
struct volume_group * vg = NULL ;
2008-04-14 23:24:16 +04:00
struct format_instance * fid ;
2011-02-21 15:07:03 +03:00
struct format_instance_ctx fic ;
2008-04-02 02:40:13 +04:00
2012-02-23 17:11:07 +04:00
/*
* We currently do not store precommitted metadata in lvmetad at
* all . This means that any request for precommitted metadata is served
* using the classic scanning mechanics , and read from disk or from
* lvmcache .
*/
if ( lvmetad_active ( ) & & ! precommitted ) {
/* Still serve the locally cached VG if available */
if ( vgid & & ( vginfo = lvmcache_vginfo_from_vgid ( vgid ) ) & &
vginfo - > vgmetadata & & ( vg = vginfo - > cached_vg ) )
goto out ;
return lvmetad_vg_lookup ( cmd , vgname , vgid ) ;
}
2012-02-10 05:28:27 +04:00
if ( ! vgid | | ! ( vginfo = lvmcache_vginfo_from_vgid ( vgid ) ) | | ! vginfo - > vgmetadata )
2008-04-02 02:40:13 +04:00
return NULL ;
if ( ! _vginfo_is_valid ( vginfo ) )
return NULL ;
2008-06-05 17:06:39 +04:00
/*
* Don ' t return cached data if either :
* ( i ) precommitted metadata is requested but we don ' t have it cached
* - caller should read it off disk ;
* ( ii ) live metadata is requested but we have precommitted metadata cached
* and no devices are suspended so caller may read it off disk .
*
* If live metadata is requested but we have precommitted metadata cached
* and devices are suspended , we assume this precommitted metadata has
* already been preloaded and committed so it ' s OK to return it as live .
* Note that we do not clear the PRECOMMITTED flag .
*/
2008-04-02 02:40:13 +04:00
if ( ( precommitted & & ! vginfo - > precommitted ) | |
2011-02-18 17:16:11 +03:00
( ! precommitted & & vginfo - > precommitted & & ! critical_section ( ) ) )
2008-04-02 02:40:13 +04:00
return NULL ;
2011-08-11 21:24:23 +04:00
/* Use already-cached VG struct when available */
if ( ( vg = vginfo - > cached_vg ) )
goto out ;
2012-02-13 03:01:19 +04:00
fic . type = FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS ;
2011-02-21 15:07:03 +03:00
fic . context . vg_ref . vg_name = vginfo - > vgname ;
fic . context . vg_ref . vg_id = vgid ;
if ( ! ( fid = vginfo - > fmt - > ops - > create_instance ( vginfo - > fmt , & fic ) ) )
2008-04-15 18:57:12 +04:00
return_NULL ;
2008-04-14 23:24:16 +04:00
2011-01-10 16:15:57 +03:00
/* Build config tree from vgmetadata, if not yet cached */
if ( ! vginfo - > cft & &
! ( vginfo - > cft =
2011-08-30 18:55:15 +04:00
dm_config_from_string ( vginfo - > vgmetadata ) ) )
2011-03-11 18:08:31 +03:00
goto_bad ;
2008-04-02 02:40:13 +04:00
2011-03-11 18:08:31 +03:00
if ( ! ( vg = import_vg_from_config_tree ( vginfo - > cft , fid ) ) )
goto_bad ;
2011-01-10 16:13:42 +03:00
2011-08-11 21:24:23 +04:00
/* Cache VG struct for reuse */
vginfo - > cached_vg = vg ;
vginfo - > holders = 1 ;
vginfo - > vg_use_count = 0 ;
vg - > vginfo = vginfo ;
2011-08-11 21:46:13 +04:00
if ( ! dm_pool_lock ( vg - > vgmem , detect_internal_vg_cache_corruption ( ) ) )
2011-08-11 21:34:30 +04:00
goto_bad ;
2011-08-11 21:24:23 +04:00
out :
vginfo - > holders + + ;
vginfo - > vg_use_count + + ;
2013-01-08 02:30:29 +04:00
log_debug_cache ( " Using cached %smetadata for VG %s with %u holder(s). " ,
vginfo - > precommitted ? " pre-committed " : " " ,
vginfo - > vgname , vginfo - > holders ) ;
2008-04-02 02:40:13 +04:00
return vg ;
2011-03-11 18:08:31 +03:00
bad :
_free_cached_vgmetadata ( vginfo ) ;
return NULL ;
2008-04-02 02:40:13 +04:00
}
2012-02-10 05:28:27 +04:00
// #if 0
int lvmcache_vginfo_holders_dec_and_test_for_zero ( struct lvmcache_vginfo * vginfo )
2011-08-11 21:24:23 +04:00
{
2013-01-08 02:30:29 +04:00
log_debug_cache ( " VG %s decrementing %d holder(s) at %p. " ,
vginfo - > cached_vg - > name , vginfo - > holders , vginfo - > cached_vg ) ;
2011-08-11 21:24:23 +04:00
if ( - - vginfo - > holders )
return 0 ;
if ( vginfo - > vg_use_count > 1 )
2013-01-08 02:30:29 +04:00
log_debug_cache ( " VG %s reused %d times. " ,
vginfo - > cached_vg - > name , vginfo - > vg_use_count ) ;
2011-08-11 21:24:23 +04:00
2011-08-11 21:34:30 +04:00
/* Debug perform crc check only when it's been used more then once */
if ( ! dm_pool_unlock ( vginfo - > cached_vg - > vgmem ,
2011-08-11 21:46:13 +04:00
detect_internal_vg_cache_corruption ( ) & &
2011-08-11 21:34:30 +04:00
( vginfo - > vg_use_count > 1 ) ) )
stack ;
2011-08-11 21:24:23 +04:00
vginfo - > cached_vg - > vginfo = NULL ;
vginfo - > cached_vg = NULL ;
return 1 ;
}
2012-02-10 05:28:27 +04:00
// #endif
2011-08-11 21:24:23 +04:00
2010-03-16 19:57:03 +03:00
struct dm_list * lvmcache_get_vgids ( struct cmd_context * cmd ,
int include_internal )
2006-04-13 01:23:04 +04:00
{
2008-11-04 01:14:30 +03:00
struct dm_list * vgids ;
2006-04-13 01:23:04 +04:00
struct lvmcache_vginfo * vginfo ;
2012-02-23 17:11:07 +04:00
// TODO plug into lvmetad here automagically?
2010-03-16 19:57:03 +03:00
lvmcache_label_scan ( cmd , 0 ) ;
2006-04-13 01:23:04 +04:00
if ( ! ( vgids = str_list_create ( cmd - > mem ) ) ) {
log_error ( " vgids list allocation failed " ) ;
return NULL ;
}
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( vginfo , & _vginfos ) {
2010-02-03 17:08:39 +03:00
if ( ! include_internal & & is_orphan_vg ( vginfo - > vgname ) )
continue ;
2008-01-30 17:00:02 +03:00
if ( ! str_list_add ( cmd - > mem , vgids ,
2006-04-13 01:23:04 +04:00
dm_pool_strdup ( cmd - > mem , vginfo - > vgid ) ) ) {
log_error ( " strlist allocation failed " ) ;
return NULL ;
}
}
return vgids ;
}
2010-03-16 19:57:03 +03:00
struct dm_list * lvmcache_get_vgnames ( struct cmd_context * cmd ,
int include_internal )
2002-11-18 16:53:58 +03:00
{
2008-11-04 01:14:30 +03:00
struct dm_list * vgnames ;
2006-04-11 23:09:55 +04:00
struct lvmcache_vginfo * vginfo ;
2002-11-18 16:53:58 +03:00
2010-03-16 19:57:03 +03:00
lvmcache_label_scan ( cmd , 0 ) ;
2002-11-18 16:53:58 +03:00
2003-10-16 00:04:29 +04:00
if ( ! ( vgnames = str_list_create ( cmd - > mem ) ) ) {
2009-07-27 15:00:17 +04:00
log_errno ( ENOMEM , " vgnames list allocation failed " ) ;
2002-11-18 16:53:58 +03:00
return NULL ;
}
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( vginfo , & _vginfos ) {
2010-02-03 17:08:39 +03:00
if ( ! include_internal & & is_orphan_vg ( vginfo - > vgname ) )
continue ;
2008-01-30 17:00:02 +03:00
if ( ! str_list_add ( cmd - > mem , vgnames ,
2006-04-11 23:09:55 +04:00
dm_pool_strdup ( cmd - > mem , vginfo - > vgname ) ) ) {
2009-07-27 15:00:17 +04:00
log_errno ( ENOMEM , " strlist allocation failed " ) ;
2002-11-18 16:53:58 +03:00
return NULL ;
}
}
return vgnames ;
}
2008-11-04 01:14:30 +03:00
struct dm_list * lvmcache_get_pvids ( struct cmd_context * cmd , const char * vgname ,
2006-04-21 23:12:41 +04:00
const char * vgid )
{
2008-11-04 01:14:30 +03:00
struct dm_list * pvids ;
2006-04-21 23:12:41 +04:00
struct lvmcache_vginfo * vginfo ;
struct lvmcache_info * info ;
if ( ! ( pvids = str_list_create ( cmd - > mem ) ) ) {
log_error ( " pvids list allocation failed " ) ;
return NULL ;
}
2012-02-10 05:28:27 +04:00
if ( ! ( vginfo = lvmcache_vginfo_from_vgname ( vgname , vgid ) ) )
2006-04-21 23:12:41 +04:00
return pvids ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( info , & vginfo - > infos ) {
2008-01-30 17:00:02 +03:00
if ( ! str_list_add ( cmd - > mem , pvids ,
2006-04-21 23:12:41 +04:00
dm_pool_strdup ( cmd - > mem , info - > dev - > pvid ) ) ) {
log_error ( " strlist allocation failed " ) ;
return NULL ;
}
}
return pvids ;
}
2011-06-01 23:29:31 +04:00
static struct device * _device_from_pvid ( const struct id * pvid ,
uint64_t * label_sector )
2002-11-18 16:53:58 +03:00
{
2003-07-05 02:34:56 +04:00
struct lvmcache_info * info ;
2011-06-01 23:29:31 +04:00
struct label * label ;
2002-11-18 16:53:58 +03:00
2012-02-10 05:28:27 +04:00
if ( ( info = lvmcache_info_from_pvid ( ( const char * ) pvid , 0 ) ) ) {
2012-02-23 17:11:07 +04:00
if ( lvmetad_active ( ) ) {
if ( info - > label & & label_sector )
* label_sector = info - > label - > sector ;
return info - > dev ;
}
2007-04-23 22:21:01 +04:00
if ( label_read ( info - > dev , & label , UINT64_C ( 0 ) ) ) {
2003-07-05 02:34:56 +04:00
info = ( struct lvmcache_info * ) label - > info ;
2011-06-01 23:29:31 +04:00
if ( id_equal ( pvid , ( struct id * ) & info - > dev - > pvid ) ) {
if ( label_sector )
* label_sector = label - > sector ;
2002-11-18 16:53:58 +03:00
return info - > dev ;
2011-06-01 23:29:31 +04:00
}
2002-11-18 16:53:58 +03:00
}
}
2011-06-01 23:29:31 +04:00
return NULL ;
}
2012-02-10 05:28:27 +04:00
struct device * lvmcache_device_from_pvid ( struct cmd_context * cmd , const struct id * pvid ,
2011-06-01 23:29:31 +04:00
unsigned * scan_done_once , uint64_t * label_sector )
{
struct device * dev ;
/* Already cached ? */
dev = _device_from_pvid ( pvid , label_sector ) ;
if ( dev )
return dev ;
2002-11-18 16:53:58 +03:00
2003-07-05 02:34:56 +04:00
lvmcache_label_scan ( cmd , 0 ) ;
2002-11-18 16:53:58 +03:00
/* Try again */
2011-06-01 23:29:31 +04:00
dev = _device_from_pvid ( pvid , label_sector ) ;
if ( dev )
return dev ;
2002-11-18 16:53:58 +03:00
2011-02-18 17:16:11 +03:00
if ( critical_section ( ) | | ( scan_done_once & & * scan_done_once ) )
2003-07-05 02:34:56 +04:00
return NULL ;
2005-03-08 16:46:17 +03:00
lvmcache_label_scan ( cmd , 2 ) ;
2010-03-16 22:06:57 +03:00
if ( scan_done_once )
* scan_done_once = 1 ;
2002-11-18 16:53:58 +03:00
/* Try again */
2011-06-01 23:29:31 +04:00
dev = _device_from_pvid ( pvid , label_sector ) ;
if ( dev )
return dev ;
2002-11-18 16:53:58 +03:00
return NULL ;
}
2012-02-10 05:28:27 +04:00
const char * lvmcache_pvid_from_devname ( struct cmd_context * cmd ,
2010-05-19 15:52:07 +04:00
const char * devname )
{
struct device * dev ;
struct label * label ;
if ( ! ( dev = dev_cache_get ( devname , cmd - > filter ) ) ) {
log_error ( " %s: Couldn't find device. Check your filters? " ,
devname ) ;
return NULL ;
}
if ( ! ( label_read ( dev , & label , UINT64_C ( 0 ) ) ) )
return NULL ;
return dev - > pvid ;
}
2008-05-19 23:49:56 +04:00
static int _free_vginfo ( struct lvmcache_vginfo * vginfo )
{
2008-06-09 20:22:33 +04:00
struct lvmcache_vginfo * primary_vginfo , * vginfo2 ;
2008-05-19 23:49:56 +04:00
int r = 1 ;
_free_cached_vgmetadata ( vginfo ) ;
2012-02-10 05:28:27 +04:00
vginfo2 = primary_vginfo = lvmcache_vginfo_from_vgname ( vginfo - > vgname , NULL ) ;
2008-06-09 20:22:33 +04:00
if ( vginfo = = primary_vginfo ) {
2008-05-29 02:27:47 +04:00
dm_hash_remove ( _vgname_hash , vginfo - > vgname ) ;
if ( vginfo - > next & & ! dm_hash_insert ( _vgname_hash , vginfo - > vgname ,
vginfo - > next ) ) {
log_error ( " _vgname_hash re-insertion for %s failed " ,
vginfo - > vgname ) ;
r = 0 ;
}
2012-06-21 14:43:31 +04:00
} else
while ( vginfo2 ) {
if ( vginfo2 - > next = = vginfo ) {
vginfo2 - > next = vginfo - > next ;
break ;
}
vginfo2 = vginfo2 - > next ;
2008-06-09 20:22:33 +04:00
}
2008-05-19 23:49:56 +04:00
2011-04-21 17:15:26 +04:00
dm_free ( vginfo - > vgname ) ;
dm_free ( vginfo - > creation_host ) ;
2008-05-19 23:49:56 +04:00
2008-06-06 16:43:40 +04:00
if ( * vginfo - > vgid & & _vgid_hash & &
2012-02-10 05:28:27 +04:00
lvmcache_vginfo_from_vgid ( vginfo - > vgid ) = = vginfo )
2008-05-19 23:49:56 +04:00
dm_hash_remove ( _vgid_hash , vginfo - > vgid ) ;
2008-11-04 01:14:30 +03:00
dm_list_del ( & vginfo - > list ) ;
2008-05-19 23:49:56 +04:00
dm_free ( vginfo ) ;
return r ;
}
2008-04-08 16:49:21 +04:00
/*
* vginfo must be info - > vginfo unless info is NULL
*/
static int _drop_vginfo ( struct lvmcache_info * info , struct lvmcache_vginfo * vginfo )
2002-11-18 16:53:58 +03:00
{
2008-05-19 23:49:56 +04:00
if ( info )
_vginfo_detach_info ( info ) ;
2006-04-12 21:54:11 +04:00
2008-05-19 23:49:56 +04:00
/* vginfo still referenced? */
if ( ! vginfo | | is_orphan_vg ( vginfo - > vgname ) | |
2008-11-04 01:14:30 +03:00
! dm_list_empty ( & vginfo - > infos ) )
2008-05-19 23:49:56 +04:00
return 1 ;
2002-11-18 16:53:58 +03:00
2008-05-19 23:49:56 +04:00
if ( ! _free_vginfo ( vginfo ) )
return_0 ;
2006-04-12 21:54:11 +04:00
return 1 ;
2002-11-18 16:53:58 +03:00
}
/* Unused
2003-07-05 02:34:56 +04:00
void lvmcache_del ( struct lvmcache_info * info )
2002-11-18 16:53:58 +03:00
{
if ( info - > dev - > pvid [ 0 ] & & _pvid_hash )
2005-10-17 03:03:59 +04:00
dm_hash_remove ( _pvid_hash , info - > dev - > pvid ) ;
2002-11-18 16:53:58 +03:00
2008-04-08 16:49:21 +04:00
_drop_vginfo ( info , info - > vginfo ) ;
2002-11-18 16:53:58 +03:00
info - > label - > labeller - > ops - > destroy_label ( info - > label - > labeller ,
2008-01-30 17:00:02 +03:00
info - > label ) ;
2005-10-17 03:03:59 +04:00
dm_free ( info ) ;
2002-11-18 16:53:58 +03:00
return ;
} */
2003-07-05 02:34:56 +04:00
static int _lvmcache_update_pvid ( struct lvmcache_info * info , const char * pvid )
2002-11-18 16:53:58 +03:00
{
2008-11-27 21:13:50 +03:00
/*
* Nothing to do if already stored with same pvid .
*/
2012-02-10 05:28:27 +04:00
2008-11-27 21:13:50 +03:00
if ( ( ( dm_hash_lookup ( _pvid_hash , pvid ) ) = = info ) & &
! strcmp ( info - > dev - > pvid , pvid ) )
2002-11-18 16:53:58 +03:00
return 1 ;
2008-11-28 18:51:40 +03:00
if ( * info - > dev - > pvid )
2005-10-17 03:03:59 +04:00
dm_hash_remove ( _pvid_hash , info - > dev - > pvid ) ;
2002-11-18 16:53:58 +03:00
strncpy ( info - > dev - > pvid , pvid , sizeof ( info - > dev - > pvid ) ) ;
2005-10-17 03:03:59 +04:00
if ( ! dm_hash_insert ( _pvid_hash , pvid , info ) ) {
2003-07-05 02:34:56 +04:00
log_error ( " _lvmcache_update: pvid insertion failed: %s " , pvid ) ;
2002-11-18 16:53:58 +03:00
return 0 ;
}
return 1 ;
}
2008-04-08 16:49:21 +04:00
/*
* vginfo must be info - > vginfo unless info is NULL ( orphans )
*/
static int _lvmcache_update_vgid ( struct lvmcache_info * info ,
struct lvmcache_vginfo * vginfo ,
const char * vgid )
2002-11-18 16:53:58 +03:00
{
2008-04-08 16:49:21 +04:00
if ( ! vgid | | ! vginfo | |
! strncmp ( vginfo - > vgid , vgid , ID_LEN ) )
2002-11-18 16:53:58 +03:00
return 1 ;
2008-04-08 16:49:21 +04:00
if ( vginfo & & * vginfo - > vgid )
dm_hash_remove ( _vgid_hash , vginfo - > vgid ) ;
2006-04-11 02:09:00 +04:00
if ( ! vgid ) {
2012-02-08 16:57:15 +04:00
/* FIXME: unreachable code path */
2013-01-08 02:30:29 +04:00
log_debug_cache ( " lvmcache: %s: clearing VGID " , info ? dev_name ( info - > dev ) : vginfo - > vgname ) ;
2002-11-18 16:53:58 +03:00
return 1 ;
2006-04-11 02:09:00 +04:00
}
2002-11-18 16:53:58 +03:00
2008-04-08 16:49:21 +04:00
strncpy ( vginfo - > vgid , vgid , ID_LEN ) ;
vginfo - > vgid [ ID_LEN ] = ' \0 ' ;
if ( ! dm_hash_insert ( _vgid_hash , vginfo - > vgid , vginfo ) ) {
2003-07-05 02:34:56 +04:00
log_error ( " _lvmcache_update: vgid hash insertion failed: %s " ,
2008-04-08 16:49:21 +04:00
vginfo - > vgid ) ;
2002-11-18 16:53:58 +03:00
return 0 ;
}
2008-04-08 16:49:21 +04:00
if ( ! is_orphan_vg ( vginfo - > vgname ) )
2013-01-08 02:30:29 +04:00
log_debug_cache ( " lvmcache: %s: setting %s VGID to %s " ,
( info ) ? dev_name ( info - > dev ) : " " ,
vginfo - > vgname , vginfo - > vgid ) ;
2006-04-11 02:09:00 +04:00
2002-11-18 16:53:58 +03:00
return 1 ;
}
2006-04-12 21:54:11 +04:00
static int _insert_vginfo ( struct lvmcache_vginfo * new_vginfo , const char * vgid ,
2006-04-13 21:32:24 +04:00
uint32_t vgstatus , const char * creation_host ,
2006-04-12 21:54:11 +04:00
struct lvmcache_vginfo * primary_vginfo )
{
struct lvmcache_vginfo * last_vginfo = primary_vginfo ;
2010-07-09 19:34:40 +04:00
char uuid_primary [ 64 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
char uuid_new [ 64 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2006-04-13 21:32:24 +04:00
int use_new = 0 ;
2009-09-14 23:44:15 +04:00
2006-04-12 21:54:11 +04:00
/* Pre-existing VG takes precedence. Unexported VG takes precedence. */
if ( primary_vginfo ) {
2006-05-10 01:23:51 +04:00
if ( ! id_write_format ( ( const struct id * ) vgid , uuid_new , sizeof ( uuid_new ) ) )
2006-04-13 01:23:04 +04:00
return_0 ;
2006-05-10 01:23:51 +04:00
if ( ! id_write_format ( ( const struct id * ) & primary_vginfo - > vgid , uuid_primary ,
2006-04-13 01:23:04 +04:00
sizeof ( uuid_primary ) ) )
return_0 ;
2006-04-13 21:32:24 +04:00
/*
* If Primary not exported , new exported = > keep
* Else Primary exported , new not exported = > change
* Else Primary has hostname for this machine = > keep
* Else Primary has no hostname , new has one = > change
* Else New has hostname for this machine = > change
* Else Keep primary .
*/
if ( ! ( primary_vginfo - > status & EXPORTED_VG ) & &
( vgstatus & EXPORTED_VG ) )
2010-04-01 14:34:09 +04:00
log_warn ( " WARNING: Duplicate VG name %s: "
" Existing %s takes precedence over "
" exported %s " , new_vginfo - > vgname ,
uuid_primary , uuid_new ) ;
2006-04-13 21:32:24 +04:00
else if ( ( primary_vginfo - > status & EXPORTED_VG ) & &
! ( vgstatus & EXPORTED_VG ) ) {
2010-04-01 14:34:09 +04:00
log_warn ( " WARNING: Duplicate VG name %s: "
" %s takes precedence over exported %s " ,
new_vginfo - > vgname , uuid_new ,
uuid_primary ) ;
2006-04-13 21:32:24 +04:00
use_new = 1 ;
} else if ( primary_vginfo - > creation_host & &
! strcmp ( primary_vginfo - > creation_host ,
primary_vginfo - > fmt - > cmd - > hostname ) )
2010-04-01 14:34:09 +04:00
log_warn ( " WARNING: Duplicate VG name %s: "
" Existing %s (created here) takes precedence "
" over %s " , new_vginfo - > vgname , uuid_primary ,
uuid_new ) ;
2006-04-13 21:32:24 +04:00
else if ( ! primary_vginfo - > creation_host & & creation_host ) {
2010-04-01 14:34:09 +04:00
log_warn ( " WARNING: Duplicate VG name %s: "
" %s (with creation_host) takes precedence over %s " ,
new_vginfo - > vgname , uuid_new ,
uuid_primary ) ;
2006-04-13 21:32:24 +04:00
use_new = 1 ;
} else if ( creation_host & &
! strcmp ( creation_host ,
primary_vginfo - > fmt - > cmd - > hostname ) ) {
2010-04-01 14:34:09 +04:00
log_warn ( " WARNING: Duplicate VG name %s: "
" %s (created here) takes precedence over %s " ,
new_vginfo - > vgname , uuid_new ,
uuid_primary ) ;
2006-04-13 21:32:24 +04:00
use_new = 1 ;
}
if ( ! use_new ) {
while ( last_vginfo - > next )
last_vginfo = last_vginfo - > next ;
last_vginfo - > next = new_vginfo ;
return 1 ;
}
2006-04-12 21:54:11 +04:00
dm_hash_remove ( _vgname_hash , primary_vginfo - > vgname ) ;
}
if ( ! dm_hash_insert ( _vgname_hash , new_vginfo - > vgname , new_vginfo ) ) {
log_error ( " cache_update: vg hash insertion failed: %s " ,
new_vginfo - > vgname ) ;
return 0 ;
}
if ( primary_vginfo )
new_vginfo - > next = primary_vginfo ;
return 1 ;
}
2006-04-11 20:00:26 +04:00
static int _lvmcache_update_vgname ( struct lvmcache_info * info ,
2006-04-13 01:23:04 +04:00
const char * vgname , const char * vgid ,
2008-04-08 16:49:21 +04:00
uint32_t vgstatus , const char * creation_host ,
const struct format_type * fmt )
2002-11-18 16:53:58 +03:00
{
2008-05-29 02:27:47 +04:00
struct lvmcache_vginfo * vginfo , * primary_vginfo , * orphan_vginfo ;
struct lvmcache_info * info2 , * info3 ;
2008-06-27 19:18:31 +04:00
char mdabuf [ 32 ] ;
2006-04-14 01:08:29 +04:00
// struct lvmcache_vginfo *old_vginfo, *next;
2002-11-18 16:53:58 +03:00
2008-04-08 16:49:21 +04:00
if ( ! vgname | | ( info & & info - > vginfo & & ! strcmp ( info - > vginfo - > vgname , vgname ) ) )
2002-11-18 16:53:58 +03:00
return 1 ;
/* Remove existing vginfo entry */
2008-04-08 16:49:21 +04:00
if ( info )
_drop_vginfo ( info , info - > vginfo ) ;
2002-11-18 16:53:58 +03:00
/* Get existing vginfo or create new one */
2012-02-10 05:28:27 +04:00
if ( ! ( vginfo = lvmcache_vginfo_from_vgname ( vgname , vgid ) ) ) {
2006-04-14 01:08:29 +04:00
/*** FIXME - vginfo ends up duplicated instead of renamed.
// Renaming? This lookup fails.
if ( ( vginfo = vginfo_from_vgid ( vgid ) ) ) {
next = vginfo - > next ;
old_vginfo = vginfo_from_vgname ( vginfo - > vgname , NULL ) ;
if ( old_vginfo = = vginfo ) {
dm_hash_remove ( _vgname_hash , old_vginfo - > vgname ) ;
if ( old_vginfo - > next ) {
if ( ! dm_hash_insert ( _vgname_hash , old_vginfo - > vgname , old_vginfo - > next ) ) {
2008-01-30 17:00:02 +03:00
log_error ( " vg hash re-insertion failed: %s " ,
2006-04-14 01:08:29 +04:00
old_vginfo - > vgname ) ;
2008-01-30 17:00:02 +03:00
return 0 ;
2006-04-14 01:08:29 +04:00
}
}
} else do {
if ( old_vginfo - > next = = vginfo ) {
old_vginfo - > next = vginfo - > next ;
break ;
}
} while ( ( old_vginfo = old_vginfo - > next ) ) ;
vginfo - > next = NULL ;
dm_free ( vginfo - > vgname ) ;
if ( ! ( vginfo - > vgname = dm_strdup ( vgname ) ) ) {
log_error ( " cache vgname alloc failed for %s " , vgname ) ;
return 0 ;
}
2008-01-30 17:00:02 +03:00
// Rename so can assume new name does not already exist
2006-04-14 01:08:29 +04:00
if ( ! dm_hash_insert ( _vgname_hash , vginfo - > vgname , vginfo - > next ) ) {
log_error ( " vg hash re-insertion failed: %s " ,
vginfo - > vgname ) ;
2008-01-30 17:00:02 +03:00
return 0 ;
2006-04-14 01:08:29 +04:00
}
} else {
* * */
2010-10-01 01:06:50 +04:00
if ( ! ( vginfo = dm_zalloc ( sizeof ( * vginfo ) ) ) ) {
2003-07-05 02:34:56 +04:00
log_error ( " lvmcache_update_vgname: list alloc failed " ) ;
2002-11-18 16:53:58 +03:00
return 0 ;
}
2005-10-17 03:03:59 +04:00
if ( ! ( vginfo - > vgname = dm_strdup ( vgname ) ) ) {
dm_free ( vginfo ) ;
2002-11-18 16:53:58 +03:00
log_error ( " cache vgname alloc failed for %s " , vgname ) ;
return 0 ;
}
2008-11-04 01:14:30 +03:00
dm_list_init ( & vginfo - > infos ) ;
2008-05-29 02:27:47 +04:00
/*
* If we ' re scanning and there ' s an invalidated entry , remove it .
* Otherwise we risk bogus warnings of duplicate VGs .
*/
2012-02-10 05:28:27 +04:00
while ( ( primary_vginfo = lvmcache_vginfo_from_vgname ( vgname , NULL ) ) & &
2011-03-30 01:34:18 +04:00
_scanning_in_progress & & _vginfo_is_invalid ( primary_vginfo ) ) {
2012-02-10 05:28:27 +04:00
orphan_vginfo = lvmcache_vginfo_from_vgname ( primary_vginfo - > fmt - > orphan_vg_name , NULL ) ;
2011-03-30 01:34:18 +04:00
if ( ! orphan_vginfo ) {
log_error ( INTERNAL_ERROR " Orphan vginfo %s lost from cache. " ,
primary_vginfo - > fmt - > orphan_vg_name ) ;
dm_free ( vginfo - > vgname ) ;
dm_free ( vginfo ) ;
return 0 ;
}
2008-11-04 01:14:30 +03:00
dm_list_iterate_items_safe ( info2 , info3 , & primary_vginfo - > infos ) {
2011-03-30 01:34:18 +04:00
_vginfo_detach_info ( info2 ) ;
2008-05-29 02:27:47 +04:00
_vginfo_attach_info ( orphan_vginfo , info2 ) ;
2008-06-27 19:18:31 +04:00
if ( info2 - > mdas . n )
sprintf ( mdabuf , " with %u mdas " ,
2008-11-04 01:14:30 +03:00
dm_list_size ( & info2 - > mdas ) ) ;
2008-06-27 19:18:31 +04:00
else
mdabuf [ 0 ] = ' \0 ' ;
2013-01-08 02:30:29 +04:00
log_debug_cache ( " lvmcache: %s: now in VG %s%s%s%s%s " ,
dev_name ( info2 - > dev ) ,
vgname , orphan_vginfo - > vgid [ 0 ] ? " ( " : " " ,
orphan_vginfo - > vgid [ 0 ] ? orphan_vginfo - > vgid : " " ,
orphan_vginfo - > vgid [ 0 ] ? " ) " : " " , mdabuf ) ;
2011-03-30 01:34:18 +04:00
}
if ( ! _drop_vginfo ( NULL , primary_vginfo ) )
return_0 ;
2008-05-29 02:27:47 +04:00
}
2006-04-13 21:32:24 +04:00
if ( ! _insert_vginfo ( vginfo , vgid , vgstatus , creation_host ,
primary_vginfo ) ) {
2005-10-17 03:03:59 +04:00
dm_free ( vginfo - > vgname ) ;
dm_free ( vginfo ) ;
2002-11-18 16:53:58 +03:00
return 0 ;
}
/* Ensure orphans appear last on list_iterate */
2007-11-02 16:06:42 +03:00
if ( is_orphan_vg ( vgname ) )
2008-11-04 01:14:30 +03:00
dm_list_add ( & _vginfos , & vginfo - > list ) ;
2002-11-18 16:53:58 +03:00
else
2008-11-04 01:14:30 +03:00
dm_list_add_h ( & _vginfos , & vginfo - > list ) ;
2006-04-14 01:08:29 +04:00
/***
}
* * */
2002-11-18 16:53:58 +03:00
}
2008-05-19 23:49:56 +04:00
if ( info )
_vginfo_attach_info ( vginfo , info ) ;
else if ( ! _lvmcache_update_vgid ( NULL , vginfo , vgid ) ) /* Orphans */
2008-04-08 16:49:21 +04:00
return_0 ;
2002-11-18 16:53:58 +03:00
2012-02-10 05:28:27 +04:00
_update_cache_vginfo_lock_state ( vginfo , lvmcache_vgname_is_locked ( vgname ) ) ;
2008-01-30 02:45:48 +03:00
2002-11-18 16:53:58 +03:00
/* FIXME Check consistency of list! */
2008-04-08 16:49:21 +04:00
vginfo - > fmt = fmt ;
2008-06-27 19:18:31 +04:00
if ( info ) {
if ( info - > mdas . n )
2008-11-04 01:14:30 +03:00
sprintf ( mdabuf , " with %u mdas " , dm_list_size ( & info - > mdas ) ) ;
2008-06-27 19:18:31 +04:00
else
mdabuf [ 0 ] = ' \0 ' ;
2013-01-08 02:30:29 +04:00
log_debug_cache ( " lvmcache: %s: now in VG %s%s%s%s%s " ,
dev_name ( info - > dev ) ,
vgname , vginfo - > vgid [ 0 ] ? " ( " : " " ,
vginfo - > vgid [ 0 ] ? vginfo - > vgid : " " ,
vginfo - > vgid [ 0 ] ? " ) " : " " , mdabuf ) ;
2008-06-27 19:18:31 +04:00
} else
2013-01-08 02:30:29 +04:00
log_debug_cache ( " lvmcache: initialised VG %s " , vgname ) ;
2005-03-22 01:40:35 +03:00
2002-11-18 16:53:58 +03:00
return 1 ;
}
2006-04-13 21:32:24 +04:00
static int _lvmcache_update_vgstatus ( struct lvmcache_info * info , uint32_t vgstatus ,
const char * creation_host )
2006-04-11 21:42:15 +04:00
{
if ( ! info | | ! info - > vginfo )
return 1 ;
if ( ( info - > vginfo - > status & EXPORTED_VG ) ! = ( vgstatus & EXPORTED_VG ) )
2013-01-08 02:30:29 +04:00
log_debug_cache ( " lvmcache: %s: VG %s %s exported " ,
dev_name ( info - > dev ) , info - > vginfo - > vgname ,
vgstatus & EXPORTED_VG ? " now " : " no longer " ) ;
2006-04-11 21:42:15 +04:00
info - > vginfo - > status = vgstatus ;
2006-04-13 21:32:24 +04:00
if ( ! creation_host )
return 1 ;
if ( info - > vginfo - > creation_host & & ! strcmp ( creation_host ,
info - > vginfo - > creation_host ) )
return 1 ;
if ( info - > vginfo - > creation_host )
dm_free ( info - > vginfo - > creation_host ) ;
if ( ! ( info - > vginfo - > creation_host = dm_strdup ( creation_host ) ) ) {
log_error ( " cache creation host alloc failed for %s " ,
creation_host ) ;
return 0 ;
}
2013-01-08 02:30:29 +04:00
log_debug_cache ( " lvmcache: %s: VG %s: Set creation host to %s. " ,
dev_name ( info - > dev ) , info - > vginfo - > vgname , creation_host ) ;
2006-04-13 21:32:24 +04:00
2006-04-11 21:42:15 +04:00
return 1 ;
}
2008-04-08 16:49:21 +04:00
int lvmcache_add_orphan_vginfo ( const char * vgname , struct format_type * fmt )
{
if ( ! _lock_hash & & ! lvmcache_init ( ) ) {
log_error ( " Internal cache initialisation failed " ) ;
return 0 ;
}
return _lvmcache_update_vgname ( NULL , vgname , vgname , 0 , " " , fmt ) ;
}
2006-04-11 21:42:15 +04:00
int lvmcache_update_vgname_and_id ( struct lvmcache_info * info ,
const char * vgname , const char * vgid ,
2006-04-13 21:32:24 +04:00
uint32_t vgstatus , const char * creation_host )
2006-04-11 20:00:26 +04:00
{
2008-02-06 18:47:28 +03:00
if ( ! vgname & & ! info - > vginfo ) {
2009-12-16 22:22:11 +03:00
log_error ( INTERNAL_ERROR " NULL vgname handed to cache " ) ;
2008-02-06 18:47:28 +03:00
/* FIXME Remove this */
vgname = info - > fmt - > orphan_vg_name ;
vgid = vgname ;
}
2008-04-08 16:49:21 +04:00
2012-02-23 17:11:07 +04:00
/* When using lvmetad, the PV could not have become orphaned. */
if ( lvmetad_active ( ) & & is_orphan_vg ( vgname ) & & info - > vginfo )
return 1 ;
2008-06-11 15:02:05 +04:00
/* If PV without mdas is already in a real VG, don't make it orphan */
2010-06-29 00:34:58 +04:00
if ( is_orphan_vg ( vgname ) & & info - > vginfo & &
mdas_empty_or_ignored ( & info - > mdas ) & &
2011-02-18 17:16:11 +03:00
! is_orphan_vg ( info - > vginfo - > vgname ) & & critical_section ( ) )
2008-06-11 15:02:05 +04:00
return 1 ;
/* If moving PV from orphan to real VG, always mark it valid */
if ( ! is_orphan_vg ( vgname ) )
info - > status & = ~ CACHE_INVALID ;
2006-04-13 21:32:24 +04:00
if ( ! _lvmcache_update_vgname ( info , vgname , vgid , vgstatus ,
2008-04-08 16:49:21 +04:00
creation_host , info - > fmt ) | |
! _lvmcache_update_vgid ( info , info - > vginfo , vgid ) | |
2006-04-13 21:32:24 +04:00
! _lvmcache_update_vgstatus ( info , vgstatus , creation_host ) )
2006-04-11 20:00:26 +04:00
return_0 ;
return 1 ;
}
2008-03-17 19:51:31 +03:00
int lvmcache_update_vg ( struct volume_group * vg , unsigned precommitted )
2002-11-18 16:53:58 +03:00
{
2005-06-01 20:51:55 +04:00
struct pv_list * pvl ;
2003-07-05 02:34:56 +04:00
struct lvmcache_info * info ;
2010-07-09 19:34:40 +04:00
char pvid_s [ ID_LEN + 1 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2002-11-18 16:53:58 +03:00
pvid_s [ sizeof ( pvid_s ) - 1 ] = ' \0 ' ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( pvl , & vg - > pvs ) {
2005-06-01 20:51:55 +04:00
strncpy ( pvid_s , ( char * ) & pvl - > pv - > id , sizeof ( pvid_s ) - 1 ) ;
/* FIXME Could pvl->pv->dev->pvid ever be different? */
2012-02-10 05:28:27 +04:00
if ( ( info = lvmcache_info_from_pvid ( pvid_s , 0 ) ) & &
2006-04-11 20:00:26 +04:00
! lvmcache_update_vgname_and_id ( info , vg - > name ,
2006-04-11 21:42:15 +04:00
( char * ) & vg - > id ,
2006-04-13 21:32:24 +04:00
vg - > status , NULL ) )
2006-04-11 20:00:26 +04:00
return_0 ;
2002-11-18 16:53:58 +03:00
}
2008-03-17 19:51:31 +03:00
/* store text representation of vg to cache */
2009-02-17 21:56:41 +03:00
if ( vg - > cmd - > current_settings . cache_vgmetadata )
_store_metadata ( vg , precommitted ) ;
2008-03-17 19:51:31 +03:00
2002-11-18 16:53:58 +03:00
return 1 ;
}
2003-07-05 02:34:56 +04:00
struct lvmcache_info * lvmcache_add ( struct labeller * labeller , const char * pvid ,
struct device * dev ,
2006-04-11 21:42:15 +04:00
const char * vgname , const char * vgid ,
uint32_t vgstatus )
2002-11-18 16:53:58 +03:00
{
2013-07-29 17:58:18 +04:00
const struct format_type * fmt = labeller - > fmt ;
2013-06-12 14:08:56 +04:00
struct dev_types * dt = fmt - > cmd - > dev_types ;
2002-11-18 16:53:58 +03:00
struct label * label ;
2003-07-05 02:34:56 +04:00
struct lvmcache_info * existing , * info ;
2010-07-09 19:34:40 +04:00
char pvid_s [ ID_LEN + 1 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2002-11-18 16:53:58 +03:00
2003-07-05 02:34:56 +04:00
if ( ! _vgname_hash & & ! lvmcache_init ( ) ) {
2002-11-18 16:53:58 +03:00
log_error ( " Internal cache initialisation failed " ) ;
return NULL ;
}
2011-03-14 02:01:08 +03:00
strncpy ( pvid_s , pvid , sizeof ( pvid_s ) - 1 ) ;
2002-11-18 16:53:58 +03:00
pvid_s [ sizeof ( pvid_s ) - 1 ] = ' \0 ' ;
2012-02-10 05:28:27 +04:00
if ( ! ( existing = lvmcache_info_from_pvid ( pvid_s , 0 ) ) & &
! ( existing = lvmcache_info_from_pvid ( dev - > pvid , 0 ) ) ) {
2008-01-30 16:19:47 +03:00
if ( ! ( label = label_create ( labeller ) ) )
return_NULL ;
2010-10-01 01:06:50 +04:00
if ( ! ( info = dm_zalloc ( sizeof ( * info ) ) ) ) {
2003-07-05 02:34:56 +04:00
log_error ( " lvmcache_info allocation failed " ) ;
2002-11-18 16:53:58 +03:00
label_destroy ( label ) ;
return NULL ;
}
label - > info = info ;
info - > label = label ;
2008-11-04 01:14:30 +03:00
dm_list_init ( & info - > list ) ;
2002-11-18 16:53:58 +03:00
info - > dev = dev ;
2012-02-23 17:11:07 +04:00
lvmcache_del_mdas ( info ) ;
lvmcache_del_das ( info ) ;
2013-05-28 14:37:22 +04:00
lvmcache_del_bas ( info ) ;
2002-11-18 16:53:58 +03:00
} else {
2003-01-07 00:10:43 +03:00
if ( existing - > dev ! = dev ) {
/* Is the existing entry a duplicate pvid e.g. md ? */
2013-06-12 14:08:56 +04:00
if ( dev_subsystem_part_major ( dt , existing - > dev ) & &
! dev_subsystem_part_major ( dt , dev ) ) {
2003-01-07 00:10:43 +03:00
log_very_verbose ( " Ignoring duplicate PV %s on "
2009-10-27 20:00:44 +03:00
" %s - using %s %s " ,
2003-01-07 00:10:43 +03:00
pvid , dev_name ( dev ) ,
2013-06-12 14:08:56 +04:00
dev_subsystem_name ( dt , existing - > dev ) ,
2003-01-07 00:10:43 +03:00
dev_name ( existing - > dev ) ) ;
return NULL ;
2005-10-25 23:08:21 +04:00
} else if ( dm_is_dm_major ( MAJOR ( existing - > dev - > dev ) ) & &
! dm_is_dm_major ( MAJOR ( dev - > dev ) ) ) {
2005-09-16 22:53:01 +04:00
log_very_verbose ( " Ignoring duplicate PV %s on "
" %s - using dm %s " ,
pvid , dev_name ( dev ) ,
dev_name ( existing - > dev ) ) ;
return NULL ;
2013-06-12 14:08:56 +04:00
} else if ( ! dev_subsystem_part_major ( dt , existing - > dev ) & &
dev_subsystem_part_major ( dt , dev ) )
2003-01-07 00:10:43 +03:00
log_very_verbose ( " Duplicate PV %s on %s - "
2009-10-27 20:00:44 +03:00
" using %s %s " , pvid ,
2003-01-07 00:10:43 +03:00
dev_name ( existing - > dev ) ,
2013-06-12 14:08:56 +04:00
dev_subsystem_name ( dt , existing - > dev ) ,
2003-01-07 00:10:43 +03:00
dev_name ( dev ) ) ;
2005-10-25 23:08:21 +04:00
else if ( ! dm_is_dm_major ( MAJOR ( existing - > dev - > dev ) ) & &
dm_is_dm_major ( MAJOR ( dev - > dev ) ) )
2005-09-16 22:53:01 +04:00
log_very_verbose ( " Duplicate PV %s on %s - "
" using dm %s " , pvid ,
dev_name ( existing - > dev ) ,
dev_name ( dev ) ) ;
2005-10-28 01:51:28 +04:00
/* FIXME If both dm, check dependencies */
//else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
//dm_is_dm_major(MAJOR(dev->dev)))
//
2008-11-28 18:51:40 +03:00
else if ( ! strcmp ( pvid_s , existing - > dev - > pvid ) )
2003-01-07 00:10:43 +03:00
log_error ( " Found duplicate PV %s: using %s not "
" %s " , pvid , dev_name ( dev ) ,
dev_name ( existing - > dev ) ) ;
}
2008-11-28 18:51:40 +03:00
if ( strcmp ( pvid_s , existing - > dev - > pvid ) )
2013-01-08 02:30:29 +04:00
log_debug_cache ( " Updating pvid cache to %s (%s) from %s (%s) " ,
pvid_s , dev_name ( dev ) ,
existing - > dev - > pvid , dev_name ( existing - > dev ) ) ;
2005-09-16 22:44:52 +04:00
/* Switch over to new preferred device */
existing - > dev = dev ;
2002-11-18 16:53:58 +03:00
info = existing ;
/* Has labeller changed? */
if ( info - > label - > labeller ! = labeller ) {
label_destroy ( info - > label ) ;
2008-01-30 16:19:47 +03:00
if ( ! ( info - > label = label_create ( labeller ) ) )
2002-11-18 16:53:58 +03:00
/* FIXME leaves info without label! */
2008-01-30 16:19:47 +03:00
return_NULL ;
2002-11-18 16:53:58 +03:00
info - > label - > info = info ;
}
label = info - > label ;
}
2013-07-29 17:58:18 +04:00
info - > fmt = labeller - > fmt ;
2002-11-18 16:53:58 +03:00
info - > status | = CACHE_INVALID ;
2003-07-05 02:34:56 +04:00
if ( ! _lvmcache_update_pvid ( info , pvid_s ) ) {
2002-11-18 16:53:58 +03:00
if ( ! existing ) {
2005-10-17 03:03:59 +04:00
dm_free ( info ) ;
2002-11-18 16:53:58 +03:00
label_destroy ( label ) ;
}
return NULL ;
}
2006-04-13 21:32:24 +04:00
if ( ! lvmcache_update_vgname_and_id ( info , vgname , vgid , vgstatus , NULL ) ) {
2002-11-18 16:53:58 +03:00
if ( ! existing ) {
2005-10-17 03:03:59 +04:00
dm_hash_remove ( _pvid_hash , pvid_s ) ;
2002-11-18 16:53:58 +03:00
strcpy ( info - > dev - > pvid , " " ) ;
2005-10-17 03:03:59 +04:00
dm_free ( info ) ;
2002-11-18 16:53:58 +03:00
label_destroy ( label ) ;
}
return NULL ;
}
return info ;
}
2003-07-05 02:34:56 +04:00
static void _lvmcache_destroy_entry ( struct lvmcache_info * info )
2002-11-18 16:53:58 +03:00
{
2008-05-19 23:49:56 +04:00
_vginfo_detach_info ( info ) ;
2013-07-19 17:32:49 +04:00
info - > dev - > pvid [ 0 ] = 0 ;
2002-11-18 16:53:58 +03:00
label_destroy ( info - > label ) ;
2005-10-17 03:03:59 +04:00
dm_free ( info ) ;
2002-11-18 16:53:58 +03:00
}
2003-07-05 02:34:56 +04:00
static void _lvmcache_destroy_vgnamelist ( struct lvmcache_vginfo * vginfo )
2002-11-18 16:53:58 +03:00
{
2006-04-12 21:54:11 +04:00
struct lvmcache_vginfo * next ;
do {
next = vginfo - > next ;
2008-05-19 23:49:56 +04:00
if ( ! _free_vginfo ( vginfo ) )
stack ;
2006-04-12 21:54:11 +04:00
} while ( ( vginfo = next ) ) ;
2002-11-18 16:53:58 +03:00
}
2008-04-03 22:56:40 +04:00
static void _lvmcache_destroy_lockname ( struct dm_hash_node * n )
2003-07-05 02:34:56 +04:00
{
2008-04-03 22:56:40 +04:00
char * vgname ;
if ( ! dm_hash_get_data ( _lock_hash , n ) )
return ;
vgname = dm_hash_get_key ( _lock_hash , n ) ;
if ( ! strcmp ( vgname , VG_GLOBAL ) )
_vg_global_lock_held = 1 ;
else
2009-12-16 22:22:11 +03:00
log_error ( INTERNAL_ERROR " Volume Group %s was not unlocked " ,
2008-04-03 22:56:40 +04:00
dm_hash_get_key ( _lock_hash , n ) ) ;
2003-07-05 02:34:56 +04:00
}
2008-04-08 16:49:21 +04:00
void lvmcache_destroy ( struct cmd_context * cmd , int retain_orphans )
2002-11-18 16:53:58 +03:00
{
2008-04-03 22:56:40 +04:00
struct dm_hash_node * n ;
2005-03-22 01:40:35 +03:00
log_verbose ( " Wiping internal VG cache " ) ;
2002-11-18 16:53:58 +03:00
_has_scanned = 0 ;
if ( _vgid_hash ) {
2005-10-17 03:03:59 +04:00
dm_hash_destroy ( _vgid_hash ) ;
2002-11-18 16:53:58 +03:00
_vgid_hash = NULL ;
}
if ( _pvid_hash ) {
2005-10-17 03:03:59 +04:00
dm_hash_iter ( _pvid_hash , ( dm_hash_iterate_fn ) _lvmcache_destroy_entry ) ;
dm_hash_destroy ( _pvid_hash ) ;
2002-11-18 16:53:58 +03:00
_pvid_hash = NULL ;
}
if ( _vgname_hash ) {
2005-10-17 03:03:59 +04:00
dm_hash_iter ( _vgname_hash ,
( dm_hash_iterate_fn ) _lvmcache_destroy_vgnamelist ) ;
dm_hash_destroy ( _vgname_hash ) ;
2002-11-18 16:53:58 +03:00
_vgname_hash = NULL ;
}
2003-07-05 02:34:56 +04:00
if ( _lock_hash ) {
2008-04-03 22:56:40 +04:00
dm_hash_iterate ( n , _lock_hash )
_lvmcache_destroy_lockname ( n ) ;
2005-10-17 03:03:59 +04:00
dm_hash_destroy ( _lock_hash ) ;
2003-07-05 02:34:56 +04:00
_lock_hash = NULL ;
}
2008-11-04 01:14:30 +03:00
if ( ! dm_list_empty ( & _vginfos ) )
2009-12-16 22:22:11 +03:00
log_error ( INTERNAL_ERROR " _vginfos list should be empty " ) ;
2008-11-04 01:14:30 +03:00
dm_list_init ( & _vginfos ) ;
2008-04-08 16:49:21 +04:00
if ( retain_orphans )
2012-02-28 15:08:04 +04:00
if ( ! init_lvmcache_orphans ( cmd ) )
stack ;
2002-11-18 16:53:58 +03:00
}
2012-02-10 05:28:27 +04:00
int lvmcache_pvid_is_locked ( const char * pvid ) {
struct lvmcache_info * info ;
info = lvmcache_info_from_pvid ( pvid , 0 ) ;
if ( ! info | | ! info - > vginfo )
return 0 ;
return lvmcache_vgname_is_locked ( info - > vginfo - > vgname ) ;
}
int lvmcache_fid_add_mdas ( struct lvmcache_info * info , struct format_instance * fid ,
const char * id , int id_len )
{
return fid_add_mdas ( fid , & info - > mdas , id , id_len ) ;
}
int lvmcache_fid_add_mdas_pv ( struct lvmcache_info * info , struct format_instance * fid )
{
return lvmcache_fid_add_mdas ( info , fid , info - > dev - > pvid , ID_LEN ) ;
}
int lvmcache_fid_add_mdas_vg ( struct lvmcache_vginfo * vginfo , struct format_instance * fid )
{
struct lvmcache_info * info ;
dm_list_iterate_items ( info , & vginfo - > infos ) {
if ( ! lvmcache_fid_add_mdas_pv ( info , fid ) )
return_0 ;
}
return 1 ;
}
static int _get_pv_if_in_vg ( struct lvmcache_info * info ,
struct physical_volume * pv )
{
char vgname [ NAME_LEN + 1 ] ;
char vgid [ ID_LEN + 1 ] ;
if ( info - > vginfo & & info - > vginfo - > vgname & &
! is_orphan_vg ( info - > vginfo - > vgname ) ) {
/*
* get_pv_from_vg_by_id ( ) may call
* lvmcache_label_scan ( ) and drop cached
* vginfo so make a local copy of string .
*/
strcpy ( vgname , info - > vginfo - > vgname ) ;
memcpy ( vgid , info - > vginfo - > vgid , sizeof ( vgid ) ) ;
if ( get_pv_from_vg_by_id ( info - > fmt , vgname , vgid ,
info - > dev - > pvid , pv ) )
return 1 ;
}
return 0 ;
}
int lvmcache_populate_pv_fields ( struct lvmcache_info * info ,
struct physical_volume * pv ,
int scan_label_only )
{
struct data_area_list * da ;
/* Have we already cached vgname? */
if ( ! scan_label_only & & _get_pv_if_in_vg ( info , pv ) )
return 1 ;
/* Perform full scan (just the first time) and try again */
if ( ! scan_label_only & & ! critical_section ( ) & & ! full_scan_done ( ) ) {
lvmcache_label_scan ( info - > fmt - > cmd , 2 ) ;
if ( _get_pv_if_in_vg ( info , pv ) )
return 1 ;
}
/* Orphan */
pv - > dev = info - > dev ;
pv - > fmt = info - > fmt ;
pv - > size = info - > device_size > > SECTOR_SHIFT ;
pv - > vg_name = FMT_TEXT_ORPHAN_VG_NAME ;
memcpy ( & pv - > id , & info - > dev - > pvid , sizeof ( pv - > id ) ) ;
/* Currently only support exactly one data area */
if ( dm_list_size ( & info - > das ) ! = 1 ) {
log_error ( " Must be exactly one data area (found %d) on PV %s " ,
dm_list_size ( & info - > das ) , dev_name ( info - > dev ) ) ;
return 0 ;
}
2013-05-28 14:37:22 +04:00
/* Currently only support one bootloader area at most */
if ( dm_list_size ( & info - > bas ) > 1 ) {
log_error ( " Must be at most one bootloader area (found %d) on PV %s " ,
dm_list_size ( & info - > bas ) , dev_name ( info - > dev ) ) ;
2013-02-14 19:04:35 +04:00
return 0 ;
}
2012-02-10 05:28:27 +04:00
dm_list_iterate_items ( da , & info - > das )
pv - > pe_start = da - > disk_locn . offset > > SECTOR_SHIFT ;
2013-05-28 14:37:22 +04:00
dm_list_iterate_items ( da , & info - > bas ) {
pv - > ba_start = da - > disk_locn . offset > > SECTOR_SHIFT ;
pv - > ba_size = da - > disk_locn . size > > SECTOR_SHIFT ;
2013-02-14 19:04:35 +04:00
}
2012-02-10 05:28:27 +04:00
return 1 ;
}
int lvmcache_check_format ( struct lvmcache_info * info , const struct format_type * fmt )
{
if ( info - > fmt ! = fmt ) {
log_error ( " PV %s is a different format (seqno %s) " ,
dev_name ( info - > dev ) , info - > fmt - > name ) ;
return 0 ;
}
return 1 ;
}
void lvmcache_del_mdas ( struct lvmcache_info * info )
{
if ( info - > mdas . n )
del_mdas ( & info - > mdas ) ;
dm_list_init ( & info - > mdas ) ;
}
void lvmcache_del_das ( struct lvmcache_info * info )
{
if ( info - > das . n )
del_das ( & info - > das ) ;
dm_list_init ( & info - > das ) ;
}
2013-05-28 14:37:22 +04:00
void lvmcache_del_bas ( struct lvmcache_info * info )
2013-02-14 18:35:57 +04:00
{
2013-05-28 14:37:22 +04:00
if ( info - > bas . n )
del_bas ( & info - > bas ) ;
dm_list_init ( & info - > bas ) ;
2013-02-14 18:35:57 +04:00
}
2012-02-10 05:28:27 +04:00
int lvmcache_add_mda ( struct lvmcache_info * info , struct device * dev ,
uint64_t start , uint64_t size , unsigned ignored )
{
return add_mda ( info - > fmt , NULL , & info - > mdas , dev , start , size , ignored ) ;
}
int lvmcache_add_da ( struct lvmcache_info * info , uint64_t start , uint64_t size )
{
return add_da ( NULL , & info - > das , start , size ) ;
}
2013-05-28 14:37:22 +04:00
int lvmcache_add_ba ( struct lvmcache_info * info , uint64_t start , uint64_t size )
2013-02-14 18:35:57 +04:00
{
2013-05-28 14:37:22 +04:00
return add_ba ( NULL , & info - > bas , start , size ) ;
2013-02-14 18:35:57 +04:00
}
2012-02-10 05:28:27 +04:00
void lvmcache_update_pv ( struct lvmcache_info * info , struct physical_volume * pv ,
const struct format_type * fmt )
{
info - > device_size = pv - > size < < SECTOR_SHIFT ;
info - > fmt = fmt ;
}
int lvmcache_update_das ( struct lvmcache_info * info , struct physical_volume * pv )
{
struct data_area_list * da ;
if ( info - > das . n ) {
if ( ! pv - > pe_start )
dm_list_iterate_items ( da , & info - > das )
pv - > pe_start = da - > disk_locn . offset > > SECTOR_SHIFT ;
del_das ( & info - > das ) ;
} else
dm_list_init ( & info - > das ) ;
2012-02-23 17:11:07 +04:00
if ( ! add_da ( NULL , & info - > das , pv - > pe_start < < SECTOR_SHIFT , 0 /*pv->size << SECTOR_SHIFT*/ ) )
2012-02-10 05:28:27 +04:00
return_0 ;
return 1 ;
}
2013-05-28 14:37:22 +04:00
int lvmcache_update_bas ( struct lvmcache_info * info , struct physical_volume * pv )
2013-02-14 18:35:57 +04:00
{
2013-05-28 14:37:22 +04:00
struct data_area_list * ba ;
if ( info - > bas . n ) {
if ( ! pv - > ba_start & & ! pv - > ba_size )
dm_list_iterate_items ( ba , & info - > bas ) {
pv - > ba_start = ba - > disk_locn . offset > > SECTOR_SHIFT ;
pv - > ba_size = ba - > disk_locn . size > > SECTOR_SHIFT ;
2013-02-14 18:35:57 +04:00
}
2013-05-28 14:37:22 +04:00
del_das ( & info - > bas ) ;
2013-02-14 18:35:57 +04:00
} else
2013-05-28 14:37:22 +04:00
dm_list_init ( & info - > bas ) ;
2013-02-14 18:35:57 +04:00
2013-05-28 14:37:22 +04:00
if ( ! add_ba ( NULL , & info - > bas , pv - > ba_start < < SECTOR_SHIFT , pv - > ba_size < < SECTOR_SHIFT ) )
2013-02-14 18:35:57 +04:00
return_0 ;
return 1 ;
}
2012-02-10 05:28:27 +04:00
int lvmcache_foreach_pv ( struct lvmcache_vginfo * vginfo ,
int ( * fun ) ( struct lvmcache_info * , void * ) ,
void * baton )
{
struct lvmcache_info * info ;
dm_list_iterate_items ( info , & vginfo - > infos ) {
if ( ! fun ( info , baton ) )
return_0 ;
}
return 1 ;
}
int lvmcache_foreach_mda ( struct lvmcache_info * info ,
int ( * fun ) ( struct metadata_area * , void * ) ,
void * baton )
{
struct metadata_area * mda ;
dm_list_iterate_items ( mda , & info - > mdas ) {
if ( ! fun ( mda , baton ) )
return_0 ;
}
return 1 ;
}
2013-02-05 19:43:16 +04:00
unsigned lvmcache_mda_count ( struct lvmcache_info * info )
2012-02-10 05:28:27 +04:00
{
return dm_list_size ( & info - > mdas ) ;
}
int lvmcache_foreach_da ( struct lvmcache_info * info ,
2012-02-23 17:11:07 +04:00
int ( * fun ) ( struct disk_locn * , void * ) ,
2012-02-10 05:28:27 +04:00
void * baton )
{
struct data_area_list * da ;
dm_list_iterate_items ( da , & info - > das ) {
2012-02-23 17:11:07 +04:00
if ( ! fun ( & da - > disk_locn , baton ) )
2012-02-10 05:28:27 +04:00
return_0 ;
}
return 1 ;
}
2013-05-28 14:37:22 +04:00
int lvmcache_foreach_ba ( struct lvmcache_info * info ,
2013-02-14 18:35:57 +04:00
int ( * fun ) ( struct disk_locn * , void * ) ,
void * baton )
{
2013-05-28 14:37:22 +04:00
struct data_area_list * ba ;
dm_list_iterate_items ( ba , & info - > bas ) {
if ( ! fun ( & ba - > disk_locn , baton ) )
2013-02-14 18:35:57 +04:00
return_0 ;
}
return 1 ;
}
2012-02-10 05:28:27 +04:00
/*
* The lifetime of the label returned is tied to the lifetime of the
* lvmcache_info which is the same as lvmcache itself .
*/
struct label * lvmcache_get_label ( struct lvmcache_info * info ) {
return info - > label ;
}
void lvmcache_make_valid ( struct lvmcache_info * info ) {
info - > status & = ~ CACHE_INVALID ;
}
uint64_t lvmcache_device_size ( struct lvmcache_info * info ) {
return info - > device_size ;
}
void lvmcache_set_device_size ( struct lvmcache_info * info , uint64_t size ) {
info - > device_size = size ;
}
struct device * lvmcache_device ( struct lvmcache_info * info ) {
return info - > dev ;
}
int lvmcache_is_orphan ( struct lvmcache_info * info ) {
if ( ! info - > vginfo )
return 1 ; /* FIXME? */
return is_orphan_vg ( info - > vginfo - > vgname ) ;
}
int lvmcache_vgid_is_cached ( const char * vgid ) {
struct lvmcache_vginfo * vginfo ;
2012-02-23 17:11:07 +04:00
if ( lvmetad_active ( ) )
return 1 ;
2012-02-10 05:28:27 +04:00
vginfo = lvmcache_vginfo_from_vgid ( vgid ) ;
if ( ! vginfo | | ! vginfo - > vgname )
return 0 ;
if ( is_orphan_vg ( vginfo - > vgname ) )
return 0 ;
return 1 ;
}
/*
* Return true iff it is impossible to find out from this info alone whether the
* PV in question is or is not an orphan .
*/
int lvmcache_uncertain_ownership ( struct lvmcache_info * info ) {
return mdas_empty_or_ignored ( & info - > mdas ) ;
}
2013-02-05 19:43:16 +04:00
uint64_t lvmcache_smallest_mda_size ( struct lvmcache_info * info )
2012-02-10 05:28:27 +04:00
{
return find_min_mda_size ( & info - > mdas ) ;
}
const struct format_type * lvmcache_fmt ( struct lvmcache_info * info ) {
return info - > fmt ;
}