2001-08-21 16:56:08 +04:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2007-08-21 00:55:30 +04:00
* Copyright ( C ) 2004 - 2007 Red Hat , Inc . All rights reserved .
2001-08-21 16:56:08 +04: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
2001-08-21 16:56:08 +04:00
*/
2002-11-18 17:01:16 +03:00
# include "lib.h"
2003-07-05 02:34:56 +04:00
# include "device.h"
# include "memlock.h"
# include "lvm-string.h"
2007-07-24 21:48:08 +04:00
# include "lvm-file.h"
2006-05-12 23:16:48 +04:00
# include "defaults.h"
2002-11-18 17:01:16 +03:00
2001-08-21 16:56:08 +04:00
# include <stdarg.h>
# include <syslog.h>
2003-07-05 02:34:56 +04:00
static FILE * _log_file ;
static struct device _log_dev ;
static struct str_list _log_dev_alias ;
2001-08-21 16:56:08 +04:00
2004-03-26 14:45:01 +03:00
static int _verbose_level = VERBOSE_BASE_LEVEL ;
2001-08-21 16:56:08 +04:00
static int _test = 0 ;
2002-01-29 20:23:33 +03:00
static int _partial = 0 ;
2004-11-19 22:25:07 +03:00
static int _md_filtering = 0 ;
2003-04-30 19:22:52 +04:00
static int _pvmove = 0 ;
2005-03-22 01:40:35 +03:00
static int _full_scan_done = 0 ; /* Restrict to one full scan during each cmd */
2006-08-01 18:56:33 +04:00
static int _trust_cache = 0 ; /* Don't scan when incomplete VGs encountered */
2001-08-21 16:56:08 +04:00
static int _debug_level = 0 ;
static int _syslog = 0 ;
2003-07-05 02:34:56 +04:00
static int _log_to_file = 0 ;
static int _log_direct = 0 ;
static int _log_while_suspended = 0 ;
2002-01-22 18:33:40 +03:00
static int _indent = 1 ;
static int _log_cmd_name = 0 ;
2002-03-16 01:54:04 +03:00
static int _log_suppress = 0 ;
2002-07-11 00:43:32 +04:00
static int _ignorelockingfailure = 0 ;
2005-03-22 01:55:12 +03:00
static int _lockingfailed = 0 ;
2004-06-19 22:55:29 +04:00
static int _security_level = SECURITY_LEVEL ;
2002-01-22 18:33:40 +03:00
static char _cmd_name [ 30 ] = " " ;
static char _msg_prefix [ 30 ] = " " ;
2003-07-05 02:34:56 +04:00
static int _already_logging = 0 ;
2006-05-11 22:39:24 +04:00
static int _mirror_in_sync = 0 ;
2007-01-20 01:21:45 +03:00
static int _dmeventd_monitor = DEFAULT_DMEVENTD_MONITOR ;
2007-01-26 00:22:30 +03:00
static int _ignore_suspended_devices = 0 ;
2008-06-06 23:28:35 +04:00
static int _error_message_produced = 0 ;
2001-08-21 16:56:08 +04:00
2004-03-26 17:47:14 +03:00
static lvm2_log_fn_t _lvm2_log_fn = NULL ;
void init_log_fn ( lvm2_log_fn_t log_fn )
{
if ( log_fn )
_lvm2_log_fn = log_fn ;
else
_lvm2_log_fn = NULL ;
}
2003-07-05 02:34:56 +04:00
void init_log_file ( const char * log_file , int append )
2002-03-16 01:54:04 +03:00
{
2003-07-05 02:34:56 +04:00
const char * open_mode = append ? " a " : " w " ;
if ( ! ( _log_file = fopen ( log_file , open_mode ) ) ) {
log_sys_error ( " fopen " , log_file ) ;
return ;
}
_log_to_file = 1 ;
}
void init_log_direct ( const char * log_file , int append )
{
int open_flags = append ? 0 : O_TRUNC ;
2005-05-03 21:28:23 +04:00
dev_create_file ( log_file , & _log_dev , & _log_dev_alias , 1 ) ;
2003-07-05 02:34:56 +04:00
if ( ! dev_open_flags ( & _log_dev , O_RDWR | O_CREAT | open_flags , 1 , 0 ) )
return ;
_log_direct = 1 ;
}
void init_log_while_suspended ( int log_while_suspended )
{
_log_while_suspended = log_while_suspended ;
2001-08-21 16:56:08 +04:00
}
2002-03-16 01:54:04 +03:00
void init_syslog ( int facility )
{
2001-08-21 16:56:08 +04:00
openlog ( " lvm " , LOG_PID , facility ) ;
_syslog = 1 ;
}
2006-04-13 21:32:24 +04:00
int log_suppress ( int suppress )
2002-03-16 01:54:04 +03:00
{
2006-04-13 21:32:24 +04:00
int old_suppress = _log_suppress ;
2002-03-16 01:54:04 +03:00
_log_suppress = suppress ;
2006-04-13 21:32:24 +04:00
return old_suppress ;
2002-03-16 01:54:04 +03:00
}
2003-07-05 02:34:56 +04:00
void release_log_memory ( void )
2002-03-16 01:54:04 +03:00
{
2004-03-08 21:13:22 +03:00
if ( ! _log_direct )
return ;
2005-10-17 03:03:59 +04:00
dm_free ( ( char * ) _log_dev_alias . str ) ;
2003-07-05 02:34:56 +04:00
_log_dev_alias . str = " activate_log file " ;
}
void fin_log ( void )
{
if ( _log_direct ) {
dev_close ( & _log_dev ) ;
_log_direct = 0 ;
}
if ( _log_to_file ) {
2007-07-24 21:48:08 +04:00
if ( dm_fclose ( _log_file ) ) {
if ( errno )
fprintf ( stderr , " failed to write log file: %s \n " ,
strerror ( errno ) ) ;
else
fprintf ( stderr , " failed to write log file \n " ) ;
}
2003-07-05 02:34:56 +04:00
_log_to_file = 0 ;
}
2001-08-21 16:56:08 +04:00
}
2002-03-16 01:54:04 +03:00
void fin_syslog ( )
{
2002-01-19 00:26:37 +03:00
if ( _syslog )
closelog ( ) ;
2001-08-21 16:56:08 +04:00
_syslog = 0 ;
}
2002-03-16 01:54:04 +03:00
void init_verbose ( int level )
{
2001-08-21 16:56:08 +04:00
_verbose_level = level ;
}
2002-03-16 01:54:04 +03:00
void init_test ( int level )
{
2002-11-18 17:01:16 +03:00
if ( ! _test & & level )
log_print ( " Test mode: Metadata will NOT be updated. " ) ;
2001-08-21 16:56:08 +04:00
_test = level ;
}
2002-03-16 01:54:04 +03:00
void init_partial ( int level )
{
2002-01-29 20:23:33 +03:00
_partial = level ;
}
2004-11-19 22:25:07 +03:00
void init_md_filtering ( int level )
{
_md_filtering = level ;
}
2003-04-30 19:22:52 +04:00
void init_pvmove ( int level )
{
_pvmove = level ;
}
2005-03-22 01:40:35 +03:00
void init_full_scan_done ( int level )
{
_full_scan_done = level ;
}
2006-08-01 18:56:33 +04:00
void init_trust_cache ( int trustcache )
{
_trust_cache = trustcache ;
}
2002-07-11 00:43:32 +04:00
void init_ignorelockingfailure ( int level )
{
_ignorelockingfailure = level ;
}
2005-03-22 01:55:12 +03:00
void init_lockingfailed ( int level )
{
_lockingfailed = level ;
}
2004-06-19 22:55:29 +04:00
void init_security_level ( int level )
{
_security_level = level ;
}
2006-05-11 22:39:24 +04:00
void init_mirror_in_sync ( int in_sync )
{
_mirror_in_sync = in_sync ;
}
2007-01-20 01:21:45 +03:00
void init_dmeventd_monitor ( int reg )
2006-05-12 23:16:48 +04:00
{
2007-01-20 01:21:45 +03:00
_dmeventd_monitor = reg ;
2006-05-12 23:16:48 +04:00
}
2007-01-26 00:22:30 +03:00
void init_ignore_suspended_devices ( int ignore )
{
_ignore_suspended_devices = ignore ;
}
2002-03-16 01:54:04 +03:00
void init_cmd_name ( int status )
{
2002-01-22 18:33:40 +03:00
_log_cmd_name = status ;
}
2002-03-16 01:54:04 +03:00
void set_cmd_name ( const char * cmd )
{
2002-01-22 18:33:40 +03:00
strncpy ( _cmd_name , cmd , sizeof ( _cmd_name ) ) ;
_cmd_name [ sizeof ( _cmd_name ) - 1 ] = ' \0 ' ;
}
2008-04-07 17:53:26 +04:00
static const char * _command_name ( )
{
if ( ! _log_cmd_name )
return " " ;
return _cmd_name ;
}
2002-03-16 01:54:04 +03:00
void init_msg_prefix ( const char * prefix )
{
2002-01-22 18:33:40 +03:00
strncpy ( _msg_prefix , prefix , sizeof ( _msg_prefix ) ) ;
_msg_prefix [ sizeof ( _msg_prefix ) - 1 ] = ' \0 ' ;
}
2002-03-16 01:54:04 +03:00
void init_indent ( int indent )
{
2002-01-22 18:33:40 +03:00
_indent = indent ;
}
2008-06-17 18:14:00 +04:00
void init_error_message_produced ( int value )
2008-06-06 23:28:35 +04:00
{
2008-06-17 18:14:00 +04:00
_error_message_produced = value ;
2008-06-06 23:28:35 +04:00
}
int error_message_produced ( void )
{
return _error_message_produced ;
}
2002-03-16 01:54:04 +03:00
int test_mode ( )
{
2001-08-21 16:56:08 +04:00
return _test ;
}
2002-03-16 01:54:04 +03:00
int partial_mode ( )
{
2002-01-29 20:23:33 +03:00
return _partial ;
}
2004-11-19 22:25:07 +03:00
int md_filtering ( )
{
return _md_filtering ;
}
2003-04-30 19:22:52 +04:00
int pvmove_mode ( )
{
return _pvmove ;
}
2005-03-22 01:40:35 +03:00
int full_scan_done ( )
{
return _full_scan_done ;
}
2006-08-01 18:56:33 +04:00
int trust_cache ( )
{
return _trust_cache ;
}
2005-03-22 01:55:12 +03:00
int lockingfailed ( )
{
return _lockingfailed ;
}
2002-07-11 00:43:32 +04:00
int ignorelockingfailure ( )
{
return _ignorelockingfailure ;
}
2004-06-19 22:55:29 +04:00
int security_level ( )
{
return _security_level ;
}
2006-05-11 22:39:24 +04:00
int mirror_in_sync ( void )
{
return _mirror_in_sync ;
}
2007-01-20 01:21:45 +03:00
int dmeventd_monitor_mode ( void )
2006-05-12 23:16:48 +04:00
{
2007-01-20 01:21:45 +03:00
return _dmeventd_monitor ;
2006-05-12 23:16:48 +04:00
}
2007-01-26 00:22:30 +03:00
int ignore_suspended_devices ( void )
{
return _ignore_suspended_devices ;
}
2002-03-16 01:54:04 +03:00
void init_debug ( int level )
{
2001-08-21 16:56:08 +04:00
_debug_level = level ;
}
2002-03-16 01:54:04 +03:00
int debug_level ( )
{
2001-08-21 16:56:08 +04:00
return _debug_level ;
}
2002-03-16 01:54:04 +03:00
void print_log ( int level , const char * file , int line , const char * format , . . . )
{
2001-08-21 16:56:08 +04:00
va_list ap ;
2004-12-10 19:01:35 +03:00
char buf [ 1024 ] , buf2 [ 4096 ] , locn [ 4096 ] ;
2003-07-05 02:34:56 +04:00
int bufused , n ;
2004-03-26 17:47:14 +03:00
const char * message ;
const char * trformat ; /* Translated format string */
2007-06-28 21:33:44 +04:00
int use_stderr = level & _LOG_STDERR ;
level & = ~ _LOG_STDERR ;
2004-02-14 01:56:45 +03:00
2006-04-13 21:32:24 +04:00
if ( _log_suppress = = 2 )
return ;
2008-06-06 23:28:35 +04:00
if ( level < = _LOG_ERR )
_error_message_produced = 1 ;
2004-02-14 01:56:45 +03:00
trformat = _ ( format ) ;
2001-08-21 16:56:08 +04:00
2004-03-26 17:47:14 +03:00
if ( _lvm2_log_fn ) {
va_start ( ap , format ) ;
n = vsnprintf ( buf2 , sizeof ( buf2 ) - 1 , trformat , ap ) ;
va_end ( ap ) ;
if ( n < 0 ) {
fprintf ( stderr , _ ( " vsnprintf failed: skipping external "
" logging function " ) ) ;
goto log_it ;
}
buf2 [ sizeof ( buf2 ) - 1 ] = ' \0 ' ;
message = & buf2 [ 0 ] ;
_lvm2_log_fn ( level , file , line , message ) ;
return ;
}
log_it :
2002-03-16 01:54:04 +03:00
if ( ! _log_suppress ) {
2004-12-10 19:01:35 +03:00
if ( _verbose_level > _LOG_DEBUG )
2006-08-21 16:54:53 +04:00
dm_snprintf ( locn , sizeof ( locn ) , " #%s:%d " ,
2004-12-10 19:01:35 +03:00
file , line ) ;
else
locn [ 0 ] = ' \0 ' ;
2002-03-16 01:54:04 +03:00
va_start ( ap , format ) ;
switch ( level ) {
case _LOG_DEBUG :
2004-12-10 19:01:35 +03:00
if ( ! strcmp ( " <backtrace> " , format ) & &
_verbose_level < = _LOG_DEBUG )
2002-03-16 01:54:04 +03:00
break ;
2004-03-26 14:45:01 +03:00
if ( _verbose_level > = _LOG_DEBUG ) {
2008-04-07 17:53:26 +04:00
fprintf ( stderr , " %s%s%s " , locn , _command_name ( ) ,
2004-12-10 19:01:35 +03:00
_msg_prefix ) ;
2002-03-16 01:54:04 +03:00
if ( _indent )
2004-12-10 19:01:35 +03:00
fprintf ( stderr , " " ) ;
vfprintf ( stderr , trformat , ap ) ;
fputc ( ' \n ' , stderr ) ;
2002-03-16 01:54:04 +03:00
}
2002-02-21 00:26:40 +03:00
break ;
2001-08-21 16:56:08 +04:00
2002-03-16 01:54:04 +03:00
case _LOG_INFO :
2004-03-26 14:45:01 +03:00
if ( _verbose_level > = _LOG_INFO ) {
2008-04-07 17:53:26 +04:00
fprintf ( stderr , " %s%s%s " , locn , _command_name ( ) ,
2004-12-10 19:01:35 +03:00
_msg_prefix ) ;
2002-03-16 01:54:04 +03:00
if ( _indent )
2004-12-10 19:01:35 +03:00
fprintf ( stderr , " " ) ;
vfprintf ( stderr , trformat , ap ) ;
fputc ( ' \n ' , stderr ) ;
2002-03-16 01:54:04 +03:00
}
break ;
case _LOG_NOTICE :
2004-03-26 14:45:01 +03:00
if ( _verbose_level > = _LOG_NOTICE ) {
2008-04-07 17:53:26 +04:00
fprintf ( stderr , " %s%s%s " , locn , _command_name ( ) ,
2004-12-10 19:01:35 +03:00
_msg_prefix ) ;
2002-03-16 01:54:04 +03:00
if ( _indent )
2004-12-10 19:01:35 +03:00
fprintf ( stderr , " " ) ;
vfprintf ( stderr , trformat , ap ) ;
fputc ( ' \n ' , stderr ) ;
2002-03-16 01:54:04 +03:00
}
break ;
case _LOG_WARN :
2004-03-26 14:45:01 +03:00
if ( _verbose_level > = _LOG_WARN ) {
2008-04-07 17:53:26 +04:00
fprintf ( use_stderr ? stderr : stdout , " %s%s " ,
_command_name ( ) , _msg_prefix ) ;
2007-06-28 21:33:44 +04:00
vfprintf ( use_stderr ? stderr : stdout , trformat , ap ) ;
fputc ( ' \n ' , use_stderr ? stderr : stdout ) ;
2004-03-26 14:45:01 +03:00
}
2002-03-16 01:54:04 +03:00
break ;
case _LOG_ERR :
2004-03-26 14:45:01 +03:00
if ( _verbose_level > = _LOG_ERR ) {
2008-04-07 17:53:26 +04:00
fprintf ( stderr , " %s%s%s " , locn , _command_name ( ) ,
2004-12-10 19:01:35 +03:00
_msg_prefix ) ;
2004-03-26 14:45:01 +03:00
vfprintf ( stderr , trformat , ap ) ;
fputc ( ' \n ' , stderr ) ;
}
2002-03-16 01:54:04 +03:00
break ;
case _LOG_FATAL :
default :
2004-03-26 14:45:01 +03:00
if ( _verbose_level > = _LOG_FATAL ) {
2008-04-07 17:53:26 +04:00
fprintf ( stderr , " %s%s%s " , locn , _command_name ( ) ,
2004-12-10 19:01:35 +03:00
_msg_prefix ) ;
2004-03-26 14:45:01 +03:00
vfprintf ( stderr , trformat , ap ) ;
fputc ( ' \n ' , stderr ) ;
}
2002-03-16 01:54:04 +03:00
break ;
2001-08-21 16:56:08 +04:00
}
2002-03-16 01:54:04 +03:00
va_end ( ap ) ;
2001-08-21 16:56:08 +04:00
}
if ( level > _debug_level )
return ;
2003-07-05 02:34:56 +04:00
if ( _log_to_file & & ( _log_while_suspended | | ! memlock ( ) ) ) {
2008-04-07 17:53:26 +04:00
fprintf ( _log_file , " %s:%d %s%s " , file , line , _command_name ( ) ,
2003-07-05 02:34:56 +04:00
_msg_prefix ) ;
2001-08-21 16:56:08 +04:00
va_start ( ap , format ) ;
2004-02-14 01:56:45 +03:00
vfprintf ( _log_file , trformat , ap ) ;
2001-08-21 16:56:08 +04:00
va_end ( ap ) ;
2003-07-05 02:34:56 +04:00
fprintf ( _log_file , " \n " ) ;
fflush ( _log_file ) ;
2001-08-21 16:56:08 +04:00
}
2003-07-05 02:34:56 +04:00
if ( _syslog & & ( _log_while_suspended | | ! memlock ( ) ) ) {
2002-03-16 01:54:04 +03:00
va_start ( ap , format ) ;
2004-02-14 01:56:45 +03:00
vsyslog ( level , trformat , ap ) ;
2001-08-21 16:56:08 +04:00
va_end ( ap ) ;
}
2003-07-05 02:34:56 +04:00
/* FIXME This code is unfinished - pre-extend & condense. */
if ( ! _already_logging & & _log_direct & & memlock ( ) ) {
_already_logging = 1 ;
memset ( & buf , ' ' , sizeof ( buf ) ) ;
bufused = 0 ;
2006-08-21 16:54:53 +04:00
if ( ( n = dm_snprintf ( buf , sizeof ( buf ) - bufused - 1 ,
2008-04-07 17:53:26 +04:00
" %s:%d %s%s " , file , line , _command_name ( ) ,
2003-07-05 02:34:56 +04:00
_msg_prefix ) ) = = - 1 )
goto done ;
bufused + = n ;
va_start ( ap , format ) ;
n = vsnprintf ( buf + bufused - 1 , sizeof ( buf ) - bufused - 1 ,
2004-02-14 01:56:45 +03:00
trformat , ap ) ;
2003-07-05 02:34:56 +04:00
va_end ( ap ) ;
bufused + = n ;
done :
buf [ bufused - 1 ] = ' \n ' ;
buf [ bufused ] = ' \n ' ;
buf [ sizeof ( buf ) - 1 ] = ' \n ' ;
/* FIXME real size bufused */
dev_append ( & _log_dev , sizeof ( buf ) , buf ) ;
_already_logging = 0 ;
}
2001-08-21 16:56:08 +04:00
}