2002-11-18 17:01:16 +03:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2009-02-23 00:14:37 +03:00
* Copyright ( C ) 2004 - 2009 Red Hat , Inc . All rights reserved .
2002-11-18 17:01:16 +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 17:01:16 +03:00
*/
# include "lib.h"
# include "toolcontext.h"
# include "metadata.h"
# include "defaults.h"
# include "lvm-string.h"
# include "activate.h"
# include "filter.h"
# include "filter-composite.h"
2004-04-16 20:12:04 +04:00
# include "filter-md.h"
2002-11-18 17:01:16 +03:00
# include "filter-persistent.h"
# include "filter-regex.h"
2004-02-13 17:46:04 +03:00
# include "filter-sysfs.h"
2002-11-18 17:01:16 +03:00
# include "label.h"
# include "lvm-file.h"
# include "format-text.h"
2002-12-12 23:55:49 +03:00
# include "display.h"
2003-07-05 02:34:56 +04:00
# include "memlock.h"
2004-03-08 21:13:22 +03:00
# include "str_list.h"
2004-09-16 22:40:56 +04:00
# include "segtype.h"
2004-05-05 01:25:57 +04:00
# include "lvmcache.h"
2005-05-09 21:41:36 +04:00
# include "dev-cache.h"
2005-05-17 17:46:38 +04:00
# include "archiver.h"
2002-11-18 17:01:16 +03:00
2003-03-24 21:08:53 +03:00
# ifdef HAVE_LIBDL
# include "sharedlib.h"
# endif
2002-11-18 17:01:16 +03:00
# ifdef LVM1_INTERNAL
# include "format1.h"
# endif
2004-06-07 23:10:21 +04:00
# ifdef POOL_INTERNAL
# include "format_pool.h"
# endif
2002-11-18 17:01:16 +03:00
# include <locale.h>
# include <sys/stat.h>
2004-03-08 20:25:59 +03:00
# include <sys/utsname.h>
2002-11-18 17:01:16 +03:00
# include <syslog.h>
# include <time.h>
2003-07-05 02:34:56 +04:00
# ifdef linux
# include <malloc.h>
# endif
2002-11-18 17:01:16 +03:00
static int _get_env_vars ( struct cmd_context * cmd )
{
const char * e ;
/* Set to "" to avoid using any system directory */
if ( ( e = getenv ( " LVM_SYSTEM_DIR " ) ) ) {
2009-02-23 00:14:37 +03:00
if ( dm_snprintf ( cmd - > system_dir , sizeof ( cmd - > system_dir ) ,
2002-11-18 17:01:16 +03:00
" %s " , e ) < 0 ) {
log_error ( " LVM_SYSTEM_DIR environment variable "
" is too long. " ) ;
return 0 ;
}
}
return 1 ;
}
2008-09-19 07:42:37 +04:00
static void _get_sysfs_dir ( struct cmd_context * cmd )
{
static char proc_mounts [ PATH_MAX ] ;
static char * split [ 4 ] , buffer [ PATH_MAX + 16 ] ;
FILE * fp ;
char * sys_mnt = NULL ;
cmd - > sysfs_dir [ 0 ] = ' \0 ' ;
if ( ! * cmd - > proc_dir ) {
log_debug ( " No proc filesystem found: skipping sysfs detection " ) ;
return ;
}
if ( dm_snprintf ( proc_mounts , sizeof ( proc_mounts ) ,
" %s/mounts " , cmd - > proc_dir ) < 0 ) {
log_error ( " Failed to create /proc/mounts string for sysfs detection " ) ;
return ;
}
if ( ! ( fp = fopen ( proc_mounts , " r " ) ) ) {
log_sys_error ( " _get_sysfs_dir: fopen %s " , proc_mounts ) ;
return ;
}
while ( fgets ( buffer , sizeof ( buffer ) , fp ) ) {
if ( dm_split_words ( buffer , 4 , 0 , split ) = = 4 & &
! strcmp ( split [ 2 ] , " sysfs " ) ) {
sys_mnt = split [ 1 ] ;
break ;
}
}
if ( fclose ( fp ) )
log_sys_error ( " fclose " , proc_mounts ) ;
if ( ! sys_mnt ) {
log_error ( " Failed to find sysfs mount point " ) ;
return ;
}
strncpy ( cmd - > sysfs_dir , sys_mnt , sizeof ( cmd - > sysfs_dir ) ) ;
}
2002-11-18 17:01:16 +03:00
static void _init_logging ( struct cmd_context * cmd )
{
2003-07-05 02:34:56 +04:00
int append = 1 ;
2002-11-18 17:01:16 +03:00
time_t t ;
const char * log_file ;
2006-05-16 20:48:31 +04:00
char timebuf [ 26 ] ;
2002-11-18 17:01:16 +03:00
/* Syslog */
cmd - > default_settings . syslog =
2006-05-16 20:48:31 +04:00
find_config_tree_int ( cmd , " log/syslog " , DEFAULT_SYSLOG ) ;
2002-11-18 17:01:16 +03:00
if ( cmd - > default_settings . syslog ! = 1 )
fin_syslog ( ) ;
if ( cmd - > default_settings . syslog > 1 )
init_syslog ( cmd - > default_settings . syslog ) ;
/* Debug level for log file output */
cmd - > default_settings . debug =
2006-05-16 20:48:31 +04:00
find_config_tree_int ( cmd , " log/level " , DEFAULT_LOGLEVEL ) ;
2002-11-18 17:01:16 +03:00
init_debug ( cmd - > default_settings . debug ) ;
/* Verbose level for tty output */
cmd - > default_settings . verbose =
2006-05-16 20:48:31 +04:00
find_config_tree_int ( cmd , " log/verbose " , DEFAULT_VERBOSE ) ;
2004-03-26 14:45:01 +03:00
init_verbose ( cmd - > default_settings . verbose + VERBOSE_BASE_LEVEL ) ;
2002-11-18 17:01:16 +03:00
/* Log message formatting */
2006-05-16 20:48:31 +04:00
init_indent ( find_config_tree_int ( cmd , " log/indent " ,
2009-11-30 20:17:11 +03:00
DEFAULT_INDENT ) ) ;
init_abort_on_internal_errors ( find_config_tree_int ( cmd , " global/abort_on_internal_errors " ,
DEFAULT_ABORT_ON_INTERNAL_ERRORS ) ) ;
2002-11-18 17:01:16 +03:00
2006-05-16 20:48:31 +04:00
cmd - > default_settings . msg_prefix = find_config_tree_str ( cmd ,
2004-03-08 21:28:45 +03:00
" log/prefix " ,
2002-11-18 17:01:16 +03:00
DEFAULT_MSG_PREFIX ) ;
init_msg_prefix ( cmd - > default_settings . msg_prefix ) ;
2006-05-16 20:48:31 +04:00
cmd - > default_settings . cmd_name = find_config_tree_int ( cmd ,
2002-11-18 17:01:16 +03:00
" log/command_names " ,
2004-03-08 21:28:45 +03:00
DEFAULT_CMD_NAME ) ;
2002-11-18 17:01:16 +03:00
init_cmd_name ( cmd - > default_settings . cmd_name ) ;
/* Test mode */
cmd - > default_settings . test =
2006-05-16 20:48:31 +04:00
find_config_tree_int ( cmd , " global/test " , 0 ) ;
2008-12-11 06:31:47 +03:00
init_test ( cmd - > default_settings . test ) ;
2002-11-18 17:01:16 +03:00
/* Settings for logging to file */
2006-05-16 20:48:31 +04:00
if ( find_config_tree_int ( cmd , " log/overwrite " , DEFAULT_OVERWRITE ) )
2003-07-05 02:34:56 +04:00
append = 0 ;
2002-11-18 17:01:16 +03:00
2006-05-16 20:48:31 +04:00
log_file = find_config_tree_str ( cmd , " log/file " , 0 ) ;
2004-03-08 21:13:22 +03:00
if ( log_file ) {
release_log_memory ( ) ;
fin_log ( ) ;
2003-07-05 02:34:56 +04:00
init_log_file ( log_file , append ) ;
2004-03-08 21:13:22 +03:00
}
2003-07-05 02:34:56 +04:00
2006-05-16 20:48:31 +04:00
log_file = find_config_tree_str ( cmd , " log/activate_file " , 0 ) ;
2003-07-05 02:34:56 +04:00
if ( log_file )
init_log_direct ( log_file , append ) ;
2006-05-16 20:48:31 +04:00
init_log_while_suspended ( find_config_tree_int ( cmd ,
2004-03-08 21:28:45 +03:00
" log/activation " , 0 ) ) ;
2002-11-18 17:01:16 +03:00
t = time ( NULL ) ;
2006-05-16 20:48:31 +04:00
ctime_r ( & t , & timebuf [ 0 ] ) ;
timebuf [ 24 ] = ' \0 ' ;
log_verbose ( " Logging initialised at %s " , timebuf ) ;
2002-11-18 17:01:16 +03:00
/* Tell device-mapper about our logging */
2003-01-09 01:44:07 +03:00
# ifdef DEVMAPPER_SUPPORT
2009-07-16 03:57:54 +04:00
dm_log_with_errno_init ( print_log ) ;
2003-01-09 01:44:07 +03:00
# endif
2010-05-06 02:37:52 +04:00
reset_log_duplicated ( ) ;
2010-06-02 01:46:29 +04:00
reset_lvm_errno ( 1 ) ;
2002-11-18 17:01:16 +03:00
}
static int _process_config ( struct cmd_context * cmd )
{
mode_t old_umask ;
2007-11-09 19:51:54 +03:00
const char * read_ahead ;
2008-09-19 10:42:00 +04:00
struct stat st ;
2010-03-09 06:16:11 +03:00
const struct config_node * cn ;
struct config_value * cv ;
2002-11-18 17:01:16 +03:00
/* umask */
2006-05-16 20:48:31 +04:00
cmd - > default_settings . umask = find_config_tree_int ( cmd ,
2004-03-08 21:28:45 +03:00
" global/umask " ,
2002-11-18 17:01:16 +03:00
DEFAULT_UMASK ) ;
if ( ( old_umask = umask ( ( mode_t ) cmd - > default_settings . umask ) ) ! =
( mode_t ) cmd - > default_settings . umask )
log_verbose ( " Set umask to %04o " , cmd - > default_settings . umask ) ;
/* dev dir */
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( cmd - > dev_dir , sizeof ( cmd - > dev_dir ) , " %s/ " ,
2006-05-16 20:48:31 +04:00
find_config_tree_str ( cmd , " devices/dir " ,
2004-03-08 21:28:45 +03:00
DEFAULT_DEV_DIR ) ) < 0 ) {
2002-11-18 17:01:16 +03:00
log_error ( " Device directory given in config file too long " ) ;
return 0 ;
}
2003-01-09 01:44:07 +03:00
# ifdef DEVMAPPER_SUPPORT
2002-11-18 17:01:16 +03:00
dm_set_dev_dir ( cmd - > dev_dir ) ;
2003-01-09 01:44:07 +03:00
# endif
2002-11-18 17:01:16 +03:00
/* proc dir */
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( cmd - > proc_dir , sizeof ( cmd - > proc_dir ) , " %s " ,
2006-05-16 20:48:31 +04:00
find_config_tree_str ( cmd , " global/proc " ,
2004-03-08 21:28:45 +03:00
DEFAULT_PROC_DIR ) ) < 0 ) {
2002-11-18 17:01:16 +03:00
log_error ( " Device directory given in config file too long " ) ;
return 0 ;
}
2005-01-27 18:50:34 +03:00
if ( * cmd - > proc_dir & & ! dir_exists ( cmd - > proc_dir ) ) {
2010-04-01 14:34:09 +04:00
log_warn ( " WARNING: proc dir %s not found - some checks will be bypassed " ,
cmd - > proc_dir ) ;
2005-01-27 18:50:34 +03:00
cmd - > proc_dir [ 0 ] = ' \0 ' ;
}
2008-09-19 07:42:37 +04:00
_get_sysfs_dir ( cmd ) ;
2002-11-18 17:01:16 +03:00
/* activation? */
2006-05-16 20:48:31 +04:00
cmd - > default_settings . activation = find_config_tree_int ( cmd ,
2002-11-18 17:01:16 +03:00
" global/activation " ,
DEFAULT_ACTIVATION ) ;
set_activation ( cmd - > default_settings . activation ) ;
2006-05-16 20:48:31 +04:00
cmd - > default_settings . suffix = find_config_tree_int ( cmd ,
2002-12-12 23:55:49 +03:00
" global/suffix " ,
2004-03-08 21:28:45 +03:00
DEFAULT_SUFFIX ) ;
2002-12-12 23:55:49 +03:00
if ( ! ( cmd - > default_settings . unit_factor =
2006-05-16 20:48:31 +04:00
units_to_bytes ( find_config_tree_str ( cmd ,
2002-12-12 23:55:49 +03:00
" global/units " ,
DEFAULT_UNITS ) ,
& cmd - > default_settings . unit_type ) ) ) {
log_error ( " Invalid units specification " ) ;
return 0 ;
2007-11-09 19:51:54 +03:00
}
read_ahead = find_config_tree_str ( cmd , " activation/readahead " , DEFAULT_READ_AHEAD ) ;
if ( ! strcasecmp ( read_ahead , " auto " ) )
cmd - > default_settings . read_ahead = DM_READ_AHEAD_AUTO ;
else if ( ! strcasecmp ( read_ahead , " none " ) )
cmd - > default_settings . read_ahead = DM_READ_AHEAD_NONE ;
else {
log_error ( " Invalid readahead specification " ) ;
return 0 ;
2002-12-12 23:55:49 +03:00
}
2010-01-07 22:54:21 +03:00
cmd - > default_settings . udev_rules = find_config_tree_int ( cmd ,
" activation/udev_rules " ,
DEFAULT_UDEV_RULES ) ;
2009-08-04 19:36:13 +04:00
cmd - > default_settings . udev_sync = find_config_tree_int ( cmd ,
" activation/udev_sync " ,
DEFAULT_UDEV_SYNC ) ;
2008-09-19 10:42:00 +04:00
cmd - > stripe_filler = find_config_tree_str ( cmd ,
" activation/missing_stripe_filler " ,
DEFAULT_STRIPE_FILLER ) ;
2008-09-19 22:26:41 +04:00
/* FIXME Missing error code checks from the stats, not log_warn?, notify if setting overridden, delay message/check till it is actually used (eg consider if lvm shell - file could appear later after this check)? */
if ( ! strcmp ( cmd - > stripe_filler , " /dev/ioerror " ) & &
stat ( cmd - > stripe_filler , & st ) )
cmd - > stripe_filler = " error " ;
2008-09-19 10:42:00 +04:00
if ( strcmp ( cmd - > stripe_filler , " error " ) ) {
if ( stat ( cmd - > stripe_filler , & st ) ) {
log_warn ( " WARNING: activation/missing_stripe_filler = \" %s \" "
" is invalid, " , cmd - > stripe_filler ) ;
log_warn ( " stat failed: %s " , strerror ( errno ) ) ;
log_warn ( " Falling back to \" error \" missing_stripe_filler. " ) ;
cmd - > stripe_filler = " error " ;
} else if ( ! S_ISBLK ( st . st_mode ) ) {
log_warn ( " WARNING: activation/missing_stripe_filler = \" %s \" "
" is not a block device. " , cmd - > stripe_filler ) ;
log_warn ( " Falling back to \" error \" missing_stripe_filler. " ) ;
cmd - > stripe_filler = " error " ;
}
}
2009-09-28 20:23:44 +04:00
cmd - > si_unit_consistency = find_config_tree_int ( cmd ,
" global/si_unit_consistency " ,
DEFAULT_SI_UNIT_CONSISTENCY ) ;
2010-03-09 06:16:11 +03:00
if ( ( cn = find_config_tree_node ( cmd , " activation/mlock_filter " ) ) )
for ( cv = cn - > v ; cv ; cv = cv - > next )
if ( ( cv - > type ! = CFG_STRING ) | | ! cv - > v . str [ 0 ] )
log_error ( " Ignoring invalid activation/mlock_filter entry in config file " ) ;
2002-11-18 17:01:16 +03:00
return 1 ;
}
2004-05-04 22:28:15 +04:00
static int _set_tag ( struct cmd_context * cmd , const char * tag )
2002-11-18 17:01:16 +03:00
{
2005-10-17 03:03:59 +04:00
log_very_verbose ( " Setting host tag: %s " , dm_pool_strdup ( cmd - > libmem , tag ) ) ;
2002-11-18 17:01:16 +03:00
2004-05-04 22:28:15 +04:00
if ( ! str_list_add ( cmd - > libmem , & cmd - > tags , tag ) ) {
log_error ( " _set_tag: str_list_add %s failed " , tag ) ;
2002-11-18 17:01:16 +03:00
return 0 ;
}
2004-05-04 22:28:15 +04:00
return 1 ;
}
static int _check_host_filters ( struct cmd_context * cmd , struct config_node * hn ,
int * passes )
{
struct config_node * cn ;
struct config_value * cv ;
* passes = 1 ;
for ( cn = hn ; cn ; cn = cn - > sib ) {
if ( ! cn - > v )
continue ;
if ( ! strcmp ( cn - > key , " host_list " ) ) {
* passes = 0 ;
if ( cn - > v - > type = = CFG_EMPTY_ARRAY )
continue ;
for ( cv = cn - > v ; cv ; cv = cv - > next ) {
if ( cv - > type ! = CFG_STRING ) {
log_error ( " Invalid hostname string "
" for tag %s " , cn - > key ) ;
return 0 ;
}
if ( ! strcmp ( cv - > v . str , cmd - > hostname ) ) {
* passes = 1 ;
return 1 ;
}
}
}
if ( ! strcmp ( cn - > key , " host_filter " ) ) {
log_error ( " host_filter not supported yet " ) ;
return 0 ;
}
}
return 1 ;
}
static int _init_tags ( struct cmd_context * cmd , struct config_tree * cft )
{
const struct config_node * tn , * cn ;
const char * tag ;
int passes ;
if ( ! ( tn = find_config_node ( cft - > root , " tags " ) ) | | ! tn - > child )
2002-11-18 17:01:16 +03:00
return 1 ;
2004-05-04 22:28:15 +04:00
/* NB hosttags 0 when already 1 intentionally does not delete the tag */
if ( ! cmd - > hosttags & & find_config_int ( cft - > root , " tags/hosttags " ,
DEFAULT_HOSTTAGS ) ) {
/* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */
2008-01-30 16:19:47 +03:00
if ( ! _set_tag ( cmd , cmd - > hostname ) )
return_0 ;
2004-05-04 22:28:15 +04:00
cmd - > hosttags = 1 ;
}
for ( cn = tn - > child ; cn ; cn = cn - > sib ) {
if ( cn - > v )
continue ;
tag = cn - > key ;
if ( * tag = = ' @ ' )
tag + + ;
if ( ! validate_name ( tag ) ) {
log_error ( " Invalid tag in config file: %s " , cn - > key ) ;
return 0 ;
}
if ( cn - > child ) {
passes = 0 ;
2008-01-30 16:19:47 +03:00
if ( ! _check_host_filters ( cmd , cn - > child , & passes ) )
return_0 ;
2004-05-04 22:28:15 +04:00
if ( ! passes )
continue ;
}
2008-01-30 16:19:47 +03:00
if ( ! _set_tag ( cmd , tag ) )
return_0 ;
2004-05-04 22:28:15 +04:00
}
return 1 ;
}
static int _load_config_file ( struct cmd_context * cmd , const char * tag )
{
char config_file [ PATH_MAX ] = " " ;
const char * filler = " " ;
struct stat info ;
struct config_tree_list * cfl ;
if ( * tag )
filler = " _ " ;
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( config_file , sizeof ( config_file ) , " %s/lvm%s%s.conf " ,
2009-02-23 00:14:37 +03:00
cmd - > system_dir , filler , tag ) < 0 ) {
2004-05-04 22:28:15 +04:00
log_error ( " LVM_SYSTEM_DIR or tag was too long " ) ;
return 0 ;
}
2005-10-17 03:03:59 +04:00
if ( ! ( cfl = dm_pool_alloc ( cmd - > libmem , sizeof ( * cfl ) ) ) ) {
2004-05-04 22:28:15 +04:00
log_error ( " config_tree_list allocation failed " ) ;
return 0 ;
}
2006-11-04 06:34:10 +03:00
if ( ! ( cfl - > cft = create_config_tree ( config_file , 0 ) ) ) {
2004-05-04 22:28:15 +04:00
log_error ( " config_tree allocation failed " ) ;
2002-11-18 17:01:16 +03:00
return 0 ;
}
/* Is there a config file? */
if ( stat ( config_file , & info ) = = - 1 ) {
2004-05-04 22:28:15 +04:00
if ( errno = = ENOENT ) {
2008-11-04 01:14:30 +03:00
dm_list_add ( & cmd - > config_files , & cfl - > list ) ;
2004-05-04 22:28:15 +04:00
goto out ;
}
2002-11-18 17:01:16 +03:00
log_sys_error ( " stat " , config_file ) ;
2004-05-04 22:28:15 +04:00
destroy_config_tree ( cfl - > cft ) ;
2002-11-18 17:01:16 +03:00
return 0 ;
}
2004-05-04 22:28:15 +04:00
log_very_verbose ( " Loading config file: %s " , config_file ) ;
if ( ! read_config_file ( cfl - > cft ) ) {
2002-11-18 17:01:16 +03:00
log_error ( " Failed to load config file %s " , config_file ) ;
2004-05-04 22:28:15 +04:00
destroy_config_tree ( cfl - > cft ) ;
2002-11-18 17:01:16 +03:00
return 0 ;
}
2008-11-04 01:14:30 +03:00
dm_list_add ( & cmd - > config_files , & cfl - > list ) ;
2004-05-04 22:28:15 +04:00
out :
if ( * tag )
_init_tags ( cmd , cfl - > cft ) ;
else
/* Use temporary copy of lvm.conf while loading other files */
cmd - > cft = cfl - > cft ;
return 1 ;
}
/* Find and read first config file */
static int _init_lvm_conf ( struct cmd_context * cmd )
{
/* No config file if LVM_SYSTEM_DIR is empty */
2009-02-23 00:14:37 +03:00
if ( ! * cmd - > system_dir ) {
2006-11-04 06:34:10 +03:00
if ( ! ( cmd - > cft = create_config_tree ( NULL , 0 ) ) ) {
2004-05-04 22:28:15 +04:00
log_error ( " Failed to create config tree " ) ;
return 0 ;
}
return 1 ;
}
2008-01-30 16:19:47 +03:00
if ( ! _load_config_file ( cmd , " " ) )
return_0 ;
2004-05-04 22:28:15 +04:00
return 1 ;
}
/* Read any additional config files */
static int _init_tag_configs ( struct cmd_context * cmd )
{
struct str_list * sl ;
/* Tag list may grow while inside this loop */
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( sl , & cmd - > tags ) {
2008-01-30 16:19:47 +03:00
if ( ! _load_config_file ( cmd , sl - > str ) )
return_0 ;
2004-05-04 22:28:15 +04:00
}
2002-11-18 17:01:16 +03:00
return 1 ;
}
2004-05-04 22:28:15 +04:00
static int _merge_config_files ( struct cmd_context * cmd )
{
struct config_tree_list * cfl ;
/* Replace temporary duplicate copy of lvm.conf */
if ( cmd - > cft - > root ) {
2006-11-04 06:34:10 +03:00
if ( ! ( cmd - > cft = create_config_tree ( NULL , 0 ) ) ) {
2004-05-04 22:28:15 +04:00
log_error ( " Failed to create config tree " ) ;
return 0 ;
}
}
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( cfl , & cmd - > config_files ) {
2004-05-04 22:28:15 +04:00
/* Merge all config trees into cmd->cft using merge/tag rules */
2008-01-30 16:19:47 +03:00
if ( ! merge_config_tree ( cmd , cmd - > cft , cfl - > cft ) )
return_0 ;
2004-05-04 22:28:15 +04:00
}
return 1 ;
}
static void _destroy_tags ( struct cmd_context * cmd )
{
2008-11-04 01:14:30 +03:00
struct dm_list * slh , * slht ;
2004-05-04 22:28:15 +04:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_safe ( slh , slht , & cmd - > tags ) {
dm_list_del ( slh ) ;
2004-05-04 22:28:15 +04:00
}
}
int config_files_changed ( struct cmd_context * cmd )
{
struct config_tree_list * cfl ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( cfl , & cmd - > config_files ) {
2004-05-04 22:28:15 +04:00
if ( config_file_changed ( cfl - > cft ) )
return 1 ;
}
return 0 ;
}
static void _destroy_tag_configs ( struct cmd_context * cmd )
{
struct config_tree_list * cfl ;
2009-06-15 15:56:31 +04:00
dm_list_iterate_items ( cfl , & cmd - > config_files ) {
2009-06-18 00:54:20 +04:00
if ( cfl - > cft = = cmd - > cft )
cmd - > cft = NULL ;
2009-06-15 15:56:31 +04:00
destroy_config_tree ( cfl - > cft ) ;
}
2009-06-18 00:54:20 +04:00
if ( cmd - > cft ) {
2004-05-04 22:28:15 +04:00
destroy_config_tree ( cmd - > cft ) ;
cmd - > cft = NULL ;
}
2008-11-04 01:14:30 +03:00
dm_list_init ( & cmd - > config_files ) ;
2004-05-04 22:28:15 +04:00
}
2002-11-18 17:01:16 +03:00
static int _init_dev_cache ( struct cmd_context * cmd )
{
2004-05-04 22:28:15 +04:00
const struct config_node * cn ;
2002-11-18 17:01:16 +03:00
struct config_value * cv ;
2007-04-26 20:44:59 +04:00
if ( ! dev_cache_init ( cmd ) )
return_0 ;
2002-11-18 17:01:16 +03:00
2006-05-16 20:48:31 +04:00
if ( ! ( cn = find_config_tree_node ( cmd , " devices/scan " ) ) ) {
2002-11-18 17:01:16 +03:00
if ( ! dev_cache_add_dir ( " /dev " ) ) {
log_error ( " Failed to add /dev to internal "
" device cache " ) ;
return 0 ;
}
log_verbose ( " device/scan not in config file: "
" Defaulting to /dev " ) ;
return 1 ;
}
for ( cv = cn - > v ; cv ; cv = cv - > next ) {
if ( cv - > type ! = CFG_STRING ) {
log_error ( " Invalid string in config file: "
" devices/scan " ) ;
return 0 ;
}
if ( ! dev_cache_add_dir ( cv - > v . str ) ) {
log_error ( " Failed to add %s to internal device cache " ,
cv - > v . str ) ;
return 0 ;
}
}
2006-05-16 20:48:31 +04:00
if ( ! ( cn = find_config_tree_node ( cmd , " devices/loopfiles " ) ) )
2005-05-03 21:28:23 +04:00
return 1 ;
for ( cv = cn - > v ; cv ; cv = cv - > next ) {
if ( cv - > type ! = CFG_STRING ) {
log_error ( " Invalid string in config file: "
" devices/loopfiles " ) ;
return 0 ;
}
if ( ! dev_cache_add_loopfile ( cv - > v . str ) ) {
log_error ( " Failed to add loopfile %s to internal "
" device cache " , cv - > v . str ) ;
return 0 ;
}
}
2002-11-18 17:01:16 +03:00
return 1 ;
}
2004-04-16 20:12:04 +04:00
# define MAX_FILTERS 4
2004-02-13 17:46:04 +03:00
2002-11-18 17:01:16 +03:00
static struct dev_filter * _init_filter_components ( struct cmd_context * cmd )
{
2004-02-13 17:46:04 +03:00
unsigned nr_filt = 0 ;
2004-05-04 22:28:15 +04:00
const struct config_node * cn ;
2004-02-13 17:46:04 +03:00
struct dev_filter * filters [ MAX_FILTERS ] ;
2002-11-18 17:01:16 +03:00
2004-02-13 17:46:04 +03:00
memset ( filters , 0 , sizeof ( filters ) ) ;
2002-12-03 19:20:38 +03:00
2004-04-16 20:12:04 +04:00
/*
* Filters listed in order : top one gets applied first .
* Failure to initialise some filters is not fatal .
* Update MAX_FILTERS definition above when adding new filters .
*/
/*
* sysfs filter . Only available on 2.6 kernels . Non - critical .
2008-01-30 17:00:02 +03:00
* Listed first because it ' s very efficient at eliminating
2004-04-16 20:12:04 +04:00
* unavailable devices .
*/
2006-05-16 20:48:31 +04:00
if ( find_config_tree_bool ( cmd , " devices/sysfs_scan " ,
2004-02-13 17:46:04 +03:00
DEFAULT_SYSFS_SCAN ) ) {
2008-09-19 07:42:37 +04:00
if ( ( filters [ nr_filt ] = sysfs_filter_create ( cmd - > sysfs_dir ) ) )
2004-02-13 17:46:04 +03:00
nr_filt + + ;
}
2002-11-18 17:01:16 +03:00
2004-04-16 20:12:04 +04:00
/* regex filter. Optional. */
2006-05-16 20:48:31 +04:00
if ( ! ( cn = find_config_tree_node ( cmd , " devices/filter " ) ) )
2004-12-10 19:01:35 +03:00
log_very_verbose ( " devices/filter not found in config file: "
" no regex filter installed " ) ;
2002-11-18 17:01:16 +03:00
2004-02-13 17:46:04 +03:00
else if ( ! ( filters [ nr_filt + + ] = regex_filter_create ( cn - > v ) ) ) {
2002-11-18 17:01:16 +03:00
log_error ( " Failed to create regex device filter " ) ;
2010-04-30 16:37:04 +04:00
goto err ;
2002-11-18 17:01:16 +03:00
}
2004-04-16 20:12:04 +04:00
/* device type filter. Required. */
2006-05-16 20:48:31 +04:00
cn = find_config_tree_node ( cmd , " devices/types " ) ;
2004-02-13 17:46:04 +03:00
if ( ! ( filters [ nr_filt + + ] = lvm_type_filter_create ( cmd - > proc_dir , cn ) ) ) {
log_error ( " Failed to create lvm type filter " ) ;
2010-04-30 16:37:04 +04:00
goto err ;
2002-11-18 17:01:16 +03:00
}
2004-04-16 20:12:04 +04:00
/* md component filter. Optional, non-critical. */
2006-05-16 20:48:31 +04:00
if ( find_config_tree_bool ( cmd , " devices/md_component_detection " ,
2004-04-16 20:12:04 +04:00
DEFAULT_MD_COMPONENT_DETECTION ) ) {
2004-11-19 22:25:07 +03:00
init_md_filtering ( 1 ) ;
2004-04-16 20:12:04 +04:00
if ( ( filters [ nr_filt ] = md_filter_create ( ) ) )
nr_filt + + ;
}
/* Only build a composite filter if we really need it. */
2004-02-13 17:46:04 +03:00
return ( nr_filt = = 1 ) ?
filters [ 0 ] : composite_filter_create ( nr_filt , filters ) ;
2010-04-30 16:37:04 +04:00
err :
nr_filt - - ; /* skip NULL */
while ( nr_filt - - > 0 )
filters [ nr_filt ] - > destroy ( filters [ nr_filt ] ) ;
return NULL ;
2002-11-18 17:01:16 +03:00
}
2007-01-23 18:58:06 +03:00
static int _init_filters ( struct cmd_context * cmd , unsigned load_persistent_cache )
2002-11-18 17:01:16 +03:00
{
2007-02-28 21:27:13 +03:00
const char * dev_cache = NULL , * cache_dir , * cache_file_prefix ;
2002-11-18 17:01:16 +03:00
struct dev_filter * f3 , * f4 ;
struct stat st ;
char cache_file [ PATH_MAX ] ;
cmd - > dump_filter = 0 ;
if ( ! ( f3 = _init_filter_components ( cmd ) ) )
return 0 ;
2007-01-26 00:22:30 +03:00
init_ignore_suspended_devices ( find_config_tree_int ( cmd ,
" devices/ignore_suspended_devices " , DEFAULT_IGNORE_SUSPENDED_DEVICES ) ) ;
2007-02-28 21:27:13 +03:00
/*
* If ' cache_dir ' or ' cache_file_prefix ' is set , ignore ' cache ' .
*/
cache_dir = find_config_tree_str ( cmd , " devices/cache_dir " , NULL ) ;
cache_file_prefix = find_config_tree_str ( cmd , " devices/cache_file_prefix " , NULL ) ;
if ( cache_dir | | cache_file_prefix ) {
if ( dm_snprintf ( cache_file , sizeof ( cache_file ) ,
" %s%s%s/%s.cache " ,
2009-02-23 00:14:37 +03:00
cache_dir ? " " : cmd - > system_dir ,
2007-02-28 21:27:13 +03:00
cache_dir ? " " : " / " ,
cache_dir ? : DEFAULT_CACHE_SUBDIR ,
cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX ) < 0 ) {
log_error ( " Persistent cache filename too long. " ) ;
return 0 ;
}
} else if ( ! ( dev_cache = find_config_tree_str ( cmd , " devices/cache " , NULL ) ) & &
( dm_snprintf ( cache_file , sizeof ( cache_file ) ,
" %s/%s/%s.cache " ,
2009-02-23 00:14:37 +03:00
cmd - > system_dir , DEFAULT_CACHE_SUBDIR ,
2007-02-28 21:27:13 +03:00
DEFAULT_CACHE_FILE_PREFIX ) < 0 ) ) {
log_error ( " Persistent cache filename too long. " ) ;
return 0 ;
}
2007-07-23 14:45:49 +04:00
if ( ! dev_cache )
dev_cache = cache_file ;
if ( ! ( f4 = persistent_filter_create ( f3 , dev_cache ) ) ) {
2002-11-18 17:01:16 +03:00
log_error ( " Failed to create persistent device filter " ) ;
return 0 ;
}
/* Should we ever dump persistent filter state? */
2006-05-16 20:48:31 +04:00
if ( find_config_tree_int ( cmd , " devices/write_cache_state " , 1 ) )
2002-11-18 17:01:16 +03:00
cmd - > dump_filter = 1 ;
2009-02-23 00:14:37 +03:00
if ( ! * cmd - > system_dir )
2002-11-18 17:01:16 +03:00
cmd - > dump_filter = 0 ;
2007-01-23 18:58:06 +03:00
/*
* Only load persistent filter device cache on startup if it is newer
* than the config file and this is not a long - lived process .
*/
if ( load_persistent_cache & & ! cmd - > is_long_lived & &
! stat ( dev_cache , & st ) & &
( st . st_ctime > config_file_timestamp ( cmd - > cft ) ) & &
2006-11-04 06:34:10 +03:00
! persistent_filter_load ( f4 , NULL ) )
2002-11-18 17:01:16 +03:00
log_verbose ( " Failed to load existing device cache from %s " ,
2003-07-05 02:34:56 +04:00
dev_cache ) ;
2002-11-18 17:01:16 +03:00
cmd - > filter = f4 ;
return 1 ;
}
2010-04-29 05:38:12 +04:00
struct format_type * get_format_by_name ( struct cmd_context * cmd , const char * format )
{
struct format_type * fmt ;
dm_list_iterate_items ( fmt , & cmd - > formats )
if ( ! strcasecmp ( fmt - > name , format ) | |
! strcasecmp ( fmt - > name + 3 , format ) | |
( fmt - > alias & & ! strcasecmp ( fmt - > alias , format ) ) )
return fmt ;
return NULL ;
}
2002-11-18 17:01:16 +03:00
static int _init_formats ( struct cmd_context * cmd )
{
const char * format ;
struct format_type * fmt ;
2003-03-24 21:08:53 +03:00
# ifdef HAVE_LIBDL
2004-05-04 22:28:15 +04:00
const struct config_node * cn ;
2003-03-24 21:08:53 +03:00
# endif
2002-11-18 17:01:16 +03:00
label_init ( ) ;
# ifdef LVM1_INTERNAL
if ( ! ( fmt = init_lvm1_format ( cmd ) ) )
return 0 ;
fmt - > library = NULL ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & cmd - > formats , & fmt - > list ) ;
2002-11-18 17:01:16 +03:00
# endif
2004-06-07 23:10:21 +04:00
# ifdef POOL_INTERNAL
if ( ! ( fmt = init_pool_format ( cmd ) ) )
return 0 ;
fmt - > library = NULL ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & cmd - > formats , & fmt - > list ) ;
2004-06-07 23:10:21 +04:00
# endif
2003-03-24 21:08:53 +03:00
# ifdef HAVE_LIBDL
2006-09-01 02:21:00 +04:00
/* Load any formats in shared libs if not static */
2008-12-18 08:27:17 +03:00
if ( ! is_static ( ) & &
2006-09-01 02:21:00 +04:00
( cn = find_config_tree_node ( cmd , " global/format_libraries " ) ) ) {
2003-03-24 21:08:53 +03:00
struct config_value * cv ;
struct format_type * ( * init_format_fn ) ( struct cmd_context * ) ;
void * lib ;
2002-11-18 17:01:16 +03:00
for ( cv = cn - > v ; cv ; cv = cv - > next ) {
if ( cv - > type ! = CFG_STRING ) {
log_error ( " Invalid string in config file: "
" global/format_libraries " ) ;
return 0 ;
}
2006-05-16 20:48:31 +04:00
if ( ! ( lib = load_shared_library ( cmd , cv - > v . str ,
2008-01-30 16:19:47 +03:00
" format " , 0 ) ) )
return_0 ;
2002-11-18 17:01:16 +03:00
if ( ! ( init_format_fn = dlsym ( lib , " init_format " ) ) ) {
log_error ( " Shared library %s does not contain "
" format functions " , cv - > v . str ) ;
dlclose ( lib ) ;
return 0 ;
}
if ( ! ( fmt = init_format_fn ( cmd ) ) )
return 0 ;
fmt - > library = lib ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & cmd - > formats , & fmt - > list ) ;
2002-11-18 17:01:16 +03:00
}
}
2003-03-24 21:08:53 +03:00
# endif
2002-11-18 17:01:16 +03:00
if ( ! ( fmt = create_text_format ( cmd ) ) )
return 0 ;
fmt - > library = NULL ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & cmd - > formats , & fmt - > list ) ;
2002-11-18 17:01:16 +03:00
cmd - > fmt_backup = fmt ;
2006-05-16 20:48:31 +04:00
format = find_config_tree_str ( cmd , " global/format " ,
2002-11-18 17:01:16 +03:00
DEFAULT_FORMAT ) ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( fmt , & cmd - > formats ) {
2002-11-18 17:01:16 +03:00
if ( ! strcasecmp ( fmt - > name , format ) | |
( fmt - > alias & & ! strcasecmp ( fmt - > alias , format ) ) ) {
2010-04-29 05:38:12 +04:00
cmd - > default_settings . fmt_name = fmt - > name ;
cmd - > fmt = fmt ;
2002-11-18 17:01:16 +03:00
return 1 ;
}
}
log_error ( " _init_formats: Default format (%s) not found " , format ) ;
return 0 ;
}
2008-04-08 16:49:21 +04:00
int init_lvmcache_orphans ( struct cmd_context * cmd )
{
struct format_type * fmt ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( fmt , & cmd - > formats )
2008-04-08 16:49:21 +04:00
if ( ! lvmcache_add_orphan_vginfo ( fmt - > orphan_vg_name , fmt ) )
return_0 ;
return 1 ;
}
2009-07-08 16:36:01 +04:00
struct segtype_library {
struct cmd_context * cmd ;
void * lib ;
const char * libname ;
} ;
int lvm_register_segtype ( struct segtype_library * seglib ,
struct segment_type * segtype )
{
struct segment_type * segtype2 ;
segtype - > library = seglib - > lib ;
segtype - > cmd = seglib - > cmd ;
dm_list_iterate_items ( segtype2 , & seglib - > cmd - > segtypes ) {
if ( strcmp ( segtype2 - > name , segtype - > name ) )
continue ;
log_error ( " Duplicate segment type %s: "
" unloading shared library %s " ,
segtype - > name , seglib - > libname ) ;
segtype - > ops - > destroy ( segtype ) ;
return 0 ;
}
dm_list_add ( & seglib - > cmd - > segtypes , & segtype - > list ) ;
return 1 ;
}
2009-07-22 00:00:02 +04:00
static int _init_single_segtype ( struct cmd_context * cmd ,
struct segtype_library * seglib )
2009-07-08 16:36:01 +04:00
{
struct segment_type * ( * init_segtype_fn ) ( struct cmd_context * ) ;
struct segment_type * segtype ;
if ( ! ( init_segtype_fn = dlsym ( seglib - > lib , " init_segtype " ) ) ) {
log_error ( " Shared library %s does not contain segment type "
" functions " , seglib - > libname ) ;
return 0 ;
}
if ( ! ( segtype = init_segtype_fn ( seglib - > cmd ) ) )
return_0 ;
return lvm_register_segtype ( seglib , segtype ) ;
}
2004-05-05 01:25:57 +04:00
static int _init_segtypes ( struct cmd_context * cmd )
{
struct segment_type * segtype ;
2009-07-14 16:17:14 +04:00
struct segtype_library seglib = { . cmd = cmd } ;
2004-05-05 01:25:57 +04:00
# ifdef HAVE_LIBDL
const struct config_node * cn ;
# endif
if ( ! ( segtype = init_striped_segtype ( cmd ) ) )
return 0 ;
segtype - > library = NULL ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & cmd - > segtypes , & segtype - > list ) ;
2004-05-05 01:25:57 +04:00
2004-05-11 20:01:58 +04:00
if ( ! ( segtype = init_zero_segtype ( cmd ) ) )
return 0 ;
segtype - > library = NULL ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & cmd - > segtypes , & segtype - > list ) ;
2004-05-11 20:01:58 +04:00
if ( ! ( segtype = init_error_segtype ( cmd ) ) )
return 0 ;
segtype - > library = NULL ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & cmd - > segtypes , & segtype - > list ) ;
2004-05-11 20:01:58 +04:00
2008-06-25 20:52:27 +04:00
if ( ! ( segtype = init_free_segtype ( cmd ) ) )
return 0 ;
segtype - > library = NULL ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & cmd - > segtypes , & segtype - > list ) ;
2008-06-25 20:52:27 +04:00
2004-05-05 01:25:57 +04:00
# ifdef SNAPSHOT_INTERNAL
if ( ! ( segtype = init_snapshot_segtype ( cmd ) ) )
return 0 ;
segtype - > library = NULL ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & cmd - > segtypes , & segtype - > list ) ;
2004-05-05 01:25:57 +04:00
# endif
# ifdef MIRRORED_INTERNAL
if ( ! ( segtype = init_mirrored_segtype ( cmd ) ) )
return 0 ;
segtype - > library = NULL ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & cmd - > segtypes , & segtype - > list ) ;
2004-05-05 01:25:57 +04:00
# endif
2010-05-21 16:36:30 +04:00
# ifdef REPLICATOR_INTERNAL
if ( ! init_replicator_segtype ( & seglib ) )
return 0 ;
# endif
2004-05-05 01:25:57 +04:00
# ifdef HAVE_LIBDL
2006-09-01 02:21:00 +04:00
/* Load any formats in shared libs unless static */
2008-12-18 08:27:17 +03:00
if ( ! is_static ( ) & &
2006-09-01 02:21:00 +04:00
( cn = find_config_tree_node ( cmd , " global/segment_libraries " ) ) ) {
2004-05-05 01:25:57 +04:00
struct config_value * cv ;
2009-07-22 00:00:02 +04:00
int ( * init_multiple_segtypes_fn ) ( struct cmd_context * ,
struct segtype_library * ) ;
2004-05-05 01:25:57 +04:00
for ( cv = cn - > v ; cv ; cv = cv - > next ) {
if ( cv - > type ! = CFG_STRING ) {
log_error ( " Invalid string in config file: "
" global/segment_libraries " ) ;
return 0 ;
}
2009-07-08 16:36:01 +04:00
seglib . libname = cv - > v . str ;
if ( ! ( seglib . lib = load_shared_library ( cmd ,
seglib . libname ,
2008-01-30 16:19:47 +03:00
" segment type " , 0 ) ) )
return_0 ;
2004-05-05 01:25:57 +04:00
2009-07-08 16:36:01 +04:00
if ( ( init_multiple_segtypes_fn =
dlsym ( seglib . lib , " init_multiple_segtypes " ) ) ) {
if ( dlsym ( seglib . lib , " init_segtype " ) )
log_warn ( " WARNING: Shared lib %s has "
" conflicting init fns. Using "
" init_multiple_segtypes(). " ,
seglib . libname ) ;
} else
init_multiple_segtypes_fn =
_init_single_segtype ;
2009-07-22 00:00:02 +04:00
if ( ! init_multiple_segtypes_fn ( cmd , & seglib ) ) {
2009-07-08 16:36:01 +04:00
struct dm_list * sgtl , * tmp ;
log_error ( " init_multiple_segtypes() failed: "
" Unloading shared library %s " ,
seglib . libname ) ;
dm_list_iterate_safe ( sgtl , tmp , & cmd - > segtypes ) {
segtype = dm_list_item ( sgtl , struct segment_type ) ;
if ( segtype - > library = = seglib . lib ) {
dm_list_del ( & segtype - > list ) ;
segtype - > ops - > destroy ( segtype ) ;
}
}
dlclose ( seglib . lib ) ;
return_0 ;
2004-05-05 01:25:57 +04:00
}
}
}
# endif
return 1 ;
}
2004-03-08 20:25:59 +03:00
static int _init_hostname ( struct cmd_context * cmd )
{
struct utsname uts ;
if ( uname ( & uts ) ) {
log_sys_error ( " uname " , " _init_hostname " ) ;
return 0 ;
}
2005-10-17 03:03:59 +04:00
if ( ! ( cmd - > hostname = dm_pool_strdup ( cmd - > libmem , uts . nodename ) ) ) {
log_error ( " _init_hostname: dm_pool_strdup failed " ) ;
2004-03-08 20:25:59 +03:00
return 0 ;
}
2005-10-17 03:03:59 +04:00
if ( ! ( cmd - > kernel_vsn = dm_pool_strdup ( cmd - > libmem , uts . release ) ) ) {
log_error ( " _init_hostname: dm_pool_strdup kernel_vsn failed " ) ;
2004-04-08 21:21:01 +04:00
return 0 ;
}
2004-03-08 20:25:59 +03:00
return 1 ;
}
2005-05-17 17:46:38 +04:00
static int _init_backup ( struct cmd_context * cmd )
{
uint32_t days , min ;
char default_dir [ PATH_MAX ] ;
const char * dir ;
2009-02-23 00:14:37 +03:00
if ( ! cmd - > system_dir ) {
2005-05-17 17:46:38 +04:00
log_warn ( " WARNING: Metadata changes will NOT be backed up " ) ;
2008-12-11 06:33:35 +03:00
backup_init ( cmd , " " , 0 ) ;
2008-12-11 06:32:56 +03:00
archive_init ( cmd , " " , 0 , 0 , 0 ) ;
2005-05-17 17:46:38 +04:00
return 1 ;
}
/* set up archiving */
cmd - > default_settings . archive =
2006-05-16 20:48:31 +04:00
find_config_tree_bool ( cmd , " backup/archive " ,
2005-05-17 17:46:38 +04:00
DEFAULT_ARCHIVE_ENABLED ) ;
2006-05-16 20:48:31 +04:00
days = ( uint32_t ) find_config_tree_int ( cmd , " backup/retain_days " ,
2005-05-17 17:46:38 +04:00
DEFAULT_ARCHIVE_DAYS ) ;
2006-05-16 20:48:31 +04:00
min = ( uint32_t ) find_config_tree_int ( cmd , " backup/retain_min " ,
2005-05-17 17:46:38 +04:00
DEFAULT_ARCHIVE_NUMBER ) ;
2006-08-21 16:54:53 +04:00
if ( dm_snprintf
2009-02-23 00:14:37 +03:00
( default_dir , sizeof ( default_dir ) , " %s/%s " , cmd - > system_dir ,
2005-05-17 17:46:38 +04:00
DEFAULT_ARCHIVE_SUBDIR ) = = - 1 ) {
2009-07-16 00:02:46 +04:00
log_error ( " Couldn't create default archive path '%s/%s'. " ,
cmd - > system_dir , DEFAULT_ARCHIVE_SUBDIR ) ;
2005-05-17 17:46:38 +04:00
return 0 ;
}
2006-05-16 20:48:31 +04:00
dir = find_config_tree_str ( cmd , " backup/archive_dir " ,
2005-05-17 17:46:38 +04:00
default_dir ) ;
2008-12-11 06:32:56 +03:00
if ( ! archive_init ( cmd , dir , days , min ,
cmd - > default_settings . archive ) ) {
2009-04-03 00:46:11 +04:00
log_debug ( " archive_init failed. " ) ;
2005-05-17 17:46:38 +04:00
return 0 ;
}
/* set up the backup */
cmd - > default_settings . backup =
2006-05-16 20:48:31 +04:00
find_config_tree_bool ( cmd , " backup/backup " ,
2005-05-17 17:46:38 +04:00
DEFAULT_BACKUP_ENABLED ) ;
2006-08-21 16:54:53 +04:00
if ( dm_snprintf
2009-02-23 00:14:37 +03:00
( default_dir , sizeof ( default_dir ) , " %s/%s " , cmd - > system_dir ,
2005-05-17 17:46:38 +04:00
DEFAULT_BACKUP_SUBDIR ) = = - 1 ) {
2009-07-16 00:02:46 +04:00
log_error ( " Couldn't create default backup path '%s/%s'. " ,
cmd - > system_dir , DEFAULT_BACKUP_SUBDIR ) ;
2005-05-17 17:46:38 +04:00
return 0 ;
}
2006-05-16 20:48:31 +04:00
dir = find_config_tree_str ( cmd , " backup/backup_dir " , default_dir ) ;
2005-05-17 17:46:38 +04:00
2008-12-11 06:33:35 +03:00
if ( ! backup_init ( cmd , dir , cmd - > default_settings . backup ) ) {
2005-05-17 17:46:38 +04:00
log_debug ( " backup_init failed. " ) ;
return 0 ;
}
return 1 ;
}
2008-12-07 07:27:56 +03:00
static void _init_rand ( struct cmd_context * cmd )
{
2010-06-02 01:47:57 +04:00
if ( read_urandom ( & cmd - > rand_seed , sizeof ( cmd - > rand_seed ) ) ) {
reset_lvm_errno ( 1 ) ;
2008-12-07 07:27:56 +03:00
return ;
2010-06-02 01:47:57 +04:00
}
2008-12-07 07:27:56 +03:00
cmd - > rand_seed = ( unsigned ) time ( NULL ) + ( unsigned ) getpid ( ) ;
2010-06-02 01:47:57 +04:00
reset_lvm_errno ( 1 ) ;
2008-12-07 07:27:56 +03:00
}
2008-12-12 06:30:41 +03:00
static void _init_globals ( struct cmd_context * cmd )
{
init_full_scan_done ( 0 ) ;
init_mirror_in_sync ( 0 ) ;
}
2002-11-18 17:01:16 +03:00
/* Entry point */
2009-02-23 00:14:37 +03:00
struct cmd_context * create_toolcontext ( unsigned is_long_lived ,
const char * system_dir )
2002-11-18 17:01:16 +03:00
{
struct cmd_context * cmd ;
2003-07-05 02:34:56 +04:00
# ifdef M_MMAP_MAX
mallopt ( M_MMAP_MAX , 0 ) ;
# endif
2002-11-18 17:01:16 +03:00
if ( ! setlocale ( LC_ALL , " " ) )
2004-06-29 17:28:57 +04:00
log_very_verbose ( " setlocale failed " ) ;
2002-11-18 17:01:16 +03:00
2004-02-14 01:56:45 +03:00
# ifdef INTL_PACKAGE
bindtextdomain ( INTL_PACKAGE , LOCALEDIR ) ;
# endif
2002-11-18 17:01:16 +03:00
init_syslog ( DEFAULT_LOG_FACILITY ) ;
2005-10-17 03:03:59 +04:00
if ( ! ( cmd = dm_malloc ( sizeof ( * cmd ) ) ) ) {
2002-11-18 17:01:16 +03:00
log_error ( " Failed to allocate command context " ) ;
return NULL ;
}
memset ( cmd , 0 , sizeof ( * cmd ) ) ;
2007-01-23 18:58:06 +03:00
cmd - > is_long_lived = is_long_lived ;
2008-09-19 10:42:00 +04:00
cmd - > handles_missing_pvs = 0 ;
2009-10-16 21:41:49 +04:00
cmd - > handles_unknown_segments = 0 ;
2004-05-04 22:28:15 +04:00
cmd - > hosttags = 0 ;
2008-11-04 01:14:30 +03:00
dm_list_init ( & cmd - > formats ) ;
dm_list_init ( & cmd - > segtypes ) ;
dm_list_init ( & cmd - > tags ) ;
dm_list_init ( & cmd - > config_files ) ;
2002-11-18 17:01:16 +03:00
2009-07-16 04:36:59 +04:00
/* FIXME Make this configurable? */
reset_lvm_errno ( 1 ) ;
2009-02-23 00:14:37 +03:00
/*
* Environment variable LVM_SYSTEM_DIR overrides this below .
*/
if ( system_dir )
strncpy ( cmd - > system_dir , system_dir , sizeof ( cmd - > system_dir ) - 1 ) ;
else
strcpy ( cmd - > system_dir , DEFAULT_SYS_DIR ) ;
2002-11-18 17:01:16 +03:00
if ( ! _get_env_vars ( cmd ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2002-11-18 17:01:16 +03:00
/* Create system directory if it doesn't already exist */
2009-02-23 00:14:37 +03:00
if ( * cmd - > system_dir & & ! dm_create_dir ( cmd - > system_dir ) ) {
2005-01-27 18:50:34 +03:00
log_error ( " Failed to create LVM2 system dir for metadata backups, config "
" files and internal cache. " ) ;
log_error ( " Set environment variable LVM_SYSTEM_DIR to alternative location "
" or empty string. " ) ;
2009-07-16 04:36:59 +04:00
goto out ;
2005-01-27 18:50:34 +03:00
}
2002-11-18 17:01:16 +03:00
2005-10-17 03:03:59 +04:00
if ( ! ( cmd - > libmem = dm_pool_create ( " library " , 4 * 1024 ) ) ) {
2004-03-08 20:25:59 +03:00
log_error ( " Library memory pool creation failed " ) ;
2009-07-16 04:36:59 +04:00
goto out ;
2004-03-08 20:25:59 +03:00
}
2004-05-04 22:28:15 +04:00
if ( ! _init_lvm_conf ( cmd ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2004-05-04 22:28:15 +04:00
_init_logging ( cmd ) ;
if ( ! _init_hostname ( cmd ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2004-05-04 22:28:15 +04:00
if ( ! _init_tags ( cmd , cmd - > cft ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2004-05-04 22:28:15 +04:00
if ( ! _init_tag_configs ( cmd ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2004-05-04 22:28:15 +04:00
if ( ! _merge_config_files ( cmd ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2004-05-04 22:28:15 +04:00
2002-11-18 17:01:16 +03:00
if ( ! _process_config ( cmd ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2002-11-18 17:01:16 +03:00
if ( ! _init_dev_cache ( cmd ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2002-11-18 17:01:16 +03:00
2007-01-23 18:58:06 +03:00
if ( ! _init_filters ( cmd , 1 ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2002-11-18 17:01:16 +03:00
2005-10-17 03:03:59 +04:00
if ( ! ( cmd - > mem = dm_pool_create ( " command " , 4 * 1024 ) ) ) {
2002-11-18 17:01:16 +03:00
log_error ( " Command memory pool creation failed " ) ;
2009-07-16 04:36:59 +04:00
goto out ;
2002-11-18 17:01:16 +03:00
}
2003-07-05 02:34:56 +04:00
memlock_init ( cmd ) ;
2002-11-18 17:01:16 +03:00
if ( ! _init_formats ( cmd ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2002-11-18 17:01:16 +03:00
2008-04-08 16:49:21 +04:00
if ( ! init_lvmcache_orphans ( cmd ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2008-04-08 16:49:21 +04:00
2004-05-05 01:25:57 +04:00
if ( ! _init_segtypes ( cmd ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2004-05-05 01:25:57 +04:00
2005-05-17 17:46:38 +04:00
if ( ! _init_backup ( cmd ) )
2009-07-16 04:36:59 +04:00
goto_out ;
2005-05-17 17:46:38 +04:00
2008-12-07 07:27:56 +03:00
_init_rand ( cmd ) ;
2008-12-12 06:30:41 +03:00
_init_globals ( cmd ) ;
2008-04-03 01:31:14 +04:00
cmd - > default_settings . cache_vgmetadata = 1 ;
2002-11-18 17:01:16 +03:00
cmd - > current_settings = cmd - > default_settings ;
2004-05-04 22:28:15 +04:00
cmd - > config_valid = 1 ;
2009-07-16 04:36:59 +04:00
out :
2002-11-18 17:01:16 +03:00
return cmd ;
}
2010-04-29 05:38:12 +04:00
static void _destroy_formats ( struct cmd_context * cmd , struct dm_list * formats )
2002-11-18 17:01:16 +03:00
{
2008-11-04 01:14:30 +03:00
struct dm_list * fmtl , * tmp ;
2002-11-18 17:01:16 +03:00
struct format_type * fmt ;
void * lib ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_safe ( fmtl , tmp , formats ) {
fmt = dm_list_item ( fmtl , struct format_type ) ;
dm_list_del ( & fmt - > list ) ;
2002-11-18 17:01:16 +03:00
lib = fmt - > library ;
fmt - > ops - > destroy ( fmt ) ;
2003-03-24 21:08:53 +03:00
# ifdef HAVE_LIBDL
2002-11-18 17:01:16 +03:00
if ( lib )
dlclose ( lib ) ;
2003-03-24 21:08:53 +03:00
# endif
2002-11-18 17:01:16 +03:00
}
}
2008-11-04 01:14:30 +03:00
static void _destroy_segtypes ( struct dm_list * segtypes )
2004-05-05 01:25:57 +04:00
{
2008-11-04 01:14:30 +03:00
struct dm_list * sgtl , * tmp ;
2004-05-05 01:25:57 +04:00
struct segment_type * segtype ;
void * lib ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_safe ( sgtl , tmp , segtypes ) {
segtype = dm_list_item ( sgtl , struct segment_type ) ;
dm_list_del ( & segtype - > list ) ;
2004-05-05 01:25:57 +04:00
lib = segtype - > library ;
segtype - > ops - > destroy ( segtype ) ;
# ifdef HAVE_LIBDL
2009-07-08 16:36:01 +04:00
/*
* If no segtypes remain from this library , close it .
*/
if ( lib ) {
struct segment_type * segtype2 ;
dm_list_iterate_items ( segtype2 , segtypes )
if ( segtype2 - > library = = lib )
goto skip_dlclose ;
2004-05-05 01:25:57 +04:00
dlclose ( lib ) ;
2009-07-08 16:36:01 +04:00
skip_dlclose :
;
}
2004-05-05 01:25:57 +04:00
# endif
}
}
2009-11-24 19:10:25 +03:00
int refresh_filters ( struct cmd_context * cmd )
{
2010-01-19 16:25:00 +03:00
int r , saved_ignore_suspended_devices = ignore_suspended_devices ( ) ;
2009-11-24 19:10:25 +03:00
if ( cmd - > filter ) {
cmd - > filter - > destroy ( cmd - > filter ) ;
cmd - > filter = NULL ;
}
2010-01-19 16:25:00 +03:00
r = _init_filters ( cmd , 0 ) ;
/*
* During repair code must not reset suspended flag .
*/
init_ignore_suspended_devices ( saved_ignore_suspended_devices ) ;
return r ;
2009-11-24 19:10:25 +03:00
}
2004-05-04 22:28:15 +04:00
int refresh_toolcontext ( struct cmd_context * cmd )
{
log_verbose ( " Reloading config files " ) ;
2007-01-23 18:58:06 +03:00
/*
* Don ' t update the persistent filter cache as we will
* perform a full rescan .
*/
2004-05-04 22:28:15 +04:00
2006-05-16 20:48:31 +04:00
activation_release ( ) ;
2008-04-08 16:49:21 +04:00
lvmcache_destroy ( cmd , 0 ) ;
2004-05-04 22:28:15 +04:00
label_exit ( ) ;
2004-05-05 01:25:57 +04:00
_destroy_segtypes ( & cmd - > segtypes ) ;
2010-04-29 05:38:12 +04:00
_destroy_formats ( cmd , & cmd - > formats ) ;
2004-05-04 22:28:15 +04:00
if ( cmd - > filter ) {
cmd - > filter - > destroy ( cmd - > filter ) ;
cmd - > filter = NULL ;
}
dev_cache_exit ( ) ;
_destroy_tags ( cmd ) ;
_destroy_tag_configs ( cmd ) ;
cmd - > config_valid = 0 ;
cmd - > hosttags = 0 ;
if ( ! _init_lvm_conf ( cmd ) )
return 0 ;
_init_logging ( cmd ) ;
if ( ! _init_tags ( cmd , cmd - > cft ) )
return 0 ;
if ( ! _init_tag_configs ( cmd ) )
return 0 ;
if ( ! _merge_config_files ( cmd ) )
return 0 ;
if ( ! _process_config ( cmd ) )
return 0 ;
if ( ! _init_dev_cache ( cmd ) )
return 0 ;
2007-01-23 18:58:06 +03:00
if ( ! _init_filters ( cmd , 0 ) )
2004-05-04 22:28:15 +04:00
return 0 ;
if ( ! _init_formats ( cmd ) )
return 0 ;
2008-04-08 16:49:21 +04:00
if ( ! init_lvmcache_orphans ( cmd ) )
return 0 ;
2004-05-05 01:25:57 +04:00
if ( ! _init_segtypes ( cmd ) )
return 0 ;
2004-05-04 22:28:15 +04:00
cmd - > config_valid = 1 ;
2009-07-16 03:57:54 +04:00
reset_lvm_errno ( 1 ) ;
2004-05-04 22:28:15 +04:00
return 1 ;
}
2002-11-18 17:01:16 +03:00
void destroy_toolcontext ( struct cmd_context * cmd )
{
if ( cmd - > dump_filter )
2010-05-13 17:04:03 +04:00
persistent_filter_dump ( cmd - > filter , 1 ) ;
2002-11-18 17:01:16 +03:00
2005-05-17 17:46:38 +04:00
archive_exit ( cmd ) ;
backup_exit ( cmd ) ;
2008-04-08 16:49:21 +04:00
lvmcache_destroy ( cmd , 0 ) ;
2002-11-18 17:01:16 +03:00
label_exit ( ) ;
2004-05-05 01:25:57 +04:00
_destroy_segtypes ( & cmd - > segtypes ) ;
2010-04-29 05:38:12 +04:00
_destroy_formats ( cmd , & cmd - > formats ) ;
2009-07-08 22:12:08 +04:00
if ( cmd - > filter )
cmd - > filter - > destroy ( cmd - > filter ) ;
if ( cmd - > mem )
dm_pool_destroy ( cmd - > mem ) ;
2002-11-18 17:01:16 +03:00
dev_cache_exit ( ) ;
2004-05-04 22:28:15 +04:00
_destroy_tags ( cmd ) ;
_destroy_tag_configs ( cmd ) ;
2009-07-08 22:12:08 +04:00
if ( cmd - > libmem )
dm_pool_destroy ( cmd - > libmem ) ;
2005-10-17 03:03:59 +04:00
dm_free ( cmd ) ;
2002-11-18 17:01:16 +03:00
2003-07-05 02:34:56 +04:00
release_log_memory ( ) ;
2005-10-17 22:21:05 +04:00
activation_exit ( ) ;
2010-05-06 02:37:52 +04:00
reset_log_duplicated ( ) ;
2002-11-18 17:01:16 +03:00
fin_log ( ) ;
fin_syslog ( ) ;
2009-07-16 03:57:54 +04:00
reset_lvm_errno ( 0 ) ;
2002-11-18 17:01:16 +03:00
}