2002-02-11 18:42:34 +03:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2011-02-18 17:16:11 +03:00
* Copyright ( C ) 2004 - 2011 Red Hat , Inc . All rights reserved .
2002-02-11 18:42:34 +03:00
*
2004-03-30 23:35:44 +04:00
* This file is part of LVM2 .
2002-02-11 18:42:34 +03:00
*
2004-03-30 23:35:44 +04:00
* 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
2002-02-11 18:42:34 +03:00
*/
2002-11-18 17:01:16 +03:00
# include "lib.h"
2002-02-11 18:42:34 +03:00
# include "locking.h"
# include "locking_types.h"
# include "lvm-string.h"
# include "activate.h"
2002-11-01 22:57:25 +03:00
# include "toolcontext.h"
2004-03-26 23:49:35 +03:00
# include "memlock.h"
2006-09-02 05:18:17 +04:00
# include "defaults.h"
2008-04-07 23:17:29 +04:00
# include "lvmcache.h"
2002-02-11 18:42:34 +03:00
2008-11-04 18:07:45 +03:00
# include <assert.h>
2002-02-11 18:42:34 +03:00
# include <signal.h>
2002-11-01 22:57:25 +03:00
# include <sys/stat.h>
# include <limits.h>
2003-07-05 02:34:56 +04:00
# include <unistd.h>
2002-02-11 18:42:34 +03:00
static struct locking_type _locking ;
2002-03-15 19:07:38 +03:00
static sigset_t _oldset ;
2002-02-11 18:42:34 +03:00
2003-11-21 22:54:40 +03:00
static int _vg_lock_count = 0 ; /* Number of locks held */
static int _vg_write_lock_held = 0 ; /* VG write lock held? */
2002-03-15 19:07:38 +03:00
static int _signals_blocked = 0 ;
2009-07-25 03:28:55 +04:00
static int _blocking_supported = 0 ;
2002-02-11 18:42:34 +03:00
2007-06-15 14:11:14 +04:00
static volatile sig_atomic_t _sigint_caught = 0 ;
static volatile sig_atomic_t _handler_installed ;
static struct sigaction _oldhandler ;
static int _oldmasked ;
2009-11-23 13:55:14 +03:00
typedef enum {
LV_NOOP ,
LV_SUSPEND ,
LV_RESUME
} lv_operation_t ;
2007-06-15 14:11:14 +04:00
static void _catch_sigint ( int unused __attribute__ ( ( unused ) ) )
{
_sigint_caught = 1 ;
}
2007-06-16 00:46:04 +04:00
int sigint_caught ( void ) {
2007-06-15 14:11:14 +04:00
return _sigint_caught ;
}
2007-06-16 00:46:04 +04:00
void sigint_clear ( void )
2007-06-15 14:11:14 +04:00
{
_sigint_caught = 0 ;
}
2007-06-16 00:46:04 +04:00
/*
* Temporarily allow keyboard interrupts to be intercepted and noted ;
* saves interrupt handler state for sigint_restore ( ) . Users should
* use the sigint_caught ( ) predicate to check whether interrupt was
* requested and act appropriately . Interrupt flags are never
* cleared automatically by this code , but the tools clear the flag
* before running each command in lvm_run_command ( ) . All other places
* where the flag needs to be cleared need to call sigint_clear ( ) .
*/
2007-06-15 14:11:14 +04:00
2007-06-16 00:46:04 +04:00
void sigint_allow ( void )
2007-06-15 14:11:14 +04:00
{
struct sigaction handler ;
sigset_t sigs ;
2007-06-16 00:46:04 +04:00
/*
* Do not overwrite the backed - up handler data -
* just increase nesting count .
*/
2007-06-15 14:11:14 +04:00
if ( _handler_installed ) {
_handler_installed + + ;
return ;
}
2007-06-16 00:46:04 +04:00
/* Grab old sigaction for SIGINT: shall not fail. */
2007-06-15 14:11:14 +04:00
sigaction ( SIGINT , NULL , & handler ) ;
2007-06-16 00:46:04 +04:00
handler . sa_flags & = ~ SA_RESTART ; /* Clear restart flag */
2007-06-15 14:11:14 +04:00
handler . sa_handler = _catch_sigint ;
_handler_installed = 1 ;
2007-06-16 00:46:04 +04:00
/* Override the signal handler: shall not fail. */
2007-06-15 14:11:14 +04:00
sigaction ( SIGINT , & handler , & _oldhandler ) ;
2007-06-16 00:46:04 +04:00
/* Unmask SIGINT. Remember to mask it again on restore. */
2007-06-15 14:11:14 +04:00
sigprocmask ( 0 , NULL , & sigs ) ;
if ( ( _oldmasked = sigismember ( & sigs , SIGINT ) ) ) {
sigdelset ( & sigs , SIGINT ) ;
sigprocmask ( SIG_SETMASK , & sigs , NULL ) ;
}
}
2007-06-16 00:46:04 +04:00
void sigint_restore ( void )
2007-06-15 14:11:14 +04:00
{
if ( ! _handler_installed )
return ;
if ( _handler_installed > 1 ) {
_handler_installed - - ;
return ;
}
2007-06-16 00:46:04 +04:00
/* Nesting count went down to 0. */
2007-06-15 14:11:14 +04:00
_handler_installed = 0 ;
if ( _oldmasked ) {
sigset_t sigs ;
sigprocmask ( 0 , NULL , & sigs ) ;
sigaddset ( & sigs , SIGINT ) ;
sigprocmask ( SIG_SETMASK , & sigs , NULL ) ;
}
sigaction ( SIGINT , & _oldhandler , NULL ) ;
}
2010-07-09 19:34:40 +04:00
static void _block_signals ( uint32_t flags __attribute__ ( ( unused ) ) )
2002-02-11 18:42:34 +03:00
{
2002-03-15 19:07:38 +03:00
sigset_t set ;
2002-02-11 18:42:34 +03:00
2002-03-15 19:07:38 +03:00
if ( _signals_blocked )
2002-02-11 18:42:34 +03:00
return ;
2002-03-15 19:07:38 +03:00
if ( sigfillset ( & set ) ) {
log_sys_error ( " sigfillset " , " _block_signals " ) ;
return ;
}
if ( sigprocmask ( SIG_SETMASK , & set , & _oldset ) ) {
log_sys_error ( " sigprocmask " , " _block_signals " ) ;
return ;
}
2002-02-11 18:42:34 +03:00
2002-03-15 19:07:38 +03:00
_signals_blocked = 1 ;
2002-02-11 18:42:34 +03:00
}
2002-03-15 19:07:38 +03:00
static void _unblock_signals ( void )
2002-02-11 18:42:34 +03:00
{
2002-03-15 19:07:38 +03:00
/* Don't unblock signals while any locks are held */
2003-11-21 22:54:40 +03:00
if ( ! _signals_blocked | | _vg_lock_count )
2002-02-11 18:42:34 +03:00
return ;
2002-03-15 19:07:38 +03:00
if ( sigprocmask ( SIG_SETMASK , & _oldset , NULL ) ) {
log_sys_error ( " sigprocmask " , " _block_signals " ) ;
return ;
}
2002-02-11 18:42:34 +03:00
2002-03-15 19:07:38 +03:00
_signals_blocked = 0 ;
2002-02-11 18:42:34 +03:00
}
2010-03-05 17:48:33 +03:00
static void _lock_memory ( struct cmd_context * cmd , lv_operation_t lv_op )
2004-03-26 23:49:35 +03:00
{
if ( ! ( _locking . flags & LCK_PRE_MEMLOCK ) )
return ;
2009-11-23 13:55:14 +03:00
if ( lv_op = = LV_SUSPEND )
2011-06-11 04:03:06 +04:00
critical_section_inc ( cmd , " locking for suspend " ) ;
2004-03-26 23:49:35 +03:00
}
2010-03-05 17:48:33 +03:00
static void _unlock_memory ( struct cmd_context * cmd , lv_operation_t lv_op )
2004-03-26 23:49:35 +03:00
{
if ( ! ( _locking . flags & LCK_PRE_MEMLOCK ) )
return ;
2009-11-23 13:55:14 +03:00
if ( lv_op = = LV_RESUME )
2011-06-11 04:03:06 +04:00
critical_section_dec ( cmd , " unlocking on resume " ) ;
2004-03-26 23:49:35 +03:00
}
2003-05-06 16:03:13 +04:00
void reset_locking ( void )
{
2003-11-21 22:54:40 +03:00
int was_locked = _vg_lock_count ;
2003-05-06 16:03:13 +04:00
2003-11-21 22:54:40 +03:00
_vg_lock_count = 0 ;
_vg_write_lock_held = 0 ;
2003-05-06 16:03:13 +04:00
2010-01-13 20:40:17 +03:00
if ( _locking . reset_locking )
_locking . reset_locking ( ) ;
2003-05-06 16:03:13 +04:00
if ( was_locked )
_unblock_signals ( ) ;
2011-02-18 17:16:11 +03:00
memlock_reset ( ) ;
2003-05-06 16:03:13 +04:00
}
2009-07-14 15:01:26 +04:00
static void _update_vg_lock_count ( const char * resource , uint32_t flags )
2002-02-11 18:42:34 +03:00
{
2009-07-14 15:01:26 +04:00
/* Ignore locks not associated with updating VG metadata */
2009-02-22 19:13:57 +03:00
if ( ( flags & LCK_SCOPE_MASK ) ! = LCK_VG | |
2009-07-14 15:01:26 +04:00
( flags & LCK_CACHE ) | |
! strcmp ( resource , VG_GLOBAL ) )
2003-11-21 22:54:40 +03:00
return ;
2002-04-04 15:18:45 +04:00
if ( ( flags & LCK_TYPE_MASK ) = = LCK_UNLOCK )
2003-11-21 22:54:40 +03:00
_vg_lock_count - - ;
2002-02-11 18:42:34 +03:00
else
2003-11-21 22:54:40 +03:00
_vg_lock_count + + ;
/* We don't bother to reset this until all VG locks are dropped */
if ( ( flags & LCK_TYPE_MASK ) = = LCK_WRITE )
_vg_write_lock_held = 1 ;
else if ( ! _vg_lock_count )
_vg_write_lock_held = 0 ;
2002-02-11 18:42:34 +03:00
}
/*
* Select a locking type
2009-02-03 19:23:19 +03:00
* type : locking type ; if < 0 , then read config tree value
2002-02-11 18:42:34 +03:00
*/
2010-05-06 15:15:55 +04:00
int init_locking ( int type , struct cmd_context * cmd , int suppress_messages )
2002-02-11 18:42:34 +03:00
{
2011-08-11 19:27:46 +04:00
if ( getenv ( " LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES " ) )
2010-02-15 19:46:56 +03:00
suppress_messages = 1 ;
2009-02-03 19:23:19 +03:00
if ( type < 0 )
2013-06-25 14:30:34 +04:00
type = find_config_tree_int ( cmd , global_locking_type_CFG , NULL ) ;
2009-07-25 03:28:55 +04:00
2013-06-25 14:31:53 +04:00
_blocking_supported = find_config_tree_bool ( cmd , global_wait_for_locks_CFG , NULL ) ;
2010-01-22 12:45:29 +03:00
2002-02-11 18:42:34 +03:00
switch ( type ) {
case 0 :
2011-08-09 15:44:57 +04:00
init_no_locking ( & _locking , cmd , suppress_messages ) ;
2007-06-28 21:33:44 +04:00
log_warn ( " WARNING: Locking disabled. Be careful! "
2002-02-11 18:42:34 +03:00
" This could corrupt your metadata. " ) ;
2002-07-11 00:43:32 +04:00
return 1 ;
2002-02-11 18:42:34 +03:00
case 1 :
2009-07-25 03:28:55 +04:00
log_very_verbose ( " %sFile-based locking selected. " ,
_blocking_supported ? " " : " Non-blocking " ) ;
2011-08-09 15:44:57 +04:00
if ( ! init_file_locking ( & _locking , cmd , suppress_messages ) ) {
2010-02-15 19:46:56 +03:00
log_error_suppress ( suppress_messages ,
" File-based locking initialisation failed. " ) ;
2002-07-11 00:43:32 +04:00
break ;
2010-01-22 12:45:29 +03:00
}
2002-07-11 00:43:32 +04:00
return 1 ;
2002-04-08 20:04:50 +04:00
2003-03-24 21:08:53 +03:00
# ifdef HAVE_LIBDL
2002-02-11 18:42:34 +03:00
case 2 :
2008-12-18 08:27:17 +03:00
if ( ! is_static ( ) ) {
2006-09-01 02:21:00 +04:00
log_very_verbose ( " External locking selected. " ) ;
2011-08-09 15:44:57 +04:00
if ( init_external_locking ( & _locking , cmd , suppress_messages ) )
2006-10-14 20:37:54 +04:00
return 1 ;
2006-09-01 02:21:00 +04:00
}
2013-06-25 14:31:53 +04:00
if ( ! find_config_tree_bool ( cmd , global_fallback_to_clustered_locking_CFG , NULL ) ) {
2011-08-09 15:44:57 +04:00
log_error_suppress ( suppress_messages , " External locking initialisation failed. " ) ;
2006-09-02 05:18:17 +04:00
break ;
2010-01-22 12:45:29 +03:00
}
2003-03-24 21:08:53 +03:00
# endif
2002-04-08 20:04:50 +04:00
2004-06-24 12:02:38 +04:00
# ifdef CLUSTER_LOCKING_INTERNAL
2006-10-14 20:37:54 +04:00
log_very_verbose ( " Falling back to internal clustered locking. " ) ;
/* Fall through */
2004-06-24 12:02:38 +04:00
case 3 :
2006-09-01 02:21:00 +04:00
log_very_verbose ( " Cluster locking selected. " ) ;
2011-08-09 15:44:57 +04:00
if ( ! init_cluster_locking ( & _locking , cmd , suppress_messages ) ) {
2010-02-15 19:46:56 +03:00
log_error_suppress ( suppress_messages ,
" Internal cluster locking initialisation failed. " ) ;
2004-06-24 12:02:38 +04:00
break ;
2010-01-22 12:45:29 +03:00
}
2004-06-24 12:02:38 +04:00
return 1 ;
# endif
2009-09-15 02:47:49 +04:00
case 4 :
log_verbose ( " Read-only locking selected. "
" Only read operations permitted. " ) ;
2011-08-09 15:44:57 +04:00
if ( ! init_readonly_locking ( & _locking , cmd , suppress_messages ) )
2009-09-15 02:47:49 +04:00
break ;
return 1 ;
2002-02-11 18:42:34 +03:00
default :
log_error ( " Unknown locking type requested. " ) ;
return 0 ;
}
2006-09-02 05:18:17 +04:00
if ( ( type = = 2 | | type = = 3 ) & &
2013-06-25 14:31:53 +04:00
find_config_tree_bool ( cmd , global_fallback_to_local_locking_CFG , NULL ) ) {
2010-04-01 14:34:09 +04:00
log_warn_suppress ( suppress_messages , " WARNING: Falling back to local file-based locking. " ) ;
2010-02-15 19:46:56 +03:00
log_warn_suppress ( suppress_messages ,
" Volume Groups with the clustered attribute will "
" be inaccessible. " ) ;
2011-08-09 15:44:57 +04:00
if ( init_file_locking ( & _locking , cmd , suppress_messages ) )
2006-09-02 05:18:17 +04:00
return 1 ;
2010-01-22 12:45:29 +03:00
else
2010-02-15 19:46:56 +03:00
log_error_suppress ( suppress_messages ,
" File-based locking initialisation failed. " ) ;
2006-09-02 05:18:17 +04:00
}
2002-07-11 00:43:32 +04:00
if ( ! ignorelockingfailure ( ) )
return 0 ;
log_verbose ( " Locking disabled - only read operations permitted. " ) ;
2011-08-09 15:44:57 +04:00
init_readonly_locking ( & _locking , cmd , suppress_messages ) ;
2002-07-11 00:43:32 +04:00
2002-02-11 18:42:34 +03:00
return 1 ;
}
void fin_locking ( void )
{
_locking . fin_locking ( ) ;
}
2002-11-01 22:57:25 +03:00
/*
* Does the LVM1 driver know of this VG name ?
*/
int check_lvm1_vg_inactive ( struct cmd_context * cmd , const char * vgname )
{
struct stat info ;
char path [ PATH_MAX ] ;
2002-11-18 17:01:16 +03:00
/* We'll allow operations on orphans */
2011-01-12 23:42:50 +03:00
if ( ! is_real_vg ( vgname ) )
2002-11-18 17:01:16 +03:00
return 1 ;
2008-09-10 14:14:59 +04:00
/* LVM1 is only present in 2.4 kernels. */
if ( strncmp ( cmd - > kernel_vsn , " 2.4. " , 4 ) )
return 1 ;
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( path , sizeof ( path ) , " %s/lvm/VGs/%s " , cmd - > proc_dir ,
2002-11-18 17:01:16 +03:00
vgname ) < 0 ) {
2002-11-01 22:57:25 +03:00
log_error ( " LVM1 proc VG pathname too long for %s " , vgname ) ;
return 0 ;
}
if ( stat ( path , & info ) = = 0 ) {
log_error ( " %s exists: Is the original LVM driver using "
" this volume group? " , path ) ;
return 0 ;
} else if ( errno ! = ENOENT & & errno ! = ENOTDIR ) {
log_sys_error ( " stat " , path ) ;
return 0 ;
}
return 1 ;
}
2002-02-11 18:42:34 +03:00
/*
2002-03-15 19:07:38 +03:00
* VG locking is by VG name .
* FIXME This should become VG uuid .
2002-02-11 18:42:34 +03:00
*/
2009-11-23 13:55:14 +03:00
static int _lock_vol ( struct cmd_context * cmd , const char * resource ,
2013-03-18 00:29:58 +04:00
uint32_t flags , lv_operation_t lv_op , struct logical_volume * lv )
2002-03-05 23:03:09 +03:00
{
2011-08-10 20:07:53 +04:00
uint32_t lck_type = flags & LCK_TYPE_MASK ;
uint32_t lck_scope = flags & LCK_SCOPE_MASK ;
2008-04-07 23:17:29 +04:00
int ret = 0 ;
2003-01-04 00:10:28 +03:00
_block_signals ( flags ) ;
2010-03-05 17:48:33 +03:00
_lock_memory ( cmd , lv_op ) ;
2002-03-05 23:03:09 +03:00
2007-11-17 00:16:20 +03:00
assert ( resource ) ;
2008-05-09 22:45:15 +04:00
if ( ! * resource ) {
2009-12-16 22:22:11 +03:00
log_error ( INTERNAL_ERROR " Use of P_orphans is deprecated. " ) ;
2008-05-09 22:45:15 +04:00
return 0 ;
}
2010-05-19 06:36:33 +04:00
if ( ( is_orphan_vg ( resource ) | | is_global_vg ( resource ) ) & & ( flags & LCK_CACHE ) ) {
2009-12-16 22:22:11 +03:00
log_error ( INTERNAL_ERROR " P_%s referenced " , resource ) ;
2008-05-09 22:45:15 +04:00
return 0 ;
}
2011-08-10 20:07:53 +04:00
if ( cmd - > metadata_read_only & & lck_type = = LCK_WRITE & &
2010-10-25 15:20:54 +04:00
strcmp ( resource , VG_GLOBAL ) ) {
log_error ( " Operation prohibited while global/metadata_read_only is set. " ) ;
return 0 ;
}
2013-03-18 00:29:58 +04:00
if ( ( ret = _locking . lock_resource ( cmd , resource , flags , lv ) ) ) {
2011-08-10 20:07:53 +04:00
if ( lck_scope = = LCK_VG & & ! ( flags & LCK_CACHE ) ) {
if ( lck_type ! = LCK_UNLOCK )
lvmcache_lock_vgname ( resource , lck_type = = LCK_READ ) ;
2010-10-13 19:40:38 +04:00
dev_reset_error_count ( cmd ) ;
2008-04-07 23:17:29 +04:00
}
2009-07-14 15:01:26 +04:00
_update_vg_lock_count ( resource , flags ) ;
2010-04-13 05:54:32 +04:00
} else
stack ;
2002-03-05 23:03:09 +03:00
2011-08-10 20:07:53 +04:00
/* If unlocking, always remove lock from lvmcache even if operation failed. */
if ( lck_scope = = LCK_VG & & ! ( flags & LCK_CACHE ) & & lck_type = = LCK_UNLOCK ) {
lvmcache_unlock_vgname ( resource ) ;
if ( ! ret )
_update_vg_lock_count ( resource , flags ) ;
}
2010-03-05 17:48:33 +03:00
_unlock_memory ( cmd , lv_op ) ;
2002-03-15 19:07:38 +03:00
_unblock_signals ( ) ;
2002-03-05 23:03:09 +03:00
2008-04-07 23:17:29 +04:00
return ret ;
2002-03-05 23:03:09 +03:00
}
2013-03-18 00:29:58 +04:00
int lock_vol ( struct cmd_context * cmd , const char * vol , uint32_t flags , struct logical_volume * lv )
2002-02-11 18:42:34 +03:00
{
2010-07-09 19:34:40 +04:00
char resource [ 258 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2009-11-23 13:55:14 +03:00
lv_operation_t lv_op ;
2011-01-13 17:56:17 +03:00
int lck_type = flags & LCK_TYPE_MASK ;
2009-11-23 13:55:14 +03:00
switch ( flags & ( LCK_SCOPE_MASK | LCK_TYPE_MASK ) ) {
case LCK_LV_SUSPEND :
lv_op = LV_SUSPEND ;
break ;
case LCK_LV_RESUME :
lv_op = LV_RESUME ;
break ;
default : lv_op = LV_NOOP ;
}
2002-02-11 18:42:34 +03:00
2007-11-16 00:30:52 +03:00
if ( flags = = LCK_NONE ) {
2013-01-08 02:30:29 +04:00
log_debug_locking ( INTERNAL_ERROR " %s: LCK_NONE lock requested " , vol ) ;
2007-11-16 00:30:52 +03:00
return 1 ;
}
2002-02-11 18:42:34 +03:00
switch ( flags & LCK_SCOPE_MASK ) {
2002-11-01 22:57:25 +03:00
case LCK_VG :
2010-03-31 21:23:56 +04:00
if ( ! _blocking_supported )
2009-05-13 17:02:52 +04:00
flags | = LCK_NONBLOCK ;
2010-05-19 05:16:40 +04:00
/* Global VG_ORPHANS lock covers all orphan formats. */
if ( is_orphan_vg ( vol ) )
vol = VG_ORPHANS ;
/* VG locks alphabetical, ORPHAN lock last */
2011-01-13 17:56:17 +03:00
if ( ( lck_type ! = LCK_UNLOCK ) & &
! ( flags & LCK_CACHE ) & &
! lvmcache_verify_lock_order ( vol ) )
return_0 ;
2009-09-03 01:34:11 +04:00
2002-11-01 22:57:25 +03:00
/* Lock VG to change on-disk metadata. */
/* If LVM1 driver knows about the VG, it can't be accessed. */
if ( ! check_lvm1_vg_inactive ( cmd , vol ) )
2011-01-13 17:56:17 +03:00
return_0 ;
2009-07-24 22:15:06 +04:00
break ;
2002-11-01 22:57:25 +03:00
case LCK_LV :
2009-07-24 22:15:06 +04:00
/* All LV locks are non-blocking. */
flags | = LCK_NONBLOCK ;
2002-02-11 18:42:34 +03:00
break ;
default :
log_error ( " Unrecognised lock scope: %d " ,
flags & LCK_SCOPE_MASK ) ;
return 0 ;
}
2012-02-08 15:05:04 +04:00
strncpy ( resource , vol , sizeof ( resource ) - 1 ) ;
resource [ sizeof ( resource ) - 1 ] = ' \0 ' ;
2009-07-24 22:15:06 +04:00
2013-03-18 00:29:58 +04:00
if ( ! _lock_vol ( cmd , resource , flags , lv_op , lv ) )
2011-01-13 17:56:17 +03:00
return_0 ;
2002-02-11 18:42:34 +03:00
2008-05-08 22:35:58 +04:00
/*
* If a real lock was acquired ( i . e . not LCK_CACHE ) ,
* perform an immediate unlock unless LCK_HOLD was requested .
*/
2011-01-13 17:56:17 +03:00
if ( ( lck_type = = LCK_NULL ) | | ( lck_type = = LCK_UNLOCK ) | |
( flags & ( LCK_CACHE | LCK_HOLD ) ) )
return 1 ;
2013-03-18 00:29:58 +04:00
if ( ! _lock_vol ( cmd , resource , ( flags & ~ LCK_TYPE_MASK ) | LCK_UNLOCK , lv_op , lv ) )
2011-01-13 17:56:17 +03:00
return_0 ;
2002-02-11 18:42:34 +03:00
return 1 ;
}
2003-11-21 22:54:40 +03:00
2004-03-26 23:49:35 +03:00
/* Unlock list of LVs */
2008-11-04 01:14:30 +03:00
int resume_lvs ( struct cmd_context * cmd , struct dm_list * lvs )
2004-03-26 23:49:35 +03:00
{
2005-06-01 20:51:55 +04:00
struct lv_list * lvl ;
2010-04-12 15:52:53 +04:00
int r = 1 ;
2004-03-26 23:49:35 +03:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( lvl , lvs )
2010-04-12 15:52:53 +04:00
if ( ! resume_lv ( cmd , lvl - > lv ) ) {
r = 0 ;
2010-01-06 00:07:31 +03:00
stack ;
2010-04-12 15:52:53 +04:00
}
2004-03-26 23:49:35 +03:00
2010-04-12 15:52:53 +04:00
return r ;
2004-03-26 23:49:35 +03:00
}
2011-09-28 02:43:40 +04:00
/* Unlock and revert list of LVs */
int revert_lvs ( struct cmd_context * cmd , struct dm_list * lvs )
{
struct lv_list * lvl ;
int r = 1 ;
dm_list_iterate_items ( lvl , lvs )
if ( ! revert_lv ( cmd , lvl - > lv ) ) {
r = 0 ;
stack ;
}
return r ;
}
2011-09-27 21:09:42 +04:00
/*
* Lock a list of LVs .
* On failure to lock any LV , calls vg_revert ( ) if vg_to_revert is set and
* then unlocks any LVs on the list already successfully locked .
*/
int suspend_lvs ( struct cmd_context * cmd , struct dm_list * lvs ,
struct volume_group * vg_to_revert )
2004-03-26 23:49:35 +03:00
{
2005-06-01 20:51:55 +04:00
struct lv_list * lvl ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( lvl , lvs ) {
2005-08-15 16:00:04 +04:00
if ( ! suspend_lv ( cmd , lvl - > lv ) ) {
2005-06-01 20:51:55 +04:00
log_error ( " Failed to suspend %s " , lvl - > lv - > name ) ;
2011-09-27 21:09:42 +04:00
if ( vg_to_revert )
vg_revert ( vg_to_revert ) ;
2012-01-10 06:03:31 +04:00
/*
* FIXME Should be
* dm_list_uniterate ( lvh , lvs , & lvl - > list ) {
* lvl = dm_list_item ( lvh , struct lv_list ) ;
* but revert would need fixing to use identical tree deps first .
*/
dm_list_iterate_items ( lvl , lvs )
2011-09-28 02:43:40 +04:00
if ( ! revert_lv ( cmd , lvl - > lv ) )
2010-01-06 00:07:31 +03:00
stack ;
2004-05-05 16:03:07 +04:00
return 0 ;
}
}
return 1 ;
}
2012-01-21 09:29:51 +04:00
/*
* First try to activate exclusively locally .
* Then if the VG is clustered and the LV is not yet active ( e . g . due to
* an activation filter ) try activating on remote nodes .
*/
int activate_lv_excl ( struct cmd_context * cmd , struct logical_volume * lv )
{
/* Non-clustered VGs are only activated locally. */
if ( ! vg_is_clustered ( lv - > vg ) )
return activate_lv_excl_local ( cmd , lv ) ;
2012-03-27 19:53:45 +04:00
if ( lv_is_active_exclusive_locally ( lv ) )
2012-01-21 09:29:51 +04:00
return 1 ;
if ( ! activate_lv_excl_local ( cmd , lv ) )
return_0 ;
if ( lv_is_active_exclusive ( lv ) )
return 1 ;
/* FIXME Deal with error return codes. */
if ( activate_lv_excl_remote ( cmd , lv ) )
stack ;
return lv_is_active_exclusive ( lv ) ;
}
2004-05-05 16:03:07 +04:00
/* Lock a list of LVs */
2008-11-04 01:14:30 +03:00
int activate_lvs ( struct cmd_context * cmd , struct dm_list * lvs , unsigned exclusive )
2004-05-05 16:03:07 +04:00
{
2008-11-04 01:14:30 +03:00
struct dm_list * lvh ;
2005-06-01 20:51:55 +04:00
struct lv_list * lvl ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( lvl , lvs ) {
2012-03-27 00:33:40 +04:00
if ( ! exclusive & & ! lv_is_active_exclusive ( lvl - > lv ) ) {
2008-04-09 16:56:34 +04:00
if ( ! activate_lv ( cmd , lvl - > lv ) ) {
log_error ( " Failed to activate %s " , lvl - > lv - > name ) ;
return 0 ;
}
} else if ( ! activate_lv_excl ( cmd , lvl - > lv ) ) {
2005-06-01 20:51:55 +04:00
log_error ( " Failed to activate %s " , lvl - > lv - > name ) ;
2008-11-04 01:14:30 +03:00
dm_list_uniterate ( lvh , lvs , & lvl - > list ) {
lvl = dm_list_item ( lvh , struct lv_list ) ;
2010-01-06 00:08:34 +03:00
if ( ! activate_lv ( cmd , lvl - > lv ) )
stack ;
2004-03-26 23:49:35 +03:00
}
return 0 ;
}
}
return 1 ;
}
2003-11-21 22:54:40 +03:00
int vg_write_lock_held ( void )
{
return _vg_write_lock_held ;
}
2005-03-22 01:55:12 +03:00
int locking_is_clustered ( void )
{
return ( _locking . flags & LCK_CLUSTERED ) ? 1 : 0 ;
}
2011-02-04 23:30:17 +03:00
int remote_lock_held ( const char * vol , int * exclusive )
2009-05-19 14:38:58 +04:00
{
int mode = LCK_NULL ;
if ( ! locking_is_clustered ( ) )
return 0 ;
2009-05-21 07:04:52 +04:00
if ( ! _locking . query_resource )
2009-05-20 16:58:03 +04:00
return - 1 ;
2009-05-19 14:38:58 +04:00
/*
* If an error occured , expect that volume is active
*/
2009-05-21 07:04:52 +04:00
if ( ! _locking . query_resource ( vol , & mode ) ) {
2009-05-19 14:38:58 +04:00
stack ;
return 1 ;
}
2011-02-04 23:30:17 +03:00
if ( exclusive )
* exclusive = ( mode = = LCK_EXCL ) ;
2009-05-19 14:38:58 +04:00
return mode = = LCK_NULL ? 0 : 1 ;
}
2011-02-18 17:16:11 +03:00
int sync_local_dev_names ( struct cmd_context * cmd )
{
memlock_unlock ( cmd ) ;
2011-04-29 00:29:59 +04:00
2013-03-18 00:29:58 +04:00
return lock_vol ( cmd , VG_SYNC_NAMES , LCK_VG_SYNC_LOCAL , NULL ) ;
2011-02-18 17:16:11 +03:00
}
int sync_dev_names ( struct cmd_context * cmd )
{
memlock_unlock ( cmd ) ;
2011-04-29 00:29:59 +04:00
2013-03-18 00:29:58 +04:00
return lock_vol ( cmd , VG_SYNC_NAMES , LCK_VG_SYNC , NULL ) ;
2011-02-18 17:16:11 +03:00
}