xref: /netbsd-src/external/gpl2/lvm2/dist/lib/locking/locking.c (revision 7c604eea85b4f330dc75ffe65e947f4d73758aa0)
1*7c604eeaShaad /*	$NetBSD: locking.c,v 1.1.1.3 2009/12/02 00:26:25 haad Exp $	*/
256a34939Shaad 
356a34939Shaad /*
456a34939Shaad  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
556a34939Shaad  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
656a34939Shaad  *
756a34939Shaad  * This file is part of LVM2.
856a34939Shaad  *
956a34939Shaad  * This copyrighted material is made available to anyone wishing to use,
1056a34939Shaad  * modify, copy, or redistribute it subject to the terms and conditions
1156a34939Shaad  * of the GNU Lesser General Public License v.2.1.
1256a34939Shaad  *
1356a34939Shaad  * You should have received a copy of the GNU Lesser General Public License
1456a34939Shaad  * along with this program; if not, write to the Free Software Foundation,
1556a34939Shaad  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1656a34939Shaad  */
1756a34939Shaad 
1856a34939Shaad #include "lib.h"
1956a34939Shaad #include "locking.h"
2056a34939Shaad #include "locking_types.h"
2156a34939Shaad #include "lvm-string.h"
2256a34939Shaad #include "activate.h"
2356a34939Shaad #include "toolcontext.h"
2456a34939Shaad #include "memlock.h"
2556a34939Shaad #include "defaults.h"
2656a34939Shaad #include "lvmcache.h"
2756a34939Shaad 
2856a34939Shaad #include <assert.h>
2956a34939Shaad #include <signal.h>
3056a34939Shaad #include <sys/stat.h>
3156a34939Shaad #include <limits.h>
3256a34939Shaad #include <unistd.h>
3356a34939Shaad 
3456a34939Shaad static struct locking_type _locking;
3556a34939Shaad static sigset_t _oldset;
3656a34939Shaad 
3756a34939Shaad static int _vg_lock_count = 0;		/* Number of locks held */
3856a34939Shaad static int _vg_write_lock_held = 0;	/* VG write lock held? */
3956a34939Shaad static int _signals_blocked = 0;
40*7c604eeaShaad static int _blocking_supported = 0;
4156a34939Shaad 
4256a34939Shaad static volatile sig_atomic_t _sigint_caught = 0;
4356a34939Shaad static volatile sig_atomic_t _handler_installed;
4456a34939Shaad static struct sigaction _oldhandler;
4556a34939Shaad static int _oldmasked;
4656a34939Shaad 
47*7c604eeaShaad typedef enum {
48*7c604eeaShaad         LV_NOOP,
49*7c604eeaShaad         LV_SUSPEND,
50*7c604eeaShaad         LV_RESUME
51*7c604eeaShaad } lv_operation_t;
52*7c604eeaShaad 
_catch_sigint(int unused)5356a34939Shaad static void _catch_sigint(int unused __attribute__((unused)))
5456a34939Shaad {
5556a34939Shaad 	_sigint_caught = 1;
5656a34939Shaad }
5756a34939Shaad 
sigint_caught(void)5856a34939Shaad int sigint_caught(void) {
5956a34939Shaad 	return _sigint_caught;
6056a34939Shaad }
6156a34939Shaad 
sigint_clear(void)6256a34939Shaad void sigint_clear(void)
6356a34939Shaad {
6456a34939Shaad 	_sigint_caught = 0;
6556a34939Shaad }
6656a34939Shaad 
6756a34939Shaad /*
6856a34939Shaad  * Temporarily allow keyboard interrupts to be intercepted and noted;
6956a34939Shaad  * saves interrupt handler state for sigint_restore().  Users should
7056a34939Shaad  * use the sigint_caught() predicate to check whether interrupt was
7156a34939Shaad  * requested and act appropriately.  Interrupt flags are never
7256a34939Shaad  * cleared automatically by this code, but the tools clear the flag
7356a34939Shaad  * before running each command in lvm_run_command().  All other places
7456a34939Shaad  * where the flag needs to be cleared need to call sigint_clear().
7556a34939Shaad  */
7656a34939Shaad 
sigint_allow(void)7756a34939Shaad void sigint_allow(void)
7856a34939Shaad {
7956a34939Shaad 	struct sigaction handler;
8056a34939Shaad 	sigset_t sigs;
8156a34939Shaad 
8256a34939Shaad 	/*
8356a34939Shaad 	 * Do not overwrite the backed-up handler data -
8456a34939Shaad 	 * just increase nesting count.
8556a34939Shaad 	 */
8656a34939Shaad 	if (_handler_installed) {
8756a34939Shaad 		_handler_installed++;
8856a34939Shaad 		return;
8956a34939Shaad 	}
9056a34939Shaad 
9156a34939Shaad 	/* Grab old sigaction for SIGINT: shall not fail. */
9256a34939Shaad 	sigaction(SIGINT, NULL, &handler);
9356a34939Shaad 	handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */
9456a34939Shaad 	handler.sa_handler = _catch_sigint;
9556a34939Shaad 
9656a34939Shaad 	_handler_installed = 1;
9756a34939Shaad 
9856a34939Shaad 	/* Override the signal handler: shall not fail. */
9956a34939Shaad 	sigaction(SIGINT, &handler, &_oldhandler);
10056a34939Shaad 
10156a34939Shaad 	/* Unmask SIGINT.  Remember to mask it again on restore. */
10256a34939Shaad 	sigprocmask(0, NULL, &sigs);
10356a34939Shaad 	if ((_oldmasked = sigismember(&sigs, SIGINT))) {
10456a34939Shaad 		sigdelset(&sigs, SIGINT);
10556a34939Shaad 		sigprocmask(SIG_SETMASK, &sigs, NULL);
10656a34939Shaad 	}
10756a34939Shaad }
10856a34939Shaad 
sigint_restore(void)10956a34939Shaad void sigint_restore(void)
11056a34939Shaad {
11156a34939Shaad 	if (!_handler_installed)
11256a34939Shaad 		return;
11356a34939Shaad 
11456a34939Shaad 	if (_handler_installed > 1) {
11556a34939Shaad 		_handler_installed--;
11656a34939Shaad 		return;
11756a34939Shaad 	}
11856a34939Shaad 
11956a34939Shaad 	/* Nesting count went down to 0. */
12056a34939Shaad 	_handler_installed = 0;
12156a34939Shaad 
12256a34939Shaad 	if (_oldmasked) {
12356a34939Shaad 		sigset_t sigs;
12456a34939Shaad 		sigprocmask(0, NULL, &sigs);
12556a34939Shaad 		sigaddset(&sigs, SIGINT);
12656a34939Shaad 		sigprocmask(SIG_SETMASK, &sigs, NULL);
12756a34939Shaad 	}
12856a34939Shaad 
12956a34939Shaad 	sigaction(SIGINT, &_oldhandler, NULL);
13056a34939Shaad }
13156a34939Shaad 
_block_signals(uint32_t flags __attribute ((unused)))13256a34939Shaad static void _block_signals(uint32_t flags __attribute((unused)))
13356a34939Shaad {
13456a34939Shaad 	sigset_t set;
13556a34939Shaad 
13656a34939Shaad 	if (_signals_blocked)
13756a34939Shaad 		return;
13856a34939Shaad 
13956a34939Shaad 	if (sigfillset(&set)) {
14056a34939Shaad 		log_sys_error("sigfillset", "_block_signals");
14156a34939Shaad 		return;
14256a34939Shaad 	}
14356a34939Shaad 
14456a34939Shaad 	if (sigprocmask(SIG_SETMASK, &set, &_oldset)) {
14556a34939Shaad 		log_sys_error("sigprocmask", "_block_signals");
14656a34939Shaad 		return;
14756a34939Shaad 	}
14856a34939Shaad 
14956a34939Shaad 	_signals_blocked = 1;
15056a34939Shaad 
15156a34939Shaad 	return;
15256a34939Shaad }
15356a34939Shaad 
_unblock_signals(void)15456a34939Shaad static void _unblock_signals(void)
15556a34939Shaad {
15656a34939Shaad 	/* Don't unblock signals while any locks are held */
15756a34939Shaad 	if (!_signals_blocked || _vg_lock_count)
15856a34939Shaad 		return;
15956a34939Shaad 
16056a34939Shaad 	if (sigprocmask(SIG_SETMASK, &_oldset, NULL)) {
16156a34939Shaad 		log_sys_error("sigprocmask", "_block_signals");
16256a34939Shaad 		return;
16356a34939Shaad 	}
16456a34939Shaad 
16556a34939Shaad 	_signals_blocked = 0;
16656a34939Shaad 
16756a34939Shaad 	return;
16856a34939Shaad }
16956a34939Shaad 
_lock_memory(lv_operation_t lv_op)170*7c604eeaShaad static void _lock_memory(lv_operation_t lv_op)
17156a34939Shaad {
17256a34939Shaad 	if (!(_locking.flags & LCK_PRE_MEMLOCK))
17356a34939Shaad 		return;
17456a34939Shaad 
175*7c604eeaShaad 	if (lv_op == LV_SUSPEND)
17656a34939Shaad 		memlock_inc();
17756a34939Shaad }
17856a34939Shaad 
_unlock_memory(lv_operation_t lv_op)179*7c604eeaShaad static void _unlock_memory(lv_operation_t lv_op)
18056a34939Shaad {
18156a34939Shaad 	if (!(_locking.flags & LCK_PRE_MEMLOCK))
18256a34939Shaad 		return;
18356a34939Shaad 
184*7c604eeaShaad 	if (lv_op == LV_RESUME)
18556a34939Shaad 		memlock_dec();
18656a34939Shaad }
18756a34939Shaad 
reset_locking(void)18856a34939Shaad void reset_locking(void)
18956a34939Shaad {
19056a34939Shaad 	int was_locked = _vg_lock_count;
19156a34939Shaad 
19256a34939Shaad 	_vg_lock_count = 0;
19356a34939Shaad 	_vg_write_lock_held = 0;
19456a34939Shaad 
19556a34939Shaad 	_locking.reset_locking();
19656a34939Shaad 
19756a34939Shaad 	if (was_locked)
19856a34939Shaad 		_unblock_signals();
19956a34939Shaad }
20056a34939Shaad 
_update_vg_lock_count(const char * resource,uint32_t flags)201*7c604eeaShaad static void _update_vg_lock_count(const char *resource, uint32_t flags)
20256a34939Shaad {
203*7c604eeaShaad 	/* Ignore locks not associated with updating VG metadata */
204*7c604eeaShaad 	if ((flags & LCK_SCOPE_MASK) != LCK_VG ||
205*7c604eeaShaad 	    (flags & LCK_CACHE) ||
206*7c604eeaShaad 	    !strcmp(resource, VG_GLOBAL))
20756a34939Shaad 		return;
20856a34939Shaad 
20956a34939Shaad 	if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)
21056a34939Shaad 		_vg_lock_count--;
21156a34939Shaad 	else
21256a34939Shaad 		_vg_lock_count++;
21356a34939Shaad 
21456a34939Shaad 	/* We don't bother to reset this until all VG locks are dropped */
21556a34939Shaad 	if ((flags & LCK_TYPE_MASK) == LCK_WRITE)
21656a34939Shaad 		_vg_write_lock_held = 1;
21756a34939Shaad 	else if (!_vg_lock_count)
21856a34939Shaad 		_vg_write_lock_held = 0;
21956a34939Shaad }
22056a34939Shaad 
22156a34939Shaad /*
22256a34939Shaad  * Select a locking type
223*7c604eeaShaad  * type: locking type; if < 0, then read config tree value
22456a34939Shaad  */
init_locking(int type,struct cmd_context * cmd)22556a34939Shaad int init_locking(int type, struct cmd_context *cmd)
22656a34939Shaad {
227*7c604eeaShaad 	if (type < 0)
228*7c604eeaShaad 		type = find_config_tree_int(cmd, "global/locking_type", 1);
229*7c604eeaShaad 
230*7c604eeaShaad 	_blocking_supported = find_config_tree_int(cmd,
231*7c604eeaShaad 	    "global/wait_for_locks", DEFAULT_WAIT_FOR_LOCKS);
23256a34939Shaad 
23356a34939Shaad 	switch (type) {
23456a34939Shaad 	case 0:
23556a34939Shaad 		init_no_locking(&_locking, cmd);
23656a34939Shaad 		log_warn("WARNING: Locking disabled. Be careful! "
23756a34939Shaad 			  "This could corrupt your metadata.");
23856a34939Shaad 		return 1;
23956a34939Shaad 
24056a34939Shaad 	case 1:
241*7c604eeaShaad 		log_very_verbose("%sFile-based locking selected.",
242*7c604eeaShaad 				 _blocking_supported ? "" : "Non-blocking ");
243*7c604eeaShaad 
24456a34939Shaad 		if (!init_file_locking(&_locking, cmd))
24556a34939Shaad 			break;
24656a34939Shaad 		return 1;
24756a34939Shaad 
24856a34939Shaad #ifdef HAVE_LIBDL
24956a34939Shaad 	case 2:
250bec4d750Shaad 		if (!is_static()) {
25156a34939Shaad 			log_very_verbose("External locking selected.");
25256a34939Shaad 			if (init_external_locking(&_locking, cmd))
25356a34939Shaad 				return 1;
25456a34939Shaad 		}
25556a34939Shaad 		if (!find_config_tree_int(cmd, "locking/fallback_to_clustered_locking",
25656a34939Shaad 			    find_config_tree_int(cmd, "global/fallback_to_clustered_locking",
25756a34939Shaad 						 DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING)))
25856a34939Shaad 			break;
25956a34939Shaad #endif
26056a34939Shaad 
26156a34939Shaad #ifdef CLUSTER_LOCKING_INTERNAL
26256a34939Shaad 		log_very_verbose("Falling back to internal clustered locking.");
26356a34939Shaad 		/* Fall through */
26456a34939Shaad 
26556a34939Shaad 	case 3:
26656a34939Shaad 		log_very_verbose("Cluster locking selected.");
26756a34939Shaad 		if (!init_cluster_locking(&_locking, cmd))
26856a34939Shaad 			break;
26956a34939Shaad 		return 1;
27056a34939Shaad #endif
27156a34939Shaad 
272*7c604eeaShaad 	case 4:
273*7c604eeaShaad 		log_verbose("Read-only locking selected. "
274*7c604eeaShaad 			    "Only read operations permitted.");
275*7c604eeaShaad 		if (!init_readonly_locking(&_locking, cmd))
276*7c604eeaShaad 			break;
277*7c604eeaShaad 		return 1;
278*7c604eeaShaad 
27956a34939Shaad 	default:
28056a34939Shaad 		log_error("Unknown locking type requested.");
28156a34939Shaad 		return 0;
28256a34939Shaad 	}
28356a34939Shaad 
28456a34939Shaad 	if ((type == 2 || type == 3) &&
28556a34939Shaad 	    find_config_tree_int(cmd, "locking/fallback_to_local_locking",
28656a34939Shaad 	    	    find_config_tree_int(cmd, "global/fallback_to_local_locking",
28756a34939Shaad 					 DEFAULT_FALLBACK_TO_LOCAL_LOCKING))) {
28856a34939Shaad 		log_warn("WARNING: Falling back to local file-based locking.");
28956a34939Shaad 		log_warn("Volume Groups with the clustered attribute will "
29056a34939Shaad 			  "be inaccessible.");
29156a34939Shaad 		if (init_file_locking(&_locking, cmd))
29256a34939Shaad 			return 1;
29356a34939Shaad 	}
29456a34939Shaad 
29556a34939Shaad 	if (!ignorelockingfailure())
29656a34939Shaad 		return 0;
29756a34939Shaad 
29856a34939Shaad 	log_verbose("Locking disabled - only read operations permitted.");
299*7c604eeaShaad 	init_readonly_locking(&_locking, cmd);
30056a34939Shaad 
30156a34939Shaad 	return 1;
30256a34939Shaad }
30356a34939Shaad 
fin_locking(void)30456a34939Shaad void fin_locking(void)
30556a34939Shaad {
30656a34939Shaad 	_locking.fin_locking();
30756a34939Shaad }
30856a34939Shaad 
30956a34939Shaad /*
31056a34939Shaad  * Does the LVM1 driver know of this VG name?
31156a34939Shaad  */
check_lvm1_vg_inactive(struct cmd_context * cmd,const char * vgname)31256a34939Shaad int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname)
31356a34939Shaad {
31456a34939Shaad 	struct stat info;
31556a34939Shaad 	char path[PATH_MAX];
31656a34939Shaad 
31756a34939Shaad 	/* We'll allow operations on orphans */
31856a34939Shaad 	if (is_orphan_vg(vgname))
31956a34939Shaad 		return 1;
32056a34939Shaad 
32156a34939Shaad 	/* LVM1 is only present in 2.4 kernels. */
32256a34939Shaad 	if (strncmp(cmd->kernel_vsn, "2.4.", 4))
32356a34939Shaad 		return 1;
32456a34939Shaad 
32556a34939Shaad 	if (dm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", cmd->proc_dir,
32656a34939Shaad 			 vgname) < 0) {
32756a34939Shaad 		log_error("LVM1 proc VG pathname too long for %s", vgname);
32856a34939Shaad 		return 0;
32956a34939Shaad 	}
33056a34939Shaad 
33156a34939Shaad 	if (stat(path, &info) == 0) {
33256a34939Shaad 		log_error("%s exists: Is the original LVM driver using "
33356a34939Shaad 			  "this volume group?", path);
33456a34939Shaad 		return 0;
33556a34939Shaad 	} else if (errno != ENOENT && errno != ENOTDIR) {
33656a34939Shaad 		log_sys_error("stat", path);
33756a34939Shaad 		return 0;
33856a34939Shaad 	}
33956a34939Shaad 
34056a34939Shaad 	return 1;
34156a34939Shaad }
34256a34939Shaad 
34356a34939Shaad /*
34456a34939Shaad  * VG locking is by VG name.
34556a34939Shaad  * FIXME This should become VG uuid.
34656a34939Shaad  */
_lock_vol(struct cmd_context * cmd,const char * resource,uint32_t flags,lv_operation_t lv_op)347*7c604eeaShaad static int _lock_vol(struct cmd_context *cmd, const char *resource,
348*7c604eeaShaad 		     uint32_t flags, lv_operation_t lv_op)
34956a34939Shaad {
35056a34939Shaad 	int ret = 0;
35156a34939Shaad 
35256a34939Shaad 	_block_signals(flags);
353*7c604eeaShaad 	_lock_memory(lv_op);
35456a34939Shaad 
35556a34939Shaad 	assert(resource);
35656a34939Shaad 
35756a34939Shaad 	if (!*resource) {
35856a34939Shaad 		log_error("Internal error: Use of P_orphans is deprecated.");
35956a34939Shaad 		return 0;
36056a34939Shaad 	}
36156a34939Shaad 
36256a34939Shaad 	if (*resource == '#' && (flags & LCK_CACHE)) {
36356a34939Shaad 		log_error("Internal error: P_%s referenced", resource);
36456a34939Shaad 		return 0;
36556a34939Shaad 	}
36656a34939Shaad 
36756a34939Shaad 	if ((ret = _locking.lock_resource(cmd, resource, flags))) {
36856a34939Shaad 		if ((flags & LCK_SCOPE_MASK) == LCK_VG &&
36956a34939Shaad 		    !(flags & LCK_CACHE)) {
37056a34939Shaad 			if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)
37156a34939Shaad 				lvmcache_unlock_vgname(resource);
37256a34939Shaad 			else
37356a34939Shaad 				lvmcache_lock_vgname(resource, (flags & LCK_TYPE_MASK)
37456a34939Shaad 								== LCK_READ);
37556a34939Shaad 		}
37656a34939Shaad 
377*7c604eeaShaad 		_update_vg_lock_count(resource, flags);
37856a34939Shaad 	}
37956a34939Shaad 
380*7c604eeaShaad 	_unlock_memory(lv_op);
38156a34939Shaad 	_unblock_signals();
38256a34939Shaad 
38356a34939Shaad 	return ret;
38456a34939Shaad }
38556a34939Shaad 
lock_vol(struct cmd_context * cmd,const char * vol,uint32_t flags)38656a34939Shaad int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags)
38756a34939Shaad {
38856a34939Shaad 	char resource[258] __attribute((aligned(8)));
389*7c604eeaShaad 	lv_operation_t lv_op;
390*7c604eeaShaad 
391*7c604eeaShaad 	switch (flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) {
392*7c604eeaShaad 		case LCK_LV_SUSPEND:
393*7c604eeaShaad 				lv_op = LV_SUSPEND;
394*7c604eeaShaad 				break;
395*7c604eeaShaad 		case LCK_LV_RESUME:
396*7c604eeaShaad 				lv_op = LV_RESUME;
397*7c604eeaShaad 				break;
398*7c604eeaShaad 		default:	lv_op = LV_NOOP;
399*7c604eeaShaad 	}
400*7c604eeaShaad 
40156a34939Shaad 
40256a34939Shaad 	if (flags == LCK_NONE) {
40356a34939Shaad 		log_debug("Internal error: %s: LCK_NONE lock requested", vol);
40456a34939Shaad 		return 1;
40556a34939Shaad 	}
40656a34939Shaad 
40756a34939Shaad 	switch (flags & LCK_SCOPE_MASK) {
40856a34939Shaad 	case LCK_VG:
409*7c604eeaShaad 		/*
410*7c604eeaShaad 		 * Automatically set LCK_NONBLOCK if one or more VGs locked.
411*7c604eeaShaad 		 * This will enforce correctness and prevent deadlocks rather
412*7c604eeaShaad 		 * than relying on the caller to set the flag properly.
413*7c604eeaShaad 		 */
414*7c604eeaShaad 		if (!_blocking_supported || vgs_locked())
415*7c604eeaShaad 			flags |= LCK_NONBLOCK;
416*7c604eeaShaad 
417*7c604eeaShaad 		if (vol[0] != '#' &&
418*7c604eeaShaad 		    ((flags & LCK_TYPE_MASK) != LCK_UNLOCK) &&
419*7c604eeaShaad 		    (!(flags & LCK_CACHE)) &&
420*7c604eeaShaad 		    !lvmcache_verify_lock_order(vol))
421*7c604eeaShaad 			return 0;
422*7c604eeaShaad 
42356a34939Shaad 		/* Lock VG to change on-disk metadata. */
42456a34939Shaad 		/* If LVM1 driver knows about the VG, it can't be accessed. */
42556a34939Shaad 		if (!check_lvm1_vg_inactive(cmd, vol))
42656a34939Shaad 			return 0;
427*7c604eeaShaad 		break;
42856a34939Shaad 	case LCK_LV:
429*7c604eeaShaad 		/* All LV locks are non-blocking. */
430*7c604eeaShaad 		flags |= LCK_NONBLOCK;
43156a34939Shaad 		break;
43256a34939Shaad 	default:
43356a34939Shaad 		log_error("Unrecognised lock scope: %d",
43456a34939Shaad 			  flags & LCK_SCOPE_MASK);
43556a34939Shaad 		return 0;
43656a34939Shaad 	}
43756a34939Shaad 
438*7c604eeaShaad 	strncpy(resource, vol, sizeof(resource));
439*7c604eeaShaad 
440*7c604eeaShaad 	if (!_lock_vol(cmd, resource, flags, lv_op))
44156a34939Shaad 		return 0;
44256a34939Shaad 
44356a34939Shaad 	/*
44456a34939Shaad 	 * If a real lock was acquired (i.e. not LCK_CACHE),
44556a34939Shaad 	 * perform an immediate unlock unless LCK_HOLD was requested.
44656a34939Shaad 	 */
44756a34939Shaad 	if (!(flags & LCK_CACHE) && !(flags & LCK_HOLD) &&
44856a34939Shaad 	    ((flags & LCK_TYPE_MASK) != LCK_UNLOCK)) {
44956a34939Shaad 		if (!_lock_vol(cmd, resource,
450*7c604eeaShaad 			       (flags & ~LCK_TYPE_MASK) | LCK_UNLOCK, lv_op))
45156a34939Shaad 			return 0;
45256a34939Shaad 	}
45356a34939Shaad 
45456a34939Shaad 	return 1;
45556a34939Shaad }
45656a34939Shaad 
45756a34939Shaad /* Unlock list of LVs */
resume_lvs(struct cmd_context * cmd,struct dm_list * lvs)45856a34939Shaad int resume_lvs(struct cmd_context *cmd, struct dm_list *lvs)
45956a34939Shaad {
46056a34939Shaad 	struct lv_list *lvl;
46156a34939Shaad 
46256a34939Shaad 	dm_list_iterate_items(lvl, lvs)
46356a34939Shaad 		resume_lv(cmd, lvl->lv);
46456a34939Shaad 
46556a34939Shaad 	return 1;
46656a34939Shaad }
46756a34939Shaad 
46856a34939Shaad /* Lock a list of LVs */
suspend_lvs(struct cmd_context * cmd,struct dm_list * lvs)46956a34939Shaad int suspend_lvs(struct cmd_context *cmd, struct dm_list *lvs)
47056a34939Shaad {
47156a34939Shaad 	struct dm_list *lvh;
47256a34939Shaad 	struct lv_list *lvl;
47356a34939Shaad 
47456a34939Shaad 	dm_list_iterate_items(lvl, lvs) {
47556a34939Shaad 		if (!suspend_lv(cmd, lvl->lv)) {
47656a34939Shaad 			log_error("Failed to suspend %s", lvl->lv->name);
47756a34939Shaad 			dm_list_uniterate(lvh, lvs, &lvl->list) {
47856a34939Shaad 				lvl = dm_list_item(lvh, struct lv_list);
47956a34939Shaad 				resume_lv(cmd, lvl->lv);
48056a34939Shaad 			}
48156a34939Shaad 
48256a34939Shaad 			return 0;
48356a34939Shaad 		}
48456a34939Shaad 	}
48556a34939Shaad 
48656a34939Shaad 	return 1;
48756a34939Shaad }
48856a34939Shaad 
48956a34939Shaad /* Lock a list of LVs */
activate_lvs(struct cmd_context * cmd,struct dm_list * lvs,unsigned exclusive)49056a34939Shaad int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive)
49156a34939Shaad {
49256a34939Shaad 	struct dm_list *lvh;
49356a34939Shaad 	struct lv_list *lvl;
49456a34939Shaad 
49556a34939Shaad 	dm_list_iterate_items(lvl, lvs) {
49656a34939Shaad 		if (!exclusive) {
49756a34939Shaad 			if (!activate_lv(cmd, lvl->lv)) {
49856a34939Shaad 				log_error("Failed to activate %s", lvl->lv->name);
49956a34939Shaad 				return 0;
50056a34939Shaad 			}
50156a34939Shaad 		} else if (!activate_lv_excl(cmd, lvl->lv)) {
50256a34939Shaad 			log_error("Failed to activate %s", lvl->lv->name);
50356a34939Shaad 			dm_list_uniterate(lvh, lvs, &lvl->list) {
50456a34939Shaad 				lvl = dm_list_item(lvh, struct lv_list);
50556a34939Shaad 				activate_lv(cmd, lvl->lv);
50656a34939Shaad 			}
50756a34939Shaad 			return 0;
50856a34939Shaad 		}
50956a34939Shaad 	}
51056a34939Shaad 
51156a34939Shaad 	return 1;
51256a34939Shaad }
51356a34939Shaad 
vg_write_lock_held(void)51456a34939Shaad int vg_write_lock_held(void)
51556a34939Shaad {
51656a34939Shaad 	return _vg_write_lock_held;
51756a34939Shaad }
51856a34939Shaad 
locking_is_clustered(void)51956a34939Shaad int locking_is_clustered(void)
52056a34939Shaad {
52156a34939Shaad 	return (_locking.flags & LCK_CLUSTERED) ? 1 : 0;
52256a34939Shaad }
52356a34939Shaad 
remote_lock_held(const char * vol)524*7c604eeaShaad int remote_lock_held(const char *vol)
525*7c604eeaShaad {
526*7c604eeaShaad 	int mode = LCK_NULL;
527*7c604eeaShaad 
528*7c604eeaShaad 	if (!locking_is_clustered())
529*7c604eeaShaad 		return 0;
530*7c604eeaShaad 
531*7c604eeaShaad 	if (!_locking.query_resource)
532*7c604eeaShaad 		return -1;
533*7c604eeaShaad 
534*7c604eeaShaad 	/*
535*7c604eeaShaad 	 * If an error occured, expect that volume is active
536*7c604eeaShaad 	 */
537*7c604eeaShaad 	if (!_locking.query_resource(vol, &mode)) {
538*7c604eeaShaad 		stack;
539*7c604eeaShaad 		return 1;
540*7c604eeaShaad 	}
541*7c604eeaShaad 
542*7c604eeaShaad 	return mode == LCK_NULL ? 0 : 1;
543*7c604eeaShaad }
544