2004-06-24 12:02:38 +04:00
/*
* Copyright ( C ) 2002 - 2004 Sistina Software , Inc . All rights reserved .
2009-05-19 14:38:58 +04:00
* Copyright ( C ) 2004 - 2009 Red Hat , Inc . All rights reserved .
2004-06-24 12:02:38 +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-06-24 12:02:38 +04:00
*
2007-08-21 00:55:30 +04:00
* You should have received a copy of the GNU Lesser General Public License
2004-06-24 12:02:38 +04:00
* along with this program ; if not , write to the Free Software Foundation ,
2016-01-21 13:49:46 +03:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2004-06-24 12:02:38 +04:00
*/
/*
* Locking functions for LVM .
* The main purpose of this part of the library is to serialise LVM
* management operations across a cluster .
*/
# include "lib.h"
# include "clvm.h"
# include "lvm-string.h"
# include "locking.h"
# include "locking_types.h"
2009-06-12 12:30:19 +04:00
# include "toolcontext.h"
2004-06-24 12:02:38 +04:00
2008-11-04 18:07:45 +03:00
# include <assert.h>
2004-06-24 12:02:38 +04:00
# include <stddef.h>
# include <sys/socket.h>
# include <sys/un.h>
# include <unistd.h>
# ifndef CLUSTER_LOCKING_INTERNAL
2014-09-22 17:50:07 +04:00
int lock_resource ( struct cmd_context * cmd , const char * resource , uint32_t flags , const struct logical_volume * lv __attribute__ ( ( unused ) ) ) ;
2016-01-20 00:42:22 +03:00
int query_resource ( const char * resource , const char * node , int * mode ) ;
2004-06-24 12:02:38 +04:00
void locking_end ( void ) ;
2011-08-30 18:55:15 +04:00
int locking_init ( int type , struct dm_config_tree * cf , uint32_t * flags ) ;
2004-06-24 12:02:38 +04:00
# endif
typedef struct lvm_response {
char node [ 255 ] ;
char * response ;
int status ;
int len ;
} lvm_response_t ;
/*
* This gets stuck at the start of memory we allocate so we
* can sanity - check it at deallocation time
*/
# define LVM_SIGNATURE 0x434C564D
/*
* NOTE : the LVMD uses the socket FD as the client ID , this means
* that any client that calls fork ( ) will inherit the context of
* it ' s parent .
*/
static int _clvmd_sock = - 1 ;
/* FIXME Install SIGPIPE handler? */
/* Open connection to the Cluster Manager daemon */
2011-08-09 15:44:57 +04:00
static int _open_local_sock ( int suppress_messages )
2004-06-24 12:02:38 +04:00
{
int local_socket ;
2012-06-21 23:19:28 +04:00
struct sockaddr_un sockaddr = { . sun_family = AF_UNIX } ;
if ( ! dm_strncpy ( sockaddr . sun_path , CLVMD_SOCKNAME , sizeof ( sockaddr . sun_path ) ) ) {
log_error ( " %s: clvmd socket name too long. " , CLVMD_SOCKNAME ) ;
return - 1 ;
}
2004-06-24 12:02:38 +04:00
/* Open local socket */
if ( ( local_socket = socket ( PF_UNIX , SOCK_STREAM , 0 ) ) < 0 ) {
2011-08-09 15:44:57 +04:00
log_error_suppress ( suppress_messages , " Local socket "
" creation failed: %s " , strerror ( errno ) ) ;
2004-06-24 12:02:38 +04:00
return - 1 ;
}
if ( connect ( local_socket , ( struct sockaddr * ) & sockaddr ,
sizeof ( sockaddr ) ) ) {
int saved_errno = errno ;
2011-08-09 15:44:57 +04:00
log_error_suppress ( suppress_messages , " connect() failed "
" on local socket: %s " , strerror ( errno ) ) ;
2004-06-24 12:02:38 +04:00
if ( close ( local_socket ) )
stack ;
errno = saved_errno ;
return - 1 ;
}
return local_socket ;
}
/* Send a request and return the status */
static int _send_request ( char * inbuf , int inlen , char * * retbuf )
{
2010-07-09 19:34:40 +04:00
char outbuf [ PIPE_BUF ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2004-06-24 12:02:38 +04:00
struct clvm_header * outheader = ( struct clvm_header * ) outbuf ;
int len ;
2011-04-08 18:40:18 +04:00
unsigned off ;
2004-06-24 12:02:38 +04:00
int buflen ;
int err ;
/* Send it to CLVMD */
rewrite :
if ( ( err = write ( _clvmd_sock , inbuf , inlen ) ) ! = inlen ) {
2008-01-30 17:00:02 +03:00
if ( err = = - 1 & & errno = = EINTR )
goto rewrite ;
2004-06-24 12:02:38 +04:00
log_error ( " Error writing data to clvmd: %s " , strerror ( errno ) ) ;
return 0 ;
}
/* Get the response */
reread :
if ( ( len = read ( _clvmd_sock , outbuf , sizeof ( struct clvm_header ) ) ) < 0 ) {
2008-01-30 17:00:02 +03:00
if ( errno = = EINTR )
goto reread ;
2004-06-24 12:02:38 +04:00
log_error ( " Error reading data from clvmd: %s " , strerror ( errno ) ) ;
return 0 ;
}
if ( len = = 0 ) {
log_error ( " EOF reading CLVMD " ) ;
errno = ENOTCONN ;
return 0 ;
}
/* Allocate buffer */
buflen = len + outheader - > arglen ;
2005-10-17 03:03:59 +04:00
* retbuf = dm_malloc ( buflen ) ;
2004-06-24 12:02:38 +04:00
if ( ! * retbuf ) {
errno = ENOMEM ;
return 0 ;
}
/* Copy the header */
memcpy ( * retbuf , outbuf , len ) ;
outheader = ( struct clvm_header * ) * retbuf ;
/* Read the returned values */
off = 1 ; /* we've already read the first byte */
2005-01-07 17:22:49 +03:00
while ( off < = outheader - > arglen & & len > 0 ) {
2004-06-24 12:02:38 +04:00
len = read ( _clvmd_sock , outheader - > args + off ,
buflen - off - offsetof ( struct clvm_header , args ) ) ;
if ( len > 0 )
off + = len ;
}
/* Was it an error ? */
2005-01-21 14:35:24 +03:00
if ( outheader - > status ! = 0 ) {
errno = outheader - > status ;
/* Only return an error here if there are no node-specific
errors present in the message that might have more detail */
if ( ! ( outheader - > flags & CLVMD_FLAG_NODEERRS ) ) {
log_error ( " cluster request failed: %s " , strerror ( errno ) ) ;
return 0 ;
}
2004-06-24 12:02:38 +04:00
}
return 1 ;
}
/* Build the structure header and parse-out wildcard node names */
2008-12-16 15:30:39 +03:00
/* FIXME: Cleanup implicit casts of clvmd_cmd (int, char, uint8_t, etc). */
static void _build_header ( struct clvm_header * head , int clvmd_cmd , const char * node ,
2004-06-24 12:02:38 +04:00
int len )
{
2008-12-16 15:30:39 +03:00
head - > cmd = clvmd_cmd ;
2004-06-24 12:02:38 +04:00
head - > status = 0 ;
head - > flags = 0 ;
2011-03-30 01:05:39 +04:00
head - > xid = 0 ;
2004-06-24 12:02:38 +04:00
head - > clientid = 0 ;
head - > arglen = len ;
2012-01-21 09:29:51 +04:00
/*
* Handle special node names .
*/
if ( ! node | | ! strcmp ( node , NODE_ALL ) )
head - > node [ 0 ] = ' \0 ' ;
else if ( ! strcmp ( node , NODE_LOCAL ) ) {
2004-06-24 12:02:38 +04:00
head - > node [ 0 ] = ' \0 ' ;
2012-01-21 09:29:51 +04:00
head - > flags = CLVMD_FLAG_LOCAL ;
} else if ( ! strcmp ( node , NODE_REMOTE ) ) {
head - > node [ 0 ] = ' \0 ' ;
head - > flags = CLVMD_FLAG_REMOTE ;
} else
strcpy ( head - > node , node ) ;
2004-06-24 12:02:38 +04:00
}
/*
* Send a message to a ( or all ) node ( s ) in the cluster and wait for replies
*/
2008-12-16 15:30:39 +03:00
static int _cluster_request ( char clvmd_cmd , const char * node , void * data , int len ,
2004-06-24 12:02:38 +04:00
lvm_response_t * * response , int * num )
{
2010-07-09 19:34:40 +04:00
char outbuf [ sizeof ( struct clvm_header ) + len + strlen ( node ) + 1 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2004-06-24 12:02:38 +04:00
char * inptr ;
char * retbuf = NULL ;
int status ;
int i ;
int num_responses = 0 ;
struct clvm_header * head = ( struct clvm_header * ) outbuf ;
lvm_response_t * rarray ;
* num = 0 ;
2018-02-08 13:03:06 +03:00
if ( _clvmd_sock = = - 1 ) {
if ( ( _clvmd_sock = _open_local_sock ( 0 ) ) = = - 1 )
return_0 ;
}
2004-06-24 12:02:38 +04:00
2011-03-30 01:05:39 +04:00
/* 1 byte is used from struct clvm_header.args[1], so -> len - 1 */
_build_header ( head , clvmd_cmd , node , len - 1 ) ;
2004-06-24 12:02:38 +04:00
memcpy ( head - > node + strlen ( head - > node ) + 1 , data , len ) ;
status = _send_request ( outbuf , sizeof ( struct clvm_header ) +
2011-03-30 01:05:39 +04:00
strlen ( head - > node ) + len - 1 , & retbuf ) ;
2004-06-24 12:02:38 +04:00
if ( ! status )
2018-02-08 13:03:06 +03:00
goto_out ;
2004-06-24 12:02:38 +04:00
/* Count the number of responses we got */
head = ( struct clvm_header * ) retbuf ;
inptr = head - > args ;
while ( inptr [ 0 ] ) {
num_responses + + ;
inptr + = strlen ( inptr ) + 1 ;
inptr + = sizeof ( int ) ;
inptr + = strlen ( inptr ) + 1 ;
}
/*
* Allocate response array .
* With an extra pair of INTs on the front to sanity
* check the pointer when we are given it back to free
*/
2013-04-19 23:11:32 +04:00
* response = NULL ;
if ( ! ( rarray = dm_malloc ( sizeof ( lvm_response_t ) * num_responses ) ) ) {
2004-06-24 12:02:38 +04:00
errno = ENOMEM ;
status = 0 ;
2018-02-08 13:03:06 +03:00
goto_out ;
2004-06-24 12:02:38 +04:00
}
/* Unpack the response into an lvm_response_t array */
inptr = head - > args ;
i = 0 ;
while ( inptr [ 0 ] ) {
strcpy ( rarray [ i ] . node , inptr ) ;
inptr + = strlen ( inptr ) + 1 ;
2006-06-12 13:46:35 +04:00
memcpy ( & rarray [ i ] . status , inptr , sizeof ( int ) ) ;
2004-06-24 12:02:38 +04:00
inptr + = sizeof ( int ) ;
2005-10-17 03:03:59 +04:00
rarray [ i ] . response = dm_malloc ( strlen ( inptr ) + 1 ) ;
2004-06-24 12:02:38 +04:00
if ( rarray [ i ] . response = = NULL ) {
/* Free up everything else and return error */
int j ;
for ( j = 0 ; j < i ; j + + )
2005-10-17 03:03:59 +04:00
dm_free ( rarray [ i ] . response ) ;
2013-04-19 23:11:32 +04:00
dm_free ( rarray ) ;
2004-06-24 12:02:38 +04:00
errno = ENOMEM ;
2013-04-19 23:11:32 +04:00
status = 0 ;
2018-02-08 13:03:06 +03:00
goto_out ;
2004-06-24 12:02:38 +04:00
}
strcpy ( rarray [ i ] . response , inptr ) ;
rarray [ i ] . len = strlen ( inptr ) ;
inptr + = strlen ( inptr ) + 1 ;
i + + ;
}
* num = num_responses ;
* response = rarray ;
out :
2011-01-28 13:16:04 +03:00
dm_free ( retbuf ) ;
2004-06-24 12:02:38 +04:00
return status ;
}
/* Free reply array */
2006-12-02 02:10:26 +03:00
static int _cluster_free_request ( lvm_response_t * response , int num )
2004-06-24 12:02:38 +04:00
{
int i ;
for ( i = 0 ; i < num ; i + + ) {
2005-10-17 03:03:59 +04:00
dm_free ( response [ i ] . response ) ;
2004-06-24 12:02:38 +04:00
}
2006-12-02 02:10:26 +03:00
dm_free ( response ) ;
2004-06-24 12:02:38 +04:00
return 1 ;
}
2009-06-12 12:30:19 +04:00
static int _lock_for_cluster ( struct cmd_context * cmd , unsigned char clvmd_cmd ,
uint32_t flags , const char * name )
2004-06-24 12:02:38 +04:00
{
2014-03-19 03:25:51 +04:00
/* TODO: convert to global usable solution and move static into cmd */
static unsigned char last_clvmd_cmd = 0 ;
2004-06-24 12:02:38 +04:00
int status ;
int i ;
char * args ;
const char * node = " " ;
int len ;
2010-03-26 18:40:13 +03:00
int dmeventd_mode ;
2010-11-29 14:13:12 +03:00
int saved_errno ;
2004-06-24 12:02:38 +04:00
lvm_response_t * response = NULL ;
int num_responses ;
assert ( name ) ;
len = strlen ( name ) + 3 ;
args = alloca ( len ) ;
strcpy ( args + 2 , name ) ;
2011-12-08 22:19:05 +04:00
/* args[0] holds bottom 8 bits except LCK_LOCAL (0x40). */
args [ 0 ] = flags & ( LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_NONBLOCK | LCK_HOLD | LCK_CLUSTER_VG ) ;
args [ 1 ] = 0 ;
2004-06-24 12:02:38 +04:00
2010-08-17 23:25:05 +04:00
if ( flags & LCK_ORIGIN_ONLY )
args [ 1 ] | = LCK_ORIGIN_ONLY_MODE ;
2011-09-28 02:43:40 +04:00
if ( flags & LCK_REVERT )
args [ 1 ] | = LCK_REVERT_MODE ;
2006-05-12 17:33:22 +04:00
if ( mirror_in_sync ( ) )
2006-05-11 23:05:21 +04:00
args [ 1 ] | = LCK_MIRROR_NOSYNC_MODE ;
2011-06-02 01:16:55 +04:00
if ( test_mode ( ) )
args [ 1 ] | = LCK_TEST_MODE ;
2010-03-26 18:40:13 +03:00
/*
2011-11-30 21:02:37 +04:00
* We propagate dmeventd_monitor_mode ( ) to clvmd faithfully , since
* dmeventd monitoring is tied to activation which happens inside clvmd
* when locking_type = 3.
2010-03-26 18:40:13 +03:00
*/
dmeventd_mode = dmeventd_monitor_mode ( ) ;
2011-11-30 21:00:57 +04:00
if ( dmeventd_mode = = DMEVENTD_MONITOR_IGNORE )
args [ 1 ] | = LCK_DMEVENTD_MONITOR_IGNORE ;
if ( dmeventd_mode )
2007-01-20 01:21:45 +03:00
args [ 1 ] | = LCK_DMEVENTD_MONITOR_MODE ;
2006-05-12 23:16:48 +04:00
2009-06-12 12:30:19 +04:00
if ( cmd - > partial_activation )
args [ 1 ] | = LCK_PARTIAL_MODE ;
2004-06-24 12:02:38 +04:00
/*
* VG locks are just that : locks , and have no side effects
* so we only need to do them on the local node because all
* locks are cluster - wide .
2011-02-03 02:57:48 +03:00
*
* P_ locks / do / get distributed across the cluster because they might
* have side - effects .
*
* SYNC_NAMES and VG_BACKUP use the VG name directly without prefix .
2004-06-24 12:02:38 +04:00
*/
2011-02-03 02:39:39 +03:00
if ( clvmd_cmd = = CLVMD_CMD_SYNC_NAMES ) {
2014-03-19 03:25:51 +04:00
if ( flags & LCK_LOCAL ) {
2012-01-21 09:29:51 +04:00
node = NODE_LOCAL ;
2014-03-19 03:25:51 +04:00
if ( clvmd_cmd = = last_clvmd_cmd ) {
log_debug ( " Skipping redundant local sync command. " ) ;
return 1 ;
}
}
2011-02-03 02:39:39 +03:00
} else if ( clvmd_cmd ! = CLVMD_CMD_VG_BACKUP ) {
if ( strncmp ( name , " P_ " , 2 ) & &
( clvmd_cmd = = CLVMD_CMD_LOCK_VG | |
( flags & LCK_LOCAL ) | |
! ( flags & LCK_CLUSTER_VG ) ) )
2012-01-21 09:29:51 +04:00
node = NODE_LOCAL ;
else if ( flags & LCK_REMOTE )
node = NODE_REMOTE ;
2011-02-03 02:39:39 +03:00
}
2004-06-24 12:02:38 +04:00
2014-03-19 03:25:51 +04:00
last_clvmd_cmd = clvmd_cmd ;
2008-12-16 15:30:39 +03:00
status = _cluster_request ( clvmd_cmd , node , args , len ,
2004-06-24 12:02:38 +04:00
& response , & num_responses ) ;
/* If any nodes were down then display them and return an error */
for ( i = 0 ; i < num_responses ; i + + ) {
2005-01-21 14:35:24 +03:00
if ( response [ i ] . status = = EHOSTDOWN ) {
2004-06-24 12:02:38 +04:00
log_error ( " clvmd not running on node %s " ,
response [ i ] . node ) ;
status = 0 ;
2005-01-21 14:35:24 +03:00
errno = response [ i ] . status ;
2004-06-24 12:02:38 +04:00
} else if ( response [ i ] . status ) {
log_error ( " Error locking on node %s: %s " ,
response [ i ] . node ,
response [ i ] . response [ 0 ] ?
response [ i ] . response :
strerror ( response [ i ] . status ) ) ;
status = 0 ;
2005-01-21 14:35:24 +03:00
errno = response [ i ] . status ;
2004-06-24 12:02:38 +04:00
}
}
saved_errno = errno ;
2006-12-02 02:10:26 +03:00
_cluster_free_request ( response , num_responses ) ;
2004-06-24 12:02:38 +04:00
errno = saved_errno ;
return status ;
}
/* API entry point for LVM */
# ifdef CLUSTER_LOCKING_INTERNAL
static int _lock_resource ( struct cmd_context * cmd , const char * resource ,
2014-09-22 17:50:07 +04:00
uint32_t flags , const struct logical_volume * lv __attribute__ ( ( unused ) ) )
2004-06-24 12:02:38 +04:00
# else
2014-09-22 17:50:07 +04:00
int lock_resource ( struct cmd_context * cmd , const char * resource , uint32_t flags , const struct logical_volume * lv __attribute__ ( ( unused ) ) )
2004-06-24 12:02:38 +04:00
# endif
{
char lockname [ PATH_MAX ] ;
2008-12-16 15:30:39 +03:00
int clvmd_cmd = 0 ;
2007-11-17 00:16:20 +03:00
const char * lock_scope ;
2014-08-19 16:19:11 +04:00
const char * lock_type ;
2004-06-24 12:02:38 +04:00
assert ( strlen ( resource ) < sizeof ( lockname ) ) ;
2006-05-10 21:49:25 +04:00
assert ( resource ) ;
2004-06-24 12:02:38 +04:00
switch ( flags & LCK_SCOPE_MASK ) {
2014-06-20 19:38:48 +04:00
case LCK_ACTIVATION :
return 1 ;
2004-06-24 12:02:38 +04:00
case LCK_VG :
2011-01-12 23:42:50 +03:00
if ( ! strcmp ( resource , VG_SYNC_NAMES ) ) {
log_very_verbose ( " Requesting sync names. " ) ;
return _lock_for_cluster ( cmd , CLVMD_CMD_SYNC_NAMES ,
flags & ~ LCK_HOLD , resource ) ;
}
2009-04-22 13:39:45 +04:00
if ( flags = = LCK_VG_BACKUP ) {
log_very_verbose ( " Requesting backup of VG metadata for %s " ,
resource ) ;
2009-06-12 12:30:19 +04:00
return _lock_for_cluster ( cmd , CLVMD_CMD_VG_BACKUP ,
2009-04-22 13:39:45 +04:00
LCK_CLUSTER_VG , resource ) ;
}
2004-06-24 12:02:38 +04:00
/* If the VG name is empty then lock the unused PVs */
2011-01-05 18:10:30 +03:00
if ( dm_snprintf ( lockname , sizeof ( lockname ) , " %c_%s " ,
( is_orphan_vg ( resource ) | |
is_global_vg ( resource ) | |
( flags & LCK_CACHE ) ) ? ' P ' : ' V ' ,
resource ) < 0 ) {
log_error ( " Locking resource %s too long. " , resource ) ;
return 0 ;
}
2004-06-24 12:02:38 +04:00
2007-11-17 00:16:20 +03:00
lock_scope = " VG " ;
2008-12-16 15:30:39 +03:00
clvmd_cmd = CLVMD_CMD_LOCK_VG ;
2010-04-13 18:36:24 +04:00
/*
* Old clvmd does not expect LCK_HOLD which was already processed
* in lock_vol , mask it for compatibility reasons .
*/
if ( flags ! = LCK_VG_COMMIT & & flags ! = LCK_VG_REVERT )
flags & = ~ LCK_HOLD ;
2004-06-24 12:02:38 +04:00
break ;
case LCK_LV :
2008-12-16 15:30:39 +03:00
clvmd_cmd = CLVMD_CMD_LOCK_LV ;
2004-06-24 12:02:38 +04:00
strcpy ( lockname , resource ) ;
2007-11-17 00:16:20 +03:00
lock_scope = " LV " ;
2009-12-09 21:16:38 +03:00
flags & = ~ LCK_HOLD ; /* Mask off HOLD flag */
2004-06-24 12:02:38 +04:00
break ;
default :
log_error ( " Unrecognised lock scope: %d " ,
flags & LCK_SCOPE_MASK ) ;
return 0 ;
}
2007-11-17 00:16:20 +03:00
switch ( flags & LCK_TYPE_MASK ) {
case LCK_UNLOCK :
lock_type = " UN " ;
break ;
case LCK_NULL :
lock_type = " NL " ;
break ;
case LCK_READ :
lock_type = " CR " ;
break ;
case LCK_PREAD :
lock_type = " PR " ;
break ;
case LCK_WRITE :
lock_type = " PW " ;
break ;
case LCK_EXCL :
lock_type = " EX " ;
break ;
default :
log_error ( " Unrecognised lock type: %u " ,
flags & LCK_TYPE_MASK ) ;
return 0 ;
}
2012-01-21 09:29:51 +04:00
log_very_verbose ( " Locking %s %s %s (%s%s%s%s%s%s%s%s%s) (0x%x) " , lock_scope , lockname ,
2010-01-05 19:03:37 +03:00
lock_type , lock_scope ,
flags & LCK_NONBLOCK ? " |NONBLOCK " : " " ,
flags & LCK_HOLD ? " |HOLD " : " " ,
flags & LCK_CLUSTER_VG ? " |CLUSTER " : " " ,
2012-01-21 09:29:51 +04:00
flags & LCK_LOCAL ? " |LOCAL " : " " ,
flags & LCK_REMOTE ? " |REMOTE " : " " ,
2010-01-05 19:03:37 +03:00
flags & LCK_CACHE ? " |CACHE " : " " ,
2010-08-17 23:25:05 +04:00
flags & LCK_ORIGIN_ONLY ? " |ORIGIN_ONLY " : " " ,
2011-12-08 22:19:05 +04:00
flags & LCK_REVERT ? " |REVERT " : " " ,
2007-11-17 00:16:20 +03:00
flags ) ;
2004-06-24 12:02:38 +04:00
2007-11-17 00:16:20 +03:00
/* Send a message to the cluster manager */
2009-06-12 12:30:19 +04:00
return _lock_for_cluster ( cmd , clvmd_cmd , flags , lockname ) ;
2004-06-24 12:02:38 +04:00
}
2017-10-18 17:57:46 +03:00
static int _decode_lock_type ( const char * response )
2009-05-19 14:38:58 +04:00
{
if ( ! response )
return LCK_NULL ;
2017-07-19 17:16:12 +03:00
if ( ! strcmp ( response , " EX " ) )
2009-05-19 14:38:58 +04:00
return LCK_EXCL ;
2017-07-19 17:16:12 +03:00
if ( ! strcmp ( response , " CR " ) )
2009-05-19 14:38:58 +04:00
return LCK_READ ;
2017-07-19 17:16:12 +03:00
if ( ! strcmp ( response , " PR " ) )
2009-05-19 14:38:58 +04:00
return LCK_PREAD ;
2013-07-01 13:27:11 +04:00
return_0 ;
2009-05-19 14:38:58 +04:00
}
# ifdef CLUSTER_LOCKING_INTERNAL
2016-01-20 00:42:22 +03:00
static int _query_resource ( const char * resource , const char * node , int * mode )
2009-05-19 14:38:58 +04:00
# else
2016-01-20 00:42:22 +03:00
int query_resource ( const char * resource , const char * node , int * mode )
2009-05-19 14:38:58 +04:00
# endif
{
int i , status , len , num_responses , saved_errno ;
char * args ;
lvm_response_t * response = NULL ;
saved_errno = errno ;
len = strlen ( resource ) + 3 ;
args = alloca ( len ) ;
strcpy ( args + 2 , resource ) ;
args [ 0 ] = 0 ;
2012-03-27 00:29:45 +04:00
args [ 1 ] = 0 ;
2009-05-19 14:38:58 +04:00
status = _cluster_request ( CLVMD_CMD_LOCK_QUERY , node , args , len ,
& response , & num_responses ) ;
* mode = LCK_NULL ;
for ( i = 0 ; i < num_responses ; i + + ) {
if ( response [ i ] . status = = EHOSTDOWN )
continue ;
if ( ! response [ i ] . response [ 0 ] )
continue ;
/*
* All nodes should use CR , or exactly one node
2011-02-01 20:31:40 +03:00
* should hold EX . ( PR is obsolete )
* If two nodes report different locks ,
2009-05-19 14:38:58 +04:00
* something is broken - just return more important mode .
*/
2017-10-18 17:57:46 +03:00
if ( _decode_lock_type ( response [ i ] . response ) > * mode )
* mode = _decode_lock_type ( response [ i ] . response ) ;
2009-05-19 14:38:58 +04:00
2013-01-08 02:30:29 +04:00
log_debug_locking ( " Lock held for %s, node %s : %s " , resource ,
response [ i ] . node , response [ i ] . response ) ;
2009-05-19 14:38:58 +04:00
}
_cluster_free_request ( response , num_responses ) ;
errno = saved_errno ;
return status ;
}
2004-06-24 12:02:38 +04:00
# ifdef CLUSTER_LOCKING_INTERNAL
static void _locking_end ( void )
# else
void locking_end ( void )
# endif
{
if ( _clvmd_sock ! = - 1 & & close ( _clvmd_sock ) )
stack ;
_clvmd_sock = - 1 ;
}
# ifdef CLUSTER_LOCKING_INTERNAL
static void _reset_locking ( void )
# else
void reset_locking ( void )
# endif
{
if ( close ( _clvmd_sock ) )
stack ;
2011-08-09 15:44:57 +04:00
_clvmd_sock = _open_local_sock ( 0 ) ;
2004-06-24 12:02:38 +04:00
if ( _clvmd_sock = = - 1 )
2008-01-30 17:00:02 +03:00
stack ;
2004-06-24 12:02:38 +04:00
}
# ifdef CLUSTER_LOCKING_INTERNAL
2011-08-09 15:44:57 +04:00
int init_cluster_locking ( struct locking_type * locking , struct cmd_context * cmd ,
int suppress_messages )
2004-06-24 12:02:38 +04:00
{
locking - > lock_resource = _lock_resource ;
2009-05-21 07:04:52 +04:00
locking - > query_resource = _query_resource ;
2004-06-24 12:02:38 +04:00
locking - > fin_locking = _locking_end ;
locking - > reset_locking = _reset_locking ;
2014-09-17 16:21:41 +04:00
locking - > flags = LCK_PRE_MEMLOCK | LCK_CLUSTERED | LCK_SUPPORTS_REMOTE_QUERIES ;
2004-06-24 12:02:38 +04:00
2011-08-09 15:44:57 +04:00
_clvmd_sock = _open_local_sock ( suppress_messages ) ;
2004-06-24 12:02:38 +04:00
if ( _clvmd_sock = = - 1 )
return 0 ;
return 1 ;
}
# else
2011-08-30 18:55:15 +04:00
int locking_init ( int type , struct dm_config_tree * cf , uint32_t * flags )
2004-06-24 12:02:38 +04:00
{
2011-08-09 15:44:57 +04:00
_clvmd_sock = _open_local_sock ( 0 ) ;
2004-06-24 12:02:38 +04:00
if ( _clvmd_sock = = - 1 )
return 0 ;
/* Ask LVM to lock memory before calling us */
* flags | = LCK_PRE_MEMLOCK ;
2005-03-22 01:55:12 +03:00
* flags | = LCK_CLUSTERED ;
2004-06-24 12:02:38 +04:00
return 1 ;
}
# endif