2015-07-03 18:34:40 +03:00
/*
* Copyright ( C ) 2014 - 2015 Red Hat , Inc .
*
* This file is part of LVM2 .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v .2 .1 .
*/
2018-05-14 12:30:20 +03:00
# include "tools/tool.h"
2015-07-06 19:30:18 +03:00
2018-05-14 12:30:20 +03:00
# include "daemons/lvmlockd/lvmlockd-client.h"
2015-03-05 23:00:44 +03:00
# include <stddef.h>
# include <getopt.h>
# include <signal.h>
# include <errno.h>
# include <fcntl.h>
2015-07-31 21:38:38 +03:00
# include <syslog.h>
2015-03-05 23:00:44 +03:00
# include <sys/socket.h>
# include <sys/un.h>
2015-07-08 14:56:06 +03:00
static int quit = 0 ;
static int info = 0 ;
static int dump = 0 ;
2018-11-27 22:41:33 +03:00
static int wait_opt = 1 ;
2015-07-08 14:56:06 +03:00
static int force_opt = 0 ;
2015-07-31 21:38:38 +03:00
static int kill_vg = 0 ;
static int drop_vg = 0 ;
2015-07-08 14:56:06 +03:00
static int gl_enable = 0 ;
static int gl_disable = 0 ;
static int stop_lockspaces = 0 ;
2015-07-31 21:38:38 +03:00
static char * arg_vg_name = NULL ;
2015-03-05 23:00:44 +03:00
# define DUMP_SOCKET_NAME "lvmlockd-dump.sock"
# define DUMP_BUF_SIZE (1024 * 1024)
2015-07-31 21:38:38 +03:00
static char dump_buf [ DUMP_BUF_SIZE + 1 ] ;
2015-03-05 23:00:44 +03:00
static int dump_len ;
static struct sockaddr_un dump_addr ;
static socklen_t dump_addrlen ;
daemon_handle _lvmlockd ;
# define log_error(fmt, args...) \
do { \
printf ( fmt " \n " , # # args ) ; \
} while ( 0 )
# define MAX_LINE 512
/* copied from lvmlockd-internal.h */
# define MAX_NAME 64
# define MAX_ARGS 64
/*
* lvmlockd dumps the client info before the lockspaces ,
* so we can look up client info when printing lockspace info .
*/
# define MAX_CLIENTS 100
struct client_info {
uint32_t client_id ;
int pid ;
char name [ MAX_NAME + 1 ] ;
} ;
static struct client_info clients [ MAX_CLIENTS ] ;
static int num_clients ;
static void save_client_info ( char * line )
{
uint32_t pid = 0 ;
int fd = 0 ;
int pi = 0 ;
uint32_t client_id = 0 ;
char name [ MAX_NAME + 1 ] = { 0 } ;
2016-05-31 11:06:19 +03:00
( void ) sscanf ( line , " info=client pid=%u fd=%d pi=%d id=%u name=%s " ,
2015-03-05 23:00:44 +03:00
& pid , & fd , & pi , & client_id , name ) ;
clients [ num_clients ] . client_id = client_id ;
clients [ num_clients ] . pid = pid ;
strcpy ( clients [ num_clients ] . name , name ) ;
num_clients + + ;
}
static void find_client_info ( uint32_t client_id , uint32_t * pid , char * cl_name )
{
int i ;
for ( i = 0 ; i < num_clients ; i + + ) {
if ( clients [ i ] . client_id = = client_id ) {
* pid = clients [ i ] . pid ;
strcpy ( cl_name , clients [ i ] . name ) ;
return ;
}
}
}
2015-07-30 18:47:41 +03:00
static int first_ls = 1 ;
2015-03-05 23:00:44 +03:00
static void format_info_ls ( char * line )
{
char ls_name [ MAX_NAME + 1 ] = { 0 } ;
char vg_name [ MAX_NAME + 1 ] = { 0 } ;
char vg_uuid [ MAX_NAME + 1 ] = { 0 } ;
char vg_sysid [ MAX_NAME + 1 ] = { 0 } ;
char lock_args [ MAX_ARGS + 1 ] = { 0 } ;
char lock_type [ MAX_NAME + 1 ] = { 0 } ;
2016-05-31 11:06:19 +03:00
( void ) sscanf ( line , " info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_sysid=%s vg_args=%s lm_type=%s " ,
2015-03-05 23:00:44 +03:00
ls_name , vg_name , vg_uuid , vg_sysid , lock_args , lock_type ) ;
2015-07-30 18:47:41 +03:00
if ( ! first_ls )
printf ( " \n " ) ;
first_ls = 0 ;
2015-03-05 23:00:44 +03:00
printf ( " VG %s lock_type=%s %s \n " , vg_name , lock_type , vg_uuid ) ;
printf ( " LS %s %s \n " , lock_type , ls_name ) ;
}
static void format_info_ls_action ( char * line )
{
uint32_t client_id = 0 ;
char flags [ MAX_NAME + 1 ] = { 0 } ;
char version [ MAX_NAME + 1 ] = { 0 } ;
char op [ MAX_NAME + 1 ] = { 0 } ;
uint32_t pid = 0 ;
char cl_name [ MAX_NAME + 1 ] = { 0 } ;
2016-05-31 11:06:19 +03:00
( void ) sscanf ( line , " info=ls_action client_id=%u %s %s op=%s " ,
2015-03-05 23:00:44 +03:00
& client_id , flags , version , op ) ;
find_client_info ( client_id , & pid , cl_name ) ;
2015-07-08 18:57:57 +03:00
printf ( " OP %s pid %u (%s) \n " , op , pid , cl_name ) ;
2015-03-05 23:00:44 +03:00
}
static void format_info_r ( char * line , char * r_name_out , char * r_type_out )
{
char r_name [ MAX_NAME + 1 ] = { 0 } ;
char r_type [ 4 ] = { 0 } ;
char mode [ 4 ] = { 0 } ;
char sh_count [ MAX_NAME + 1 ] = { 0 } ;
uint32_t ver = 0 ;
2016-05-31 11:06:19 +03:00
( void ) sscanf ( line , " info=r name=%s type=%s mode=%s %s version=%u " ,
2015-03-05 23:00:44 +03:00
r_name , r_type , mode , sh_count , & ver ) ;
2015-08-19 00:49:33 +03:00
strcpy ( r_name_out , r_name ) ;
strcpy ( r_type_out , r_type ) ;
2015-03-05 23:00:44 +03:00
2015-08-19 00:49:33 +03:00
/* when mode is not un, wait and print each lk line */
if ( strcmp ( mode , " un " ) )
2015-03-05 23:00:44 +03:00
return ;
/* when mode is un, there will be no lk lines, so print now */
if ( ! strcmp ( r_type , " gl " ) ) {
2015-07-30 18:47:41 +03:00
printf ( " LK GL un ver %u \n " , ver ) ;
2015-03-05 23:00:44 +03:00
} else if ( ! strcmp ( r_type , " vg " ) ) {
2015-07-30 18:47:41 +03:00
printf ( " LK VG un ver %u \n " , ver ) ;
2015-03-05 23:00:44 +03:00
} else if ( ! strcmp ( r_type , " lv " ) ) {
printf ( " LK LV un %s \n " , r_name ) ;
}
}
static void format_info_lk ( char * line , char * r_name , char * r_type )
{
char mode [ 4 ] = { 0 } ;
uint32_t ver = 0 ;
char flags [ MAX_NAME + 1 ] = { 0 } ;
uint32_t client_id = 0 ;
uint32_t pid = 0 ;
char cl_name [ MAX_NAME + 1 ] = { 0 } ;
if ( ! r_name [ 0 ] | | ! r_type [ 0 ] ) {
printf ( " format_info_lk error r_name %s r_type %s \n " , r_name , r_type ) ;
printf ( " %s \n " , line ) ;
return ;
}
2016-05-31 11:06:19 +03:00
( void ) sscanf ( line , " info=lk mode=%s version=%u %s client_id=%u " ,
2015-03-05 23:00:44 +03:00
mode , & ver , flags , & client_id ) ;
find_client_info ( client_id , & pid , cl_name ) ;
if ( ! strcmp ( r_type , " gl " ) ) {
2015-07-30 18:47:41 +03:00
printf ( " LK GL %s ver %u pid %u (%s) \n " , mode , ver , pid , cl_name ) ;
2015-03-05 23:00:44 +03:00
} else if ( ! strcmp ( r_type , " vg " ) ) {
2015-07-30 18:47:41 +03:00
printf ( " LK VG %s ver %u pid %u (%s) \n " , mode , ver , pid , cl_name ) ;
2015-03-05 23:00:44 +03:00
} else if ( ! strcmp ( r_type , " lv " ) ) {
printf ( " LK LV %s %s \n " , mode , r_name ) ;
}
}
static void format_info_r_action ( char * line , char * r_name , char * r_type )
{
uint32_t client_id = 0 ;
char flags [ MAX_NAME + 1 ] = { 0 } ;
char version [ MAX_NAME + 1 ] = { 0 } ;
char op [ MAX_NAME + 1 ] = { 0 } ;
char rt [ 4 ] = { 0 } ;
char mode [ 4 ] = { 0 } ;
char lm [ MAX_NAME + 1 ] = { 0 } ;
char result [ MAX_NAME + 1 ] = { 0 } ;
char lm_rv [ MAX_NAME + 1 ] = { 0 } ;
uint32_t pid = 0 ;
char cl_name [ MAX_NAME + 1 ] = { 0 } ;
if ( ! r_name [ 0 ] | | ! r_type [ 0 ] ) {
printf ( " format_info_r_action error r_name %s r_type %s \n " , r_name , r_type ) ;
printf ( " %s \n " , line ) ;
return ;
}
2016-05-31 11:06:19 +03:00
( void ) sscanf ( line , " info=r_action client_id=%u %s %s op=%s rt=%s mode=%s %s %s %s " ,
2015-03-05 23:00:44 +03:00
& client_id , flags , version , op , rt , mode , lm , result , lm_rv ) ;
find_client_info ( client_id , & pid , cl_name ) ;
if ( strcmp ( op , " lock " ) ) {
2015-08-19 00:49:33 +03:00
printf ( " OP %s pid %u (%s) \n " , op , pid , cl_name ) ;
2015-03-05 23:00:44 +03:00
return ;
}
if ( ! strcmp ( r_type , " gl " ) ) {
2015-07-30 18:47:41 +03:00
printf ( " LW GL %s ver %u pid %u (%s) \n " , mode , 0 , pid , cl_name ) ;
2015-03-05 23:00:44 +03:00
} else if ( ! strcmp ( r_type , " vg " ) ) {
2015-07-30 18:47:41 +03:00
printf ( " LW VG %s ver %u pid %u (%s) \n " , mode , 0 , pid , cl_name ) ;
2015-03-05 23:00:44 +03:00
} else if ( ! strcmp ( r_type , " lv " ) ) {
printf ( " LW LV %s %s \n " , mode , r_name ) ;
}
}
2015-07-08 18:57:57 +03:00
static void format_info_line ( char * line , char * r_name , char * r_type )
2015-03-05 23:00:44 +03:00
{
if ( ! strncmp ( line , " info=structs " , strlen ( " info=structs " ) ) ) {
2015-07-30 18:47:41 +03:00
/* only print this in the raw info dump */
2015-03-05 23:00:44 +03:00
} else if ( ! strncmp ( line , " info=client " , strlen ( " info=client " ) ) ) {
save_client_info ( line ) ;
} else if ( ! strncmp ( line , " info=ls " , strlen ( " info=ls " ) ) ) {
format_info_ls ( line ) ;
} else if ( ! strncmp ( line , " info=ls_action " , strlen ( " info=ls_action " ) ) ) {
format_info_ls_action ( line ) ;
} else if ( ! strncmp ( line , " info=r " , strlen ( " info=r " ) ) ) {
2015-07-08 18:57:57 +03:00
/*
* r_name / r_type are reset when a new resource is found .
* They are reused for the lock and action lines that
* follow a resource line .
*/
memset ( r_name , 0 , MAX_NAME + 1 ) ;
memset ( r_type , 0 , MAX_NAME + 1 ) ;
2015-03-05 23:00:44 +03:00
format_info_r ( line , r_name , r_type ) ;
} else if ( ! strncmp ( line , " info=lk " , strlen ( " info=lk " ) ) ) {
/* will use info from previous r */
format_info_lk ( line , r_name , r_type ) ;
} else if ( ! strncmp ( line , " info=r_action " , strlen ( " info=r_action " ) ) ) {
/* will use info from previous r */
format_info_r_action ( line , r_name , r_type ) ;
} else {
printf ( " UN %s \n " , line ) ;
}
}
static void format_info ( void )
{
char line [ MAX_LINE ] ;
2015-07-08 18:57:57 +03:00
char r_name [ MAX_NAME + 1 ] ;
char r_type [ MAX_NAME + 1 ] ;
2015-03-05 23:00:44 +03:00
int i , j ;
j = 0 ;
memset ( line , 0 , sizeof ( line ) ) ;
for ( i = 0 ; i < dump_len ; i + + ) {
line [ j + + ] = dump_buf [ i ] ;
if ( ( line [ j - 1 ] = = ' \n ' ) | | ( line [ j - 1 ] = = ' \0 ' ) ) {
2015-07-08 18:57:57 +03:00
format_info_line ( line , r_name , r_type ) ;
2015-03-05 23:00:44 +03:00
j = 0 ;
memset ( line , 0 , sizeof ( line ) ) ;
}
}
}
static daemon_reply _lvmlockd_send ( const char * req_name , . . . )
{
va_list ap ;
daemon_reply repl ;
daemon_request req ;
req = daemon_request_make ( req_name ) ;
va_start ( ap , req_name ) ;
daemon_request_extend_v ( req , ap ) ;
va_end ( ap ) ;
repl = daemon_send ( _lvmlockd , req ) ;
daemon_request_destroy ( req ) ;
return repl ;
}
/* See the same in lib/locking/lvmlockd.c */
# define NO_LOCKD_RESULT -1000
static int _lvmlockd_result ( daemon_reply reply , int * result )
{
int reply_result ;
if ( reply . error ) {
log_error ( " lvmlockd_result reply error %d " , reply . error ) ;
return 0 ;
}
if ( strcmp ( daemon_reply_str ( reply , " response " , " " ) , " OK " ) ) {
log_error ( " lvmlockd_result bad response " ) ;
return 0 ;
}
reply_result = daemon_reply_int ( reply , " op_result " , NO_LOCKD_RESULT ) ;
if ( reply_result = = - 1000 ) {
log_error ( " lvmlockd_result no op_result " ) ;
return 0 ;
}
* result = reply_result ;
return 1 ;
}
static int do_quit ( void )
{
daemon_reply reply ;
int rv = 0 ;
reply = daemon_send_simple ( _lvmlockd , " quit " , NULL ) ;
if ( reply . error ) {
log_error ( " reply error %d " , reply . error ) ;
rv = reply . error ;
}
daemon_reply_destroy ( reply ) ;
return rv ;
}
static int setup_dump_socket ( void )
{
int s , rv ;
s = socket ( AF_LOCAL , SOCK_DGRAM , 0 ) ;
if ( s < 0 )
return s ;
memset ( & dump_addr , 0 , sizeof ( dump_addr ) ) ;
dump_addr . sun_family = AF_LOCAL ;
strcpy ( & dump_addr . sun_path [ 1 ] , DUMP_SOCKET_NAME ) ;
dump_addrlen = sizeof ( sa_family_t ) + strlen ( dump_addr . sun_path + 1 ) + 1 ;
rv = bind ( s , ( struct sockaddr * ) & dump_addr , dump_addrlen ) ;
2015-07-08 14:56:06 +03:00
if ( rv < 0 ) {
2015-08-20 22:00:12 +03:00
rv = - errno ;
2017-08-25 12:57:49 +03:00
if ( close ( s ) )
2015-07-08 14:56:06 +03:00
log_error ( " failed to close dump socket " ) ;
2015-03-05 23:00:44 +03:00
return rv ;
2015-07-08 14:56:06 +03:00
}
2015-03-05 23:00:44 +03:00
return s ;
}
static int do_dump ( const char * req_name )
{
daemon_reply reply ;
int result ;
int fd , rv = 0 ;
2015-08-20 22:00:12 +03:00
int count = 0 ;
2015-03-05 23:00:44 +03:00
fd = setup_dump_socket ( ) ;
if ( fd < 0 ) {
log_error ( " socket error %d " , fd ) ;
return fd ;
}
reply = daemon_send_simple ( _lvmlockd , req_name , NULL ) ;
if ( reply . error ) {
log_error ( " reply error %d " , reply . error ) ;
rv = reply . error ;
goto out ;
}
result = daemon_reply_int ( reply , " result " , 0 ) ;
dump_len = daemon_reply_int ( reply , " dump_len " , 0 ) ;
daemon_reply_destroy ( reply ) ;
if ( result < 0 ) {
rv = result ;
log_error ( " result %d " , result ) ;
}
if ( ! dump_len )
goto out ;
memset ( dump_buf , 0 , sizeof ( dump_buf ) ) ;
2015-08-20 22:00:12 +03:00
retry :
rv = recvfrom ( fd , dump_buf + count , dump_len - count , MSG_WAITALL ,
2015-03-05 23:00:44 +03:00
( struct sockaddr * ) & dump_addr , & dump_addrlen ) ;
if ( rv < 0 ) {
log_error ( " recvfrom error %d %d " , rv , errno ) ;
rv = - errno ;
goto out ;
}
2015-08-20 22:00:12 +03:00
count + = rv ;
if ( count < dump_len )
goto retry ;
2015-03-05 23:00:44 +03:00
rv = 0 ;
if ( ( info & & dump ) | | ! strcmp ( req_name , " dump " ) )
printf ( " %s \n " , dump_buf ) ;
else
format_info ( ) ;
out :
2015-07-09 16:15:15 +03:00
if ( close ( fd ) )
log_error ( " failed to close dump socket %d " , fd ) ;
2015-03-05 23:00:44 +03:00
return rv ;
}
static int do_able ( const char * req_name )
{
daemon_reply reply ;
int result ;
int rv ;
reply = _lvmlockd_send ( req_name ,
2015-07-31 21:38:38 +03:00
" cmd = %s " , " lvmlockctl " ,
2015-11-09 17:15:37 +03:00
" pid = " FMTd64 , ( int64_t ) getpid ( ) ,
2015-07-31 21:38:38 +03:00
" vg_name = %s " , arg_vg_name ,
2015-03-05 23:00:44 +03:00
NULL ) ;
if ( ! _lvmlockd_result ( reply , & result ) ) {
log_error ( " lvmlockd result %d " , result ) ;
rv = result ;
} else {
rv = 0 ;
}
daemon_reply_destroy ( reply ) ;
return rv ;
}
static int do_stop_lockspaces ( void )
{
daemon_reply reply ;
char opts [ 32 ] ;
int result ;
int rv ;
memset ( opts , 0 , sizeof ( opts ) ) ;
if ( wait_opt )
strcat ( opts , " wait " ) ;
if ( force_opt )
strcat ( opts , " force " ) ;
reply = _lvmlockd_send ( " stop_all " ,
2015-07-31 21:38:38 +03:00
" cmd = %s " , " lvmlockctl " ,
2015-11-09 17:15:37 +03:00
" pid = " FMTd64 , ( int64_t ) getpid ( ) ,
2015-03-05 23:00:44 +03:00
" opts = %s " , opts [ 0 ] ? opts : " none " ,
NULL ) ;
if ( ! _lvmlockd_result ( reply , & result ) ) {
log_error ( " lvmlockd result %d " , result ) ;
rv = result ;
} else {
rv = 0 ;
}
daemon_reply_destroy ( reply ) ;
return rv ;
}
2015-07-31 21:38:38 +03:00
static int do_kill ( void )
{
daemon_reply reply ;
int result ;
int rv ;
syslog ( LOG_EMERG , " Lost access to sanlock lease storage in VG %s. " , arg_vg_name ) ;
/* These two lines explain the manual alternative to the FIXME below. */
syslog ( LOG_EMERG , " Immediately deactivate LVs in VG %s. " , arg_vg_name ) ;
syslog ( LOG_EMERG , " Once VG is unused, run lvmlockctl --drop %s. " , arg_vg_name ) ;
/*
* It may not be strictly necessary to notify lvmlockd of the kill , but
* lvmlockd can use this information to avoid attempting any new lock
* requests in the VG ( which would fail anyway ) , and can return an
* error indicating that the VG has been killed .
*/
reply = _lvmlockd_send ( " kill_vg " ,
" cmd = %s " , " lvmlockctl " ,
2015-11-09 17:15:37 +03:00
" pid = " FMTd64 , ( int64_t ) getpid ( ) ,
2015-07-31 21:38:38 +03:00
" vg_name = %s " , arg_vg_name ,
NULL ) ;
if ( ! _lvmlockd_result ( reply , & result ) ) {
log_error ( " lvmlockd result %d " , result ) ;
rv = result ;
} else {
rv = 0 ;
}
daemon_reply_destroy ( reply ) ;
/*
* FIXME : here is where we should implement a strong form of
* blkdeactivate , and if it completes successfully , automatically call
* do_drop ( ) afterward . ( The drop step may not always be necessary
* if the lvm commands run while shutting things down release all the
* leases . )
*
* run_strong_blkdeactivate ( ) ;
* do_drop ( ) ;
*/
return rv ;
}
static int do_drop ( void )
{
daemon_reply reply ;
int result ;
int rv ;
syslog ( LOG_WARNING , " Dropping locks for VG %s. " , arg_vg_name ) ;
/*
* Check for misuse by looking for any active LVs in the VG
* and refusing this operation if found ? One possible way
* to kill LVs ( e . g . if fs cannot be unmounted ) is to suspend
* them , or replace them with the error target . In that
* case the LV will still appear to be active , but it is
* safe to release the lock .
*/
reply = _lvmlockd_send ( " drop_vg " ,
" cmd = %s " , " lvmlockctl " ,
2015-11-09 17:15:37 +03:00
" pid = " FMTd64 , ( int64_t ) getpid ( ) ,
2015-07-31 21:38:38 +03:00
" vg_name = %s " , arg_vg_name ,
NULL ) ;
if ( ! _lvmlockd_result ( reply , & result ) ) {
log_error ( " lvmlockd result %d " , result ) ;
rv = result ;
} else {
rv = 0 ;
}
daemon_reply_destroy ( reply ) ;
return rv ;
}
2015-03-05 23:00:44 +03:00
static void print_usage ( void )
{
printf ( " lvmlockctl options \n " ) ;
printf ( " Options: \n " ) ;
printf ( " --help | -h \n " ) ;
printf ( " Show this help information. \n " ) ;
printf ( " --quit | -q \n " ) ;
printf ( " Tell lvmlockd to quit. \n " ) ;
printf ( " --info | -i \n " ) ;
printf ( " Print lock state information from lvmlockd. \n " ) ;
printf ( " --dump | -d \n " ) ;
printf ( " Print log buffer from lvmlockd. \n " ) ;
printf ( " --wait | -w 0|1 \n " ) ;
printf ( " Wait option for other commands. \n " ) ;
printf ( " --force | -f 0|1> \n " ) ;
printf ( " Force option for other commands. \n " ) ;
2015-09-04 19:01:25 +03:00
printf ( " --kill | -k <vgname> \n " ) ;
printf ( " Kill access to the VG when sanlock cannot renew lease. \n " ) ;
printf ( " --drop | -r <vgname> \n " ) ;
printf ( " Clear locks for the VG when it is unused after kill (-k). \n " ) ;
printf ( " --gl-enable | -E <vgname> \n " ) ;
printf ( " Tell lvmlockd to enable the global lock in a sanlock VG. \n " ) ;
printf ( " --gl-disable | -D <vgname> \n " ) ;
printf ( " Tell lvmlockd to disable the global lock in a sanlock VG. \n " ) ;
2015-07-31 21:38:38 +03:00
printf ( " --stop-lockspaces | -S \n " ) ;
printf ( " Stop all lockspaces. \n " ) ;
2015-03-05 23:00:44 +03:00
}
static int read_options ( int argc , char * argv [ ] )
{
int option_index = 0 ;
int c ;
static struct option long_options [ ] = {
{ " help " , no_argument , 0 , ' h ' } ,
{ " quit " , no_argument , 0 , ' q ' } ,
{ " info " , no_argument , 0 , ' i ' } ,
{ " dump " , no_argument , 0 , ' d ' } ,
{ " wait " , required_argument , 0 , ' w ' } ,
{ " force " , required_argument , 0 , ' f ' } ,
2015-07-31 21:38:38 +03:00
{ " kill " , required_argument , 0 , ' k ' } ,
{ " drop " , required_argument , 0 , ' r ' } ,
2015-03-05 23:00:44 +03:00
{ " gl-enable " , required_argument , 0 , ' E ' } ,
{ " gl-disable " , required_argument , 0 , ' D ' } ,
{ " stop-lockspaces " , no_argument , 0 , ' S ' } ,
{ 0 , 0 , 0 , 0 }
} ;
if ( argc = = 1 ) {
print_usage ( ) ;
exit ( 0 ) ;
}
while ( 1 ) {
2015-07-31 21:38:38 +03:00
c = getopt_long ( argc , argv , " hqidE:D:w:k:r:S " , long_options , & option_index ) ;
2015-03-05 23:00:44 +03:00
if ( c = = - 1 )
break ;
switch ( c ) {
case ' h ' :
/* --help */
print_usage ( ) ;
exit ( 0 ) ;
case ' q ' :
/* --quit */
quit = 1 ;
break ;
case ' i ' :
/* --info */
info = 1 ;
break ;
case ' d ' :
/* --dump */
dump = 1 ;
break ;
case ' w ' :
wait_opt = atoi ( optarg ) ;
break ;
2015-07-31 21:38:38 +03:00
case ' k ' :
kill_vg = 1 ;
arg_vg_name = strdup ( optarg ) ;
break ;
case ' r ' :
drop_vg = 1 ;
arg_vg_name = strdup ( optarg ) ;
break ;
2015-03-05 23:00:44 +03:00
case ' E ' :
gl_enable = 1 ;
2015-07-31 21:38:38 +03:00
arg_vg_name = strdup ( optarg ) ;
2015-03-05 23:00:44 +03:00
break ;
case ' D ' :
gl_disable = 1 ;
2015-07-31 21:38:38 +03:00
arg_vg_name = strdup ( optarg ) ;
2015-03-05 23:00:44 +03:00
break ;
case ' S ' :
stop_lockspaces = 1 ;
break ;
default :
print_usage ( ) ;
exit ( 1 ) ;
}
}
return 0 ;
}
int main ( int argc , char * * argv )
{
int rv = 0 ;
rv = read_options ( argc , argv ) ;
if ( rv < 0 )
return rv ;
_lvmlockd = lvmlockd_open ( NULL ) ;
if ( _lvmlockd . socket_fd < 0 | | _lvmlockd . error ) {
2015-07-30 18:47:41 +03:00
log_error ( " Cannot connect to lvmlockd. " ) ;
2015-03-05 23:00:44 +03:00
return - 1 ;
}
if ( quit ) {
rv = do_quit ( ) ;
goto out ;
}
if ( info ) {
rv = do_dump ( " info " ) ;
goto out ;
}
if ( dump ) {
rv = do_dump ( " dump " ) ;
goto out ;
}
2015-07-31 21:38:38 +03:00
if ( kill_vg ) {
rv = do_kill ( ) ;
goto out ;
}
if ( drop_vg ) {
rv = do_drop ( ) ;
goto out ;
}
2015-03-05 23:00:44 +03:00
if ( gl_enable ) {
2015-09-04 19:01:25 +03:00
syslog ( LOG_INFO , " Enabling global lock in VG %s. " , arg_vg_name ) ;
2015-03-05 23:00:44 +03:00
rv = do_able ( " enable_gl " ) ;
goto out ;
}
if ( gl_disable ) {
2015-09-04 19:01:25 +03:00
syslog ( LOG_INFO , " Disabling global lock in VG %s. " , arg_vg_name ) ;
2015-03-05 23:00:44 +03:00
rv = do_able ( " disable_gl " ) ;
goto out ;
}
if ( stop_lockspaces ) {
rv = do_stop_lockspaces ( ) ;
goto out ;
}
out :
lvmlockd_close ( _lvmlockd ) ;
return rv ;
}