2002-02-11 15:42:34 +00:00
/*
2008-01-30 14:00:02 +00:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2011-02-18 14:16:11 +00:00
* Copyright ( C ) 2004 - 2011 Red Hat , Inc . All rights reserved .
2002-02-11 15:42:34 +00:00
*
2004-03-30 19:35:44 +00:00
* This file is part of LVM2 .
2002-02-11 15:42:34 +00:00
*
2004-03-30 19:35:44 +00: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-20 20:55:30 +00:00
* of the GNU Lesser General Public License v .2 .1 .
2004-03-30 19:35:44 +00:00
*
2007-08-20 20:55:30 +00:00
* You should have received a copy of the GNU Lesser General Public License
2004-03-30 19:35:44 +00:00
* along with this program ; if not , write to the Free Software Foundation ,
2016-01-21 11:49:46 +01:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2002-02-11 15:42:34 +00:00
*/
2018-05-14 10:30:20 +01:00
# include "lib/misc/lib.h"
# include "lib/locking/locking.h"
2002-02-11 15:42:34 +00:00
# include "locking_types.h"
2018-05-14 10:30:20 +01:00
# include "lib/misc/lvm-string.h"
# include "lib/activate/activate.h"
# include "lib/commands/toolcontext.h"
# include "lib/mm/memlock.h"
# include "lib/config/defaults.h"
# include "lib/cache/lvmcache.h"
# include "lib/misc/lvm-signal.h"
2002-02-11 15:42:34 +00:00
2008-11-04 15:07:45 +00:00
# include <assert.h>
2002-11-01 19:57:25 +00:00
# include <sys/stat.h>
# include <limits.h>
2003-07-04 22:34:56 +00:00
# include <unistd.h>
2002-02-11 15:42:34 +00:00
static struct locking_type _locking ;
2003-11-21 19:54:40 +00:00
static int _vg_lock_count = 0 ; /* Number of locks held */
static int _vg_write_lock_held = 0 ; /* VG write lock held? */
2009-07-24 23:28:55 +00:00
static int _blocking_supported = 0 ;
2002-02-11 15:42:34 +00:00
2014-05-01 20:07:17 +01:00
static void _unblock_signals ( void )
{
/* Don't unblock signals while any locks are held */
if ( ! _vg_lock_count )
unblock_signals ( ) ;
}
2003-05-06 12:03:13 +00:00
void reset_locking ( void )
{
2003-11-21 19:54:40 +00:00
int was_locked = _vg_lock_count ;
2003-05-06 12:03:13 +00:00
2003-11-21 19:54:40 +00:00
_vg_lock_count = 0 ;
_vg_write_lock_held = 0 ;
2003-05-06 12:03:13 +00:00
2010-01-13 17:40:17 +00:00
if ( _locking . reset_locking )
_locking . reset_locking ( ) ;
2003-05-06 12:03:13 +00:00
if ( was_locked )
_unblock_signals ( ) ;
2011-02-18 14:16:11 +00:00
memlock_reset ( ) ;
2003-05-06 12:03:13 +00:00
}
2009-07-14 11:01:26 +00:00
static void _update_vg_lock_count ( const char * resource , uint32_t flags )
2002-02-11 15:42:34 +00:00
{
2009-07-14 11:01:26 +00:00
/* Ignore locks not associated with updating VG metadata */
2009-02-22 16:13:57 +00:00
if ( ( flags & LCK_SCOPE_MASK ) ! = LCK_VG | |
2009-07-14 11:01:26 +00:00
( flags & LCK_CACHE ) | |
! strcmp ( resource , VG_GLOBAL ) )
2003-11-21 19:54:40 +00:00
return ;
2002-04-04 11:18:45 +00:00
if ( ( flags & LCK_TYPE_MASK ) = = LCK_UNLOCK )
2003-11-21 19:54:40 +00:00
_vg_lock_count - - ;
2002-02-11 15:42:34 +00:00
else
2003-11-21 19:54:40 +00: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 15:42:34 +00:00
}
/*
* Select a locking type
2009-02-03 16:23:19 +00:00
* type : locking type ; if < 0 , then read config tree value
2002-02-11 15:42:34 +00:00
*/
2010-05-06 11:15:55 +00:00
int init_locking ( int type , struct cmd_context * cmd , int suppress_messages )
2002-02-11 15:42:34 +00:00
{
2011-08-11 15:27:46 +00:00
if ( getenv ( " LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES " ) )
2010-02-15 16:46:56 +00:00
suppress_messages = 1 ;
2009-02-03 16:23:19 +00:00
if ( type < 0 )
2013-06-25 12:30:34 +02:00
type = find_config_tree_int ( cmd , global_locking_type_CFG , NULL ) ;
2009-07-24 23:28:55 +00:00
2013-06-25 12:31:53 +02:00
_blocking_supported = find_config_tree_bool ( cmd , global_wait_for_locks_CFG , NULL ) ;
2010-01-22 09:45:29 +00:00
2018-06-05 10:47:01 -05:00
if ( type ! = 1 )
log_warn ( " WARNING: locking_type deprecated, using file locking. " ) ;
2009-07-24 23:28:55 +00:00
2018-06-05 10:47:01 -05:00
if ( type = = 3 )
2018-05-23 10:15:39 -05:00
log_warn ( " WARNING: See lvmlockd(8) for information on using cluster/clvm VGs. " ) ;
2018-06-05 10:47:01 -05:00
log_very_verbose ( " %sFile-based locking selected. " , _blocking_supported ? " " : " Non-blocking " ) ;
2018-05-23 10:15:39 -05:00
2018-06-05 10:47:01 -05:00
if ( ! init_file_locking ( & _locking , cmd , suppress_messages ) )
log_error_suppress ( suppress_messages , " File-based locking initialisation failed. " ) ;
2002-07-10 20:43:32 +00:00
2002-02-11 15:42:34 +00:00
return 1 ;
}
void fin_locking ( void )
{
_locking . fin_locking ( ) ;
}
/*
2002-03-15 16:07:38 +00:00
* VG locking is by VG name .
* FIXME This should become VG uuid .
2002-02-11 15:42:34 +00:00
*/
2018-06-05 16:47:24 -05:00
static int _lock_vol ( struct cmd_context * cmd , const char * resource , uint32_t flags )
2002-03-05 20:03:09 +00:00
{
2011-08-10 16:07:53 +00:00
uint32_t lck_type = flags & LCK_TYPE_MASK ;
uint32_t lck_scope = flags & LCK_SCOPE_MASK ;
2008-04-07 19:17:29 +00:00
int ret = 0 ;
2014-05-01 20:07:17 +01:00
block_signals ( flags ) ;
2002-03-05 20:03:09 +00:00
2007-11-16 21:16:20 +00:00
assert ( resource ) ;
2008-05-09 18:45:15 +00:00
if ( ! * resource ) {
2009-12-16 19:22:11 +00:00
log_error ( INTERNAL_ERROR " Use of P_orphans is deprecated. " ) ;
2013-07-06 10:58:56 +02:00
goto out ;
2008-05-09 18:45:15 +00:00
}
2010-05-19 02:36:33 +00:00
if ( ( is_orphan_vg ( resource ) | | is_global_vg ( resource ) ) & & ( flags & LCK_CACHE ) ) {
2018-02-19 15:30:55 +01:00
log_error ( INTERNAL_ERROR " P_%s referenced. " , resource ) ;
2013-07-06 10:58:56 +02:00
goto out ;
2008-05-09 18:45:15 +00:00
}
2011-08-10 16:07:53 +00:00
if ( cmd - > metadata_read_only & & lck_type = = LCK_WRITE & &
2010-10-25 11:20:54 +00:00
strcmp ( resource , VG_GLOBAL ) ) {
log_error ( " Operation prohibited while global/metadata_read_only is set. " ) ;
2013-07-06 10:58:56 +02:00
goto out ;
2010-10-25 11:20:54 +00:00
}
2018-06-05 16:47:24 -05:00
if ( ( ret = _locking . lock_resource ( cmd , resource , flags , NULL ) ) ) {
2011-08-10 16:07:53 +00: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 15:40:38 +00:00
dev_reset_error_count ( cmd ) ;
2008-04-07 19:17:29 +00:00
}
2009-07-14 11:01:26 +00:00
_update_vg_lock_count ( resource , flags ) ;
2010-04-13 01:54:32 +00:00
} else
stack ;
2002-03-05 20:03:09 +00:00
2011-08-10 16:07:53 +00: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 ) ;
}
2013-07-06 10:58:56 +02:00
out :
2002-03-15 16:07:38 +00:00
_unblock_signals ( ) ;
2002-03-05 20:03:09 +00:00
2008-04-07 19:17:29 +00:00
return ret ;
2002-03-05 20:03:09 +00:00
}
2014-09-22 15:50:07 +02:00
int lock_vol ( struct cmd_context * cmd , const char * vol , uint32_t flags , const struct logical_volume * lv )
2002-02-11 15:42:34 +00:00
{
2010-07-09 15:34:40 +00:00
char resource [ 258 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2011-01-13 14:56:17 +00:00
int lck_type = flags & LCK_TYPE_MASK ;
2009-11-23 10:55:14 +00:00
2007-11-15 21:30:52 +00:00
if ( flags = = LCK_NONE ) {
2013-01-07 22:30:29 +00:00
log_debug_locking ( INTERNAL_ERROR " %s: LCK_NONE lock requested " , vol ) ;
2007-11-15 21:30:52 +00:00
return 1 ;
}
2002-02-11 15:42:34 +00:00
switch ( flags & LCK_SCOPE_MASK ) {
2002-11-01 19:57:25 +00:00
case LCK_VG :
2010-03-31 17:23:56 +00:00
if ( ! _blocking_supported )
2009-05-13 13:02:52 +00:00
flags | = LCK_NONBLOCK ;
2010-05-19 01:16:40 +00:00
/* Global VG_ORPHANS lock covers all orphan formats. */
if ( is_orphan_vg ( vol ) )
vol = VG_ORPHANS ;
2009-07-24 18:15:06 +00:00
break ;
2002-02-11 15:42:34 +00:00
default :
log_error ( " Unrecognised lock scope: %d " ,
flags & LCK_SCOPE_MASK ) ;
return 0 ;
}
2018-02-19 15:30:55 +01:00
if ( ! dm_strncpy ( resource , vol , sizeof ( resource ) ) ) {
log_error ( INTERNAL_ERROR " Resource name %s is too long. " , vol ) ;
return 0 ;
}
2009-07-24 18:15:06 +00:00
2018-06-05 16:47:24 -05:00
if ( ! _lock_vol ( cmd , resource , flags ) )
2011-01-13 14:56:17 +00:00
return_0 ;
2002-02-11 15:42:34 +00:00
2008-05-08 18:35:58 +00:00
/*
* If a real lock was acquired ( i . e . not LCK_CACHE ) ,
* perform an immediate unlock unless LCK_HOLD was requested .
*/
2011-01-13 14:56:17 +00:00
if ( ( lck_type = = LCK_NULL ) | | ( lck_type = = LCK_UNLOCK ) | |
( flags & ( LCK_CACHE | LCK_HOLD ) ) )
return 1 ;
2018-06-05 16:47:24 -05:00
if ( ! _lock_vol ( cmd , resource , ( flags & ~ LCK_TYPE_MASK ) | LCK_UNLOCK ) )
2011-01-13 14:56:17 +00:00
return_0 ;
2002-02-11 15:42:34 +00:00
return 1 ;
}
2003-11-21 19:54:40 +00:00
2004-05-05 12:03:07 +00:00
/* Lock a list of LVs */
2018-01-31 10:53:09 +01:00
int activate_lvs ( struct cmd_context * cmd , struct dm_list * lvs , unsigned exclusive )
2004-05-05 12:03:07 +00:00
{
2008-11-03 22:14:30 +00:00
struct dm_list * lvh ;
2005-06-01 16:51:55 +00:00
struct lv_list * lvl ;
2008-11-03 22:14:30 +00:00
dm_list_iterate_items ( lvl , lvs ) {
2018-06-05 13:21:28 -05:00
if ( ! activate_lv ( cmd , lvl - > lv ) ) {
2018-01-31 10:53:09 +01:00
log_error ( " Failed to activate %s " , display_lvname ( lvl - > lv ) ) ;
2018-06-05 13:21:28 -05:00
2008-11-03 22:14:30 +00:00
dm_list_uniterate ( lvh , lvs , & lvl - > list ) {
lvl = dm_list_item ( lvh , struct lv_list ) ;
2017-11-14 11:35:50 +01:00
if ( ! deactivate_lv ( cmd , lvl - > lv ) )
2010-01-05 21:08:34 +00:00
stack ;
2004-03-26 20:49:35 +00:00
}
return 0 ;
}
}
return 1 ;
}
2003-11-21 19:54:40 +00:00
int vg_write_lock_held ( void )
{
return _vg_write_lock_held ;
}
2005-03-21 22:55:12 +00:00
int locking_is_clustered ( void )
{
return ( _locking . flags & LCK_CLUSTERED ) ? 1 : 0 ;
}
2011-02-18 14:16:11 +00:00
int sync_local_dev_names ( struct cmd_context * cmd )
{
memlock_unlock ( cmd ) ;
2011-04-28 20:29:59 +00:00
2013-03-17 21:29:58 +01:00
return lock_vol ( cmd , VG_SYNC_NAMES , LCK_VG_SYNC_LOCAL , NULL ) ;
2011-02-18 14:16:11 +00:00
}
int sync_dev_names ( struct cmd_context * cmd )
{
memlock_unlock ( cmd ) ;
2011-04-28 20:29:59 +00:00
2013-03-17 21:29:58 +01:00
return lock_vol ( cmd , VG_SYNC_NAMES , LCK_VG_SYNC , NULL ) ;
2011-02-18 14:16:11 +00:00
}
2018-06-05 16:47:24 -05:00