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 .
2014-01-27 15:11:09 +04:00
* Copyright ( C ) 2004 - 2014 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 ,
2016-01-21 13:49:46 +03:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 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 "activate.h"
# include "config.h"
# include "defaults.h"
# include "lvm-string.h"
2014-05-01 20:37:14 +04:00
# include "lvm-flock.h"
2008-04-15 18:46:19 +04:00
# include "lvmcache.h"
2002-02-11 18:42:34 +03:00
# include <limits.h>
# include <unistd.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <signal.h>
2014-03-19 03:22:18 +04:00
static char _lock_dir [ PATH_MAX ] ;
2002-02-11 18:42:34 +03:00
2002-12-20 02:25:55 +03:00
static void _fin_file_locking ( void )
2002-02-11 18:42:34 +03:00
{
2014-05-01 20:37:14 +04:00
release_flocks ( 1 ) ;
2003-05-06 16:03:13 +04:00
}
static void _reset_file_locking ( void )
{
2014-05-01 20:37:14 +04:00
release_flocks ( 0 ) ;
2002-02-11 18:42:34 +03:00
}
2002-12-20 02:25:55 +03:00
static int _file_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 )
2002-02-11 18:42:34 +03:00
{
char lockfile [ PATH_MAX ] ;
2010-08-17 23:25:05 +04:00
unsigned origin_only = ( flags & LCK_ORIGIN_ONLY ) ? 1 : 0 ;
2011-09-28 02:43:40 +04:00
unsigned revert = ( flags & LCK_REVERT ) ? 1 : 0 ;
2002-02-11 18:42:34 +03:00
switch ( flags & LCK_SCOPE_MASK ) {
2014-06-20 16:24:02 +04:00
case LCK_ACTIVATION :
if ( dm_snprintf ( lockfile , sizeof ( lockfile ) ,
" %s/A_%s " , _lock_dir , resource + 1 ) < 0 ) {
log_error ( " Too long locking filename %s/A_%s. " , _lock_dir , resource + 1 ) ;
return 0 ;
}
if ( ! lock_file ( lockfile , flags ) )
return_0 ;
break ;
2002-02-11 18:42:34 +03:00
case LCK_VG :
2014-10-21 16:47:46 +04:00
if ( ! strcmp ( resource , VG_SYNC_NAMES ) ) {
2011-01-12 23:42:50 +03:00
fs_unlock ( ) ;
2014-10-21 16:47:46 +04:00
} else if ( strcmp ( resource , VG_GLOBAL ) )
/* Skip cache refresh for VG_GLOBAL - the caller handles it */
lvmcache_drop_metadata ( resource , 0 ) ;
2011-01-12 23:42:50 +03:00
2008-05-09 23:26:58 +04:00
/* LCK_CACHE does not require a real lock */
if ( flags & LCK_CACHE )
2008-04-15 18:46:19 +04:00
break ;
2008-05-09 23:26:58 +04:00
2011-01-05 18:10:30 +03:00
if ( is_orphan_vg ( resource ) | | is_global_vg ( resource ) ) {
if ( dm_snprintf ( lockfile , sizeof ( lockfile ) ,
" %s/P_%s " , _lock_dir , resource + 1 ) < 0 ) {
log_error ( " Too long locking filename %s/P_%s. " ,
_lock_dir , resource + 1 ) ;
return 0 ;
}
} else
if ( dm_snprintf ( lockfile , sizeof ( lockfile ) ,
" %s/V_%s " , _lock_dir , resource ) < 0 ) {
log_error ( " Too long locking filename %s/V_%s. " ,
_lock_dir , resource ) ;
return 0 ;
}
2003-07-05 02:34:56 +04:00
2014-05-01 20:37:14 +04:00
if ( ! lock_file ( lockfile , flags ) )
2008-04-03 22:56:40 +04:00
return_0 ;
2002-02-11 18:42:34 +03:00
break ;
case LCK_LV :
2002-02-21 00:30:27 +03:00
switch ( flags & LCK_TYPE_MASK ) {
2002-04-04 15:18:45 +04:00
case LCK_UNLOCK :
2011-09-28 02:43:40 +04:00
log_very_verbose ( " Unlocking LV %s%s%s " , resource , origin_only ? " without snapshots " : " " , revert ? " (reverting) " : " " ) ;
2015-11-25 13:10:32 +03:00
if ( ! lv_resume_if_active ( cmd , resource , origin_only , 0 , revert , lv_committed ( lv ) ) )
2002-02-25 15:56:16 +03:00
return 0 ;
2002-02-21 00:30:27 +03:00
break ;
2004-05-05 16:03:07 +04:00
case LCK_NULL :
2007-11-17 00:16:20 +03:00
log_very_verbose ( " Locking LV %s (NL) " , resource ) ;
2015-11-25 13:10:32 +03:00
if ( ! lv_deactivate ( cmd , resource , lv_committed ( lv ) ) )
2004-05-05 16:03:07 +04:00
return 0 ;
break ;
2002-02-27 15:26:41 +03:00
case LCK_READ :
2007-11-17 00:16:20 +03:00
log_very_verbose ( " Locking LV %s (R) " , resource ) ;
2015-11-25 13:10:32 +03:00
if ( ! lv_activate_with_filter ( cmd , resource , 0 , ( lv - > status & LV_NOSCAN ) ? 1 : 0 ,
( lv - > status & LV_TEMPORARY ) ? 1 : 0 , lv_committed ( lv ) ) )
2002-02-27 15:26:41 +03:00
return 0 ;
break ;
2007-11-17 00:16:20 +03:00
case LCK_PREAD :
log_very_verbose ( " Locking LV %s (PR) - ignored " , resource ) ;
break ;
2002-02-21 00:30:27 +03:00
case LCK_WRITE :
2010-08-17 23:25:05 +04:00
log_very_verbose ( " Locking LV %s (W)%s " , resource , origin_only ? " without snapshots " : " " ) ;
2015-11-25 13:10:32 +03:00
if ( ! lv_suspend_if_active ( cmd , resource , origin_only , 0 , lv_committed ( lv ) , lv ) )
2002-02-25 15:56:16 +03:00
return 0 ;
2002-02-21 00:30:27 +03:00
break ;
2002-02-27 15:26:41 +03:00
case LCK_EXCL :
2007-11-17 00:16:20 +03:00
log_very_verbose ( " Locking LV %s (EX) " , resource ) ;
2015-11-25 13:10:32 +03:00
if ( ! lv_activate_with_filter ( cmd , resource , 1 , ( lv - > status & LV_NOSCAN ) ? 1 : 0 ,
( lv - > status & LV_TEMPORARY ) ? 1 : 0 , lv_committed ( lv ) ) )
2002-02-27 15:26:41 +03:00
return 0 ;
break ;
2002-02-21 00:30:27 +03:00
default :
break ;
}
2002-02-25 15:56:16 +03:00
break ;
default :
log_error ( " Unrecognised lock scope: %d " ,
flags & LCK_SCOPE_MASK ) ;
return 0 ;
2002-02-21 00:30:27 +03:00
}
2002-02-25 15:56:16 +03:00
return 1 ;
}
2011-08-09 15:44:57 +04:00
int init_file_locking ( struct locking_type * locking , struct cmd_context * cmd ,
int suppress_messages )
2002-02-11 18:42:34 +03:00
{
2011-04-08 18:13:08 +04:00
int r ;
2012-02-08 15:17:34 +04:00
const char * locking_dir ;
2011-04-08 18:13:08 +04:00
2014-05-01 20:37:14 +04:00
init_flock ( cmd ) ;
2002-12-20 02:25:55 +03:00
locking - > lock_resource = _file_lock_resource ;
2003-05-06 16:03:13 +04:00
locking - > reset_locking = _reset_file_locking ;
2002-12-20 02:25:55 +03:00
locking - > fin_locking = _fin_file_locking ;
2004-03-26 23:17:11 +03:00
locking - > flags = 0 ;
2002-02-11 18:42:34 +03:00
/* Get lockfile directory from config file */
2013-06-25 14:29:54 +04:00
locking_dir = find_config_tree_str ( cmd , global_locking_dir_CFG , NULL ) ;
2012-02-08 15:17:34 +04:00
if ( strlen ( locking_dir ) > = sizeof ( _lock_dir ) ) {
log_error ( " Path for locking_dir %s is invalid. " , locking_dir ) ;
return 0 ;
}
strcpy ( _lock_dir , locking_dir ) ;
2002-02-11 18:42:34 +03:00
2010-12-13 13:43:56 +03:00
( void ) dm_prepare_selinux_context ( _lock_dir , S_IFDIR ) ;
r = dm_create_dir ( _lock_dir ) ;
( void ) dm_prepare_selinux_context ( NULL , 0 ) ;
if ( ! r )
2002-02-11 18:42:34 +03:00
return 0 ;
2002-07-11 00:43:32 +04:00
/* Trap a read-only file system */
if ( ( access ( _lock_dir , R_OK | W_OK | X_OK ) = = - 1 ) & & ( errno = = EROFS ) )
return 0 ;
2002-02-11 18:42:34 +03:00
return 1 ;
}