2002-11-18 17:01:16 +03:00
/*
2004-03-30 23:35:44 +04:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
* Copyright ( C ) 2004 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
* of the GNU General Public License v .2 .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
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 FILE * _log ;
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 " ) ) ) {
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( cmd - > sys_dir , sizeof ( cmd - > sys_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 ;
}
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 " ,
2002-11-18 17:01:16 +03:00
DEFAULT_INDENT ) ) ;
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 ) ;
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
2002-11-18 17:01:16 +03:00
dm_log_init ( print_log ) ;
2003-01-09 01:44:07 +03:00
# endif
2002-11-18 17:01:16 +03:00
}
static int _process_config ( struct cmd_context * cmd )
{
mode_t old_umask ;
/* 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 ) ) {
log_error ( " Warning: proc dir %s not found - some checks will be bypassed " ,
cmd - > proc_dir ) ;
cmd - > proc_dir [ 0 ] = ' \0 ' ;
}
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 ;
}
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_+.- */
if ( ! _set_tag ( cmd , cmd - > hostname ) ) {
stack ;
return 0 ;
}
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 ;
if ( ! _check_host_filters ( cmd , cn - > child , & passes ) ) {
stack ;
return 0 ;
}
if ( ! passes )
continue ;
}
if ( ! _set_tag ( cmd , tag ) ) {
stack ;
return 0 ;
}
}
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 " ,
2004-05-04 22:28:15 +04:00
cmd - > sys_dir , filler , tag ) < 0 ) {
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 ) {
list_add ( & cmd - > config_files , & cfl - > list ) ;
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 ;
}
2004-05-04 22:28:15 +04:00
list_add ( & cmd - > config_files , & cfl - > list ) ;
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 */
if ( ! * cmd - > sys_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 ;
}
if ( ! _load_config_file ( cmd , " " ) ) {
stack ;
return 0 ;
}
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 */
list_iterate_items ( sl , & cmd - > tags ) {
if ( ! _load_config_file ( cmd , sl - > str ) ) {
stack ;
return 0 ;
}
}
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 ;
}
}
list_iterate_items ( cfl , & cmd - > config_files ) {
/* Merge all config trees into cmd->cft using merge/tag rules */
if ( ! merge_config_tree ( cmd , cmd - > cft , cfl - > cft ) ) {
stack ;
return 0 ;
}
}
return 1 ;
}
static void _destroy_tags ( struct cmd_context * cmd )
{
struct list * slh , * slht ;
list_iterate_safe ( slh , slht , & cmd - > tags ) {
list_del ( slh ) ;
}
}
int config_files_changed ( struct cmd_context * cmd )
{
struct config_tree_list * cfl ;
list_iterate_items ( cfl , & cmd - > config_files ) {
if ( config_file_changed ( cfl - > cft ) )
return 1 ;
}
return 0 ;
}
static void _destroy_tag_configs ( struct cmd_context * cmd )
{
struct config_tree_list * cfl ;
if ( cmd - > cft & & cmd - > cft - > root ) {
destroy_config_tree ( cmd - > cft ) ;
cmd - > cft = NULL ;
}
list_iterate_items ( cfl , & cmd - > config_files ) {
destroy_config_tree ( cfl - > cft ) ;
}
list_init ( & cmd - > config_files ) ;
}
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 ;
if ( ! dev_cache_init ( ) ) {
stack ;
return 0 ;
}
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 .
* Listed first because it ' s very efficient at eliminating
* 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 ) ) {
if ( ( filters [ nr_filt ] = sysfs_filter_create ( cmd - > proc_dir ) ) )
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 " ) ;
2003-04-15 17:22:43 +04:00
return NULL ;
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 " ) ;
2003-04-15 17:22:43 +04:00
return NULL ;
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 ) ;
2002-11-18 17:01:16 +03:00
}
static int _init_filters ( struct cmd_context * cmd )
{
2003-07-05 02:34:56 +04:00
const char * dev_cache ;
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 ;
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( cache_file , sizeof ( cache_file ) ,
2002-11-18 17:01:16 +03:00
" %s/.cache " , cmd - > sys_dir ) < 0 ) {
log_error ( " Persistent cache filename too long ('%s/.cache'). " ,
cmd - > sys_dir ) ;
return 0 ;
}
2006-05-16 20:48:31 +04:00
dev_cache = find_config_tree_str ( cmd , " devices/cache " ,
2004-05-04 22:28:15 +04:00
cache_file ) ;
2003-07-05 02:34:56 +04:00
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 ;
if ( ! * cmd - > sys_dir )
cmd - > dump_filter = 0 ;
2003-07-05 02:34:56 +04:00
if ( ! stat ( dev_cache , & st ) & &
2006-11-04 06:34:10 +03:00
( st . st_ctime ! = config_file_timestamp ( cmd - > cft ) ) & &
! 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 ;
}
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 ;
list_add ( & cmd - > formats , & fmt - > list ) ;
# endif
2004-06-07 23:10:21 +04:00
# ifdef POOL_INTERNAL
if ( ! ( fmt = init_pool_format ( cmd ) ) )
return 0 ;
fmt - > library = NULL ;
list_add ( & cmd - > formats , & fmt - > list ) ;
# 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 */
if ( ! cmd - > is_static & &
( 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 ,
2006-04-03 22:43:55 +04:00
" format " , 0 ) ) ) {
2002-11-18 17:01:16 +03:00
stack ;
return 0 ;
}
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 ;
list_add ( & cmd - > formats , & fmt - > list ) ;
}
}
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 ;
list_add ( & cmd - > formats , & fmt - > list ) ;
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 ) ;
2005-06-01 20:51:55 +04:00
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 ) ) ) {
cmd - > default_settings . fmt = fmt ;
return 1 ;
}
}
log_error ( " _init_formats: Default format (%s) not found " , format ) ;
return 0 ;
}
2004-05-05 01:25:57 +04:00
static int _init_segtypes ( struct cmd_context * cmd )
{
struct segment_type * segtype ;
# ifdef HAVE_LIBDL
const struct config_node * cn ;
# endif
if ( ! ( segtype = init_striped_segtype ( cmd ) ) )
return 0 ;
segtype - > library = NULL ;
list_add ( & cmd - > segtypes , & segtype - > list ) ;
2004-05-11 20:01:58 +04:00
if ( ! ( segtype = init_zero_segtype ( cmd ) ) )
return 0 ;
segtype - > library = NULL ;
list_add ( & cmd - > segtypes , & segtype - > list ) ;
if ( ! ( segtype = init_error_segtype ( cmd ) ) )
return 0 ;
segtype - > library = NULL ;
list_add ( & cmd - > segtypes , & segtype - > list ) ;
2004-05-05 01:25:57 +04:00
# ifdef SNAPSHOT_INTERNAL
if ( ! ( segtype = init_snapshot_segtype ( cmd ) ) )
return 0 ;
segtype - > library = NULL ;
list_add ( & cmd - > segtypes , & segtype - > list ) ;
# endif
# ifdef MIRRORED_INTERNAL
if ( ! ( segtype = init_mirrored_segtype ( cmd ) ) )
return 0 ;
segtype - > library = NULL ;
list_add ( & cmd - > segtypes , & segtype - > list ) ;
# endif
# ifdef HAVE_LIBDL
2006-09-01 02:21:00 +04:00
/* Load any formats in shared libs unless static */
if ( ! cmd - > is_static & &
( cn = find_config_tree_node ( cmd , " global/segment_libraries " ) ) ) {
2004-05-05 01:25:57 +04:00
struct config_value * cv ;
struct segment_type * ( * init_segtype_fn ) ( struct cmd_context * ) ;
void * lib ;
struct list * sgtl , * tmp ;
struct segment_type * segtype2 ;
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 ;
}
2006-05-16 20:48:31 +04:00
if ( ! ( lib = load_shared_library ( cmd , cv - > v . str ,
2006-04-03 22:43:55 +04:00
" segment type " , 0 ) ) ) {
2004-05-05 01:25:57 +04:00
stack ;
return 0 ;
}
if ( ! ( init_segtype_fn = dlsym ( lib , " init_segtype " ) ) ) {
log_error ( " Shared library %s does not contain "
" segment type functions " , cv - > v . str ) ;
dlclose ( lib ) ;
return 0 ;
}
if ( ! ( segtype = init_segtype_fn ( cmd ) ) )
return 0 ;
segtype - > library = lib ;
list_add ( & cmd - > segtypes , & segtype - > list ) ;
list_iterate_safe ( sgtl , tmp , & cmd - > segtypes ) {
segtype2 = list_item ( sgtl , struct segment_type ) ;
if ( ! strcmp ( segtype2 - > name , segtype - > name ) ) {
log_error ( " Duplicate segment type %s: "
" unloading shared library %s " ,
segtype - > name , cv - > v . str ) ;
list_del ( & segtype - > list ) ;
segtype - > ops - > destroy ( segtype ) ;
dlclose ( lib ) ;
break ;
}
}
}
}
# 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 ;
if ( ! cmd - > sys_dir ) {
log_warn ( " WARNING: Metadata changes will NOT be backed up " ) ;
backup_init ( cmd , " " ) ;
archive_init ( cmd , " " , 0 , 0 ) ;
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
2005-05-17 17:46:38 +04:00
( default_dir , sizeof ( default_dir ) , " %s/%s " , cmd - > sys_dir ,
DEFAULT_ARCHIVE_SUBDIR ) = = - 1 ) {
log_err ( " Couldn't create default archive path '%s/%s'. " ,
cmd - > sys_dir , DEFAULT_ARCHIVE_SUBDIR ) ;
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 ) ;
if ( ! archive_init ( cmd , dir , days , min ) ) {
log_debug ( " backup_init failed. " ) ;
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
2005-05-17 17:46:38 +04:00
( default_dir , sizeof ( default_dir ) , " %s/%s " , cmd - > sys_dir ,
DEFAULT_BACKUP_SUBDIR ) = = - 1 ) {
log_err ( " Couldn't create default backup path '%s/%s'. " ,
cmd - > sys_dir , DEFAULT_BACKUP_SUBDIR ) ;
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
if ( ! backup_init ( cmd , dir ) ) {
log_debug ( " backup_init failed. " ) ;
return 0 ;
}
return 1 ;
}
2002-11-18 17:01:16 +03:00
/* Entry point */
2006-08-19 01:17:18 +04:00
struct cmd_context * create_toolcontext ( struct arg * the_args , unsigned is_static )
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 ) ) ;
cmd - > args = the_args ;
2006-08-19 01:17:18 +04:00
cmd - > is_static = is_static ;
2004-05-04 22:28:15 +04:00
cmd - > hosttags = 0 ;
2002-11-18 17:01:16 +03:00
list_init ( & cmd - > formats ) ;
2004-05-05 01:25:57 +04:00
list_init ( & cmd - > segtypes ) ;
2004-05-04 22:28:15 +04:00
list_init ( & cmd - > tags ) ;
list_init ( & cmd - > config_files ) ;
2002-11-18 17:01:16 +03:00
strcpy ( cmd - > sys_dir , DEFAULT_SYS_DIR ) ;
if ( ! _get_env_vars ( cmd ) )
goto error ;
/* Create system directory if it doesn't already exist */
2005-01-27 18:50:34 +03:00
if ( * cmd - > sys_dir & & ! create_dir ( cmd - > sys_dir ) ) {
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. " ) ;
2002-11-18 17:01:16 +03:00
goto error ;
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 " ) ;
2006-05-17 00:42:01 +04:00
goto error ;
2004-03-08 20:25:59 +03:00
}
2004-05-04 22:28:15 +04:00
if ( ! _init_lvm_conf ( cmd ) )
goto error ;
_init_logging ( cmd ) ;
if ( ! _init_hostname ( cmd ) )
goto error ;
if ( ! _init_tags ( cmd , cmd - > cft ) )
goto error ;
if ( ! _init_tag_configs ( cmd ) )
goto error ;
if ( ! _merge_config_files ( cmd ) )
goto error ;
2002-11-18 17:01:16 +03:00
if ( ! _process_config ( cmd ) )
goto error ;
if ( ! _init_dev_cache ( cmd ) )
goto error ;
if ( ! _init_filters ( cmd ) )
goto error ;
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 " ) ;
2006-05-10 21:49:25 +04:00
goto error ;
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 ) )
goto error ;
2004-05-05 01:25:57 +04:00
if ( ! _init_segtypes ( cmd ) )
goto error ;
2005-05-17 17:46:38 +04:00
if ( ! _init_backup ( cmd ) )
goto error ;
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 ;
2002-11-18 17:01:16 +03:00
return cmd ;
error :
2005-10-17 03:03:59 +04:00
dm_free ( cmd ) ;
2002-11-18 17:01:16 +03:00
return NULL ;
}
2002-12-20 02:25:55 +03:00
static void _destroy_formats ( struct list * formats )
2002-11-18 17:01:16 +03:00
{
struct list * fmtl , * tmp ;
struct format_type * fmt ;
void * lib ;
list_iterate_safe ( fmtl , tmp , formats ) {
fmt = list_item ( fmtl , struct format_type ) ;
list_del ( & fmt - > list ) ;
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
}
}
2004-05-05 01:25:57 +04:00
static void _destroy_segtypes ( struct list * segtypes )
{
struct list * sgtl , * tmp ;
struct segment_type * segtype ;
void * lib ;
list_iterate_safe ( sgtl , tmp , segtypes ) {
segtype = list_item ( sgtl , struct segment_type ) ;
list_del ( & segtype - > list ) ;
lib = segtype - > library ;
segtype - > ops - > destroy ( segtype ) ;
# ifdef HAVE_LIBDL
if ( lib )
dlclose ( lib ) ;
# endif
}
}
2004-05-04 22:28:15 +04:00
int refresh_toolcontext ( struct cmd_context * cmd )
{
log_verbose ( " Reloading config files " ) ;
if ( cmd - > config_valid ) {
if ( cmd - > dump_filter )
persistent_filter_dump ( cmd - > filter ) ;
}
2006-05-16 20:48:31 +04:00
activation_release ( ) ;
2004-05-04 22:28:15 +04:00
lvmcache_destroy ( ) ;
label_exit ( ) ;
2004-05-05 01:25:57 +04:00
_destroy_segtypes ( & cmd - > segtypes ) ;
2004-05-04 22:28:15 +04:00
_destroy_formats ( & cmd - > formats ) ;
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 ;
if ( ! _init_filters ( cmd ) )
return 0 ;
if ( ! _init_formats ( 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 ;
return 1 ;
}
2002-11-18 17:01:16 +03:00
void destroy_toolcontext ( struct cmd_context * cmd )
{
if ( cmd - > dump_filter )
persistent_filter_dump ( cmd - > filter ) ;
2005-05-17 17:46:38 +04:00
archive_exit ( cmd ) ;
backup_exit ( cmd ) ;
2003-07-05 02:34:56 +04:00
lvmcache_destroy ( ) ;
2002-11-18 17:01:16 +03:00
label_exit ( ) ;
2004-05-05 01:25:57 +04:00
_destroy_segtypes ( & cmd - > segtypes ) ;
2002-12-20 02:25:55 +03:00
_destroy_formats ( & cmd - > formats ) ;
2002-11-18 17:01:16 +03:00
cmd - > filter - > destroy ( cmd - > filter ) ;
2005-10-17 03:03:59 +04:00
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 ) ;
2005-10-17 03:03:59 +04:00
dm_pool_destroy ( cmd - > libmem ) ;
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 ( ) ;
2002-11-18 17:01:16 +03:00
fin_log ( ) ;
fin_syslog ( ) ;
if ( _log )
fclose ( _log ) ;
}