2002-02-11 18:42:34 +03:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
* This file is released under the LGPL .
*
*/
# include "log.h"
# include "locking.h"
# include "locking_types.h"
# include "lvm-string.h"
# include "activate.h"
# include <signal.h>
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
2002-03-15 19:07:38 +03:00
static int _lock_count = 0 ; /* Number of locks held */
static int _signals_blocked = 0 ;
2002-02-11 18:42:34 +03:00
2002-03-15 19:07:38 +03:00
static void _block_signals ( void )
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
return ;
}
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 */
if ( ! _signals_blocked | | _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
return ;
}
static inline void _update_lock_count ( int flags )
{
2002-04-04 15:18:45 +04:00
if ( ( flags & LCK_TYPE_MASK ) = = LCK_UNLOCK )
2002-02-11 18:42:34 +03:00
_lock_count - - ;
else
_lock_count + + ;
}
/*
* Select a locking type
*/
int init_locking ( int type , struct config_file * cf )
{
switch ( type ) {
case 0 :
2002-04-11 18:10:32 +04:00
init_no_locking ( & _locking , cf ) ;
2002-03-25 21:50:37 +03:00
log_print ( " WARNING: Locking disabled. Be careful! "
2002-02-11 18:42:34 +03:00
" This could corrupt your metadata. " ) ;
break ;
case 1 :
if ( ! init_file_locking ( & _locking , cf ) )
return 0 ;
log_very_verbose ( " File-based locking enabled. " ) ;
break ;
2002-04-08 20:04:50 +04:00
2002-02-11 18:42:34 +03:00
case 2 :
2002-04-08 20:04:50 +04:00
if ( ! init_external_locking ( & _locking , cf ) )
2002-02-11 18:42:34 +03:00
return 0 ;
2002-04-08 20:04:50 +04:00
log_very_verbose ( " External locking enabled. " ) ;
2002-02-11 18:42:34 +03:00
break ;
2002-04-08 20:04:50 +04:00
2002-02-11 18:42:34 +03:00
default :
log_error ( " Unknown locking type requested. " ) ;
return 0 ;
}
return 1 ;
}
void fin_locking ( void )
{
_locking . fin_locking ( ) ;
}
/*
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
*/
2002-03-05 23:03:09 +03:00
int _lock_vol ( struct cmd_context * cmd , const char * resource , int flags )
{
2002-03-15 19:07:38 +03:00
_block_signals ( ) ;
2002-03-05 23:03:09 +03:00
if ( ! ( _locking . lock_resource ( cmd , resource , flags ) ) ) {
2002-03-15 19:07:38 +03:00
_unblock_signals ( ) ;
2002-03-05 23:03:09 +03:00
return 0 ;
}
_update_lock_count ( flags ) ;
2002-03-15 19:07:38 +03:00
_unblock_signals ( ) ;
2002-03-05 23:03:09 +03:00
return 1 ;
}
2002-02-25 15:56:16 +03:00
int lock_vol ( struct cmd_context * cmd , const char * vol , int flags )
2002-02-11 18:42:34 +03:00
{
char resource [ 258 ] ;
switch ( flags & LCK_SCOPE_MASK ) {
2002-03-15 19:07:38 +03:00
case LCK_VG : /* Lock VG to change on-disk metadata. */
case LCK_LV : /* Suspends LV if it's active. */
2002-02-11 18:42:34 +03:00
strncpy ( resource , ( char * ) vol , sizeof ( resource ) ) ;
break ;
default :
log_error ( " Unrecognised lock scope: %d " ,
flags & LCK_SCOPE_MASK ) ;
return 0 ;
}
2002-03-05 23:03:09 +03:00
if ( ! _lock_vol ( cmd , resource , flags ) )
2002-02-11 18:42:34 +03:00
return 0 ;
2002-03-05 23:03:09 +03:00
/* Perform immediate unlock unless LCK_HOLD set */
2002-04-04 15:18:45 +04:00
if ( ! ( flags & LCK_HOLD ) & & ( ( flags & LCK_TYPE_MASK ) ! = LCK_UNLOCK ) ) {
2002-03-15 19:07:38 +03:00
if ( ! _lock_vol ( cmd , resource ,
2002-04-04 15:18:45 +04:00
( flags & ~ LCK_TYPE_MASK ) | LCK_UNLOCK ) )
2002-03-05 23:03:09 +03:00
return 0 ;
}
2002-02-11 18:42:34 +03:00
return 1 ;
}