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