Home | History | Annotate | Line # | Download | only in locking
      1      1.1  haad /*	$NetBSD: locking.c,v 1.1.1.3 2009/12/02 00:26:25 haad Exp $	*/
      2      1.1  haad 
      3      1.1  haad /*
      4      1.1  haad  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
      5      1.1  haad  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
      6      1.1  haad  *
      7      1.1  haad  * This file is part of LVM2.
      8      1.1  haad  *
      9      1.1  haad  * This copyrighted material is made available to anyone wishing to use,
     10      1.1  haad  * modify, copy, or redistribute it subject to the terms and conditions
     11      1.1  haad  * of the GNU Lesser General Public License v.2.1.
     12      1.1  haad  *
     13      1.1  haad  * You should have received a copy of the GNU Lesser General Public License
     14      1.1  haad  * along with this program; if not, write to the Free Software Foundation,
     15      1.1  haad  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     16      1.1  haad  */
     17      1.1  haad 
     18      1.1  haad #include "lib.h"
     19      1.1  haad #include "locking.h"
     20      1.1  haad #include "locking_types.h"
     21      1.1  haad #include "lvm-string.h"
     22      1.1  haad #include "activate.h"
     23      1.1  haad #include "toolcontext.h"
     24      1.1  haad #include "memlock.h"
     25      1.1  haad #include "defaults.h"
     26      1.1  haad #include "lvmcache.h"
     27      1.1  haad 
     28      1.1  haad #include <assert.h>
     29      1.1  haad #include <signal.h>
     30      1.1  haad #include <sys/stat.h>
     31      1.1  haad #include <limits.h>
     32      1.1  haad #include <unistd.h>
     33      1.1  haad 
     34      1.1  haad static struct locking_type _locking;
     35      1.1  haad static sigset_t _oldset;
     36      1.1  haad 
     37      1.1  haad static int _vg_lock_count = 0;		/* Number of locks held */
     38      1.1  haad static int _vg_write_lock_held = 0;	/* VG write lock held? */
     39      1.1  haad static int _signals_blocked = 0;
     40  1.1.1.3  haad static int _blocking_supported = 0;
     41      1.1  haad 
     42      1.1  haad static volatile sig_atomic_t _sigint_caught = 0;
     43      1.1  haad static volatile sig_atomic_t _handler_installed;
     44      1.1  haad static struct sigaction _oldhandler;
     45      1.1  haad static int _oldmasked;
     46      1.1  haad 
     47  1.1.1.3  haad typedef enum {
     48  1.1.1.3  haad         LV_NOOP,
     49  1.1.1.3  haad         LV_SUSPEND,
     50  1.1.1.3  haad         LV_RESUME
     51  1.1.1.3  haad } lv_operation_t;
     52  1.1.1.3  haad 
     53      1.1  haad static void _catch_sigint(int unused __attribute__((unused)))
     54      1.1  haad {
     55      1.1  haad 	_sigint_caught = 1;
     56      1.1  haad }
     57      1.1  haad 
     58      1.1  haad int sigint_caught(void) {
     59      1.1  haad 	return _sigint_caught;
     60      1.1  haad }
     61      1.1  haad 
     62      1.1  haad void sigint_clear(void)
     63      1.1  haad {
     64      1.1  haad 	_sigint_caught = 0;
     65      1.1  haad }
     66      1.1  haad 
     67      1.1  haad /*
     68      1.1  haad  * Temporarily allow keyboard interrupts to be intercepted and noted;
     69      1.1  haad  * saves interrupt handler state for sigint_restore().  Users should
     70      1.1  haad  * use the sigint_caught() predicate to check whether interrupt was
     71      1.1  haad  * requested and act appropriately.  Interrupt flags are never
     72      1.1  haad  * cleared automatically by this code, but the tools clear the flag
     73      1.1  haad  * before running each command in lvm_run_command().  All other places
     74      1.1  haad  * where the flag needs to be cleared need to call sigint_clear().
     75      1.1  haad  */
     76      1.1  haad 
     77      1.1  haad void sigint_allow(void)
     78      1.1  haad {
     79      1.1  haad 	struct sigaction handler;
     80      1.1  haad 	sigset_t sigs;
     81      1.1  haad 
     82      1.1  haad 	/*
     83      1.1  haad 	 * Do not overwrite the backed-up handler data -
     84      1.1  haad 	 * just increase nesting count.
     85      1.1  haad 	 */
     86      1.1  haad 	if (_handler_installed) {
     87      1.1  haad 		_handler_installed++;
     88      1.1  haad 		return;
     89      1.1  haad 	}
     90      1.1  haad 
     91      1.1  haad 	/* Grab old sigaction for SIGINT: shall not fail. */
     92      1.1  haad 	sigaction(SIGINT, NULL, &handler);
     93      1.1  haad 	handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */
     94      1.1  haad 	handler.sa_handler = _catch_sigint;
     95      1.1  haad 
     96      1.1  haad 	_handler_installed = 1;
     97      1.1  haad 
     98      1.1  haad 	/* Override the signal handler: shall not fail. */
     99      1.1  haad 	sigaction(SIGINT, &handler, &_oldhandler);
    100      1.1  haad 
    101      1.1  haad 	/* Unmask SIGINT.  Remember to mask it again on restore. */
    102      1.1  haad 	sigprocmask(0, NULL, &sigs);
    103      1.1  haad 	if ((_oldmasked = sigismember(&sigs, SIGINT))) {
    104      1.1  haad 		sigdelset(&sigs, SIGINT);
    105      1.1  haad 		sigprocmask(SIG_SETMASK, &sigs, NULL);
    106      1.1  haad 	}
    107      1.1  haad }
    108      1.1  haad 
    109      1.1  haad void sigint_restore(void)
    110      1.1  haad {
    111      1.1  haad 	if (!_handler_installed)
    112      1.1  haad 		return;
    113      1.1  haad 
    114      1.1  haad 	if (_handler_installed > 1) {
    115      1.1  haad 		_handler_installed--;
    116      1.1  haad 		return;
    117      1.1  haad 	}
    118      1.1  haad 
    119      1.1  haad 	/* Nesting count went down to 0. */
    120      1.1  haad 	_handler_installed = 0;
    121      1.1  haad 
    122      1.1  haad 	if (_oldmasked) {
    123      1.1  haad 		sigset_t sigs;
    124      1.1  haad 		sigprocmask(0, NULL, &sigs);
    125      1.1  haad 		sigaddset(&sigs, SIGINT);
    126      1.1  haad 		sigprocmask(SIG_SETMASK, &sigs, NULL);
    127      1.1  haad 	}
    128      1.1  haad 
    129      1.1  haad 	sigaction(SIGINT, &_oldhandler, NULL);
    130      1.1  haad }
    131      1.1  haad 
    132      1.1  haad static void _block_signals(uint32_t flags __attribute((unused)))
    133      1.1  haad {
    134      1.1  haad 	sigset_t set;
    135      1.1  haad 
    136      1.1  haad 	if (_signals_blocked)
    137      1.1  haad 		return;
    138      1.1  haad 
    139      1.1  haad 	if (sigfillset(&set)) {
    140      1.1  haad 		log_sys_error("sigfillset", "_block_signals");
    141      1.1  haad 		return;
    142      1.1  haad 	}
    143      1.1  haad 
    144      1.1  haad 	if (sigprocmask(SIG_SETMASK, &set, &_oldset)) {
    145      1.1  haad 		log_sys_error("sigprocmask", "_block_signals");
    146      1.1  haad 		return;
    147      1.1  haad 	}
    148      1.1  haad 
    149      1.1  haad 	_signals_blocked = 1;
    150      1.1  haad 
    151      1.1  haad 	return;
    152      1.1  haad }
    153      1.1  haad 
    154      1.1  haad static void _unblock_signals(void)
    155      1.1  haad {
    156      1.1  haad 	/* Don't unblock signals while any locks are held */
    157      1.1  haad 	if (!_signals_blocked || _vg_lock_count)
    158      1.1  haad 		return;
    159      1.1  haad 
    160      1.1  haad 	if (sigprocmask(SIG_SETMASK, &_oldset, NULL)) {
    161      1.1  haad 		log_sys_error("sigprocmask", "_block_signals");
    162      1.1  haad 		return;
    163      1.1  haad 	}
    164      1.1  haad 
    165      1.1  haad 	_signals_blocked = 0;
    166      1.1  haad 
    167      1.1  haad 	return;
    168      1.1  haad }
    169      1.1  haad 
    170  1.1.1.3  haad static void _lock_memory(lv_operation_t lv_op)
    171      1.1  haad {
    172      1.1  haad 	if (!(_locking.flags & LCK_PRE_MEMLOCK))
    173      1.1  haad 		return;
    174      1.1  haad 
    175  1.1.1.3  haad 	if (lv_op == LV_SUSPEND)
    176      1.1  haad 		memlock_inc();
    177      1.1  haad }
    178      1.1  haad 
    179  1.1.1.3  haad static void _unlock_memory(lv_operation_t lv_op)
    180      1.1  haad {
    181      1.1  haad 	if (!(_locking.flags & LCK_PRE_MEMLOCK))
    182      1.1  haad 		return;
    183      1.1  haad 
    184  1.1.1.3  haad 	if (lv_op == LV_RESUME)
    185      1.1  haad 		memlock_dec();
    186      1.1  haad }
    187      1.1  haad 
    188      1.1  haad void reset_locking(void)
    189      1.1  haad {
    190      1.1  haad 	int was_locked = _vg_lock_count;
    191      1.1  haad 
    192      1.1  haad 	_vg_lock_count = 0;
    193      1.1  haad 	_vg_write_lock_held = 0;
    194      1.1  haad 
    195      1.1  haad 	_locking.reset_locking();
    196      1.1  haad 
    197      1.1  haad 	if (was_locked)
    198      1.1  haad 		_unblock_signals();
    199      1.1  haad }
    200      1.1  haad 
    201  1.1.1.3  haad static void _update_vg_lock_count(const char *resource, uint32_t flags)
    202      1.1  haad {
    203  1.1.1.3  haad 	/* Ignore locks not associated with updating VG metadata */
    204  1.1.1.3  haad 	if ((flags & LCK_SCOPE_MASK) != LCK_VG ||
    205  1.1.1.3  haad 	    (flags & LCK_CACHE) ||
    206  1.1.1.3  haad 	    !strcmp(resource, VG_GLOBAL))
    207      1.1  haad 		return;
    208      1.1  haad 
    209      1.1  haad 	if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)
    210      1.1  haad 		_vg_lock_count--;
    211      1.1  haad 	else
    212      1.1  haad 		_vg_lock_count++;
    213      1.1  haad 
    214      1.1  haad 	/* We don't bother to reset this until all VG locks are dropped */
    215      1.1  haad 	if ((flags & LCK_TYPE_MASK) == LCK_WRITE)
    216      1.1  haad 		_vg_write_lock_held = 1;
    217      1.1  haad 	else if (!_vg_lock_count)
    218      1.1  haad 		_vg_write_lock_held = 0;
    219      1.1  haad }
    220      1.1  haad 
    221      1.1  haad /*
    222      1.1  haad  * Select a locking type
    223  1.1.1.3  haad  * type: locking type; if < 0, then read config tree value
    224      1.1  haad  */
    225      1.1  haad int init_locking(int type, struct cmd_context *cmd)
    226      1.1  haad {
    227  1.1.1.3  haad 	if (type < 0)
    228  1.1.1.3  haad 		type = find_config_tree_int(cmd, "global/locking_type", 1);
    229      1.1  haad 
    230  1.1.1.3  haad 	_blocking_supported = find_config_tree_int(cmd,
    231  1.1.1.3  haad 	    "global/wait_for_locks", DEFAULT_WAIT_FOR_LOCKS);
    232  1.1.1.3  haad 
    233      1.1  haad 	switch (type) {
    234      1.1  haad 	case 0:
    235      1.1  haad 		init_no_locking(&_locking, cmd);
    236      1.1  haad 		log_warn("WARNING: Locking disabled. Be careful! "
    237      1.1  haad 			  "This could corrupt your metadata.");
    238      1.1  haad 		return 1;
    239      1.1  haad 
    240      1.1  haad 	case 1:
    241  1.1.1.3  haad 		log_very_verbose("%sFile-based locking selected.",
    242  1.1.1.3  haad 				 _blocking_supported ? "" : "Non-blocking ");
    243  1.1.1.3  haad 
    244      1.1  haad 		if (!init_file_locking(&_locking, cmd))
    245      1.1  haad 			break;
    246      1.1  haad 		return 1;
    247      1.1  haad 
    248      1.1  haad #ifdef HAVE_LIBDL
    249      1.1  haad 	case 2:
    250  1.1.1.2  haad 		if (!is_static()) {
    251      1.1  haad 			log_very_verbose("External locking selected.");
    252      1.1  haad 			if (init_external_locking(&_locking, cmd))
    253      1.1  haad 				return 1;
    254      1.1  haad 		}
    255      1.1  haad 		if (!find_config_tree_int(cmd, "locking/fallback_to_clustered_locking",
    256      1.1  haad 			    find_config_tree_int(cmd, "global/fallback_to_clustered_locking",
    257      1.1  haad 						 DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING)))
    258      1.1  haad 			break;
    259      1.1  haad #endif
    260      1.1  haad 
    261      1.1  haad #ifdef CLUSTER_LOCKING_INTERNAL
    262      1.1  haad 		log_very_verbose("Falling back to internal clustered locking.");
    263      1.1  haad 		/* Fall through */
    264      1.1  haad 
    265      1.1  haad 	case 3:
    266      1.1  haad 		log_very_verbose("Cluster locking selected.");
    267      1.1  haad 		if (!init_cluster_locking(&_locking, cmd))
    268      1.1  haad 			break;
    269      1.1  haad 		return 1;
    270      1.1  haad #endif
    271      1.1  haad 
    272  1.1.1.3  haad 	case 4:
    273  1.1.1.3  haad 		log_verbose("Read-only locking selected. "
    274  1.1.1.3  haad 			    "Only read operations permitted.");
    275  1.1.1.3  haad 		if (!init_readonly_locking(&_locking, cmd))
    276  1.1.1.3  haad 			break;
    277  1.1.1.3  haad 		return 1;
    278  1.1.1.3  haad 
    279      1.1  haad 	default:
    280      1.1  haad 		log_error("Unknown locking type requested.");
    281      1.1  haad 		return 0;
    282      1.1  haad 	}
    283      1.1  haad 
    284      1.1  haad 	if ((type == 2 || type == 3) &&
    285      1.1  haad 	    find_config_tree_int(cmd, "locking/fallback_to_local_locking",
    286      1.1  haad 	    	    find_config_tree_int(cmd, "global/fallback_to_local_locking",
    287      1.1  haad 					 DEFAULT_FALLBACK_TO_LOCAL_LOCKING))) {
    288      1.1  haad 		log_warn("WARNING: Falling back to local file-based locking.");
    289      1.1  haad 		log_warn("Volume Groups with the clustered attribute will "
    290      1.1  haad 			  "be inaccessible.");
    291      1.1  haad 		if (init_file_locking(&_locking, cmd))
    292      1.1  haad 			return 1;
    293      1.1  haad 	}
    294      1.1  haad 
    295      1.1  haad 	if (!ignorelockingfailure())
    296      1.1  haad 		return 0;
    297      1.1  haad 
    298      1.1  haad 	log_verbose("Locking disabled - only read operations permitted.");
    299  1.1.1.3  haad 	init_readonly_locking(&_locking, cmd);
    300      1.1  haad 
    301      1.1  haad 	return 1;
    302      1.1  haad }
    303      1.1  haad 
    304      1.1  haad void fin_locking(void)
    305      1.1  haad {
    306      1.1  haad 	_locking.fin_locking();
    307      1.1  haad }
    308      1.1  haad 
    309      1.1  haad /*
    310      1.1  haad  * Does the LVM1 driver know of this VG name?
    311      1.1  haad  */
    312      1.1  haad int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname)
    313      1.1  haad {
    314      1.1  haad 	struct stat info;
    315      1.1  haad 	char path[PATH_MAX];
    316      1.1  haad 
    317      1.1  haad 	/* We'll allow operations on orphans */
    318      1.1  haad 	if (is_orphan_vg(vgname))
    319      1.1  haad 		return 1;
    320      1.1  haad 
    321      1.1  haad 	/* LVM1 is only present in 2.4 kernels. */
    322      1.1  haad 	if (strncmp(cmd->kernel_vsn, "2.4.", 4))
    323      1.1  haad 		return 1;
    324      1.1  haad 
    325      1.1  haad 	if (dm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", cmd->proc_dir,
    326      1.1  haad 			 vgname) < 0) {
    327      1.1  haad 		log_error("LVM1 proc VG pathname too long for %s", vgname);
    328      1.1  haad 		return 0;
    329      1.1  haad 	}
    330      1.1  haad 
    331      1.1  haad 	if (stat(path, &info) == 0) {
    332      1.1  haad 		log_error("%s exists: Is the original LVM driver using "
    333      1.1  haad 			  "this volume group?", path);
    334      1.1  haad 		return 0;
    335      1.1  haad 	} else if (errno != ENOENT && errno != ENOTDIR) {
    336      1.1  haad 		log_sys_error("stat", path);
    337      1.1  haad 		return 0;
    338      1.1  haad 	}
    339      1.1  haad 
    340      1.1  haad 	return 1;
    341      1.1  haad }
    342      1.1  haad 
    343      1.1  haad /*
    344      1.1  haad  * VG locking is by VG name.
    345      1.1  haad  * FIXME This should become VG uuid.
    346      1.1  haad  */
    347  1.1.1.3  haad static int _lock_vol(struct cmd_context *cmd, const char *resource,
    348  1.1.1.3  haad 		     uint32_t flags, lv_operation_t lv_op)
    349      1.1  haad {
    350      1.1  haad 	int ret = 0;
    351      1.1  haad 
    352      1.1  haad 	_block_signals(flags);
    353  1.1.1.3  haad 	_lock_memory(lv_op);
    354      1.1  haad 
    355      1.1  haad 	assert(resource);
    356      1.1  haad 
    357      1.1  haad 	if (!*resource) {
    358      1.1  haad 		log_error("Internal error: Use of P_orphans is deprecated.");
    359      1.1  haad 		return 0;
    360      1.1  haad 	}
    361      1.1  haad 
    362      1.1  haad 	if (*resource == '#' && (flags & LCK_CACHE)) {
    363      1.1  haad 		log_error("Internal error: P_%s referenced", resource);
    364      1.1  haad 		return 0;
    365      1.1  haad 	}
    366      1.1  haad 
    367      1.1  haad 	if ((ret = _locking.lock_resource(cmd, resource, flags))) {
    368      1.1  haad 		if ((flags & LCK_SCOPE_MASK) == LCK_VG &&
    369      1.1  haad 		    !(flags & LCK_CACHE)) {
    370      1.1  haad 			if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)
    371      1.1  haad 				lvmcache_unlock_vgname(resource);
    372      1.1  haad 			else
    373      1.1  haad 				lvmcache_lock_vgname(resource, (flags & LCK_TYPE_MASK)
    374      1.1  haad 								== LCK_READ);
    375      1.1  haad 		}
    376      1.1  haad 
    377  1.1.1.3  haad 		_update_vg_lock_count(resource, flags);
    378      1.1  haad 	}
    379      1.1  haad 
    380  1.1.1.3  haad 	_unlock_memory(lv_op);
    381      1.1  haad 	_unblock_signals();
    382      1.1  haad 
    383      1.1  haad 	return ret;
    384      1.1  haad }
    385      1.1  haad 
    386      1.1  haad int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags)
    387      1.1  haad {
    388      1.1  haad 	char resource[258] __attribute((aligned(8)));
    389  1.1.1.3  haad 	lv_operation_t lv_op;
    390  1.1.1.3  haad 
    391  1.1.1.3  haad 	switch (flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) {
    392  1.1.1.3  haad 		case LCK_LV_SUSPEND:
    393  1.1.1.3  haad 				lv_op = LV_SUSPEND;
    394  1.1.1.3  haad 				break;
    395  1.1.1.3  haad 		case LCK_LV_RESUME:
    396  1.1.1.3  haad 				lv_op = LV_RESUME;
    397  1.1.1.3  haad 				break;
    398  1.1.1.3  haad 		default:	lv_op = LV_NOOP;
    399  1.1.1.3  haad 	}
    400  1.1.1.3  haad 
    401      1.1  haad 
    402      1.1  haad 	if (flags == LCK_NONE) {
    403      1.1  haad 		log_debug("Internal error: %s: LCK_NONE lock requested", vol);
    404      1.1  haad 		return 1;
    405      1.1  haad 	}
    406      1.1  haad 
    407      1.1  haad 	switch (flags & LCK_SCOPE_MASK) {
    408      1.1  haad 	case LCK_VG:
    409  1.1.1.3  haad 		/*
    410  1.1.1.3  haad 		 * Automatically set LCK_NONBLOCK if one or more VGs locked.
    411  1.1.1.3  haad 		 * This will enforce correctness and prevent deadlocks rather
    412  1.1.1.3  haad 		 * than relying on the caller to set the flag properly.
    413  1.1.1.3  haad 		 */
    414  1.1.1.3  haad 		if (!_blocking_supported || vgs_locked())
    415  1.1.1.3  haad 			flags |= LCK_NONBLOCK;
    416  1.1.1.3  haad 
    417  1.1.1.3  haad 		if (vol[0] != '#' &&
    418  1.1.1.3  haad 		    ((flags & LCK_TYPE_MASK) != LCK_UNLOCK) &&
    419  1.1.1.3  haad 		    (!(flags & LCK_CACHE)) &&
    420  1.1.1.3  haad 		    !lvmcache_verify_lock_order(vol))
    421  1.1.1.3  haad 			return 0;
    422  1.1.1.3  haad 
    423      1.1  haad 		/* Lock VG to change on-disk metadata. */
    424      1.1  haad 		/* If LVM1 driver knows about the VG, it can't be accessed. */
    425      1.1  haad 		if (!check_lvm1_vg_inactive(cmd, vol))
    426      1.1  haad 			return 0;
    427  1.1.1.3  haad 		break;
    428      1.1  haad 	case LCK_LV:
    429  1.1.1.3  haad 		/* All LV locks are non-blocking. */
    430  1.1.1.3  haad 		flags |= LCK_NONBLOCK;
    431      1.1  haad 		break;
    432      1.1  haad 	default:
    433      1.1  haad 		log_error("Unrecognised lock scope: %d",
    434      1.1  haad 			  flags & LCK_SCOPE_MASK);
    435      1.1  haad 		return 0;
    436      1.1  haad 	}
    437      1.1  haad 
    438  1.1.1.3  haad 	strncpy(resource, vol, sizeof(resource));
    439  1.1.1.3  haad 
    440  1.1.1.3  haad 	if (!_lock_vol(cmd, resource, flags, lv_op))
    441      1.1  haad 		return 0;
    442      1.1  haad 
    443      1.1  haad 	/*
    444      1.1  haad 	 * If a real lock was acquired (i.e. not LCK_CACHE),
    445      1.1  haad 	 * perform an immediate unlock unless LCK_HOLD was requested.
    446      1.1  haad 	 */
    447      1.1  haad 	if (!(flags & LCK_CACHE) && !(flags & LCK_HOLD) &&
    448      1.1  haad 	    ((flags & LCK_TYPE_MASK) != LCK_UNLOCK)) {
    449      1.1  haad 		if (!_lock_vol(cmd, resource,
    450  1.1.1.3  haad 			       (flags & ~LCK_TYPE_MASK) | LCK_UNLOCK, lv_op))
    451      1.1  haad 			return 0;
    452      1.1  haad 	}
    453      1.1  haad 
    454      1.1  haad 	return 1;
    455      1.1  haad }
    456      1.1  haad 
    457      1.1  haad /* Unlock list of LVs */
    458      1.1  haad int resume_lvs(struct cmd_context *cmd, struct dm_list *lvs)
    459      1.1  haad {
    460      1.1  haad 	struct lv_list *lvl;
    461      1.1  haad 
    462      1.1  haad 	dm_list_iterate_items(lvl, lvs)
    463      1.1  haad 		resume_lv(cmd, lvl->lv);
    464      1.1  haad 
    465      1.1  haad 	return 1;
    466      1.1  haad }
    467      1.1  haad 
    468      1.1  haad /* Lock a list of LVs */
    469      1.1  haad int suspend_lvs(struct cmd_context *cmd, struct dm_list *lvs)
    470      1.1  haad {
    471      1.1  haad 	struct dm_list *lvh;
    472      1.1  haad 	struct lv_list *lvl;
    473      1.1  haad 
    474      1.1  haad 	dm_list_iterate_items(lvl, lvs) {
    475      1.1  haad 		if (!suspend_lv(cmd, lvl->lv)) {
    476      1.1  haad 			log_error("Failed to suspend %s", lvl->lv->name);
    477      1.1  haad 			dm_list_uniterate(lvh, lvs, &lvl->list) {
    478      1.1  haad 				lvl = dm_list_item(lvh, struct lv_list);
    479      1.1  haad 				resume_lv(cmd, lvl->lv);
    480      1.1  haad 			}
    481      1.1  haad 
    482      1.1  haad 			return 0;
    483      1.1  haad 		}
    484      1.1  haad 	}
    485      1.1  haad 
    486      1.1  haad 	return 1;
    487      1.1  haad }
    488      1.1  haad 
    489      1.1  haad /* Lock a list of LVs */
    490      1.1  haad int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive)
    491      1.1  haad {
    492      1.1  haad 	struct dm_list *lvh;
    493      1.1  haad 	struct lv_list *lvl;
    494      1.1  haad 
    495      1.1  haad 	dm_list_iterate_items(lvl, lvs) {
    496      1.1  haad 		if (!exclusive) {
    497      1.1  haad 			if (!activate_lv(cmd, lvl->lv)) {
    498      1.1  haad 				log_error("Failed to activate %s", lvl->lv->name);
    499      1.1  haad 				return 0;
    500      1.1  haad 			}
    501      1.1  haad 		} else if (!activate_lv_excl(cmd, lvl->lv)) {
    502      1.1  haad 			log_error("Failed to activate %s", lvl->lv->name);
    503      1.1  haad 			dm_list_uniterate(lvh, lvs, &lvl->list) {
    504      1.1  haad 				lvl = dm_list_item(lvh, struct lv_list);
    505      1.1  haad 				activate_lv(cmd, lvl->lv);
    506      1.1  haad 			}
    507      1.1  haad 			return 0;
    508      1.1  haad 		}
    509      1.1  haad 	}
    510      1.1  haad 
    511      1.1  haad 	return 1;
    512      1.1  haad }
    513      1.1  haad 
    514      1.1  haad int vg_write_lock_held(void)
    515      1.1  haad {
    516      1.1  haad 	return _vg_write_lock_held;
    517      1.1  haad }
    518      1.1  haad 
    519      1.1  haad int locking_is_clustered(void)
    520      1.1  haad {
    521      1.1  haad 	return (_locking.flags & LCK_CLUSTERED) ? 1 : 0;
    522      1.1  haad }
    523      1.1  haad 
    524  1.1.1.3  haad int remote_lock_held(const char *vol)
    525  1.1.1.3  haad {
    526  1.1.1.3  haad 	int mode = LCK_NULL;
    527  1.1.1.3  haad 
    528  1.1.1.3  haad 	if (!locking_is_clustered())
    529  1.1.1.3  haad 		return 0;
    530  1.1.1.3  haad 
    531  1.1.1.3  haad 	if (!_locking.query_resource)
    532  1.1.1.3  haad 		return -1;
    533  1.1.1.3  haad 
    534  1.1.1.3  haad 	/*
    535  1.1.1.3  haad 	 * If an error occured, expect that volume is active
    536  1.1.1.3  haad 	 */
    537  1.1.1.3  haad 	if (!_locking.query_resource(vol, &mode)) {
    538  1.1.1.3  haad 		stack;
    539  1.1.1.3  haad 		return 1;
    540  1.1.1.3  haad 	}
    541  1.1.1.3  haad 
    542  1.1.1.3  haad 	return mode == LCK_NULL ? 0 : 1;
    543  1.1.1.3  haad }
    544