2004-03-26 15:00:24 +03:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2012-09-07 13:13:41 +04:00
* Copyright ( C ) 2004 - 2012 Red Hat , Inc . All rights reserved .
2004-05-05 01:25:57 +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
2004-03-26 15:00:24 +03:00
*/
# include "tools.h"
2015-07-06 19:30:18 +03:00
2004-03-26 15:00:24 +03:00
# include "lvm2cmdline.h"
# include "label.h"
2009-02-23 01:11:58 +03:00
# include "lvm-version.h"
2015-03-05 23:00:44 +03:00
# include "lvmlockd.h"
2004-03-26 15:00:24 +03:00
# include "stub.h"
2007-10-03 20:10:04 +04:00
# include "last-path-component.h"
2004-03-26 15:00:24 +03:00
# include <signal.h>
# include <sys/stat.h>
# include <time.h>
2004-12-10 19:01:35 +03:00
# include <sys/resource.h>
2012-03-15 04:18:23 +04:00
# include <dirent.h>
2012-09-07 13:13:41 +04:00
# include <paths.h>
2014-10-28 13:20:33 +03:00
# include <locale.h>
2004-03-26 15:00:24 +03:00
2015-02-12 17:32:30 +03:00
# ifdef HAVE_VALGRIND
# include <valgrind.h>
# endif
2004-03-26 15:00:24 +03:00
# ifdef HAVE_GETOPTLONG
# include <getopt.h>
# define GETOPTLONG_FN(a, b, c, d, e) getopt_long((a), (b), (c), (d), (e))
# define OPTIND_INIT 0
# else
struct option {
} ;
extern int optind ;
extern char * optarg ;
# define GETOPTLONG_FN(a, b, c, d, e) getopt((a), (b), (c))
# define OPTIND_INIT 1
# endif
/*
2007-02-14 19:51:48 +03:00
* Table of valid switches
2004-03-26 15:00:24 +03:00
*/
2010-11-11 20:29:05 +03:00
static struct arg_props _arg_props [ ARG_COUNT + 1 ] = {
# define arg(a, b, c, d, e) {b, "", "--" c, d, e},
2004-03-26 15:00:24 +03:00
# include "args.h"
# undef arg
} ;
2007-02-14 19:51:48 +03:00
static struct cmdline_context _cmdline ;
2004-03-26 15:00:24 +03:00
2008-12-17 19:45:32 +03:00
/* Command line args */
2010-11-11 20:29:05 +03:00
unsigned arg_count ( const struct cmd_context * cmd , int a )
2008-12-17 19:45:32 +03:00
{
2010-11-11 20:29:05 +03:00
return cmd - > arg_values [ a ] . count ;
}
unsigned grouped_arg_count ( const struct arg_values * av , int a )
{
return av [ a ] . count ;
2008-12-17 19:45:32 +03:00
}
2009-11-03 18:50:42 +03:00
unsigned arg_is_set ( const struct cmd_context * cmd , int a )
{
return arg_count ( cmd , a ) ? 1 : 0 ;
}
2014-07-18 23:56:37 +04:00
int arg_from_list_is_set ( const struct cmd_context * cmd , const char * err_found , . . . )
2014-07-11 00:52:53 +04:00
{
int arg ;
va_list ap ;
2014-07-18 23:56:37 +04:00
va_start ( ap , err_found ) ;
2014-07-11 00:52:53 +04:00
while ( ( arg = va_arg ( ap , int ) ) ! = - 1 & & ! arg_count ( cmd , arg ) )
/* empty */ ;
va_end ( ap ) ;
2014-07-18 23:56:37 +04:00
if ( arg = = - 1 )
2014-07-11 00:52:53 +04:00
return 0 ;
2014-07-18 23:56:37 +04:00
if ( err_found )
log_error ( " %s %s. " , arg_long_option_name ( arg ) , err_found ) ;
2014-07-11 00:52:53 +04:00
return 1 ;
}
2014-07-18 23:56:37 +04:00
int arg_outside_list_is_set ( const struct cmd_context * cmd , const char * err_found , . . . )
2014-07-11 00:52:53 +04:00
{
int i , arg ;
va_list ap ;
for ( i = 0 ; i < ARG_COUNT ; + + i ) {
switch ( i ) {
/* skip common options */
case commandprofile_ARG :
case config_ARG :
case debug_ARG :
case driverloaded_ARG :
case help2_ARG :
case help_ARG :
case profile_ARG :
case quiet_ARG :
case verbose_ARG :
case version_ARG :
case yes_ARG :
continue ;
}
if ( ! arg_count ( cmd , i ) )
continue ; /* unset */
2014-07-18 23:56:37 +04:00
va_start ( ap , err_found ) ;
2014-07-11 00:52:53 +04:00
while ( ( ( arg = va_arg ( ap , int ) ) ! = - 1 ) & & ( arg ! = i ) )
/* empty */ ;
va_end ( ap ) ;
2014-07-18 23:56:37 +04:00
if ( arg = = i )
continue ; /* set and in list */
if ( err_found )
log_error ( " Option %s %s. " , arg_long_option_name ( i ) , err_found ) ;
return 1 ;
2014-07-11 00:52:53 +04:00
}
2014-07-18 23:56:37 +04:00
return 0 ;
2014-07-11 00:52:53 +04:00
}
2014-10-15 17:06:42 +04:00
int arg_from_list_is_negative ( const struct cmd_context * cmd , const char * err_found , . . . )
{
int arg , ret = 0 ;
va_list ap ;
va_start ( ap , err_found ) ;
while ( ( arg = va_arg ( ap , int ) ) ! = - 1 )
if ( arg_sign_value ( cmd , arg , SIGN_NONE ) = = SIGN_MINUS ) {
if ( err_found )
log_error ( " %s %s. " , arg_long_option_name ( arg ) , err_found ) ;
ret = 1 ;
}
va_end ( ap ) ;
return ret ;
}
int arg_from_list_is_zero ( const struct cmd_context * cmd , const char * err_found , . . . )
{
int arg , ret = 0 ;
va_list ap ;
va_start ( ap , err_found ) ;
while ( ( arg = va_arg ( ap , int ) ) ! = - 1 )
if ( arg_is_set ( cmd , arg ) & &
! arg_int_value ( cmd , arg , 0 ) ) {
if ( err_found )
log_error ( " %s %s. " , arg_long_option_name ( arg ) , err_found ) ;
ret = 1 ;
}
va_end ( ap ) ;
return ret ;
}
2010-11-11 20:29:05 +03:00
unsigned grouped_arg_is_set ( const struct arg_values * av , int a )
{
return grouped_arg_count ( av , a ) ? 1 : 0 ;
}
2013-03-22 23:20:33 +04:00
const char * arg_long_option_name ( int a )
{
return _cmdline . arg_props [ a ] . long_arg ;
}
2014-09-19 16:29:12 +04:00
const char * arg_value ( const struct cmd_context * cmd , int a )
2008-12-17 19:45:32 +03:00
{
2010-11-11 20:29:05 +03:00
return cmd - > arg_values [ a ] . value ;
2008-12-17 19:45:32 +03:00
}
2014-09-19 16:29:12 +04:00
const char * arg_str_value ( const struct cmd_context * cmd , int a , const char * def )
2008-12-17 19:45:32 +03:00
{
2010-11-11 20:29:05 +03:00
return arg_count ( cmd , a ) ? cmd - > arg_values [ a ] . value : def ;
}
const char * grouped_arg_str_value ( const struct arg_values * av , int a , const char * def )
{
return grouped_arg_count ( av , a ) ? av [ a ] . value : def ;
2008-12-17 19:45:32 +03:00
}
2012-03-06 06:30:49 +04:00
int32_t grouped_arg_int_value ( const struct arg_values * av , int a , const int32_t def )
{
return grouped_arg_count ( av , a ) ? av [ a ] . i_value : def ;
}
2014-09-19 16:29:12 +04:00
int32_t first_grouped_arg_int_value ( const struct cmd_context * cmd , int a , const int32_t def )
2012-03-16 14:43:52 +04:00
{
struct arg_value_group_list * current_group ;
struct arg_values * av ;
2012-04-11 16:49:10 +04:00
dm_list_iterate_items ( current_group , & cmd - > arg_value_groups ) {
2012-03-16 14:43:52 +04:00
av = current_group - > arg_values ;
if ( grouped_arg_count ( av , a ) )
return grouped_arg_int_value ( av , a , def ) ;
}
return def ;
}
2014-09-19 16:29:12 +04:00
int32_t arg_int_value ( const struct cmd_context * cmd , int a , const int32_t def )
2008-12-17 19:45:32 +03:00
{
2012-03-16 14:43:52 +04:00
return ( _cmdline . arg_props [ a ] . flags & ARG_GROUPABLE ) ?
first_grouped_arg_int_value ( cmd , a , def ) : ( arg_count ( cmd , a ) ? cmd - > arg_values [ a ] . i_value : def ) ;
2008-12-17 19:45:32 +03:00
}
2014-09-19 16:29:12 +04:00
uint32_t arg_uint_value ( const struct cmd_context * cmd , int a , const uint32_t def )
2008-12-17 19:45:32 +03:00
{
2010-11-11 20:29:05 +03:00
return arg_count ( cmd , a ) ? cmd - > arg_values [ a ] . ui_value : def ;
2008-12-17 19:45:32 +03:00
}
2014-09-19 16:29:12 +04:00
int64_t arg_int64_value ( const struct cmd_context * cmd , int a , const int64_t def )
2008-12-17 19:45:32 +03:00
{
2010-11-11 20:29:05 +03:00
return arg_count ( cmd , a ) ? cmd - > arg_values [ a ] . i64_value : def ;
2008-12-17 19:45:32 +03:00
}
2014-09-19 16:29:12 +04:00
uint64_t arg_uint64_value ( const struct cmd_context * cmd , int a , const uint64_t def )
2008-12-17 19:45:32 +03:00
{
2010-11-11 20:29:05 +03:00
return arg_count ( cmd , a ) ? cmd - > arg_values [ a ] . ui64_value : def ;
2008-12-17 19:45:32 +03:00
}
2010-04-29 05:38:12 +04:00
/* No longer used.
2009-11-03 18:50:42 +03:00
const void * arg_ptr_value ( struct cmd_context * cmd , int a , const void * def )
2008-12-17 19:45:32 +03:00
{
2010-11-11 20:29:05 +03:00
return arg_count ( cmd , a ) ? cmd - > arg_values [ a ] . ptr : def ;
2008-12-17 19:45:32 +03:00
}
2010-04-29 05:38:12 +04:00
*/
2008-12-17 19:45:32 +03:00
2014-09-19 16:29:12 +04:00
sign_t arg_sign_value ( const struct cmd_context * cmd , int a , const sign_t def )
2008-12-17 19:45:32 +03:00
{
2010-11-11 20:29:05 +03:00
return arg_count ( cmd , a ) ? cmd - > arg_values [ a ] . sign : def ;
2008-12-17 19:45:32 +03:00
}
2014-09-19 16:29:12 +04:00
percent_type_t arg_percent_value ( const struct cmd_context * cmd , int a , const percent_type_t def )
2008-12-17 19:45:32 +03:00
{
2010-11-11 20:29:05 +03:00
return arg_count ( cmd , a ) ? cmd - > arg_values [ a ] . percent : def ;
2008-12-17 19:45:32 +03:00
}
2010-11-11 20:29:05 +03:00
int arg_count_increment ( struct cmd_context * cmd , int a )
2008-12-17 19:45:32 +03:00
{
2010-11-11 20:29:05 +03:00
return cmd - > arg_values [ a ] . count + + ;
2008-12-17 19:45:32 +03:00
}
2010-11-11 20:29:05 +03:00
int yes_no_arg ( struct cmd_context * cmd __attribute__ ( ( unused ) ) , struct arg_values * av )
2004-03-26 15:00:24 +03:00
{
2010-11-11 20:29:05 +03:00
av - > sign = SIGN_NONE ;
av - > percent = PERCENT_NONE ;
2004-03-26 15:00:24 +03:00
2010-11-11 20:29:05 +03:00
if ( ! strcmp ( av - > value , " y " ) ) {
av - > i_value = 1 ;
av - > ui_value = 1 ;
2004-05-24 17:44:10 +04:00
}
2010-11-11 20:29:05 +03:00
else if ( ! strcmp ( av - > value , " n " ) ) {
av - > i_value = 0 ;
av - > ui_value = 0 ;
2004-05-24 17:44:10 +04:00
}
else
return 0 ;
return 1 ;
}
2012-06-27 15:48:31 +04:00
int activation_arg ( struct cmd_context * cmd __attribute__ ( ( unused ) ) , struct arg_values * av )
2004-05-24 17:44:10 +04:00
{
2010-11-11 20:29:05 +03:00
av - > sign = SIGN_NONE ;
av - > percent = PERCENT_NONE ;
2004-05-24 17:44:10 +04:00
2010-11-11 20:29:05 +03:00
if ( ! strcmp ( av - > value , " e " ) | | ! strcmp ( av - > value , " ey " ) | |
! strcmp ( av - > value , " ye " ) ) {
2014-09-19 16:28:28 +04:00
av - > i_value = CHANGE_AEY ;
av - > ui_value = CHANGE_AEY ;
2004-05-24 17:44:10 +04:00
}
2015-06-16 18:18:16 +03:00
else if ( ! strcmp ( av - > value , " s " ) | | ! strcmp ( av - > value , " sy " ) | |
! strcmp ( av - > value , " ys " ) ) {
av - > i_value = CHANGE_ASY ;
av - > ui_value = CHANGE_ASY ;
}
2010-11-11 20:29:05 +03:00
else if ( ! strcmp ( av - > value , " y " ) ) {
av - > i_value = CHANGE_AY ;
av - > ui_value = CHANGE_AY ;
2004-03-26 15:00:24 +03:00
}
2012-06-27 16:59:34 +04:00
else if ( ! strcmp ( av - > value , " a " ) | | ! strcmp ( av - > value , " ay " ) | |
! strcmp ( av - > value , " ya " ) ) {
av - > i_value = CHANGE_AAY ;
av - > ui_value = CHANGE_AAY ;
}
2010-11-11 20:29:05 +03:00
else if ( ! strcmp ( av - > value , " n " ) | | ! strcmp ( av - > value , " en " ) | |
! strcmp ( av - > value , " ne " ) ) {
av - > i_value = CHANGE_AN ;
av - > ui_value = CHANGE_AN ;
2004-06-16 21:13:41 +04:00
}
2010-11-11 20:29:05 +03:00
else if ( ! strcmp ( av - > value , " ln " ) | | ! strcmp ( av - > value , " nl " ) ) {
av - > i_value = CHANGE_ALN ;
av - > ui_value = CHANGE_ALN ;
2004-06-16 21:13:41 +04:00
}
2010-11-11 20:29:05 +03:00
else if ( ! strcmp ( av - > value , " ly " ) | | ! strcmp ( av - > value , " yl " ) ) {
av - > i_value = CHANGE_ALY ;
av - > ui_value = CHANGE_ALY ;
2004-03-26 15:00:24 +03:00
}
else
return 0 ;
return 1 ;
}
2012-08-08 00:24:41 +04:00
int discards_arg ( struct cmd_context * cmd __attribute__ ( ( unused ) ) , struct arg_values * av )
2012-06-28 16:47:34 +04:00
{
2012-08-08 00:24:41 +04:00
thin_discards_t discards ;
2012-06-28 16:47:34 +04:00
2014-11-08 03:28:38 +03:00
if ( ! set_pool_discards ( & discards , av - > value ) )
2012-06-28 16:47:34 +04:00
return_0 ;
2012-08-08 00:24:41 +04:00
av - > i_value = discards ;
av - > ui_value = discards ;
2012-06-28 16:47:34 +04:00
return 1 ;
}
2014-10-22 23:02:29 +04:00
int mirrorlog_arg ( struct cmd_context * cmd __attribute__ ( ( unused ) ) , struct arg_values * av )
{
int log_count ;
2014-11-08 03:28:38 +03:00
if ( ! set_mirror_log_count ( & log_count , av - > value ) )
2014-10-22 23:02:29 +04:00
return_0 ;
av - > i_value = log_count ;
av - > ui_value = log_count ;
return 1 ;
}
2010-11-11 20:29:05 +03:00
int metadatatype_arg ( struct cmd_context * cmd , struct arg_values * av )
2004-03-26 15:00:24 +03:00
{
2010-11-11 20:29:05 +03:00
return get_format_by_name ( cmd , av - > value ) ? 1 : 0 ;
2004-03-26 15:00:24 +03:00
}
2010-11-11 20:29:05 +03:00
static int _get_int_arg ( struct arg_values * av , char * * ptr )
2004-03-26 15:00:24 +03:00
{
char * val ;
2013-09-18 04:16:48 +04:00
unsigned long long v ;
2004-03-26 15:00:24 +03:00
2010-11-11 20:29:05 +03:00
av - > percent = PERCENT_NONE ;
2006-09-26 13:35:43 +04:00
2010-11-11 20:29:05 +03:00
val = av - > value ;
2004-03-26 15:00:24 +03:00
switch ( * val ) {
case ' + ' :
2010-11-11 20:29:05 +03:00
av - > sign = SIGN_PLUS ;
2004-03-26 15:00:24 +03:00
val + + ;
break ;
case ' - ' :
2010-11-11 20:29:05 +03:00
av - > sign = SIGN_MINUS ;
2004-03-26 15:00:24 +03:00
val + + ;
break ;
default :
2010-11-11 20:29:05 +03:00
av - > sign = SIGN_NONE ;
2004-03-26 15:00:24 +03:00
}
if ( ! isdigit ( * val ) )
return 0 ;
2013-09-18 04:16:48 +04:00
errno = 0 ;
v = strtoull ( val , ptr , 10 ) ;
2004-03-26 15:00:24 +03:00
2013-09-18 04:16:48 +04:00
if ( * ptr = = val | | errno )
2004-03-26 15:00:24 +03:00
return 0 ;
2010-11-11 20:29:05 +03:00
av - > i_value = ( int32_t ) v ;
av - > ui_value = ( uint32_t ) v ;
av - > i64_value = ( int64_t ) v ;
av - > ui64_value = ( uint64_t ) v ;
2004-03-26 15:00:24 +03:00
return 1 ;
}
2014-10-30 16:52:37 +03:00
static int _get_percent_arg ( struct arg_values * av , const char * ptr )
{
if ( ! strcasecmp ( ptr , " V " ) | | ! strcasecmp ( ptr , " VG " ) )
av - > percent = PERCENT_VG ;
else if ( ! strcasecmp ( ptr , " L " ) | | ! strcasecmp ( ptr , " LV " ) )
av - > percent = PERCENT_LV ;
else if ( ! strcasecmp ( ptr , " P " ) | | ! strcasecmp ( ptr , " PV " ) | |
! strcasecmp ( ptr , " PVS " ) )
av - > percent = PERCENT_PVS ;
else if ( ! strcasecmp ( ptr , " F " ) | | ! strcasecmp ( ptr , " FR " ) | |
! strcasecmp ( ptr , " FREE " ) )
av - > percent = PERCENT_FREE ;
else if ( ! strcasecmp ( ptr , " O " ) | | ! strcasecmp ( ptr , " OR " ) | |
! strcasecmp ( ptr , " ORIGIN " ) )
av - > percent = PERCENT_ORIGIN ;
else {
log_error ( " Specified %%%s is unknown. " , ptr ) ;
return 0 ;
}
return 1 ;
}
2007-11-14 03:08:25 +03:00
/* Size stored in sectors */
2014-10-30 16:52:37 +03:00
static int _size_arg ( struct cmd_context * cmd __attribute__ ( ( unused ) ) ,
struct arg_values * av , int factor , int percent )
2004-03-26 15:00:24 +03:00
{
char * ptr ;
int i ;
2009-07-06 23:13:26 +04:00
static const char * suffixes = " kmgtpebs " ;
2004-03-26 15:00:24 +03:00
char * val ;
double v ;
2009-07-06 23:13:26 +04:00
uint64_t v_tmp , adjustment ;
2004-03-26 15:00:24 +03:00
2010-11-11 20:29:05 +03:00
av - > percent = PERCENT_NONE ;
2006-09-26 13:35:43 +04:00
2010-11-11 20:29:05 +03:00
val = av - > value ;
2004-03-26 15:00:24 +03:00
switch ( * val ) {
case ' + ' :
2010-11-11 20:29:05 +03:00
av - > sign = SIGN_PLUS ;
2004-03-26 15:00:24 +03:00
val + + ;
break ;
case ' - ' :
2010-11-11 20:29:05 +03:00
av - > sign = SIGN_MINUS ;
2004-03-26 15:00:24 +03:00
val + + ;
break ;
default :
2010-11-11 20:29:05 +03:00
av - > sign = SIGN_NONE ;
2004-03-26 15:00:24 +03:00
}
if ( ! isdigit ( * val ) )
return 0 ;
v = strtod ( val , & ptr ) ;
2014-10-28 13:20:33 +03:00
if ( * ptr = = ' . ' ) {
/*
* Maybe user has non - C locale with different decimal point ?
* Lets be toleran and retry with standard C locales
*/
if ( setlocale ( LC_ALL , " C " ) ) {
v = strtod ( val , & ptr ) ;
setlocale ( LC_ALL , " " ) ;
}
}
2004-03-26 15:00:24 +03:00
if ( ptr = = val )
return 0 ;
2014-10-30 16:52:37 +03:00
if ( percent & & * ptr = = ' % ' ) {
if ( ! _get_percent_arg ( av , + + ptr ) )
return_0 ;
if ( ( uint64_t ) v > = UINT32_MAX ) {
log_error ( " Percentage is too big (>=%d%%). " , UINT32_MAX ) ;
return 0 ;
}
} else if ( * ptr ) {
2004-03-26 15:00:24 +03:00
for ( i = strlen ( suffixes ) - 1 ; i > = 0 ; i - - )
if ( suffixes [ i ] = = tolower ( ( int ) * ptr ) )
break ;
2009-07-06 23:13:26 +04:00
if ( i < 0 ) {
2004-03-26 15:00:24 +03:00
return 0 ;
2009-07-06 23:13:26 +04:00
} else if ( i = = 7 ) {
2011-08-04 18:11:28 +04:00
/* v is already in sectors */
2011-08-04 18:54:48 +04:00
;
2009-07-06 23:13:26 +04:00
} else if ( i = = 6 ) {
/* bytes */
v_tmp = ( uint64_t ) v ;
adjustment = v_tmp % 512 ;
if ( adjustment ) {
v_tmp + = ( 512 - adjustment ) ;
log_error ( " Size is not a multiple of 512. "
2009-07-07 05:51:00 +04:00
" Try using % " PRIu64 " or % " PRIu64 " . " ,
2009-07-06 23:13:26 +04:00
v_tmp - 512 , v_tmp ) ;
return 0 ;
}
v / = 512 ;
} else {
/* all other units: kmgtpe */
while ( i - - > 0 )
v * = 1024 ;
v * = 2 ;
}
2004-03-26 15:00:24 +03:00
} else
v * = factor ;
2013-05-29 16:50:21 +04:00
if ( ( uint64_t ) v > = ( UINT64_MAX > > SECTOR_SHIFT ) ) {
log_error ( " Size is too big (>=16EiB). " ) ;
return 0 ;
}
2010-11-11 20:29:05 +03:00
av - > i_value = ( int32_t ) v ;
av - > ui_value = ( uint32_t ) v ;
av - > i64_value = ( int64_t ) v ;
av - > ui64_value = ( uint64_t ) v ;
2004-03-26 15:00:24 +03:00
return 1 ;
}
2010-11-11 20:29:05 +03:00
int size_kb_arg ( struct cmd_context * cmd , struct arg_values * av )
2004-03-26 15:00:24 +03:00
{
2014-10-30 16:52:37 +03:00
return _size_arg ( cmd , av , 2 , 0 ) ;
2004-03-26 15:00:24 +03:00
}
2010-11-11 20:29:05 +03:00
int size_mb_arg ( struct cmd_context * cmd , struct arg_values * av )
2004-03-26 15:00:24 +03:00
{
2014-10-30 16:52:37 +03:00
return _size_arg ( cmd , av , 2048 , 0 ) ;
}
int size_mb_arg_with_percent ( struct cmd_context * cmd , struct arg_values * av )
{
return _size_arg ( cmd , av , 2048 , 1 ) ;
2004-03-26 15:00:24 +03:00
}
2010-11-11 20:29:05 +03:00
int int_arg ( struct cmd_context * cmd __attribute__ ( ( unused ) ) , struct arg_values * av )
2004-03-26 15:00:24 +03:00
{
char * ptr ;
2010-11-11 20:29:05 +03:00
if ( ! _get_int_arg ( av , & ptr ) | | ( * ptr ) | | ( av - > sign = = SIGN_MINUS ) )
2004-03-26 15:00:24 +03:00
return 0 ;
return 1 ;
}
2010-11-11 20:29:05 +03:00
int int_arg_with_sign ( struct cmd_context * cmd __attribute__ ( ( unused ) ) , struct arg_values * av )
2004-03-26 15:00:24 +03:00
{
char * ptr ;
2010-11-11 20:29:05 +03:00
if ( ! _get_int_arg ( av , & ptr ) | | ( * ptr ) )
2004-03-26 15:00:24 +03:00
return 0 ;
return 1 ;
}
2010-07-09 19:34:40 +04:00
int int_arg_with_sign_and_percent ( struct cmd_context * cmd __attribute__ ( ( unused ) ) ,
2010-11-11 20:29:05 +03:00
struct arg_values * av )
2006-09-26 13:35:43 +04:00
{
char * ptr ;
2010-11-11 20:29:05 +03:00
if ( ! _get_int_arg ( av , & ptr ) )
2006-09-26 13:35:43 +04:00
return 0 ;
if ( ! * ptr )
return 1 ;
if ( * ptr + + ! = ' % ' )
return 0 ;
2014-10-30 16:52:37 +03:00
if ( ! _get_percent_arg ( av , ptr ) )
return_0 ;
if ( av - > ui64_value > = UINT32_MAX ) {
log_error ( " Percentage is too big (>=%d%%). " , UINT32_MAX ) ;
2006-09-26 13:35:43 +04:00
return 0 ;
2014-10-30 16:52:37 +03:00
}
2006-09-26 13:35:43 +04:00
return 1 ;
}
2010-07-09 19:34:40 +04:00
int string_arg ( struct cmd_context * cmd __attribute__ ( ( unused ) ) ,
2010-11-11 20:29:05 +03:00
struct arg_values * av __attribute__ ( ( unused ) ) )
2004-03-26 15:00:24 +03:00
{
return 1 ;
}
2010-11-11 20:29:05 +03:00
int tag_arg ( struct cmd_context * cmd __attribute__ ( ( unused ) ) , struct arg_values * av )
2004-03-26 15:00:24 +03:00
{
2010-11-11 20:29:05 +03:00
char * pos = av - > value ;
2004-03-26 15:00:24 +03:00
if ( * pos = = ' @ ' )
pos + + ;
2010-11-17 13:19:29 +03:00
if ( ! validate_tag ( pos ) )
2004-03-26 15:00:24 +03:00
return 0 ;
2010-11-11 20:29:05 +03:00
av - > value = pos ;
2007-11-16 00:59:11 +03:00
2004-03-26 15:00:24 +03:00
return 1 ;
}
2010-11-11 20:29:05 +03:00
int permission_arg ( struct cmd_context * cmd __attribute__ ( ( unused ) ) , struct arg_values * av )
2004-03-26 15:00:24 +03:00
{
2010-11-11 20:29:05 +03:00
av - > sign = SIGN_NONE ;
2004-03-26 15:00:24 +03:00
2010-11-11 20:29:05 +03:00
if ( ( ! strcmp ( av - > value , " rw " ) ) | | ( ! strcmp ( av - > value , " wr " ) ) )
av - > ui_value = LVM_READ | LVM_WRITE ;
2004-03-26 15:00:24 +03:00
2010-11-11 20:29:05 +03:00
else if ( ! strcmp ( av - > value , " r " ) )
av - > ui_value = LVM_READ ;
2004-03-26 15:00:24 +03:00
else
return 0 ;
return 1 ;
}
2010-11-11 20:29:05 +03:00
int alloc_arg ( struct cmd_context * cmd __attribute__ ( ( unused ) ) , struct arg_values * av )
2004-05-19 02:12:53 +04:00
{
alloc_policy_t alloc ;
2010-11-11 20:29:05 +03:00
av - > sign = SIGN_NONE ;
2004-05-19 02:12:53 +04:00
2010-11-11 20:29:05 +03:00
alloc = get_alloc_from_string ( av - > value ) ;
2004-05-19 02:12:53 +04:00
if ( alloc = = ALLOC_INVALID )
return 0 ;
2010-11-11 20:29:05 +03:00
av - > ui_value = ( uint32_t ) alloc ;
2004-05-19 02:12:53 +04:00
return 1 ;
}
2015-03-05 23:00:44 +03:00
int locktype_arg ( struct cmd_context * cmd __attribute__ ( ( unused ) ) , struct arg_values * av )
{
lock_type_t lock_type ;
av - > sign = SIGN_NONE ;
lock_type = get_lock_type_from_string ( av - > value ) ;
if ( lock_type = = LOCK_TYPE_INVALID )
return 0 ;
return 1 ;
}
2010-11-11 20:29:05 +03:00
int segtype_arg ( struct cmd_context * cmd , struct arg_values * av )
2004-05-11 20:01:58 +04:00
{
2014-10-11 20:36:40 +04:00
struct segment_type * segtype ;
2015-09-22 21:04:12 +03:00
const char * str = ( ! strcmp ( av - > value , SEG_TYPE_NAME_LINEAR ) ) ? SEG_TYPE_NAME_STRIPED : av - > value ;
2014-10-11 20:36:40 +04:00
if ( ! ( segtype = get_segtype_from_string ( cmd , str ) ) )
return_0 ;
return ( ! segtype_is_unknown ( segtype ) ) ? 1 : 0 ;
2004-05-11 20:01:58 +04:00
}
2007-11-09 19:51:54 +03:00
/*
* Positive integer , zero or " auto " .
*/
2010-11-11 20:29:05 +03:00
int readahead_arg ( struct cmd_context * cmd __attribute__ ( ( unused ) ) , struct arg_values * av )
2007-11-09 19:51:54 +03:00
{
2010-11-11 20:29:05 +03:00
if ( ! strcasecmp ( av - > value , " auto " ) ) {
av - > ui_value = DM_READ_AHEAD_AUTO ;
2007-11-09 19:51:54 +03:00
return 1 ;
}
2010-11-11 20:29:05 +03:00
if ( ! strcasecmp ( av - > value , " none " ) ) {
av - > ui_value = DM_READ_AHEAD_NONE ;
2007-11-09 19:51:54 +03:00
return 1 ;
}
2014-10-30 16:52:37 +03:00
if ( ! _size_arg ( cmd , av , 1 , 0 ) )
2007-11-14 03:08:25 +03:00
return 0 ;
2010-11-11 20:29:05 +03:00
if ( av - > sign = = SIGN_MINUS )
2007-11-14 03:08:25 +03:00
return 0 ;
return 1 ;
2007-11-09 19:51:54 +03:00
}
Allow 'all' and 'unmanaged' values for --vgmetadatacopies.
Allowing an 'all' and 'unmanaged' value is more intuitive, and
provides a simple way for users to get back to original LVM behavior
of metadata written to all PVs in the volume group.
If the user requests "--vgmetadatacopies unmanaged", this instructs
LVM not to manage the ignore bits to achieve a specific number of
metadata copies in the volume group. The user is free to use
"pvchange --metadataignore" to control the mdas on a per-PV basis.
If the user requests "--vgmetadatacopies all", this instructs LVM
to do 2 things: 1) clear all ignore bits, and 2) set the "unmanaged"
policy going forward.
Internally, we use the special MAX_UINT32 value to indicate 'all'.
This 'just' works since it's the largest value possible for the
field and so all 'ignore' bits on all mdas in the VG will get
cleared inside _vg_metadata_balance(). However, after we've
called the _vg_metadata_balance function, we check for the special
'all' value, and if set, we write the "unmanaged" value into the
metadata. As such, the 'all' value is never written to disk.
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
2010-06-29 00:40:01 +04:00
/*
* Non - zero , positive integer , " all " , or " unmanaged "
*/
2010-11-11 20:29:05 +03:00
int metadatacopies_arg ( struct cmd_context * cmd , struct arg_values * av )
Allow 'all' and 'unmanaged' values for --vgmetadatacopies.
Allowing an 'all' and 'unmanaged' value is more intuitive, and
provides a simple way for users to get back to original LVM behavior
of metadata written to all PVs in the volume group.
If the user requests "--vgmetadatacopies unmanaged", this instructs
LVM not to manage the ignore bits to achieve a specific number of
metadata copies in the volume group. The user is free to use
"pvchange --metadataignore" to control the mdas on a per-PV basis.
If the user requests "--vgmetadatacopies all", this instructs LVM
to do 2 things: 1) clear all ignore bits, and 2) set the "unmanaged"
policy going forward.
Internally, we use the special MAX_UINT32 value to indicate 'all'.
This 'just' works since it's the largest value possible for the
field and so all 'ignore' bits on all mdas in the VG will get
cleared inside _vg_metadata_balance(). However, after we've
called the _vg_metadata_balance function, we check for the special
'all' value, and if set, we write the "unmanaged" value into the
metadata. As such, the 'all' value is never written to disk.
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
2010-06-29 00:40:01 +04:00
{
2010-07-01 00:21:03 +04:00
if ( ! strncmp ( cmd - > command - > name , " vg " , 2 ) ) {
2010-11-11 20:29:05 +03:00
if ( ! strcasecmp ( av - > value , " all " ) ) {
av - > ui_value = VGMETADATACOPIES_ALL ;
2010-07-01 00:21:03 +04:00
return 1 ;
}
Allow 'all' and 'unmanaged' values for --vgmetadatacopies.
Allowing an 'all' and 'unmanaged' value is more intuitive, and
provides a simple way for users to get back to original LVM behavior
of metadata written to all PVs in the volume group.
If the user requests "--vgmetadatacopies unmanaged", this instructs
LVM not to manage the ignore bits to achieve a specific number of
metadata copies in the volume group. The user is free to use
"pvchange --metadataignore" to control the mdas on a per-PV basis.
If the user requests "--vgmetadatacopies all", this instructs LVM
to do 2 things: 1) clear all ignore bits, and 2) set the "unmanaged"
policy going forward.
Internally, we use the special MAX_UINT32 value to indicate 'all'.
This 'just' works since it's the largest value possible for the
field and so all 'ignore' bits on all mdas in the VG will get
cleared inside _vg_metadata_balance(). However, after we've
called the _vg_metadata_balance function, we check for the special
'all' value, and if set, we write the "unmanaged" value into the
metadata. As such, the 'all' value is never written to disk.
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
2010-06-29 00:40:01 +04:00
2010-11-11 20:29:05 +03:00
if ( ! strcasecmp ( av - > value , " unmanaged " ) ) {
av - > ui_value = VGMETADATACOPIES_UNMANAGED ;
2010-07-01 00:21:03 +04:00
return 1 ;
}
Allow 'all' and 'unmanaged' values for --vgmetadatacopies.
Allowing an 'all' and 'unmanaged' value is more intuitive, and
provides a simple way for users to get back to original LVM behavior
of metadata written to all PVs in the volume group.
If the user requests "--vgmetadatacopies unmanaged", this instructs
LVM not to manage the ignore bits to achieve a specific number of
metadata copies in the volume group. The user is free to use
"pvchange --metadataignore" to control the mdas on a per-PV basis.
If the user requests "--vgmetadatacopies all", this instructs LVM
to do 2 things: 1) clear all ignore bits, and 2) set the "unmanaged"
policy going forward.
Internally, we use the special MAX_UINT32 value to indicate 'all'.
This 'just' works since it's the largest value possible for the
field and so all 'ignore' bits on all mdas in the VG will get
cleared inside _vg_metadata_balance(). However, after we've
called the _vg_metadata_balance function, we check for the special
'all' value, and if set, we write the "unmanaged" value into the
metadata. As such, the 'all' value is never written to disk.
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
2010-06-29 00:40:01 +04:00
}
2010-11-11 20:29:05 +03:00
return int_arg ( cmd , av ) ;
Allow 'all' and 'unmanaged' values for --vgmetadatacopies.
Allowing an 'all' and 'unmanaged' value is more intuitive, and
provides a simple way for users to get back to original LVM behavior
of metadata written to all PVs in the volume group.
If the user requests "--vgmetadatacopies unmanaged", this instructs
LVM not to manage the ignore bits to achieve a specific number of
metadata copies in the volume group. The user is free to use
"pvchange --metadataignore" to control the mdas on a per-PV basis.
If the user requests "--vgmetadatacopies all", this instructs LVM
to do 2 things: 1) clear all ignore bits, and 2) set the "unmanaged"
policy going forward.
Internally, we use the special MAX_UINT32 value to indicate 'all'.
This 'just' works since it's the largest value possible for the
field and so all 'ignore' bits on all mdas in the VG will get
cleared inside _vg_metadata_balance(). However, after we've
called the _vg_metadata_balance function, we check for the special
'all' value, and if set, we write the "unmanaged" value into the
metadata. As such, the 'all' value is never written to disk.
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
2010-06-29 00:40:01 +04:00
}
2004-03-26 15:00:24 +03:00
static void __alloc ( int size )
{
2007-02-14 19:51:48 +03:00
if ( ! ( _cmdline . commands = dm_realloc ( _cmdline . commands , sizeof ( * _cmdline . commands ) * size ) ) ) {
2004-03-26 15:00:24 +03:00
log_fatal ( " Couldn't allocate memory. " ) ;
exit ( ECMD_FAILED ) ;
}
2007-02-14 19:51:48 +03:00
_cmdline . commands_size = size ;
2004-03-26 15:00:24 +03:00
}
static void _alloc_command ( void )
{
2007-02-14 19:51:48 +03:00
if ( ! _cmdline . commands_size )
2004-03-26 15:00:24 +03:00
__alloc ( 32 ) ;
2007-02-14 19:51:48 +03:00
if ( _cmdline . commands_size < = _cmdline . num_commands )
__alloc ( 2 * _cmdline . commands_size ) ;
2004-03-26 15:00:24 +03:00
}
static void _create_new_command ( const char * name , command_fn command ,
2008-04-03 01:23:39 +04:00
unsigned flags ,
2004-03-26 15:00:24 +03:00
const char * desc , const char * usagestr ,
int nargs , int * args )
{
struct command * nc ;
_alloc_command ( ) ;
2007-02-14 19:51:48 +03:00
nc = _cmdline . commands + _cmdline . num_commands + + ;
2004-03-26 15:00:24 +03:00
nc - > name = name ;
nc - > desc = desc ;
nc - > usage = usagestr ;
nc - > fn = command ;
2008-04-03 01:23:39 +04:00
nc - > flags = flags ;
2004-03-26 15:00:24 +03:00
nc - > num_args = nargs ;
nc - > valid_args = args ;
}
2008-04-03 01:23:39 +04:00
static void _register_command ( const char * name , command_fn fn , const char * desc ,
unsigned flags , const char * usagestr , . . . )
2004-03-26 15:00:24 +03:00
{
int nargs = 0 , i ;
int * args ;
va_list ap ;
/* count how many arguments we have */
va_start ( ap , usagestr ) ;
while ( va_arg ( ap , int ) > = 0 )
nargs + + ;
va_end ( ap ) ;
/* allocate space for them */
2005-10-17 03:03:59 +04:00
if ( ! ( args = dm_malloc ( sizeof ( * args ) * nargs ) ) ) {
2004-03-26 15:00:24 +03:00
log_fatal ( " Out of memory. " ) ;
exit ( ECMD_FAILED ) ;
}
/* fill them in */
va_start ( ap , usagestr ) ;
for ( i = 0 ; i < nargs ; i + + )
args [ i ] = va_arg ( ap , int ) ;
va_end ( ap ) ;
/* enter the command in the register */
2008-04-03 01:23:39 +04:00
_create_new_command ( name , fn , flags , desc , usagestr , nargs , args ) ;
2004-03-26 15:00:24 +03:00
}
2006-08-19 01:17:18 +04:00
void lvm_register_commands ( void )
2004-03-26 15:00:24 +03:00
{
2008-04-03 01:23:39 +04:00
# define xx(a, b, c, d...) _register_command(# a, a, b, c, ## d, \
driverloaded_ARG , \
debug_ARG , help_ARG , help2_ARG , \
version_ARG , verbose_ARG , \
2013-05-14 21:45:37 +04:00
yes_ARG , \
2013-06-25 14:27:04 +04:00
quiet_ARG , config_ARG , \
config: differentiate command and metadata profiles and consolidate profile handling code
- When defining configuration source, the code now uses separate
CONFIG_PROFILE_COMMAND and CONFIG_PROFILE_METADATA markers
(before, it was just CONFIG_PROFILE that did not make the
difference between the two). This helps when checking the
configuration if it contains correct set of options which
are all in either command-profilable or metadata-profilable
group without mixing these groups together - so it's a firm
distinction. The "command profile" can't contain
"metadata profile" and vice versa! This is strictly checked
and if the settings are mixed, such profile is rejected and
it's not used. So in the end, the CONFIG_PROFILE_COMMAND
set of options and CONFIG_PROFILE_METADATA are mutually exclusive
sets.
- Marking configuration with one or the other marker will also
determine the way these configuration sources are positioned
in the configuration cascade which is now:
CONFIG_STRING -> CONFIG_PROFILE_COMMAND -> CONFIG_PROFILE_METADATA -> CONFIG_FILE/CONFIG_MERGED_FILES
- Marking configuration with one or the other marker will also make
it possible to issue a command context refresh (will be probably
a part of a future patch) if needed for settings in global profile
set. For settings in metadata profile set this is impossible since
we can't refresh cmd context in the middle of reading VG/LV metadata
and for each VG/LV separately because each VG/LV can have a different
metadata profile assinged and it's not possible to change these
settings at this level.
- When command profile is incorrect, it's rejected *and also* the
command exits immediately - the profile *must* be correct for the
command that was run with a profile to be executed. Before this
patch, when the profile was found incorrect, there was just the
warning message and the command continued without profile applied.
But it's more correct to exit immediately in this case.
- When metadata profile is incorrect, we reject it during command
runtime (as we know the profile name from metadata and not early
from command line as it is in case of command profiles) and we
*do continue* with the command as we're in the middle of operation.
Also, the metadata profile is applied directly and on the fly on
find_config_tree_* fn call and even if the metadata profile is
found incorrect, we still need to return the non-profiled value
as found in the other configuration provided or default value.
To exit immediately even in this case, we'd need to refactor
existing find_config_tree_* fns so they can return error. Currently,
these fns return only config values (which end up with default
values in the end if the config is not found).
- To check the profile validity before use to be sure it's correct,
one can use :
lvm dumpconfig --commandprofile/--metadataprofile ProfileName --validate
(the --commandprofile/--metadataprofile for dumpconfig will come
as part of the subsequent patch)
- This patch also adds a reference to --commandprofile and
--metadataprofile in the cmd help string (which was missing before
for the --profile for some commands). We do not mention --profile
now as people should use --commandprofile or --metadataprofile
directly. However, the --profile is still supported for backward
compatibility and it's translated as:
--profile == --metadataprofile for lvcreate, vgcreate, lvchange and vgchange
(as these commands are able to attach profile to metadata)
--profile == --commandprofile for all the other commands
(--metadataprofile is not allowed there as it makes no sense)
- This patch also contains some cleanups to make the code handling
the profiles more readable...
2014-05-20 16:13:10 +04:00
commandprofile_ARG , \
2013-06-25 14:27:04 +04:00
profile_ARG , - 1 ) ;
2004-03-26 15:00:24 +03:00
# include "commands.h"
# undef xx
}
static struct command * _find_command ( const char * name )
{
int i ;
2008-11-12 12:53:33 +03:00
const char * base ;
2004-03-26 15:00:24 +03:00
2007-07-20 19:48:39 +04:00
base = last_path_component ( name ) ;
2004-03-26 15:00:24 +03:00
2007-02-14 19:51:48 +03:00
for ( i = 0 ; i < _cmdline . num_commands ; i + + ) {
if ( ! strcmp ( base , _cmdline . commands [ i ] . name ) )
2004-03-26 15:00:24 +03:00
break ;
}
2007-02-14 19:51:48 +03:00
if ( i > = _cmdline . num_commands )
2004-03-26 15:00:24 +03:00
return 0 ;
2007-02-14 19:51:48 +03:00
return _cmdline . commands + i ;
2004-03-26 15:00:24 +03:00
}
2007-09-21 22:06:33 +04:00
static void _short_usage ( const char * name )
{
2007-09-21 22:43:55 +04:00
log_error ( " Run `%s --help' for more information. " , name ) ;
2007-09-21 22:06:33 +04:00
}
2008-12-19 17:43:02 +03:00
static int _usage ( const char * name )
2004-03-26 15:00:24 +03:00
{
struct command * com = _find_command ( name ) ;
2008-12-19 17:43:02 +03:00
if ( ! com ) {
log_print ( " %s: no such command. " , name ) ;
return 0 ;
}
2004-03-26 15:00:24 +03:00
2007-09-21 22:06:56 +04:00
log_print ( " %s: %s \n \n %s " , com - > name , com - > desc , com - > usage ) ;
2008-12-19 17:43:02 +03:00
return 1 ;
2004-03-26 15:00:24 +03:00
}
/*
* Sets up the short and long argument . If there
* is no short argument then the index of the
* argument in the the_args array is set as the
* long opt value . Yuck . Of course this means we
* can ' t have more than ' a ' long arguments .
*/
static void _add_getopt_arg ( int arg , char * * ptr , struct option * * o )
{
2010-11-11 20:29:05 +03:00
struct arg_props * a = _cmdline . arg_props + arg ;
2004-03-26 15:00:24 +03:00
if ( a - > short_arg ) {
* ( * ptr ) + + = a - > short_arg ;
if ( a - > fn )
* ( * ptr ) + + = ' : ' ;
}
# ifdef HAVE_GETOPTLONG
if ( * ( a - > long_arg + 2 ) ) {
( * o ) - > name = a - > long_arg + 2 ;
( * o ) - > has_arg = a - > fn ? 1 : 0 ;
( * o ) - > flag = NULL ;
if ( a - > short_arg )
( * o ) - > val = a - > short_arg ;
else
2011-09-16 16:10:02 +04:00
( * o ) - > val = arg + 128 ;
2004-03-26 15:00:24 +03:00
( * o ) + + ;
}
# endif
}
2010-11-11 20:29:05 +03:00
static int _find_arg ( struct command * com , int opt )
2004-03-26 15:00:24 +03:00
{
2010-11-11 20:29:05 +03:00
struct arg_props * a ;
2004-03-26 15:00:24 +03:00
int i , arg ;
for ( i = 0 ; i < com - > num_args ; i + + ) {
arg = com - > valid_args [ i ] ;
2010-11-11 20:29:05 +03:00
a = _cmdline . arg_props + arg ;
2004-03-26 15:00:24 +03:00
/*
* opt should equal either the
* short arg , or the index into
2007-02-14 19:51:48 +03:00
* the_args .
2004-03-26 15:00:24 +03:00
*/
if ( ( a - > short_arg & & ( opt = = a - > short_arg ) ) | |
2011-09-16 16:10:02 +04:00
( ! a - > short_arg & & ( opt = = ( arg + 128 ) ) ) )
2010-11-11 20:29:05 +03:00
return arg ;
2004-03-26 15:00:24 +03:00
}
2010-11-11 20:29:05 +03:00
return - 1 ;
2004-03-26 15:00:24 +03:00
}
static int _process_command_line ( struct cmd_context * cmd , int * argc ,
char * * * argv )
{
2010-11-11 20:29:05 +03:00
int i , opt , arg ;
2004-03-26 15:00:24 +03:00
char str [ ( ( ARG_COUNT + 1 ) * 2 ) + 1 ] , * ptr = str ;
struct option opts [ ARG_COUNT + 1 ] , * o = opts ;
2010-11-11 20:29:05 +03:00
struct arg_props * a ;
struct arg_values * av ;
struct arg_value_group_list * current_group = NULL ;
if ( ! ( cmd - > arg_values = dm_pool_zalloc ( cmd - > mem , sizeof ( * cmd - > arg_values ) * ARG_COUNT ) ) ) {
log_fatal ( " Unable to allocate memory for command line arguments. " ) ;
return 0 ;
2004-03-26 15:00:24 +03:00
}
/* fill in the short and long opts */
for ( i = 0 ; i < cmd - > command - > num_args ; i + + )
_add_getopt_arg ( cmd - > command - > valid_args [ i ] , & ptr , & o ) ;
* ptr = ' \0 ' ;
memset ( o , 0 , sizeof ( * o ) ) ;
/* initialise getopt_long & scan for command line switches */
optarg = 0 ;
optind = OPTIND_INIT ;
while ( ( opt = GETOPTLONG_FN ( * argc , * argv , str , opts , NULL ) ) > = 0 ) {
if ( opt = = ' ? ' )
return 0 ;
2010-11-11 20:29:05 +03:00
if ( ( arg = _find_arg ( cmd - > command , opt ) ) < 0 ) {
2004-03-26 15:00:24 +03:00
log_fatal ( " Unrecognised option. " ) ;
return 0 ;
}
2010-11-11 20:29:05 +03:00
a = _cmdline . arg_props + arg ;
av = & cmd - > arg_values [ arg ] ;
if ( a - > flags & ARG_GROUPABLE ) {
/* Start a new group of arguments the first time or if a non-countable argument is repeated. */
if ( ! current_group | | ( current_group - > arg_values [ arg ] . count & & ! ( a - > flags & ARG_COUNTABLE ) ) ) {
/* FIXME Reduce size including only groupable args */
if ( ! ( current_group = dm_pool_zalloc ( cmd - > mem , sizeof ( struct arg_value_group_list ) + sizeof ( * cmd - > arg_values ) * ARG_COUNT ) ) ) {
log_fatal ( " Unable to allocate memory for command line arguments. " ) ;
return 0 ;
}
dm_list_add ( & cmd - > arg_value_groups , & current_group - > list ) ;
}
/* Maintain total argument count as well as count within each group */
av - > count + + ;
av = & current_group - > arg_values [ arg ] ;
}
if ( av - > count & & ! ( a - > flags & ARG_COUNTABLE ) ) {
log_error ( " Option%s%c%s%s may not be repeated. " ,
2007-08-21 23:46:36 +04:00
a - > short_arg ? " - " : " " ,
a - > short_arg ? : ' ' ,
( a - > short_arg & & a - > long_arg ) ?
" / " : " " , a - > long_arg ? : " " ) ;
return 0 ;
}
2004-03-26 15:00:24 +03:00
2007-08-21 23:46:36 +04:00
if ( a - > fn ) {
2004-03-26 15:00:24 +03:00
if ( ! optarg ) {
log_error ( " Option requires argument. " ) ;
return 0 ;
}
2010-11-11 20:29:05 +03:00
av - > value = optarg ;
2004-03-26 15:00:24 +03:00
2010-11-11 20:29:05 +03:00
if ( ! a - > fn ( cmd , av ) ) {
log_error ( " Invalid argument for %s: %s " , a - > long_arg , optarg ) ;
2004-03-26 15:00:24 +03:00
return 0 ;
}
}
2010-11-11 20:29:05 +03:00
av - > count + + ;
2004-03-26 15:00:24 +03:00
}
* argc - = optind ;
* argv + = optind ;
return 1 ;
}
2013-07-19 23:37:43 +04:00
static void _copy_arg_values ( struct arg_values * av , int oldarg , int newarg )
{
const struct arg_values * old = av + oldarg ;
struct arg_values * new = av + newarg ;
new - > count = old - > count ;
new - > value = old - > value ;
new - > i_value = old - > i_value ;
new - > ui_value = old - > ui_value ;
new - > i64_value = old - > i64_value ;
new - > ui64_value = old - > ui64_value ;
new - > sign = old - > sign ;
}
2004-03-26 15:00:24 +03:00
static int _merge_synonym ( struct cmd_context * cmd , int oldarg , int newarg )
{
2013-07-19 23:37:43 +04:00
struct arg_values * av ;
struct arg_value_group_list * current_group ;
2004-03-26 15:00:24 +03:00
if ( arg_count ( cmd , oldarg ) & & arg_count ( cmd , newarg ) ) {
log_error ( " %s and %s are synonyms. Please only supply one. " ,
2010-11-11 20:29:05 +03:00
_cmdline . arg_props [ oldarg ] . long_arg , _cmdline . arg_props [ newarg ] . long_arg ) ;
2004-03-26 15:00:24 +03:00
return 0 ;
}
2013-07-19 23:37:43 +04:00
/* Not groupable? */
if ( ! ( _cmdline . arg_props [ oldarg ] . flags & ARG_GROUPABLE ) ) {
if ( arg_count ( cmd , oldarg ) )
_copy_arg_values ( cmd - > arg_values , oldarg , newarg ) ;
2004-03-26 15:00:24 +03:00
return 1 ;
2013-07-19 23:37:43 +04:00
}
2004-03-26 15:00:24 +03:00
2013-07-19 23:37:43 +04:00
if ( arg_count ( cmd , oldarg ) )
cmd - > arg_values [ newarg ] . count = cmd - > arg_values [ oldarg ] . count ;
2004-03-26 15:00:24 +03:00
2013-07-19 23:37:43 +04:00
/* Groupable */
dm_list_iterate_items ( current_group , & cmd - > arg_value_groups ) {
av = current_group - > arg_values ;
if ( ! grouped_arg_count ( av , oldarg ) )
continue ;
_copy_arg_values ( av , oldarg , newarg ) ;
}
2004-03-26 15:00:24 +03:00
return 1 ;
}
2015-02-23 20:26:50 +03:00
int systemid ( struct cmd_context * cmd __attribute__ ( ( unused ) ) ,
int argc __attribute__ ( ( unused ) ) ,
char * * argv __attribute__ ( ( unused ) ) )
{
2015-02-27 22:32:00 +03:00
log_print ( " system ID: %s " , cmd - > system_id ? : " " ) ;
2015-02-23 20:26:50 +03:00
return ECMD_PROCESSED ;
}
2010-07-09 19:34:40 +04:00
int version ( struct cmd_context * cmd __attribute__ ( ( unused ) ) ,
int argc __attribute__ ( ( unused ) ) ,
char * * argv __attribute__ ( ( unused ) ) )
2004-03-26 15:00:24 +03:00
{
char vsn [ 80 ] ;
log_print ( " LVM version: %s " , LVM_VERSION ) ;
if ( library_version ( vsn , sizeof ( vsn ) ) )
log_print ( " Library version: %s " , vsn ) ;
if ( driver_version ( vsn , sizeof ( vsn ) ) )
log_print ( " Driver version: %s " , vsn ) ;
return ECMD_PROCESSED ;
}
static int _get_settings ( struct cmd_context * cmd )
{
activation: Add "degraded" activation mode
Currently, we have two modes of activation, an unnamed nominal mode
(which I will refer to as "complete") and "partial" mode. The
"complete" mode requires that a volume group be 'complete' - that
is, no missing PVs. If there are any missing PVs, no affected LVs
are allowed to activate - even RAID LVs which might be able to
tolerate a failure. The "partial" mode allows anything to be
activated (or at least attempted). If a non-redundant LV is
missing a portion of its addressable space due to a device failure,
it will be replaced with an error target. RAID LVs will either
activate or fail to activate depending on how badly their
redundancy is compromised.
This patch adds a third option, "degraded" mode. This mode can
be selected via the '--activationmode {complete|degraded|partial}'
option to lvchange/vgchange. It can also be set in lvm.conf.
The "degraded" activation mode allows RAID LVs with a sufficient
level of redundancy to activate (e.g. a RAID5 LV with one device
failure, a RAID6 with two device failures, or RAID1 with n-1
failures). RAID LVs with too many device failures are not allowed
to activate - nor are any non-redundant LVs that may have been
affected. This patch also makes the "degraded" mode the default
activation mode.
The degraded activation mode does not yet work in a cluster. A
new cluster lock flag (LCK_DEGRADED_MODE) will need to be created
to make that work. Currently, there is limited space for this
extra flag and I am looking for possible solutions. One possible
solution is to usurp LCK_CONVERT, as it is not used. When the
locking_type is 3, the degraded mode flag simply gets dropped and
the old ("complete") behavior is exhibited.
2014-07-10 07:56:11 +04:00
const char * activation_mode ;
2004-03-26 15:00:24 +03:00
cmd - > current_settings = cmd - > default_settings ;
if ( arg_count ( cmd , debug_ARG ) )
cmd - > current_settings . debug = _LOG_FATAL +
( arg_count ( cmd , debug_ARG ) - 1 ) ;
if ( arg_count ( cmd , verbose_ARG ) )
cmd - > current_settings . verbose = arg_count ( cmd , verbose_ARG ) ;
if ( arg_count ( cmd , quiet_ARG ) ) {
cmd - > current_settings . debug = 0 ;
cmd - > current_settings . verbose = 0 ;
2014-07-14 19:34:49 +04:00
cmd - > current_settings . silent = ( arg_count ( cmd , quiet_ARG ) > 1 ) ? 1 : 0 ;
2004-03-26 15:00:24 +03:00
}
if ( arg_count ( cmd , test_ARG ) )
cmd - > current_settings . test = arg_count ( cmd , test_ARG ) ;
if ( arg_count ( cmd , driverloaded_ARG ) ) {
cmd - > current_settings . activation =
arg_int_value ( cmd , driverloaded_ARG ,
cmd - > default_settings . activation ) ;
}
2006-11-14 18:28:50 +03:00
cmd - > current_settings . archive = arg_int_value ( cmd , autobackup_ARG , cmd - > current_settings . archive ) ;
cmd - > current_settings . backup = arg_int_value ( cmd , autobackup_ARG , cmd - > current_settings . backup ) ;
2008-04-03 01:23:39 +04:00
cmd - > current_settings . cache_vgmetadata = cmd - > command - > flags & CACHE_VGMETADATA ? 1 : 0 ;
2014-04-18 05:46:34 +04:00
if ( arg_count ( cmd , readonly_ARG ) ) {
cmd - > current_settings . activation = 0 ;
cmd - > current_settings . archive = 0 ;
cmd - > current_settings . backup = 0 ;
}
2015-03-05 23:00:44 +03:00
if ( cmd - > command - > flags & LOCKD_VG_SH )
cmd - > lockd_vg_default_sh = 1 ;
2008-09-19 11:12:45 +04:00
cmd - > partial_activation = 0 ;
activation: Add "degraded" activation mode
Currently, we have two modes of activation, an unnamed nominal mode
(which I will refer to as "complete") and "partial" mode. The
"complete" mode requires that a volume group be 'complete' - that
is, no missing PVs. If there are any missing PVs, no affected LVs
are allowed to activate - even RAID LVs which might be able to
tolerate a failure. The "partial" mode allows anything to be
activated (or at least attempted). If a non-redundant LV is
missing a portion of its addressable space due to a device failure,
it will be replaced with an error target. RAID LVs will either
activate or fail to activate depending on how badly their
redundancy is compromised.
This patch adds a third option, "degraded" mode. This mode can
be selected via the '--activationmode {complete|degraded|partial}'
option to lvchange/vgchange. It can also be set in lvm.conf.
The "degraded" activation mode allows RAID LVs with a sufficient
level of redundancy to activate (e.g. a RAID5 LV with one device
failure, a RAID6 with two device failures, or RAID1 with n-1
failures). RAID LVs with too many device failures are not allowed
to activate - nor are any non-redundant LVs that may have been
affected. This patch also makes the "degraded" mode the default
activation mode.
The degraded activation mode does not yet work in a cluster. A
new cluster lock flag (LCK_DEGRADED_MODE) will need to be created
to make that work. Currently, there is limited space for this
extra flag and I am looking for possible solutions. One possible
solution is to usurp LCK_CONVERT, as it is not used. When the
locking_type is 3, the degraded mode flag simply gets dropped and
the old ("complete") behavior is exhibited.
2014-07-10 07:56:11 +04:00
cmd - > degraded_activation = 0 ;
activation_mode = find_config_tree_str ( cmd , activation_mode_CFG , NULL ) ;
if ( ! activation_mode )
activation_mode = DEFAULT_ACTIVATION_MODE ;
if ( arg_count ( cmd , activationmode_ARG ) ) {
activation_mode = arg_str_value ( cmd , activationmode_ARG ,
activation_mode ) ;
/* complain only if the two arguments conflict */
if ( arg_count ( cmd , partial_ARG ) & &
strcmp ( activation_mode , " partial " ) ) {
log_error ( " --partial and --activationmode are mutually "
" exclusive arguments " ) ;
return EINVALID_CMD_LINE ;
}
} else if ( arg_count ( cmd , partial_ARG ) )
activation_mode = " partial " ;
2004-03-26 15:00:24 +03:00
activation: Add "degraded" activation mode
Currently, we have two modes of activation, an unnamed nominal mode
(which I will refer to as "complete") and "partial" mode. The
"complete" mode requires that a volume group be 'complete' - that
is, no missing PVs. If there are any missing PVs, no affected LVs
are allowed to activate - even RAID LVs which might be able to
tolerate a failure. The "partial" mode allows anything to be
activated (or at least attempted). If a non-redundant LV is
missing a portion of its addressable space due to a device failure,
it will be replaced with an error target. RAID LVs will either
activate or fail to activate depending on how badly their
redundancy is compromised.
This patch adds a third option, "degraded" mode. This mode can
be selected via the '--activationmode {complete|degraded|partial}'
option to lvchange/vgchange. It can also be set in lvm.conf.
The "degraded" activation mode allows RAID LVs with a sufficient
level of redundancy to activate (e.g. a RAID5 LV with one device
failure, a RAID6 with two device failures, or RAID1 with n-1
failures). RAID LVs with too many device failures are not allowed
to activate - nor are any non-redundant LVs that may have been
affected. This patch also makes the "degraded" mode the default
activation mode.
The degraded activation mode does not yet work in a cluster. A
new cluster lock flag (LCK_DEGRADED_MODE) will need to be created
to make that work. Currently, there is limited space for this
extra flag and I am looking for possible solutions. One possible
solution is to usurp LCK_CONVERT, as it is not used. When the
locking_type is 3, the degraded mode flag simply gets dropped and
the old ("complete") behavior is exhibited.
2014-07-10 07:56:11 +04:00
if ( ! strcmp ( activation_mode , " partial " ) ) {
2008-09-19 11:12:45 +04:00
cmd - > partial_activation = 1 ;
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
log_warn ( " PARTIAL MODE. Incomplete logical volumes will be processed. " ) ;
2014-07-22 23:50:29 +04:00
} else if ( ! strcmp ( activation_mode , " degraded " ) )
activation: Add "degraded" activation mode
Currently, we have two modes of activation, an unnamed nominal mode
(which I will refer to as "complete") and "partial" mode. The
"complete" mode requires that a volume group be 'complete' - that
is, no missing PVs. If there are any missing PVs, no affected LVs
are allowed to activate - even RAID LVs which might be able to
tolerate a failure. The "partial" mode allows anything to be
activated (or at least attempted). If a non-redundant LV is
missing a portion of its addressable space due to a device failure,
it will be replaced with an error target. RAID LVs will either
activate or fail to activate depending on how badly their
redundancy is compromised.
This patch adds a third option, "degraded" mode. This mode can
be selected via the '--activationmode {complete|degraded|partial}'
option to lvchange/vgchange. It can also be set in lvm.conf.
The "degraded" activation mode allows RAID LVs with a sufficient
level of redundancy to activate (e.g. a RAID5 LV with one device
failure, a RAID6 with two device failures, or RAID1 with n-1
failures). RAID LVs with too many device failures are not allowed
to activate - nor are any non-redundant LVs that may have been
affected. This patch also makes the "degraded" mode the default
activation mode.
The degraded activation mode does not yet work in a cluster. A
new cluster lock flag (LCK_DEGRADED_MODE) will need to be created
to make that work. Currently, there is limited space for this
extra flag and I am looking for possible solutions. One possible
solution is to usurp LCK_CONVERT, as it is not used. When the
locking_type is 3, the degraded mode flag simply gets dropped and
the old ("complete") behavior is exhibited.
2014-07-10 07:56:11 +04:00
cmd - > degraded_activation = 1 ;
2014-07-22 23:50:29 +04:00
else if ( strcmp ( activation_mode , " complete " ) ) {
activation: Add "degraded" activation mode
Currently, we have two modes of activation, an unnamed nominal mode
(which I will refer to as "complete") and "partial" mode. The
"complete" mode requires that a volume group be 'complete' - that
is, no missing PVs. If there are any missing PVs, no affected LVs
are allowed to activate - even RAID LVs which might be able to
tolerate a failure. The "partial" mode allows anything to be
activated (or at least attempted). If a non-redundant LV is
missing a portion of its addressable space due to a device failure,
it will be replaced with an error target. RAID LVs will either
activate or fail to activate depending on how badly their
redundancy is compromised.
This patch adds a third option, "degraded" mode. This mode can
be selected via the '--activationmode {complete|degraded|partial}'
option to lvchange/vgchange. It can also be set in lvm.conf.
The "degraded" activation mode allows RAID LVs with a sufficient
level of redundancy to activate (e.g. a RAID5 LV with one device
failure, a RAID6 with two device failures, or RAID1 with n-1
failures). RAID LVs with too many device failures are not allowed
to activate - nor are any non-redundant LVs that may have been
affected. This patch also makes the "degraded" mode the default
activation mode.
The degraded activation mode does not yet work in a cluster. A
new cluster lock flag (LCK_DEGRADED_MODE) will need to be created
to make that work. Currently, there is limited space for this
extra flag and I am looking for possible solutions. One possible
solution is to usurp LCK_CONVERT, as it is not used. When the
locking_type is 3, the degraded mode flag simply gets dropped and
the old ("complete") behavior is exhibited.
2014-07-10 07:56:11 +04:00
log_error ( " Invalid activation mode given. " ) ;
return EINVALID_CMD_LINE ;
2008-09-19 10:42:00 +04:00
}
2004-03-26 15:00:24 +03:00
2010-05-06 15:15:55 +04:00
if ( arg_count ( cmd , ignorelockingfailure_ARG ) | | arg_count ( cmd , sysinit_ARG ) )
2004-03-26 15:00:24 +03:00
init_ignorelockingfailure ( 1 ) ;
else
init_ignorelockingfailure ( 0 ) ;
2015-02-24 02:41:38 +03:00
cmd - > ignore_clustered_vgs = arg_is_set ( cmd , ignoreskippedcluster_ARG ) ;
2015-02-25 19:44:42 +03:00
cmd - > include_foreign_vgs = arg_is_set ( cmd , foreign_ARG ) ? 1 : 0 ;
2015-03-05 23:00:44 +03:00
cmd - > include_shared_vgs = arg_is_set ( cmd , shared_ARG ) ? 1 : 0 ;
/*
* This is set to zero by process_each which wants to print errors
* itself rather than having them printed in vg_read .
*/
cmd - > vg_read_print_access_error = 1 ;
2015-02-25 19:44:42 +03:00
2012-10-12 04:48:39 +04:00
if ( ! arg_count ( cmd , sysinit_ARG ) )
2013-01-05 03:22:30 +04:00
lvmetad_connect_or_warn ( ) ;
2012-10-12 04:48:39 +04:00
2004-03-26 15:00:24 +03:00
if ( arg_count ( cmd , nosuffix_ARG ) )
cmd - > current_settings . suffix = 0 ;
if ( arg_count ( cmd , units_ARG ) )
if ( ! ( cmd - > current_settings . unit_factor =
2014-04-28 12:25:43 +04:00
dm_units_to_factor ( arg_str_value ( cmd , units_ARG , " " ) ,
& cmd - > current_settings . unit_type , 1 , NULL ) ) ) {
2004-03-26 15:00:24 +03:00
log_error ( " Invalid units specification " ) ;
return EINVALID_CMD_LINE ;
}
2014-07-02 15:16:32 +04:00
if ( arg_count ( cmd , binary_ARG ) )
cmd - > report_binary_values_as_numeric = 1 ;
2006-08-01 18:56:33 +04:00
if ( arg_count ( cmd , trustcache_ARG ) ) {
if ( arg_count ( cmd , all_ARG ) ) {
log_error ( " --trustcache is incompatible with --all " ) ;
return EINVALID_CMD_LINE ;
}
init_trust_cache ( 1 ) ;
2007-06-28 21:33:44 +04:00
log_warn ( " WARNING: Cache file of PVs will be trusted. "
2006-08-01 18:56:33 +04:00
" New devices holding PVs may get ignored. " ) ;
} else
init_trust_cache ( 0 ) ;
2012-11-29 16:59:12 +04:00
if ( arg_count ( cmd , noudevsync_ARG ) )
2009-08-04 19:36:13 +04:00
cmd - > current_settings . udev_sync = 0 ;
2004-03-26 15:00:24 +03:00
/* Handle synonyms */
if ( ! _merge_synonym ( cmd , resizable_ARG , resizeable_ARG ) | |
! _merge_synonym ( cmd , allocation_ARG , allocatable_ARG ) | |
2009-05-27 20:30:29 +04:00
! _merge_synonym ( cmd , allocation_ARG , resizeable_ARG ) | |
2012-06-27 15:48:31 +04:00
! _merge_synonym ( cmd , virtualoriginsize_ARG , virtualsize_ARG ) | |
2013-07-19 22:24:54 +04:00
! _merge_synonym ( cmd , available_ARG , activate_ARG ) | |
! _merge_synonym ( cmd , raidsyncaction_ARG , syncaction_ARG ) | |
! _merge_synonym ( cmd , raidwritemostly_ARG , writemostly_ARG ) | |
! _merge_synonym ( cmd , raidminrecoveryrate_ARG , minrecoveryrate_ARG ) | |
! _merge_synonym ( cmd , raidmaxrecoveryrate_ARG , maxrecoveryrate_ARG ) | |
! _merge_synonym ( cmd , raidwritebehind_ARG , writebehind_ARG ) )
2010-06-29 00:39:39 +04:00
return EINVALID_CMD_LINE ;
if ( ( ! strncmp ( cmd - > command - > name , " pv " , 2 ) & &
! _merge_synonym ( cmd , metadatacopies_ARG , pvmetadatacopies_ARG ) ) | |
( ! strncmp ( cmd - > command - > name , " vg " , 2 ) & &
! _merge_synonym ( cmd , metadatacopies_ARG , vgmetadatacopies_ARG ) ) )
2004-03-26 15:00:24 +03:00
return EINVALID_CMD_LINE ;
/* Zero indicates success */
return 0 ;
}
static int _process_common_commands ( struct cmd_context * cmd )
{
if ( arg_count ( cmd , help_ARG ) | | arg_count ( cmd , help2_ARG ) ) {
_usage ( cmd - > command - > name ) ;
return ECMD_PROCESSED ;
}
if ( arg_count ( cmd , version_ARG ) ) {
return version ( cmd , 0 , ( char * * ) NULL ) ;
}
/* Zero indicates it's OK to continue processing this command */
return 0 ;
}
static void _display_help ( void )
{
int i ;
log_error ( " Available lvm commands: " ) ;
log_error ( " Use 'lvm help <command>' for more information " ) ;
log_error ( " " ) ;
2007-02-14 19:51:48 +03:00
for ( i = 0 ; i < _cmdline . num_commands ; i + + ) {
struct command * com = _cmdline . commands + i ;
2004-03-26 15:00:24 +03:00
log_error ( " %-16.16s%s " , com - > name , com - > desc ) ;
}
}
2010-07-09 19:34:40 +04:00
int help ( struct cmd_context * cmd __attribute__ ( ( unused ) ) , int argc , char * * argv )
2004-03-26 15:00:24 +03:00
{
2008-12-19 17:43:02 +03:00
int ret = ECMD_PROCESSED ;
2004-03-26 15:00:24 +03:00
if ( ! argc )
_display_help ( ) ;
else {
int i ;
for ( i = 0 ; i < argc ; i + + )
2008-12-19 17:43:02 +03:00
if ( ! _usage ( argv [ i ] ) )
ret = EINVALID_CMD_LINE ;
2004-03-26 15:00:24 +03:00
}
2008-12-19 17:43:02 +03:00
return ret ;
2004-03-26 15:00:24 +03:00
}
static void _apply_settings ( struct cmd_context * cmd )
{
init_debug ( cmd - > current_settings . debug ) ;
2013-01-08 02:30:29 +04:00
init_debug_classes_logged ( cmd - > default_settings . debug_classes ) ;
2004-03-26 15:00:24 +03:00
init_verbose ( cmd - > current_settings . verbose + VERBOSE_BASE_LEVEL ) ;
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
init_silent ( cmd - > current_settings . silent ) ;
2004-03-26 15:00:24 +03:00
init_test ( cmd - > current_settings . test ) ;
2005-03-22 01:40:35 +03:00
init_full_scan_done ( 0 ) ;
2006-05-16 20:48:31 +04:00
init_mirror_in_sync ( 0 ) ;
2012-02-15 19:18:43 +04:00
init_dmeventd_monitor ( DEFAULT_DMEVENTD_MONITOR ) ;
2004-03-26 15:00:24 +03:00
init_msg_prefix ( cmd - > default_settings . msg_prefix ) ;
init_cmd_name ( cmd - > default_settings . cmd_name ) ;
2005-05-17 17:46:38 +04:00
archive_enable ( cmd , cmd - > current_settings . archive ) ;
backup_enable ( cmd , cmd - > current_settings . backup ) ;
2004-03-26 15:00:24 +03:00
2014-04-18 05:46:34 +04:00
set_activation ( cmd - > current_settings . activation , cmd - > metadata_read_only ) ;
2004-03-26 15:00:24 +03:00
2010-04-29 05:38:12 +04:00
cmd - > fmt = get_format_by_name ( cmd , arg_str_value ( cmd , metadatatype_ARG ,
cmd - > current_settings . fmt_name ) ) ;
2008-09-19 10:42:00 +04:00
cmd - > handles_missing_pvs = 0 ;
2004-03-26 15:00:24 +03:00
}
2009-07-13 23:49:48 +04:00
static const char * _copy_command_line ( struct cmd_context * cmd , int argc , char * * argv )
2004-03-26 15:00:24 +03:00
{
2006-05-16 20:48:31 +04:00
int i , space ;
2004-03-26 15:00:24 +03:00
/*
* Build up the complete command line , used as a
* description for backups .
*/
2005-10-17 03:03:59 +04:00
if ( ! dm_pool_begin_object ( cmd - > mem , 128 ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2004-03-26 15:00:24 +03:00
for ( i = 0 ; i < argc ; i + + ) {
2006-05-16 20:48:31 +04:00
space = strchr ( argv [ i ] , ' ' ) ? 1 : 0 ;
if ( space & & ! dm_pool_grow_object ( cmd - > mem , " ' " , 1 ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2006-05-16 20:48:31 +04:00
2005-10-17 03:03:59 +04:00
if ( ! dm_pool_grow_object ( cmd - > mem , argv [ i ] , strlen ( argv [ i ] ) ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2004-03-26 15:00:24 +03:00
2006-05-16 20:48:31 +04:00
if ( space & & ! dm_pool_grow_object ( cmd - > mem , " ' " , 1 ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2006-05-16 20:48:31 +04:00
2004-03-26 15:00:24 +03:00
if ( i < ( argc - 1 ) )
2005-10-17 03:03:59 +04:00
if ( ! dm_pool_grow_object ( cmd - > mem , " " , 1 ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2004-03-26 15:00:24 +03:00
}
/*
* Terminate .
*/
2005-10-17 03:03:59 +04:00
if ( ! dm_pool_grow_object ( cmd - > mem , " \0 " , 1 ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2004-03-26 15:00:24 +03:00
2005-10-17 03:03:59 +04:00
return dm_pool_end_object ( cmd - > mem ) ;
2004-03-26 15:00:24 +03:00
bad :
2009-07-16 00:02:46 +04:00
log_error ( " Couldn't copy command line. " ) ;
2005-10-17 03:03:59 +04:00
dm_pool_abandon_object ( cmd - > mem ) ;
2004-03-26 15:00:24 +03:00
return NULL ;
}
config: differentiate command and metadata profiles and consolidate profile handling code
- When defining configuration source, the code now uses separate
CONFIG_PROFILE_COMMAND and CONFIG_PROFILE_METADATA markers
(before, it was just CONFIG_PROFILE that did not make the
difference between the two). This helps when checking the
configuration if it contains correct set of options which
are all in either command-profilable or metadata-profilable
group without mixing these groups together - so it's a firm
distinction. The "command profile" can't contain
"metadata profile" and vice versa! This is strictly checked
and if the settings are mixed, such profile is rejected and
it's not used. So in the end, the CONFIG_PROFILE_COMMAND
set of options and CONFIG_PROFILE_METADATA are mutually exclusive
sets.
- Marking configuration with one or the other marker will also
determine the way these configuration sources are positioned
in the configuration cascade which is now:
CONFIG_STRING -> CONFIG_PROFILE_COMMAND -> CONFIG_PROFILE_METADATA -> CONFIG_FILE/CONFIG_MERGED_FILES
- Marking configuration with one or the other marker will also make
it possible to issue a command context refresh (will be probably
a part of a future patch) if needed for settings in global profile
set. For settings in metadata profile set this is impossible since
we can't refresh cmd context in the middle of reading VG/LV metadata
and for each VG/LV separately because each VG/LV can have a different
metadata profile assinged and it's not possible to change these
settings at this level.
- When command profile is incorrect, it's rejected *and also* the
command exits immediately - the profile *must* be correct for the
command that was run with a profile to be executed. Before this
patch, when the profile was found incorrect, there was just the
warning message and the command continued without profile applied.
But it's more correct to exit immediately in this case.
- When metadata profile is incorrect, we reject it during command
runtime (as we know the profile name from metadata and not early
from command line as it is in case of command profiles) and we
*do continue* with the command as we're in the middle of operation.
Also, the metadata profile is applied directly and on the fly on
find_config_tree_* fn call and even if the metadata profile is
found incorrect, we still need to return the non-profiled value
as found in the other configuration provided or default value.
To exit immediately even in this case, we'd need to refactor
existing find_config_tree_* fns so they can return error. Currently,
these fns return only config values (which end up with default
values in the end if the config is not found).
- To check the profile validity before use to be sure it's correct,
one can use :
lvm dumpconfig --commandprofile/--metadataprofile ProfileName --validate
(the --commandprofile/--metadataprofile for dumpconfig will come
as part of the subsequent patch)
- This patch also adds a reference to --commandprofile and
--metadataprofile in the cmd help string (which was missing before
for the --profile for some commands). We do not mention --profile
now as people should use --commandprofile or --metadataprofile
directly. However, the --profile is still supported for backward
compatibility and it's translated as:
--profile == --metadataprofile for lvcreate, vgcreate, lvchange and vgchange
(as these commands are able to attach profile to metadata)
--profile == --commandprofile for all the other commands
(--metadataprofile is not allowed there as it makes no sense)
- This patch also contains some cleanups to make the code handling
the profiles more readable...
2014-05-20 16:13:10 +04:00
static int _prepare_profiles ( struct cmd_context * cmd )
2004-03-26 15:00:24 +03:00
{
2015-02-09 16:16:24 +03:00
static const char COMMAND_PROFILE_ENV_VAR_NAME [ ] = " LVM_COMMAND_PROFILE " ;
static const char _cmd_profile_arg_preferred_over_env_var_msg [ ] = " Giving "
" preference to command profile specified on command "
" line over the one specified via environment variable. " ;
config: differentiate command and metadata profiles and consolidate profile handling code
- When defining configuration source, the code now uses separate
CONFIG_PROFILE_COMMAND and CONFIG_PROFILE_METADATA markers
(before, it was just CONFIG_PROFILE that did not make the
difference between the two). This helps when checking the
configuration if it contains correct set of options which
are all in either command-profilable or metadata-profilable
group without mixing these groups together - so it's a firm
distinction. The "command profile" can't contain
"metadata profile" and vice versa! This is strictly checked
and if the settings are mixed, such profile is rejected and
it's not used. So in the end, the CONFIG_PROFILE_COMMAND
set of options and CONFIG_PROFILE_METADATA are mutually exclusive
sets.
- Marking configuration with one or the other marker will also
determine the way these configuration sources are positioned
in the configuration cascade which is now:
CONFIG_STRING -> CONFIG_PROFILE_COMMAND -> CONFIG_PROFILE_METADATA -> CONFIG_FILE/CONFIG_MERGED_FILES
- Marking configuration with one or the other marker will also make
it possible to issue a command context refresh (will be probably
a part of a future patch) if needed for settings in global profile
set. For settings in metadata profile set this is impossible since
we can't refresh cmd context in the middle of reading VG/LV metadata
and for each VG/LV separately because each VG/LV can have a different
metadata profile assinged and it's not possible to change these
settings at this level.
- When command profile is incorrect, it's rejected *and also* the
command exits immediately - the profile *must* be correct for the
command that was run with a profile to be executed. Before this
patch, when the profile was found incorrect, there was just the
warning message and the command continued without profile applied.
But it's more correct to exit immediately in this case.
- When metadata profile is incorrect, we reject it during command
runtime (as we know the profile name from metadata and not early
from command line as it is in case of command profiles) and we
*do continue* with the command as we're in the middle of operation.
Also, the metadata profile is applied directly and on the fly on
find_config_tree_* fn call and even if the metadata profile is
found incorrect, we still need to return the non-profiled value
as found in the other configuration provided or default value.
To exit immediately even in this case, we'd need to refactor
existing find_config_tree_* fns so they can return error. Currently,
these fns return only config values (which end up with default
values in the end if the config is not found).
- To check the profile validity before use to be sure it's correct,
one can use :
lvm dumpconfig --commandprofile/--metadataprofile ProfileName --validate
(the --commandprofile/--metadataprofile for dumpconfig will come
as part of the subsequent patch)
- This patch also adds a reference to --commandprofile and
--metadataprofile in the cmd help string (which was missing before
for the --profile for some commands). We do not mention --profile
now as people should use --commandprofile or --metadataprofile
directly. However, the --profile is still supported for backward
compatibility and it's translated as:
--profile == --metadataprofile for lvcreate, vgcreate, lvchange and vgchange
(as these commands are able to attach profile to metadata)
--profile == --commandprofile for all the other commands
(--metadataprofile is not allowed there as it makes no sense)
- This patch also contains some cleanups to make the code handling
the profiles more readable...
2014-05-20 16:13:10 +04:00
static const char _failed_to_add_profile_msg [ ] = " Failed to add %s %s. " ;
static const char _failed_to_apply_profile_msg [ ] = " Failed to apply %s %s. " ;
static const char _command_profile_source_name [ ] = " command profile " ;
static const char _metadata_profile_source_name [ ] = " metadata profile " ;
static const char _setting_global_profile_msg [ ] = " Setting global %s \" %s \" . " ;
2015-02-09 16:16:24 +03:00
const char * env_cmd_profile_name = NULL ;
config: differentiate command and metadata profiles and consolidate profile handling code
- When defining configuration source, the code now uses separate
CONFIG_PROFILE_COMMAND and CONFIG_PROFILE_METADATA markers
(before, it was just CONFIG_PROFILE that did not make the
difference between the two). This helps when checking the
configuration if it contains correct set of options which
are all in either command-profilable or metadata-profilable
group without mixing these groups together - so it's a firm
distinction. The "command profile" can't contain
"metadata profile" and vice versa! This is strictly checked
and if the settings are mixed, such profile is rejected and
it's not used. So in the end, the CONFIG_PROFILE_COMMAND
set of options and CONFIG_PROFILE_METADATA are mutually exclusive
sets.
- Marking configuration with one or the other marker will also
determine the way these configuration sources are positioned
in the configuration cascade which is now:
CONFIG_STRING -> CONFIG_PROFILE_COMMAND -> CONFIG_PROFILE_METADATA -> CONFIG_FILE/CONFIG_MERGED_FILES
- Marking configuration with one or the other marker will also make
it possible to issue a command context refresh (will be probably
a part of a future patch) if needed for settings in global profile
set. For settings in metadata profile set this is impossible since
we can't refresh cmd context in the middle of reading VG/LV metadata
and for each VG/LV separately because each VG/LV can have a different
metadata profile assinged and it's not possible to change these
settings at this level.
- When command profile is incorrect, it's rejected *and also* the
command exits immediately - the profile *must* be correct for the
command that was run with a profile to be executed. Before this
patch, when the profile was found incorrect, there was just the
warning message and the command continued without profile applied.
But it's more correct to exit immediately in this case.
- When metadata profile is incorrect, we reject it during command
runtime (as we know the profile name from metadata and not early
from command line as it is in case of command profiles) and we
*do continue* with the command as we're in the middle of operation.
Also, the metadata profile is applied directly and on the fly on
find_config_tree_* fn call and even if the metadata profile is
found incorrect, we still need to return the non-profiled value
as found in the other configuration provided or default value.
To exit immediately even in this case, we'd need to refactor
existing find_config_tree_* fns so they can return error. Currently,
these fns return only config values (which end up with default
values in the end if the config is not found).
- To check the profile validity before use to be sure it's correct,
one can use :
lvm dumpconfig --commandprofile/--metadataprofile ProfileName --validate
(the --commandprofile/--metadataprofile for dumpconfig will come
as part of the subsequent patch)
- This patch also adds a reference to --commandprofile and
--metadataprofile in the cmd help string (which was missing before
for the --profile for some commands). We do not mention --profile
now as people should use --commandprofile or --metadataprofile
directly. However, the --profile is still supported for backward
compatibility and it's translated as:
--profile == --metadataprofile for lvcreate, vgcreate, lvchange and vgchange
(as these commands are able to attach profile to metadata)
--profile == --commandprofile for all the other commands
(--metadataprofile is not allowed there as it makes no sense)
- This patch also contains some cleanups to make the code handling
the profiles more readable...
2014-05-20 16:13:10 +04:00
const char * name ;
2014-05-19 15:59:23 +04:00
struct profile * profile ;
config: differentiate command and metadata profiles and consolidate profile handling code
- When defining configuration source, the code now uses separate
CONFIG_PROFILE_COMMAND and CONFIG_PROFILE_METADATA markers
(before, it was just CONFIG_PROFILE that did not make the
difference between the two). This helps when checking the
configuration if it contains correct set of options which
are all in either command-profilable or metadata-profilable
group without mixing these groups together - so it's a firm
distinction. The "command profile" can't contain
"metadata profile" and vice versa! This is strictly checked
and if the settings are mixed, such profile is rejected and
it's not used. So in the end, the CONFIG_PROFILE_COMMAND
set of options and CONFIG_PROFILE_METADATA are mutually exclusive
sets.
- Marking configuration with one or the other marker will also
determine the way these configuration sources are positioned
in the configuration cascade which is now:
CONFIG_STRING -> CONFIG_PROFILE_COMMAND -> CONFIG_PROFILE_METADATA -> CONFIG_FILE/CONFIG_MERGED_FILES
- Marking configuration with one or the other marker will also make
it possible to issue a command context refresh (will be probably
a part of a future patch) if needed for settings in global profile
set. For settings in metadata profile set this is impossible since
we can't refresh cmd context in the middle of reading VG/LV metadata
and for each VG/LV separately because each VG/LV can have a different
metadata profile assinged and it's not possible to change these
settings at this level.
- When command profile is incorrect, it's rejected *and also* the
command exits immediately - the profile *must* be correct for the
command that was run with a profile to be executed. Before this
patch, when the profile was found incorrect, there was just the
warning message and the command continued without profile applied.
But it's more correct to exit immediately in this case.
- When metadata profile is incorrect, we reject it during command
runtime (as we know the profile name from metadata and not early
from command line as it is in case of command profiles) and we
*do continue* with the command as we're in the middle of operation.
Also, the metadata profile is applied directly and on the fly on
find_config_tree_* fn call and even if the metadata profile is
found incorrect, we still need to return the non-profiled value
as found in the other configuration provided or default value.
To exit immediately even in this case, we'd need to refactor
existing find_config_tree_* fns so they can return error. Currently,
these fns return only config values (which end up with default
values in the end if the config is not found).
- To check the profile validity before use to be sure it's correct,
one can use :
lvm dumpconfig --commandprofile/--metadataprofile ProfileName --validate
(the --commandprofile/--metadataprofile for dumpconfig will come
as part of the subsequent patch)
- This patch also adds a reference to --commandprofile and
--metadataprofile in the cmd help string (which was missing before
for the --profile for some commands). We do not mention --profile
now as people should use --commandprofile or --metadataprofile
directly. However, the --profile is still supported for backward
compatibility and it's translated as:
--profile == --metadataprofile for lvcreate, vgcreate, lvchange and vgchange
(as these commands are able to attach profile to metadata)
--profile == --commandprofile for all the other commands
(--metadataprofile is not allowed there as it makes no sense)
- This patch also contains some cleanups to make the code handling
the profiles more readable...
2014-05-20 16:13:10 +04:00
config_source_t source ;
const char * source_name ;
2015-02-09 16:16:24 +03:00
/* Check whether default global command profile is set via env. var. */
if ( ( env_cmd_profile_name = getenv ( COMMAND_PROFILE_ENV_VAR_NAME ) ) ) {
if ( ! * env_cmd_profile_name )
env_cmd_profile_name = NULL ;
else
log_debug ( " Command profile '%s' requested via "
" environment variable. " ,
env_cmd_profile_name ) ;
}
if ( ! arg_count ( cmd , profile_ARG ) & &
! arg_count ( cmd , commandprofile_ARG ) & &
! arg_count ( cmd , metadataprofile_ARG ) & &
! env_cmd_profile_name )
/* nothing to do */
return 1 ;
config: differentiate command and metadata profiles and consolidate profile handling code
- When defining configuration source, the code now uses separate
CONFIG_PROFILE_COMMAND and CONFIG_PROFILE_METADATA markers
(before, it was just CONFIG_PROFILE that did not make the
difference between the two). This helps when checking the
configuration if it contains correct set of options which
are all in either command-profilable or metadata-profilable
group without mixing these groups together - so it's a firm
distinction. The "command profile" can't contain
"metadata profile" and vice versa! This is strictly checked
and if the settings are mixed, such profile is rejected and
it's not used. So in the end, the CONFIG_PROFILE_COMMAND
set of options and CONFIG_PROFILE_METADATA are mutually exclusive
sets.
- Marking configuration with one or the other marker will also
determine the way these configuration sources are positioned
in the configuration cascade which is now:
CONFIG_STRING -> CONFIG_PROFILE_COMMAND -> CONFIG_PROFILE_METADATA -> CONFIG_FILE/CONFIG_MERGED_FILES
- Marking configuration with one or the other marker will also make
it possible to issue a command context refresh (will be probably
a part of a future patch) if needed for settings in global profile
set. For settings in metadata profile set this is impossible since
we can't refresh cmd context in the middle of reading VG/LV metadata
and for each VG/LV separately because each VG/LV can have a different
metadata profile assinged and it's not possible to change these
settings at this level.
- When command profile is incorrect, it's rejected *and also* the
command exits immediately - the profile *must* be correct for the
command that was run with a profile to be executed. Before this
patch, when the profile was found incorrect, there was just the
warning message and the command continued without profile applied.
But it's more correct to exit immediately in this case.
- When metadata profile is incorrect, we reject it during command
runtime (as we know the profile name from metadata and not early
from command line as it is in case of command profiles) and we
*do continue* with the command as we're in the middle of operation.
Also, the metadata profile is applied directly and on the fly on
find_config_tree_* fn call and even if the metadata profile is
found incorrect, we still need to return the non-profiled value
as found in the other configuration provided or default value.
To exit immediately even in this case, we'd need to refactor
existing find_config_tree_* fns so they can return error. Currently,
these fns return only config values (which end up with default
values in the end if the config is not found).
- To check the profile validity before use to be sure it's correct,
one can use :
lvm dumpconfig --commandprofile/--metadataprofile ProfileName --validate
(the --commandprofile/--metadataprofile for dumpconfig will come
as part of the subsequent patch)
- This patch also adds a reference to --commandprofile and
--metadataprofile in the cmd help string (which was missing before
for the --profile for some commands). We do not mention --profile
now as people should use --commandprofile or --metadataprofile
directly. However, the --profile is still supported for backward
compatibility and it's translated as:
--profile == --metadataprofile for lvcreate, vgcreate, lvchange and vgchange
(as these commands are able to attach profile to metadata)
--profile == --commandprofile for all the other commands
(--metadataprofile is not allowed there as it makes no sense)
- This patch also contains some cleanups to make the code handling
the profiles more readable...
2014-05-20 16:13:10 +04:00
if ( arg_count ( cmd , profile_ARG ) ) {
/*
* If - - profile is used with dumpconfig , it ' s used
* to dump the profile without the profile being applied .
*/
2015-04-28 19:00:37 +03:00
if ( ! strcmp ( cmd - > command - > name , " dumpconfig " ) | |
! strcmp ( cmd - > command - > name , " lvmconfig " ) | |
! strcmp ( cmd - > command - > name , " config " ) )
config: differentiate command and metadata profiles and consolidate profile handling code
- When defining configuration source, the code now uses separate
CONFIG_PROFILE_COMMAND and CONFIG_PROFILE_METADATA markers
(before, it was just CONFIG_PROFILE that did not make the
difference between the two). This helps when checking the
configuration if it contains correct set of options which
are all in either command-profilable or metadata-profilable
group without mixing these groups together - so it's a firm
distinction. The "command profile" can't contain
"metadata profile" and vice versa! This is strictly checked
and if the settings are mixed, such profile is rejected and
it's not used. So in the end, the CONFIG_PROFILE_COMMAND
set of options and CONFIG_PROFILE_METADATA are mutually exclusive
sets.
- Marking configuration with one or the other marker will also
determine the way these configuration sources are positioned
in the configuration cascade which is now:
CONFIG_STRING -> CONFIG_PROFILE_COMMAND -> CONFIG_PROFILE_METADATA -> CONFIG_FILE/CONFIG_MERGED_FILES
- Marking configuration with one or the other marker will also make
it possible to issue a command context refresh (will be probably
a part of a future patch) if needed for settings in global profile
set. For settings in metadata profile set this is impossible since
we can't refresh cmd context in the middle of reading VG/LV metadata
and for each VG/LV separately because each VG/LV can have a different
metadata profile assinged and it's not possible to change these
settings at this level.
- When command profile is incorrect, it's rejected *and also* the
command exits immediately - the profile *must* be correct for the
command that was run with a profile to be executed. Before this
patch, when the profile was found incorrect, there was just the
warning message and the command continued without profile applied.
But it's more correct to exit immediately in this case.
- When metadata profile is incorrect, we reject it during command
runtime (as we know the profile name from metadata and not early
from command line as it is in case of command profiles) and we
*do continue* with the command as we're in the middle of operation.
Also, the metadata profile is applied directly and on the fly on
find_config_tree_* fn call and even if the metadata profile is
found incorrect, we still need to return the non-profiled value
as found in the other configuration provided or default value.
To exit immediately even in this case, we'd need to refactor
existing find_config_tree_* fns so they can return error. Currently,
these fns return only config values (which end up with default
values in the end if the config is not found).
- To check the profile validity before use to be sure it's correct,
one can use :
lvm dumpconfig --commandprofile/--metadataprofile ProfileName --validate
(the --commandprofile/--metadataprofile for dumpconfig will come
as part of the subsequent patch)
- This patch also adds a reference to --commandprofile and
--metadataprofile in the cmd help string (which was missing before
for the --profile for some commands). We do not mention --profile
now as people should use --commandprofile or --metadataprofile
directly. However, the --profile is still supported for backward
compatibility and it's translated as:
--profile == --metadataprofile for lvcreate, vgcreate, lvchange and vgchange
(as these commands are able to attach profile to metadata)
--profile == --commandprofile for all the other commands
(--metadataprofile is not allowed there as it makes no sense)
- This patch also contains some cleanups to make the code handling
the profiles more readable...
2014-05-20 16:13:10 +04:00
return 1 ;
/*
* If - - profile is used with lvcreate / lvchange / vgchange ,
* it ' s recognized as shortcut to - - metadataprofile .
* The - - commandprofile is assumed otherwise .
*/
if ( ! strcmp ( cmd - > command - > name , " lvcreate " ) | |
! strcmp ( cmd - > command - > name , " vgcreate " ) | |
! strcmp ( cmd - > command - > name , " lvchange " ) | |
! strcmp ( cmd - > command - > name , " vgchange " ) ) {
if ( arg_count ( cmd , metadataprofile_ARG ) ) {
log_error ( " Only one of --profile or "
" --metadataprofile allowed. " ) ;
return 0 ;
}
source = CONFIG_PROFILE_METADATA ;
source_name = _metadata_profile_source_name ;
}
else {
if ( arg_count ( cmd , commandprofile_ARG ) ) {
log_error ( " Only one of --profile or "
" --commandprofile allowed. " ) ;
return 0 ;
}
2015-02-09 16:16:24 +03:00
/*
* Prefer command profile specified on command
* line over the profile specified via
* COMMAND_PROFILE_ENV_VAR_NAME env . var .
*/
if ( env_cmd_profile_name ) {
log_debug ( _cmd_profile_arg_preferred_over_env_var_msg ) ;
env_cmd_profile_name = NULL ;
}
config: differentiate command and metadata profiles and consolidate profile handling code
- When defining configuration source, the code now uses separate
CONFIG_PROFILE_COMMAND and CONFIG_PROFILE_METADATA markers
(before, it was just CONFIG_PROFILE that did not make the
difference between the two). This helps when checking the
configuration if it contains correct set of options which
are all in either command-profilable or metadata-profilable
group without mixing these groups together - so it's a firm
distinction. The "command profile" can't contain
"metadata profile" and vice versa! This is strictly checked
and if the settings are mixed, such profile is rejected and
it's not used. So in the end, the CONFIG_PROFILE_COMMAND
set of options and CONFIG_PROFILE_METADATA are mutually exclusive
sets.
- Marking configuration with one or the other marker will also
determine the way these configuration sources are positioned
in the configuration cascade which is now:
CONFIG_STRING -> CONFIG_PROFILE_COMMAND -> CONFIG_PROFILE_METADATA -> CONFIG_FILE/CONFIG_MERGED_FILES
- Marking configuration with one or the other marker will also make
it possible to issue a command context refresh (will be probably
a part of a future patch) if needed for settings in global profile
set. For settings in metadata profile set this is impossible since
we can't refresh cmd context in the middle of reading VG/LV metadata
and for each VG/LV separately because each VG/LV can have a different
metadata profile assinged and it's not possible to change these
settings at this level.
- When command profile is incorrect, it's rejected *and also* the
command exits immediately - the profile *must* be correct for the
command that was run with a profile to be executed. Before this
patch, when the profile was found incorrect, there was just the
warning message and the command continued without profile applied.
But it's more correct to exit immediately in this case.
- When metadata profile is incorrect, we reject it during command
runtime (as we know the profile name from metadata and not early
from command line as it is in case of command profiles) and we
*do continue* with the command as we're in the middle of operation.
Also, the metadata profile is applied directly and on the fly on
find_config_tree_* fn call and even if the metadata profile is
found incorrect, we still need to return the non-profiled value
as found in the other configuration provided or default value.
To exit immediately even in this case, we'd need to refactor
existing find_config_tree_* fns so they can return error. Currently,
these fns return only config values (which end up with default
values in the end if the config is not found).
- To check the profile validity before use to be sure it's correct,
one can use :
lvm dumpconfig --commandprofile/--metadataprofile ProfileName --validate
(the --commandprofile/--metadataprofile for dumpconfig will come
as part of the subsequent patch)
- This patch also adds a reference to --commandprofile and
--metadataprofile in the cmd help string (which was missing before
for the --profile for some commands). We do not mention --profile
now as people should use --commandprofile or --metadataprofile
directly. However, the --profile is still supported for backward
compatibility and it's translated as:
--profile == --metadataprofile for lvcreate, vgcreate, lvchange and vgchange
(as these commands are able to attach profile to metadata)
--profile == --commandprofile for all the other commands
(--metadataprofile is not allowed there as it makes no sense)
- This patch also contains some cleanups to make the code handling
the profiles more readable...
2014-05-20 16:13:10 +04:00
source = CONFIG_PROFILE_COMMAND ;
source_name = _command_profile_source_name ;
}
name = arg_str_value ( cmd , profile_ARG , NULL ) ;
if ( ! ( profile = add_profile ( cmd , name , source ) ) ) {
log_error ( _failed_to_add_profile_msg , source_name , name ) ;
return 0 ;
}
if ( source = = CONFIG_PROFILE_COMMAND ) {
log_debug ( _setting_global_profile_msg , _command_profile_source_name , profile - > name ) ;
cmd - > profile_params - > global_command_profile = profile ;
} else if ( source = = CONFIG_PROFILE_METADATA ) {
log_debug ( _setting_global_profile_msg , _metadata_profile_source_name , profile - > name ) ;
/* This profile will override any VG/LV-based profile if present */
cmd - > profile_params - > global_metadata_profile = profile ;
}
if ( ! override_config_tree_from_profile ( cmd , profile ) ) {
log_error ( _failed_to_apply_profile_msg , source_name , name ) ;
return 0 ;
}
}
2015-02-09 16:16:24 +03:00
if ( arg_count ( cmd , commandprofile_ARG ) | | env_cmd_profile_name ) {
if ( arg_count ( cmd , commandprofile_ARG ) ) {
/*
* Prefer command profile specified on command
* line over the profile specified via
* COMMAND_PROFILE_ENV_VAR_NAME env . var .
*/
if ( env_cmd_profile_name )
log_debug ( _cmd_profile_arg_preferred_over_env_var_msg ) ;
name = arg_str_value ( cmd , commandprofile_ARG , NULL ) ;
} else
name = env_cmd_profile_name ;
config: differentiate command and metadata profiles and consolidate profile handling code
- When defining configuration source, the code now uses separate
CONFIG_PROFILE_COMMAND and CONFIG_PROFILE_METADATA markers
(before, it was just CONFIG_PROFILE that did not make the
difference between the two). This helps when checking the
configuration if it contains correct set of options which
are all in either command-profilable or metadata-profilable
group without mixing these groups together - so it's a firm
distinction. The "command profile" can't contain
"metadata profile" and vice versa! This is strictly checked
and if the settings are mixed, such profile is rejected and
it's not used. So in the end, the CONFIG_PROFILE_COMMAND
set of options and CONFIG_PROFILE_METADATA are mutually exclusive
sets.
- Marking configuration with one or the other marker will also
determine the way these configuration sources are positioned
in the configuration cascade which is now:
CONFIG_STRING -> CONFIG_PROFILE_COMMAND -> CONFIG_PROFILE_METADATA -> CONFIG_FILE/CONFIG_MERGED_FILES
- Marking configuration with one or the other marker will also make
it possible to issue a command context refresh (will be probably
a part of a future patch) if needed for settings in global profile
set. For settings in metadata profile set this is impossible since
we can't refresh cmd context in the middle of reading VG/LV metadata
and for each VG/LV separately because each VG/LV can have a different
metadata profile assinged and it's not possible to change these
settings at this level.
- When command profile is incorrect, it's rejected *and also* the
command exits immediately - the profile *must* be correct for the
command that was run with a profile to be executed. Before this
patch, when the profile was found incorrect, there was just the
warning message and the command continued without profile applied.
But it's more correct to exit immediately in this case.
- When metadata profile is incorrect, we reject it during command
runtime (as we know the profile name from metadata and not early
from command line as it is in case of command profiles) and we
*do continue* with the command as we're in the middle of operation.
Also, the metadata profile is applied directly and on the fly on
find_config_tree_* fn call and even if the metadata profile is
found incorrect, we still need to return the non-profiled value
as found in the other configuration provided or default value.
To exit immediately even in this case, we'd need to refactor
existing find_config_tree_* fns so they can return error. Currently,
these fns return only config values (which end up with default
values in the end if the config is not found).
- To check the profile validity before use to be sure it's correct,
one can use :
lvm dumpconfig --commandprofile/--metadataprofile ProfileName --validate
(the --commandprofile/--metadataprofile for dumpconfig will come
as part of the subsequent patch)
- This patch also adds a reference to --commandprofile and
--metadataprofile in the cmd help string (which was missing before
for the --profile for some commands). We do not mention --profile
now as people should use --commandprofile or --metadataprofile
directly. However, the --profile is still supported for backward
compatibility and it's translated as:
--profile == --metadataprofile for lvcreate, vgcreate, lvchange and vgchange
(as these commands are able to attach profile to metadata)
--profile == --commandprofile for all the other commands
(--metadataprofile is not allowed there as it makes no sense)
- This patch also contains some cleanups to make the code handling
the profiles more readable...
2014-05-20 16:13:10 +04:00
source_name = _command_profile_source_name ;
if ( ! ( profile = add_profile ( cmd , name , CONFIG_PROFILE_COMMAND ) ) ) {
log_error ( _failed_to_add_profile_msg , source_name , name ) ;
return 0 ;
}
if ( ! override_config_tree_from_profile ( cmd , profile ) ) {
log_error ( _failed_to_apply_profile_msg , source_name , name ) ;
return 0 ;
}
log_debug ( _setting_global_profile_msg , _command_profile_source_name , profile - > name ) ;
cmd - > profile_params - > global_command_profile = profile ;
}
if ( arg_count ( cmd , metadataprofile_ARG ) ) {
name = arg_str_value ( cmd , metadataprofile_ARG , NULL ) ;
source_name = _metadata_profile_source_name ;
if ( ! ( profile = add_profile ( cmd , name , CONFIG_PROFILE_METADATA ) ) ) {
log_error ( _failed_to_add_profile_msg , source_name , name ) ;
return 0 ;
}
if ( ! override_config_tree_from_profile ( cmd , profile ) ) {
log_error ( _failed_to_apply_profile_msg , source_name , name ) ;
return 0 ;
}
log_debug ( _setting_global_profile_msg , _metadata_profile_source_name , profile - > name ) ;
cmd - > profile_params - > global_metadata_profile = profile ;
}
if ( ! process_profilable_config ( cmd ) )
return_0 ;
return 1 ;
}
2015-03-05 23:00:44 +03:00
static int _init_lvmlockd ( struct cmd_context * cmd )
{
const char * lvmlockd_socket ;
int use_lvmlockd = find_config_tree_bool ( cmd , global_use_lvmlockd_CFG , NULL ) ;
lockd: allow nolocking and readonly options
When --nolocking is used (by vgs, lvs, pvs):
. don't use lvmlockd at all (set use_lvmlockd to 0)
. allow lockd VGs to be read
When --readonly is used (by vgs, lvs, pvs, vgdisplay, lvdisplay,
pvdisplay, lvmdiskscan, lvscan, pvscan, vgcfgbackup):
. skip actual lvmlockd locking calls
. allow lockd VGs to be read
. check that only shared gl/vg locks are being requested
(even though the actually locking is being skipped)
. check that no LV locks are requested, because no LVs
should be activated or used in readonly mode
. disable using lvmetad so VGs are read from disk
It is important to note the limited commands that accept
the --nolocking and --readonly options, i.e. no commands
that change/write a VG or change/activate LVs accept these
options, only commands that read VGs.
2015-07-11 01:20:22 +03:00
if ( use_lvmlockd & & arg_count ( cmd , nolocking_ARG ) ) {
/* --nolocking is only allowed with vgs/lvs/pvs commands */
cmd - > lockd_gl_disable = 1 ;
cmd - > lockd_vg_disable = 1 ;
cmd - > lockd_lv_disable = 1 ;
return 1 ;
}
2015-03-05 23:00:44 +03:00
if ( use_lvmlockd & & locking_is_clustered ( ) ) {
log_error ( " ERROR: configuration setting use_lvmlockd cannot be used with clustered locking_type 3. " ) ;
return 0 ;
}
lvmlockd_disconnect ( ) ; /* start over when tool context is refreshed */
lvmlockd_socket = getenv ( " LVM_LVMLOCKD_SOCKET " ) ;
if ( ! lvmlockd_socket )
lvmlockd_socket = DEFAULT_RUN_DIR " /lvmlockd.socket " ;
lvmlockd_set_socket ( lvmlockd_socket ) ;
lvmlockd_set_use ( use_lvmlockd ) ;
if ( use_lvmlockd ) {
lvmlockd_init ( cmd ) ;
lvmlockd_connect ( ) ;
}
return 1 ;
}
commands: add new NO_METADATA_PROCESSING flag to selected commands
When a command is flagged with NO_METADATA_PROCESSING flag, it means
such command does not process any metadata and hence it doens't require
lvmetad, lvmpolld and it can get away with no locking too. These are
mostly simple commands (like lvmconfig/dumpconfig, version, types,
segtypes and other builtin commands that do not process metadata
in any way).
At first, when lvm command is executed, create toolcontext without
initializing connections (lvmetad,lvmpolld) and without initializing
filters (which depend on connections init). Instead, delay this
initialization until we know we need this. That is, until the
lvm_run_command fn is called in which we know what the actual
command to run is and hence we can avoid any connection, filter
or locking initiliazation for commands that would not make use
of it anyway.
For all the other create_toolcontext calls, we keep the original
behaviour - the filters and connections are initialized together
with the toolcontext.
2015-07-30 11:48:28 +03:00
static int _cmd_no_meta_proc ( struct cmd_context * cmd )
{
return cmd - > command - > flags & NO_METADATA_PROCESSING ;
}
config: differentiate command and metadata profiles and consolidate profile handling code
- When defining configuration source, the code now uses separate
CONFIG_PROFILE_COMMAND and CONFIG_PROFILE_METADATA markers
(before, it was just CONFIG_PROFILE that did not make the
difference between the two). This helps when checking the
configuration if it contains correct set of options which
are all in either command-profilable or metadata-profilable
group without mixing these groups together - so it's a firm
distinction. The "command profile" can't contain
"metadata profile" and vice versa! This is strictly checked
and if the settings are mixed, such profile is rejected and
it's not used. So in the end, the CONFIG_PROFILE_COMMAND
set of options and CONFIG_PROFILE_METADATA are mutually exclusive
sets.
- Marking configuration with one or the other marker will also
determine the way these configuration sources are positioned
in the configuration cascade which is now:
CONFIG_STRING -> CONFIG_PROFILE_COMMAND -> CONFIG_PROFILE_METADATA -> CONFIG_FILE/CONFIG_MERGED_FILES
- Marking configuration with one or the other marker will also make
it possible to issue a command context refresh (will be probably
a part of a future patch) if needed for settings in global profile
set. For settings in metadata profile set this is impossible since
we can't refresh cmd context in the middle of reading VG/LV metadata
and for each VG/LV separately because each VG/LV can have a different
metadata profile assinged and it's not possible to change these
settings at this level.
- When command profile is incorrect, it's rejected *and also* the
command exits immediately - the profile *must* be correct for the
command that was run with a profile to be executed. Before this
patch, when the profile was found incorrect, there was just the
warning message and the command continued without profile applied.
But it's more correct to exit immediately in this case.
- When metadata profile is incorrect, we reject it during command
runtime (as we know the profile name from metadata and not early
from command line as it is in case of command profiles) and we
*do continue* with the command as we're in the middle of operation.
Also, the metadata profile is applied directly and on the fly on
find_config_tree_* fn call and even if the metadata profile is
found incorrect, we still need to return the non-profiled value
as found in the other configuration provided or default value.
To exit immediately even in this case, we'd need to refactor
existing find_config_tree_* fns so they can return error. Currently,
these fns return only config values (which end up with default
values in the end if the config is not found).
- To check the profile validity before use to be sure it's correct,
one can use :
lvm dumpconfig --commandprofile/--metadataprofile ProfileName --validate
(the --commandprofile/--metadataprofile for dumpconfig will come
as part of the subsequent patch)
- This patch also adds a reference to --commandprofile and
--metadataprofile in the cmd help string (which was missing before
for the --profile for some commands). We do not mention --profile
now as people should use --commandprofile or --metadataprofile
directly. However, the --profile is still supported for backward
compatibility and it's translated as:
--profile == --metadataprofile for lvcreate, vgcreate, lvchange and vgchange
(as these commands are able to attach profile to metadata)
--profile == --commandprofile for all the other commands
(--metadataprofile is not allowed there as it makes no sense)
- This patch also contains some cleanups to make the code handling
the profiles more readable...
2014-05-20 16:13:10 +04:00
int lvm_run_command ( struct cmd_context * cmd , int argc , char * * argv )
{
struct dm_config_tree * config_string_cft ;
struct dm_config_tree * config_profile_command_cft , * config_profile_metadata_cft ;
2004-03-26 15:00:24 +03:00
int ret = 0 ;
int locking_type ;
2012-02-15 19:18:43 +04:00
int monitoring ;
2015-07-24 21:45:49 +03:00
char * arg_new , * arg ;
int i ;
int skip_hyphens ;
2015-09-10 17:00:14 +03:00
int refresh_done = 0 ;
2004-03-26 15:00:24 +03:00
2008-06-06 23:28:35 +04:00
init_error_message_produced ( 0 ) ;
2007-06-15 14:11:14 +04:00
/* each command should start out with sigint flag cleared */
sigint_clear ( ) ;
2015-06-19 10:44:14 +03:00
/* eliminate '-' from all options starting with -- */
2015-07-24 18:25:13 +03:00
for ( i = 1 ; i < argc ; i + + ) {
2015-07-24 21:45:49 +03:00
2015-07-24 18:25:13 +03:00
arg = argv [ i ] ;
2015-06-19 10:44:14 +03:00
2015-07-24 21:45:49 +03:00
if ( * arg + + ! = ' - ' | | * arg + + ! = ' - ' )
continue ;
/* If we reach "--" then stop. */
if ( ! * arg )
2015-07-24 18:25:13 +03:00
break ;
2015-06-19 10:44:14 +03:00
2015-07-24 21:45:49 +03:00
arg_new = arg ;
skip_hyphens = 1 ;
while ( * arg ) {
/* If we encounter '=', stop any further hyphen removal. */
if ( * arg = = ' = ' )
skip_hyphens = 0 ;
/* Do we need to keep the next character? */
if ( * arg ! = ' - ' | | ! skip_hyphens ) {
if ( arg_new ! = arg )
* arg_new = * arg ;
+ + arg_new ;
2015-06-19 10:44:14 +03:00
}
2015-07-24 21:45:49 +03:00
arg + + ;
2015-07-24 18:25:13 +03:00
}
2015-07-24 21:45:49 +03:00
/* Terminate a shortened arg */
if ( arg_new ! = arg )
* arg_new = ' \0 ' ;
2015-06-19 10:44:14 +03:00
}
2013-07-01 13:27:22 +04:00
if ( ! ( cmd - > cmd_line = _copy_command_line ( cmd , argc , argv ) ) )
return_ECMD_FAILED ;
2004-03-26 15:00:24 +03:00
2004-12-10 19:01:35 +03:00
log_debug ( " Parsing: %s " , cmd - > cmd_line ) ;
2004-03-26 15:00:24 +03:00
if ( ! ( cmd - > command = _find_command ( argv [ 0 ] ) ) )
return ENO_SUCH_CMD ;
if ( ! _process_command_line ( cmd , & argc , & argv ) ) {
log_error ( " Error during parsing of command line. " ) ;
return EINVALID_CMD_LINE ;
}
set_cmd_name ( cmd - > command - > name ) ;
2013-09-06 04:43:24 +04:00
if ( arg_count ( cmd , backgroundfork_ARG ) ) {
2013-09-03 18:06:16 +04:00
if ( ! become_daemon ( cmd , 1 ) ) {
/* parent - quit immediately */
ret = ECMD_PROCESSED ;
goto out ;
}
}
2006-05-16 20:48:31 +04:00
if ( arg_count ( cmd , config_ARG ) )
2012-10-16 12:07:27 +04:00
if ( ! override_config_tree_from_string ( cmd , arg_str_value ( cmd , config_ARG , " " ) ) ) {
2009-07-28 01:01:56 +04:00
ret = EINVALID_CMD_LINE ;
2006-05-16 20:48:31 +04:00
goto_out ;
2009-07-28 01:01:56 +04:00
}
2006-05-16 20:48:31 +04:00
2015-07-30 10:59:39 +03:00
if ( arg_count ( cmd , config_ARG ) | | ! cmd - > initialized . config | | config_files_changed ( cmd ) ) {
2004-03-26 15:00:24 +03:00
/* Reinitialise various settings inc. logging, filters */
if ( ! refresh_toolcontext ( cmd ) ) {
2014-05-19 15:59:23 +04:00
if ( ( config_string_cft = remove_config_tree_by_source ( cmd , CONFIG_STRING ) ) )
dm_config_destroy ( config_string_cft ) ;
2004-03-26 15:00:24 +03:00
log_error ( " Updated config file invalid. Aborting. " ) ;
return ECMD_FAILED ;
}
2015-09-10 17:00:14 +03:00
refresh_done = 1 ;
2004-03-26 15:00:24 +03:00
}
2015-02-09 16:16:24 +03:00
if ( ! _prepare_profiles ( cmd ) )
return_ECMD_FAILED ;
2013-06-25 14:27:04 +04:00
commands: add new NO_METADATA_PROCESSING flag to selected commands
When a command is flagged with NO_METADATA_PROCESSING flag, it means
such command does not process any metadata and hence it doens't require
lvmetad, lvmpolld and it can get away with no locking too. These are
mostly simple commands (like lvmconfig/dumpconfig, version, types,
segtypes and other builtin commands that do not process metadata
in any way).
At first, when lvm command is executed, create toolcontext without
initializing connections (lvmetad,lvmpolld) and without initializing
filters (which depend on connections init). Instead, delay this
initialization until we know we need this. That is, until the
lvm_run_command fn is called in which we know what the actual
command to run is and hence we can avoid any connection, filter
or locking initiliazation for commands that would not make use
of it anyway.
For all the other create_toolcontext calls, we keep the original
behaviour - the filters and connections are initialized together
with the toolcontext.
2015-07-30 11:48:28 +03:00
if ( ! cmd - > initialized . connections & & ! _cmd_no_meta_proc ( cmd ) & & ! init_connections ( cmd ) )
return_ECMD_FAILED ;
2015-09-10 17:00:14 +03:00
/* Note: Load persistent cache only if we haven't refreshed toolcontext!
* If toolcontext has been refreshed , it means config has changed
* and we can ' t rely on persistent cache anymore .
*/
if ( ! cmd - > initialized . filters & & ! _cmd_no_meta_proc ( cmd ) & & ! init_filters ( cmd , ! refresh_done ) )
commands: add new NO_METADATA_PROCESSING flag to selected commands
When a command is flagged with NO_METADATA_PROCESSING flag, it means
such command does not process any metadata and hence it doens't require
lvmetad, lvmpolld and it can get away with no locking too. These are
mostly simple commands (like lvmconfig/dumpconfig, version, types,
segtypes and other builtin commands that do not process metadata
in any way).
At first, when lvm command is executed, create toolcontext without
initializing connections (lvmetad,lvmpolld) and without initializing
filters (which depend on connections init). Instead, delay this
initialization until we know we need this. That is, until the
lvm_run_command fn is called in which we know what the actual
command to run is and hence we can avoid any connection, filter
or locking initiliazation for commands that would not make use
of it anyway.
For all the other create_toolcontext calls, we keep the original
behaviour - the filters and connections are initialized together
with the toolcontext.
2015-07-30 11:48:28 +03:00
return_ECMD_FAILED ;
2014-04-18 05:46:34 +04:00
if ( arg_count ( cmd , readonly_ARG ) )
cmd - > metadata_read_only = 1 ;
2004-03-26 15:00:24 +03:00
if ( ( ret = _get_settings ( cmd ) ) )
2006-05-16 20:48:31 +04:00
goto_out ;
2004-03-26 15:00:24 +03:00
_apply_settings ( cmd ) ;
2014-07-22 23:50:29 +04:00
if ( cmd - > degraded_activation )
2014-09-10 12:10:13 +04:00
log_debug ( " DEGRADED MODE. Incomplete RAID LVs will be processed. " ) ;
2004-03-26 15:00:24 +03:00
2012-02-15 19:18:43 +04:00
if ( ! get_activation_monitoring_mode ( cmd , & monitoring ) )
goto_out ;
init_dmeventd_monitor ( monitoring ) ;
2004-12-10 19:01:35 +03:00
log_debug ( " Processing: %s " , cmd - > cmd_line ) ;
2015-02-27 22:32:00 +03:00
log_debug ( " system ID: %s " , cmd - > system_id ? : " " ) ;
2004-12-10 19:01:35 +03:00
# ifdef O_DIRECT_SUPPORT
log_debug ( " O_DIRECT will be used " ) ;
# endif
2011-01-13 18:00:29 +03:00
if ( ( ret = _process_common_commands ( cmd ) ) ) {
if ( ret ! = ECMD_PROCESSED )
stack ;
goto out ;
}
2004-03-26 15:00:24 +03:00
2010-10-25 15:20:54 +04:00
if ( cmd - > metadata_read_only & &
! ( cmd - > command - > flags & PERMITTED_READ_ONLY ) ) {
log_error ( " %s: Command not permitted while global/metadata_read_only "
" is set. " , cmd - > cmd_line ) ;
goto out ;
}
commands: add new NO_METADATA_PROCESSING flag to selected commands
When a command is flagged with NO_METADATA_PROCESSING flag, it means
such command does not process any metadata and hence it doens't require
lvmetad, lvmpolld and it can get away with no locking too. These are
mostly simple commands (like lvmconfig/dumpconfig, version, types,
segtypes and other builtin commands that do not process metadata
in any way).
At first, when lvm command is executed, create toolcontext without
initializing connections (lvmetad,lvmpolld) and without initializing
filters (which depend on connections init). Instead, delay this
initialization until we know we need this. That is, until the
lvm_run_command fn is called in which we know what the actual
command to run is and hence we can avoid any connection, filter
or locking initiliazation for commands that would not make use
of it anyway.
For all the other create_toolcontext calls, we keep the original
behaviour - the filters and connections are initialized together
with the toolcontext.
2015-07-30 11:48:28 +03:00
if ( _cmd_no_meta_proc ( cmd ) )
locking_type = 0 ;
else if ( arg_count ( cmd , readonly_ARG ) ) {
lockd: allow nolocking and readonly options
When --nolocking is used (by vgs, lvs, pvs):
. don't use lvmlockd at all (set use_lvmlockd to 0)
. allow lockd VGs to be read
When --readonly is used (by vgs, lvs, pvs, vgdisplay, lvdisplay,
pvdisplay, lvmdiskscan, lvscan, pvscan, vgcfgbackup):
. skip actual lvmlockd locking calls
. allow lockd VGs to be read
. check that only shared gl/vg locks are being requested
(even though the actually locking is being skipped)
. check that no LV locks are requested, because no LVs
should be activated or used in readonly mode
. disable using lvmetad so VGs are read from disk
It is important to note the limited commands that accept
the --nolocking and --readonly options, i.e. no commands
that change/write a VG or change/activate LVs accept these
options, only commands that read VGs.
2015-07-11 01:20:22 +03:00
if ( find_config_tree_bool ( cmd , global_use_lvmlockd_CFG , NULL ) ) {
/*
* FIXME : we could use locking_type 5 here if that didn ' t
* cause CLUSTERED to be set , which conflicts with using lvmlockd .
*/
locking_type = 1 ;
cmd - > lockd_gl_disable = 1 ;
cmd - > lockd_vg_disable = 1 ;
cmd - > lockd_lv_disable = 1 ;
} else {
locking_type = 5 ;
}
2014-04-18 05:46:34 +04:00
if ( lvmetad_used ( ) ) {
2014-09-30 18:08:05 +04:00
lvmetad_set_active ( cmd , 0 ) ;
2014-04-18 05:46:34 +04:00
log_verbose ( " Disabling use of lvmetad because read-only is set. " ) ;
}
} else if ( arg_count ( cmd , nolocking_ARG ) )
2004-03-26 15:09:33 +03:00
locking_type = 0 ;
else
2009-02-03 19:23:19 +03:00
locking_type = - 1 ;
2004-03-26 15:09:33 +03:00
commands: add new NO_METADATA_PROCESSING flag to selected commands
When a command is flagged with NO_METADATA_PROCESSING flag, it means
such command does not process any metadata and hence it doens't require
lvmetad, lvmpolld and it can get away with no locking too. These are
mostly simple commands (like lvmconfig/dumpconfig, version, types,
segtypes and other builtin commands that do not process metadata
in any way).
At first, when lvm command is executed, create toolcontext without
initializing connections (lvmetad,lvmpolld) and without initializing
filters (which depend on connections init). Instead, delay this
initialization until we know we need this. That is, until the
lvm_run_command fn is called in which we know what the actual
command to run is and hence we can avoid any connection, filter
or locking initiliazation for commands that would not make use
of it anyway.
For all the other create_toolcontext calls, we keep the original
behaviour - the filters and connections are initialized together
with the toolcontext.
2015-07-30 11:48:28 +03:00
if ( ! init_locking ( locking_type , cmd , _cmd_no_meta_proc ( cmd ) | | arg_count ( cmd , sysinit_ARG ) ) ) {
2004-03-26 15:00:24 +03:00
ret = ECMD_FAILED ;
2013-07-01 13:27:11 +04:00
goto_out ;
2004-03-26 15:00:24 +03:00
}
commands: add new NO_METADATA_PROCESSING flag to selected commands
When a command is flagged with NO_METADATA_PROCESSING flag, it means
such command does not process any metadata and hence it doens't require
lvmetad, lvmpolld and it can get away with no locking too. These are
mostly simple commands (like lvmconfig/dumpconfig, version, types,
segtypes and other builtin commands that do not process metadata
in any way).
At first, when lvm command is executed, create toolcontext without
initializing connections (lvmetad,lvmpolld) and without initializing
filters (which depend on connections init). Instead, delay this
initialization until we know we need this. That is, until the
lvm_run_command fn is called in which we know what the actual
command to run is and hence we can avoid any connection, filter
or locking initiliazation for commands that would not make use
of it anyway.
For all the other create_toolcontext calls, we keep the original
behaviour - the filters and connections are initialized together
with the toolcontext.
2015-07-30 11:48:28 +03:00
if ( ! _cmd_no_meta_proc ( cmd ) & & ! _init_lvmlockd ( cmd ) ) {
2015-03-05 23:00:44 +03:00
ret = ECMD_FAILED ;
goto_out ;
}
2015-02-24 02:41:38 +03:00
/*
* Other hosts might have changed foreign VGs so enforce a rescan
* before processing any command using them .
*/
if ( cmd - > include_foreign_vgs & & lvmetad_used ( ) & &
! lvmetad_pvscan_foreign_vgs ( cmd , NULL ) ) {
log_error ( " Failed to scan devices. " ) ;
return ECMD_FAILED ;
}
/*
* FIXME Break up into multiple functions .
*/
2004-03-26 15:00:24 +03:00
ret = cmd - > command - > fn ( cmd , argc , argv ) ;
2015-03-05 23:00:44 +03:00
lvmlockd_disconnect ( ) ;
2004-03-26 15:00:24 +03:00
fin_locking ( ) ;
out :
if ( test_mode ( ) ) {
log_verbose ( " Test mode: Wiping internal cache " ) ;
2014-03-22 01:26:39 +04:00
lvmcache_destroy ( cmd , 1 , 0 ) ;
2004-03-26 15:00:24 +03:00
}
2014-05-19 15:59:23 +04:00
if ( ( config_string_cft = remove_config_tree_by_source ( cmd , CONFIG_STRING ) ) )
dm_config_destroy ( config_string_cft ) ;
config: differentiate command and metadata profiles and consolidate profile handling code
- When defining configuration source, the code now uses separate
CONFIG_PROFILE_COMMAND and CONFIG_PROFILE_METADATA markers
(before, it was just CONFIG_PROFILE that did not make the
difference between the two). This helps when checking the
configuration if it contains correct set of options which
are all in either command-profilable or metadata-profilable
group without mixing these groups together - so it's a firm
distinction. The "command profile" can't contain
"metadata profile" and vice versa! This is strictly checked
and if the settings are mixed, such profile is rejected and
it's not used. So in the end, the CONFIG_PROFILE_COMMAND
set of options and CONFIG_PROFILE_METADATA are mutually exclusive
sets.
- Marking configuration with one or the other marker will also
determine the way these configuration sources are positioned
in the configuration cascade which is now:
CONFIG_STRING -> CONFIG_PROFILE_COMMAND -> CONFIG_PROFILE_METADATA -> CONFIG_FILE/CONFIG_MERGED_FILES
- Marking configuration with one or the other marker will also make
it possible to issue a command context refresh (will be probably
a part of a future patch) if needed for settings in global profile
set. For settings in metadata profile set this is impossible since
we can't refresh cmd context in the middle of reading VG/LV metadata
and for each VG/LV separately because each VG/LV can have a different
metadata profile assinged and it's not possible to change these
settings at this level.
- When command profile is incorrect, it's rejected *and also* the
command exits immediately - the profile *must* be correct for the
command that was run with a profile to be executed. Before this
patch, when the profile was found incorrect, there was just the
warning message and the command continued without profile applied.
But it's more correct to exit immediately in this case.
- When metadata profile is incorrect, we reject it during command
runtime (as we know the profile name from metadata and not early
from command line as it is in case of command profiles) and we
*do continue* with the command as we're in the middle of operation.
Also, the metadata profile is applied directly and on the fly on
find_config_tree_* fn call and even if the metadata profile is
found incorrect, we still need to return the non-profiled value
as found in the other configuration provided or default value.
To exit immediately even in this case, we'd need to refactor
existing find_config_tree_* fns so they can return error. Currently,
these fns return only config values (which end up with default
values in the end if the config is not found).
- To check the profile validity before use to be sure it's correct,
one can use :
lvm dumpconfig --commandprofile/--metadataprofile ProfileName --validate
(the --commandprofile/--metadataprofile for dumpconfig will come
as part of the subsequent patch)
- This patch also adds a reference to --commandprofile and
--metadataprofile in the cmd help string (which was missing before
for the --profile for some commands). We do not mention --profile
now as people should use --commandprofile or --metadataprofile
directly. However, the --profile is still supported for backward
compatibility and it's translated as:
--profile == --metadataprofile for lvcreate, vgcreate, lvchange and vgchange
(as these commands are able to attach profile to metadata)
--profile == --commandprofile for all the other commands
(--metadataprofile is not allowed there as it makes no sense)
- This patch also contains some cleanups to make the code handling
the profiles more readable...
2014-05-20 16:13:10 +04:00
config_profile_command_cft = remove_config_tree_by_source ( cmd , CONFIG_PROFILE_COMMAND ) ;
config_profile_metadata_cft = remove_config_tree_by_source ( cmd , CONFIG_PROFILE_METADATA ) ;
cmd - > profile_params - > global_metadata_profile = NULL ;
2014-05-19 15:59:23 +04:00
config: differentiate command and metadata profiles and consolidate profile handling code
- When defining configuration source, the code now uses separate
CONFIG_PROFILE_COMMAND and CONFIG_PROFILE_METADATA markers
(before, it was just CONFIG_PROFILE that did not make the
difference between the two). This helps when checking the
configuration if it contains correct set of options which
are all in either command-profilable or metadata-profilable
group without mixing these groups together - so it's a firm
distinction. The "command profile" can't contain
"metadata profile" and vice versa! This is strictly checked
and if the settings are mixed, such profile is rejected and
it's not used. So in the end, the CONFIG_PROFILE_COMMAND
set of options and CONFIG_PROFILE_METADATA are mutually exclusive
sets.
- Marking configuration with one or the other marker will also
determine the way these configuration sources are positioned
in the configuration cascade which is now:
CONFIG_STRING -> CONFIG_PROFILE_COMMAND -> CONFIG_PROFILE_METADATA -> CONFIG_FILE/CONFIG_MERGED_FILES
- Marking configuration with one or the other marker will also make
it possible to issue a command context refresh (will be probably
a part of a future patch) if needed for settings in global profile
set. For settings in metadata profile set this is impossible since
we can't refresh cmd context in the middle of reading VG/LV metadata
and for each VG/LV separately because each VG/LV can have a different
metadata profile assinged and it's not possible to change these
settings at this level.
- When command profile is incorrect, it's rejected *and also* the
command exits immediately - the profile *must* be correct for the
command that was run with a profile to be executed. Before this
patch, when the profile was found incorrect, there was just the
warning message and the command continued without profile applied.
But it's more correct to exit immediately in this case.
- When metadata profile is incorrect, we reject it during command
runtime (as we know the profile name from metadata and not early
from command line as it is in case of command profiles) and we
*do continue* with the command as we're in the middle of operation.
Also, the metadata profile is applied directly and on the fly on
find_config_tree_* fn call and even if the metadata profile is
found incorrect, we still need to return the non-profiled value
as found in the other configuration provided or default value.
To exit immediately even in this case, we'd need to refactor
existing find_config_tree_* fns so they can return error. Currently,
these fns return only config values (which end up with default
values in the end if the config is not found).
- To check the profile validity before use to be sure it's correct,
one can use :
lvm dumpconfig --commandprofile/--metadataprofile ProfileName --validate
(the --commandprofile/--metadataprofile for dumpconfig will come
as part of the subsequent patch)
- This patch also adds a reference to --commandprofile and
--metadataprofile in the cmd help string (which was missing before
for the --profile for some commands). We do not mention --profile
now as people should use --commandprofile or --metadataprofile
directly. However, the --profile is still supported for backward
compatibility and it's translated as:
--profile == --metadataprofile for lvcreate, vgcreate, lvchange and vgchange
(as these commands are able to attach profile to metadata)
--profile == --commandprofile for all the other commands
(--metadataprofile is not allowed there as it makes no sense)
- This patch also contains some cleanups to make the code handling
the profiles more readable...
2014-05-20 16:13:10 +04:00
if ( config_string_cft | | config_profile_command_cft | | config_profile_metadata_cft ) {
2006-05-16 20:48:31 +04:00
/* Move this? */
if ( ! refresh_toolcontext ( cmd ) )
stack ;
}
2008-01-30 17:00:02 +03:00
2007-02-14 19:51:48 +03:00
if ( ret = = EINVALID_CMD_LINE & & ! _cmdline . interactive )
2007-09-21 22:06:33 +04:00
_short_usage ( cmd - > command - > name ) ;
2004-03-26 15:00:24 +03:00
2006-05-16 20:48:31 +04:00
log_debug ( " Completed: %s " , cmd - > cmd_line ) ;
2013-09-06 04:47:41 +04:00
cmd - > current_settings = cmd - > default_settings ;
_apply_settings ( cmd ) ;
2009-04-02 18:59:48 +04:00
/*
* free off any memory the command used .
*/
2010-11-11 20:29:05 +03:00
dm_list_init ( & cmd - > arg_value_groups ) ;
2009-04-02 18:59:48 +04:00
dm_pool_empty ( cmd - > mem ) ;
2009-07-16 03:57:54 +04:00
reset_lvm_errno ( 1 ) ;
2010-05-06 02:37:52 +04:00
reset_log_duplicated ( ) ;
2009-07-16 03:57:54 +04:00
2004-03-26 15:00:24 +03:00
return ret ;
}
2010-01-11 22:19:17 +03:00
int lvm_return_code ( int ret )
{
2015-04-20 11:04:18 +03:00
unlink_log_file ( ret ) ;
2010-01-11 22:19:17 +03:00
return ( ret = = ECMD_PROCESSED ? 0 : ret ) ;
}
2006-08-19 01:17:18 +04:00
int lvm_split ( char * str , int * argc , char * * argv , int max )
2004-03-26 15:00:24 +03:00
{
char * b = str , * e ;
2014-10-17 15:55:06 +04:00
char quote = 0 ;
2014-11-08 17:33:17 +03:00
* argc = 0 ;
2004-03-26 15:00:24 +03:00
while ( * b ) {
while ( * b & & isspace ( * b ) )
b + + ;
if ( ( ! * b ) | | ( * b = = ' # ' ) )
break ;
2014-10-17 15:55:06 +04:00
if ( * b = = ' \' ' | | * b = = ' " ' ) {
quote = * b ;
b + + ;
}
2004-03-26 15:00:24 +03:00
e = b ;
2014-10-17 15:55:06 +04:00
while ( * e & & ( quote ? * e ! = quote : ! isspace ( * e ) ) )
2004-03-26 15:00:24 +03:00
e + + ;
argv [ ( * argc ) + + ] = b ;
if ( ! * e )
break ;
* e + + = ' \0 ' ;
2014-10-17 15:55:06 +04:00
quote = 0 ;
2004-03-26 15:00:24 +03:00
b = e ;
if ( * argc = = max )
break ;
}
return * argc ;
}
2012-09-07 13:13:41 +04:00
/* Make sure we have always valid filedescriptors 0,1,2 */
static int _check_standard_fds ( void )
{
int err = is_valid_fd ( STDERR_FILENO ) ;
if ( ! is_valid_fd ( STDIN_FILENO ) & &
! ( stdin = fopen ( _PATH_DEVNULL , " r " ) ) ) {
if ( err )
perror ( " stdin stream open " ) ;
else
printf ( " stdin stream open: %s \n " ,
strerror ( errno ) ) ;
return 0 ;
}
if ( ! is_valid_fd ( STDOUT_FILENO ) & &
! ( stdout = fopen ( _PATH_DEVNULL , " w " ) ) ) {
if ( err )
perror ( " stdout stream open " ) ;
/* else no stdout */
return 0 ;
}
if ( ! is_valid_fd ( STDERR_FILENO ) & &
! ( stderr = fopen ( _PATH_DEVNULL , " w " ) ) ) {
printf ( " stderr stream open: %s \n " ,
strerror ( errno ) ) ;
return 0 ;
}
return 1 ;
}
2008-08-01 23:51:27 +04:00
static const char * _get_cmdline ( pid_t pid )
{
static char _proc_cmdline [ 32 ] ;
char buf [ 256 ] ;
2010-12-20 16:16:30 +03:00
int fd , n = 0 ;
2008-08-01 23:51:27 +04:00
snprintf ( buf , sizeof ( buf ) , DEFAULT_PROC_DIR " /%u/cmdline " , pid ) ;
2010-12-20 16:16:30 +03:00
/* FIXME Use generic read code. */
2012-02-13 16:07:51 +04:00
if ( ( fd = open ( buf , O_RDONLY ) ) > = 0 ) {
2010-12-20 16:16:30 +03:00
if ( ( n = read ( fd , _proc_cmdline , sizeof ( _proc_cmdline ) - 1 ) ) < 0 ) {
log_sys_error ( " read " , buf ) ;
n = 0 ;
}
if ( close ( fd ) )
log_sys_error ( " close " , buf ) ;
}
_proc_cmdline [ n ] = ' \0 ' ;
2008-08-01 23:51:27 +04:00
return _proc_cmdline ;
}
static const char * _get_filename ( int fd )
{
static char filename [ PATH_MAX ] ;
char buf [ 32 ] ; /* Assumes short DEFAULT_PROC_DIR */
int size ;
snprintf ( buf , sizeof ( buf ) , DEFAULT_PROC_DIR " /self/fd/%u " , fd ) ;
if ( ( size = readlink ( buf , filename , sizeof ( filename ) - 1 ) ) = = - 1 )
filename [ 0 ] = ' \0 ' ;
else
filename [ size ] = ' \0 ' ;
return filename ;
}
static void _close_descriptor ( int fd , unsigned suppress_warnings ,
const char * command , pid_t ppid ,
const char * parent_cmdline )
{
int r ;
const char * filename ;
/* Ignore bad file descriptors */
2012-08-27 15:07:07 +04:00
if ( ! is_valid_fd ( fd ) )
2008-08-01 23:51:27 +04:00
return ;
if ( ! suppress_warnings )
filename = _get_filename ( fd ) ;
r = close ( fd ) ;
if ( suppress_warnings )
return ;
if ( ! r )
fprintf ( stderr , " File descriptor %d (%s) leaked on "
" %s invocation. " , fd , filename , command ) ;
else if ( errno = = EBADF )
return ;
else
fprintf ( stderr , " Close failed on stray file descriptor "
" %d (%s): %s " , fd , filename , strerror ( errno ) ) ;
fprintf ( stderr , " Parent PID % " PRIpid_t " : %s \n " , ppid , parent_cmdline ) ;
}
2012-03-15 04:18:23 +04:00
static int _close_stray_fds ( const char * command )
2004-12-10 19:01:35 +03:00
{
2012-10-12 18:52:38 +04:00
# ifndef VALGRIND_POOL
2004-12-10 19:01:35 +03:00
struct rlimit rlim ;
int fd ;
2008-08-01 23:51:27 +04:00
unsigned suppress_warnings = 0 ;
pid_t ppid = getppid ( ) ;
const char * parent_cmdline = _get_cmdline ( ppid ) ;
2012-03-15 04:18:23 +04:00
static const char _fd_dir [ ] = DEFAULT_PROC_DIR " /self/fd " ;
struct dirent * dirent ;
DIR * d ;
2004-12-10 19:01:35 +03:00
2015-02-12 17:32:30 +03:00
# ifdef HAVE_VALGRIND
if ( RUNNING_ON_VALGRIND ) {
log_debug ( " Skipping close of descriptors within valgrind execution. " ) ;
return 1 ;
}
# endif
2005-03-04 01:09:20 +03:00
if ( getenv ( " LVM_SUPPRESS_FD_WARNINGS " ) )
suppress_warnings = 1 ;
2012-03-15 04:18:23 +04:00
if ( ! ( d = opendir ( _fd_dir ) ) ) {
if ( errno ! = ENOENT ) {
log_sys_error ( " opendir " , _fd_dir ) ;
return 0 ; /* broken system */
}
/* Path does not exist, use the old way */
if ( getrlimit ( RLIMIT_NOFILE , & rlim ) < 0 ) {
log_sys_error ( " getrlimit " , " RLIMIT_NOFILE " ) ;
return 1 ;
}
for ( fd = 3 ; fd < ( int ) rlim . rlim_cur ; fd + + )
_close_descriptor ( fd , suppress_warnings , command , ppid ,
parent_cmdline ) ;
return 1 ;
}
while ( ( dirent = readdir ( d ) ) ) {
fd = atoi ( dirent - > d_name ) ;
if ( fd > 2 & & fd ! = dirfd ( d ) )
_close_descriptor ( fd , suppress_warnings ,
command , ppid , parent_cmdline ) ;
}
if ( closedir ( d ) )
log_sys_error ( " closedir " , _fd_dir ) ;
2012-10-12 18:52:38 +04:00
# endif
2012-03-15 04:18:23 +04:00
return 1 ;
2004-12-10 19:01:35 +03:00
}
2015-07-30 11:34:10 +03:00
struct cmd_context * init_lvm ( unsigned set_connections , unsigned set_filters )
2004-03-26 15:00:24 +03:00
{
struct cmd_context * cmd ;
2011-04-22 16:05:32 +04:00
if ( ! udev_init_library_context ( ) )
stack ;
2014-05-22 11:56:44 +04:00
/*
* It ' s not necessary to use name mangling for LVM :
* - the character set used for LV names is subset of udev character set
2014-09-23 14:47:11 +04:00
* - when we check other devices ( e . g . device_is_usable fn ) , we use major : minor , not dm names
2014-05-22 11:56:44 +04:00
*/
dm_set_name_mangling_mode ( DM_STRING_MANGLING_NONE ) ;
2015-07-30 11:34:10 +03:00
if ( ! ( cmd = create_toolcontext ( 0 , NULL , 1 , 0 ,
set_connections , set_filters ) ) ) {
2012-03-12 18:15:04 +04:00
udev_fin_library_context ( ) ;
2008-01-30 16:19:47 +03:00
return_NULL ;
2012-03-12 18:15:04 +04:00
}
2004-03-26 15:00:24 +03:00
2010-11-11 20:29:05 +03:00
_cmdline . arg_props = & _arg_props [ 0 ] ;
2009-07-16 04:36:59 +04:00
if ( stored_errno ( ) ) {
destroy_toolcontext ( cmd ) ;
2012-03-12 18:15:04 +04:00
udev_fin_library_context ( ) ;
2009-07-16 04:36:59 +04:00
return_NULL ;
}
2004-03-26 15:00:24 +03:00
return cmd ;
}
2006-05-10 01:23:51 +04:00
static void _fin_commands ( void )
2004-03-26 15:00:24 +03:00
{
int i ;
2007-02-14 19:51:48 +03:00
for ( i = 0 ; i < _cmdline . num_commands ; i + + )
dm_free ( _cmdline . commands [ i ] . valid_args ) ;
2004-03-26 15:00:24 +03:00
2007-02-14 19:51:48 +03:00
dm_free ( _cmdline . commands ) ;
2010-01-21 16:41:39 +03:00
_cmdline . commands = NULL ;
_cmdline . num_commands = 0 ;
_cmdline . commands_size = 0 ;
2004-03-26 15:00:24 +03:00
}
2006-08-19 01:17:18 +04:00
void lvm_fin ( struct cmd_context * cmd )
2004-03-26 15:00:24 +03:00
{
2006-05-10 01:23:51 +04:00
_fin_commands ( ) ;
2004-03-26 15:00:24 +03:00
destroy_toolcontext ( cmd ) ;
2011-04-22 16:05:32 +04:00
udev_fin_library_context ( ) ;
2004-03-26 15:00:24 +03:00
}
static int _run_script ( struct cmd_context * cmd , int argc , char * * argv )
{
FILE * script ;
char buffer [ CMD_LEN ] ;
int ret = 0 ;
int magic_number = 0 ;
2007-01-25 17:37:48 +03:00
char * script_file = argv [ 0 ] ;
2004-03-26 15:00:24 +03:00
2007-01-25 17:37:48 +03:00
if ( ( script = fopen ( script_file , " r " ) ) = = NULL )
2004-03-26 15:00:24 +03:00
return ENO_SUCH_CMD ;
while ( fgets ( buffer , sizeof ( buffer ) , script ) ! = NULL ) {
if ( ! magic_number ) {
if ( buffer [ 0 ] = = ' # ' & & buffer [ 1 ] = = ' ! ' )
magic_number = 1 ;
2006-05-10 01:23:51 +04:00
else {
ret = ENO_SUCH_CMD ;
break ;
}
2004-03-26 15:00:24 +03:00
}
if ( ( strlen ( buffer ) = = sizeof ( buffer ) - 1 )
& & ( buffer [ sizeof ( buffer ) - 1 ] - 2 ! = ' \n ' ) ) {
buffer [ 50 ] = ' \0 ' ;
log_error ( " Line too long (max 255) beginning: %s " ,
buffer ) ;
ret = EINVALID_CMD_LINE ;
break ;
}
2006-08-19 01:17:18 +04:00
if ( lvm_split ( buffer , & argc , argv , MAX_ARGS ) = = MAX_ARGS ) {
2004-03-26 15:00:24 +03:00
buffer [ 50 ] = ' \0 ' ;
log_error ( " Too many arguments: %s " , buffer ) ;
ret = EINVALID_CMD_LINE ;
break ;
}
if ( ! argc )
continue ;
if ( ! strcmp ( argv [ 0 ] , " quit " ) | | ! strcmp ( argv [ 0 ] , " exit " ) )
break ;
2008-06-06 23:28:35 +04:00
ret = lvm_run_command ( cmd , argc , argv ) ;
if ( ret ! = ECMD_PROCESSED ) {
if ( ! error_message_produced ( ) ) {
2009-12-16 22:22:11 +03:00
log_debug ( INTERNAL_ERROR " Failed command did not use log_error " ) ;
2008-06-06 23:28:35 +04:00
log_error ( " Command failed with status code %d. " , ret ) ;
}
break ;
}
2004-03-26 15:00:24 +03:00
}
2007-01-25 17:37:48 +03:00
if ( fclose ( script ) )
log_sys_error ( " fclose " , script_file ) ;
2004-03-26 15:00:24 +03:00
return ret ;
}
2004-04-08 19:23:23 +04:00
/*
* Determine whether we should fall back and exec the equivalent LVM1 tool
*/
static int _lvm1_fallback ( struct cmd_context * cmd )
{
char vsn [ 80 ] ;
int dm_present ;
2013-06-25 14:31:53 +04:00
if ( ! find_config_tree_bool ( cmd , global_fallback_to_lvm1_CFG , NULL ) | |
2004-04-08 19:23:23 +04:00
strncmp ( cmd - > kernel_vsn , " 2.4. " , 4 ) )
return 0 ;
log_suppress ( 1 ) ;
dm_present = driver_version ( vsn , sizeof ( vsn ) ) ;
log_suppress ( 0 ) ;
if ( dm_present | | ! lvm1_present ( cmd ) )
return 0 ;
return 1 ;
}
2006-05-10 01:23:51 +04:00
static void _exec_lvm1_command ( char * * argv )
2004-04-08 19:23:23 +04:00
{
char path [ PATH_MAX ] ;
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( path , sizeof ( path ) , " %s.lvm1 " , argv [ 0 ] ) < 0 ) {
2004-04-08 19:23:23 +04:00
log_error ( " Failed to create LVM1 tool pathname " ) ;
return ;
}
execvp ( path , argv ) ;
log_sys_error ( " execvp " , path ) ;
}
2008-11-12 12:49:06 +03:00
static void _nonroot_warning ( void )
2008-01-09 18:55:44 +03:00
{
if ( getuid ( ) | | geteuid ( ) )
log_warn ( " WARNING: Running as a non-root user. Functionality may be unavailable. " ) ;
}
2008-12-18 08:27:17 +03:00
int lvm2_main ( int argc , char * * argv )
2004-03-26 15:00:24 +03:00
{
2008-11-18 13:13:23 +03:00
const char * base ;
2004-03-26 15:00:24 +03:00
int ret , alias = 0 ;
struct cmd_context * cmd ;
2013-04-29 15:50:26 +04:00
if ( ! argv )
return - 1 ;
2007-07-20 19:48:39 +04:00
base = last_path_component ( argv [ 0 ] ) ;
2004-06-29 17:27:19 +04:00
if ( strcmp ( base , " lvm " ) & & strcmp ( base , " lvm.static " ) & &
strcmp ( base , " initrd-lvm " ) )
2004-03-26 15:00:24 +03:00
alias = 1 ;
2005-02-18 21:58:31 +03:00
2012-09-07 13:13:41 +04:00
if ( ! _check_standard_fds ( ) )
return - 1 ;
2012-03-15 04:18:23 +04:00
if ( ! _close_stray_fds ( base ) )
return - 1 ;
2008-08-01 23:51:27 +04:00
2008-12-18 08:27:17 +03:00
if ( is_static ( ) & & strcmp ( base , " lvm.static " ) & &
2015-05-18 13:16:24 +03:00
path_exists ( LVM_PATH ) & &
2005-02-18 21:58:31 +03:00
! getenv ( " LVM_DID_EXEC " ) ) {
2012-03-02 01:17:29 +04:00
if ( setenv ( " LVM_DID_EXEC " , base , 1 ) )
log_sys_error ( " setenv " , " LVM_DID_EXEC " ) ;
2015-05-18 13:16:24 +03:00
if ( execvp ( LVM_PATH , argv ) = = - 1 )
log_sys_error ( " execvp " , LVM_PATH ) ;
2012-03-02 01:17:29 +04:00
if ( unsetenv ( " LVM_DID_EXEC " ) )
log_sys_error ( " unsetenv " , " LVM_DID_EXEC " ) ;
2005-02-18 21:58:31 +03:00
}
2010-04-30 17:28:44 +04:00
/* "version" command is simple enough so it doesn't need any complex init */
if ( ! alias & & argc > 1 & & ! strcmp ( argv [ 1 ] , " version " ) )
2010-04-30 17:47:11 +04:00
return lvm_return_code ( version ( NULL , argc , argv ) ) ;
2010-04-30 17:28:44 +04:00
commands: add new NO_METADATA_PROCESSING flag to selected commands
When a command is flagged with NO_METADATA_PROCESSING flag, it means
such command does not process any metadata and hence it doens't require
lvmetad, lvmpolld and it can get away with no locking too. These are
mostly simple commands (like lvmconfig/dumpconfig, version, types,
segtypes and other builtin commands that do not process metadata
in any way).
At first, when lvm command is executed, create toolcontext without
initializing connections (lvmetad,lvmpolld) and without initializing
filters (which depend on connections init). Instead, delay this
initialization until we know we need this. That is, until the
lvm_run_command fn is called in which we know what the actual
command to run is and hence we can avoid any connection, filter
or locking initiliazation for commands that would not make use
of it anyway.
For all the other create_toolcontext calls, we keep the original
behaviour - the filters and connections are initialized together
with the toolcontext.
2015-07-30 11:48:28 +03:00
if ( ! ( cmd = init_lvm ( 0 , 0 ) ) )
2005-02-18 21:58:31 +03:00
return - 1 ;
cmd - > argv = argv ;
2006-08-19 01:17:18 +04:00
lvm_register_commands ( ) ;
2004-03-26 15:00:24 +03:00
2004-04-08 19:23:23 +04:00
if ( _lvm1_fallback ( cmd ) ) {
/* Attempt to run equivalent LVM1 tool instead */
if ( ! alias ) {
argv + + ;
argc - - ;
}
if ( ! argc ) {
log_error ( " Falling back to LVM1 tools, but no "
" command specified. " ) ;
2010-11-24 12:53:31 +03:00
ret = ECMD_FAILED ;
goto out ;
2004-04-08 19:23:23 +04:00
}
2006-05-10 01:23:51 +04:00
_exec_lvm1_command ( argv ) ;
2010-11-24 12:53:31 +03:00
ret = ECMD_FAILED ;
2013-07-01 13:27:11 +04:00
goto_out ;
2004-04-08 19:23:23 +04:00
}
2004-03-26 15:00:24 +03:00
# ifdef READLINE_SUPPORT
if ( ! alias & & argc = = 1 ) {
2008-01-09 18:55:44 +03:00
_nonroot_warning ( ) ;
2007-02-14 19:51:48 +03:00
ret = lvm_shell ( cmd , & _cmdline ) ;
2004-03-26 15:00:24 +03:00
goto out ;
}
# endif
if ( ! alias ) {
if ( argc < 2 ) {
log_fatal ( " Please supply an LVM command. " ) ;
_display_help ( ) ;
ret = EINVALID_CMD_LINE ;
goto out ;
}
argc - - ;
argv + + ;
}
2008-01-09 18:55:44 +03:00
_nonroot_warning ( ) ;
2006-08-19 01:17:18 +04:00
ret = lvm_run_command ( cmd , argc , argv ) ;
2004-03-26 15:00:24 +03:00
if ( ( ret = = ENO_SUCH_CMD ) & & ( ! alias ) )
ret = _run_script ( cmd , argc , argv ) ;
if ( ret = = ENO_SUCH_CMD )
log_error ( " No such command. Try 'help'. " ) ;
2008-06-06 23:28:35 +04:00
if ( ( ret ! = ECMD_PROCESSED ) & & ! error_message_produced ( ) ) {
2009-12-16 22:22:11 +03:00
log_debug ( INTERNAL_ERROR " Failed command did not use log_error " ) ;
2008-06-06 23:28:35 +04:00
log_error ( " Command failed with status code %d. " , ret ) ;
}
2004-03-26 15:00:24 +03:00
out :
2006-08-19 01:17:18 +04:00
lvm_fin ( cmd ) ;
2010-01-11 22:19:17 +03:00
return lvm_return_code ( ret ) ;
2004-03-26 15:00:24 +03:00
}