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