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 ;
static int _lock_count = 0 ; /* Number of locks held */
static int _signals_ignored = 0 ;
static void _ignore_signals ( void )
{
int s ;
if ( _signals_ignored )
return ;
for ( s = 0 ; s < NSIG ; s + + )
signal ( s , SIG_IGN ) ;
_signals_ignored = 1 ;
return ;
}
static void _enable_signals ( void )
{
int s ;
/* Don't enable signals while any locks are held */
if ( ! _signals_ignored | | _lock_count )
return ;
for ( s = 0 ; s < NSIG ; s + + )
signal ( s , SIG_DFL ) ;
_signals_ignored = 0 ;
return ;
}
static inline void _update_lock_count ( int flags )
{
if ( ( flags & LCK_TYPE_MASK ) = = LCK_NONE )
_lock_count - - ;
else
_lock_count + + ;
}
/*
* No locking - currently does nothing .
*/
int no_lock_resource ( const char * resource , int flags )
{
return 1 ;
}
void no_fin_locking ( void )
{
return ;
}
static void _init_no_locking ( struct locking_type * locking ,
struct config_file * cf )
{
locking - > lock_resource = no_lock_resource ;
locking - > fin_locking = no_fin_locking ;
}
/*
* Select a locking type
*/
int init_locking ( int type , struct config_file * cf )
{
switch ( type ) {
case 0 :
_init_no_locking ( & _locking , cf ) ;
log_print ( " WARNING: Locking disabled. Be carefui! "
" This could corrupt your metadata. " ) ;
break ;
case 1 :
if ( ! init_file_locking ( & _locking , cf ) )
return 0 ;
log_very_verbose ( " File-based locking enabled. " ) ;
break ;
/******
case 2 :
if ( ! init_other_locking ( & _locking , cf ) )
return 0 ;
log_very_verbose ( " Other locking enabled. " ) ;
break ;
* * * * * */
default :
log_error ( " Unknown locking type requested. " ) ;
return 0 ;
}
return 1 ;
}
void fin_locking ( void )
{
_locking . fin_locking ( ) ;
}
/*
* VG locking is by name
* LV locking is by struct logical_volume
* FIXME This should take a unique name or id for an LV
*/
int lock_vol ( const void * vol , int flags )
{
2002-02-21 00:30:27 +03:00
struct logical_volume * lv ;
2002-02-11 18:42:34 +03:00
char resource [ 258 ] ;
switch ( flags & LCK_SCOPE_MASK ) {
case LCK_VG :
/*
* Lock a volume group before changing on - disk metadata .
*/
strncpy ( resource , ( char * ) vol , sizeof ( resource ) ) ;
break ;
case LCK_LV :
/*
* Suspends LV if it ' s active .
*/
2002-02-21 00:30:27 +03:00
lv = ( struct logical_volume * ) vol ;
if ( lvm_snprintf ( resource , sizeof ( resource ) , " %s/%s " ,
lv - > vg - > name , lv - > name ) < 0 ) {
log_error ( " Lock resource name too long: %s " , resource ) ;
return 0 ;
}
break ;
2002-02-11 18:42:34 +03:00
default :
log_error ( " Unrecognised lock scope: %d " ,
flags & LCK_SCOPE_MASK ) ;
return 0 ;
}
_ignore_signals ( ) ;
if ( ! ( _locking . lock_resource ( resource , flags ) ) ) {
_enable_signals ( ) ;
return 0 ;
}
2002-02-21 00:30:27 +03:00
/****** FIXME
This should move down into lock_resource when the activation calls
can handle struct ids and read their own metadata .
* * * * * */
if ( ( flags & LCK_SCOPE_MASK ) = = LCK_LV ) {
switch ( flags & LCK_TYPE_MASK ) {
case LCK_NONE :
if ( lv_active ( lv ) )
lv_reactivate ( lv ) ;
break ;
case LCK_WRITE :
if ( lv_active ( lv ) )
lv_suspend ( lv ) ;
break ;
default :
break ;
}
}
2002-02-11 18:42:34 +03:00
_update_lock_count ( flags ) ;
_enable_signals ( ) ;
return 1 ;
}