locking.c revision 1.1.1.2 1 1.1 haad /* $NetBSD: locking.c,v 1.1.1.2 2009/02/18 11:17:08 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 haad
41 1.1 haad static volatile sig_atomic_t _sigint_caught = 0;
42 1.1 haad static volatile sig_atomic_t _handler_installed;
43 1.1 haad static struct sigaction _oldhandler;
44 1.1 haad static int _oldmasked;
45 1.1 haad
46 1.1 haad static void _catch_sigint(int unused __attribute__((unused)))
47 1.1 haad {
48 1.1 haad _sigint_caught = 1;
49 1.1 haad }
50 1.1 haad
51 1.1 haad int sigint_caught(void) {
52 1.1 haad return _sigint_caught;
53 1.1 haad }
54 1.1 haad
55 1.1 haad void sigint_clear(void)
56 1.1 haad {
57 1.1 haad _sigint_caught = 0;
58 1.1 haad }
59 1.1 haad
60 1.1 haad /*
61 1.1 haad * Temporarily allow keyboard interrupts to be intercepted and noted;
62 1.1 haad * saves interrupt handler state for sigint_restore(). Users should
63 1.1 haad * use the sigint_caught() predicate to check whether interrupt was
64 1.1 haad * requested and act appropriately. Interrupt flags are never
65 1.1 haad * cleared automatically by this code, but the tools clear the flag
66 1.1 haad * before running each command in lvm_run_command(). All other places
67 1.1 haad * where the flag needs to be cleared need to call sigint_clear().
68 1.1 haad */
69 1.1 haad
70 1.1 haad void sigint_allow(void)
71 1.1 haad {
72 1.1 haad struct sigaction handler;
73 1.1 haad sigset_t sigs;
74 1.1 haad
75 1.1 haad /*
76 1.1 haad * Do not overwrite the backed-up handler data -
77 1.1 haad * just increase nesting count.
78 1.1 haad */
79 1.1 haad if (_handler_installed) {
80 1.1 haad _handler_installed++;
81 1.1 haad return;
82 1.1 haad }
83 1.1 haad
84 1.1 haad /* Grab old sigaction for SIGINT: shall not fail. */
85 1.1 haad sigaction(SIGINT, NULL, &handler);
86 1.1 haad handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */
87 1.1 haad handler.sa_handler = _catch_sigint;
88 1.1 haad
89 1.1 haad _handler_installed = 1;
90 1.1 haad
91 1.1 haad /* Override the signal handler: shall not fail. */
92 1.1 haad sigaction(SIGINT, &handler, &_oldhandler);
93 1.1 haad
94 1.1 haad /* Unmask SIGINT. Remember to mask it again on restore. */
95 1.1 haad sigprocmask(0, NULL, &sigs);
96 1.1 haad if ((_oldmasked = sigismember(&sigs, SIGINT))) {
97 1.1 haad sigdelset(&sigs, SIGINT);
98 1.1 haad sigprocmask(SIG_SETMASK, &sigs, NULL);
99 1.1 haad }
100 1.1 haad }
101 1.1 haad
102 1.1 haad void sigint_restore(void)
103 1.1 haad {
104 1.1 haad if (!_handler_installed)
105 1.1 haad return;
106 1.1 haad
107 1.1 haad if (_handler_installed > 1) {
108 1.1 haad _handler_installed--;
109 1.1 haad return;
110 1.1 haad }
111 1.1 haad
112 1.1 haad /* Nesting count went down to 0. */
113 1.1 haad _handler_installed = 0;
114 1.1 haad
115 1.1 haad if (_oldmasked) {
116 1.1 haad sigset_t sigs;
117 1.1 haad sigprocmask(0, NULL, &sigs);
118 1.1 haad sigaddset(&sigs, SIGINT);
119 1.1 haad sigprocmask(SIG_SETMASK, &sigs, NULL);
120 1.1 haad }
121 1.1 haad
122 1.1 haad sigaction(SIGINT, &_oldhandler, NULL);
123 1.1 haad }
124 1.1 haad
125 1.1 haad static void _block_signals(uint32_t flags __attribute((unused)))
126 1.1 haad {
127 1.1 haad sigset_t set;
128 1.1 haad
129 1.1 haad if (_signals_blocked)
130 1.1 haad return;
131 1.1 haad
132 1.1 haad if (sigfillset(&set)) {
133 1.1 haad log_sys_error("sigfillset", "_block_signals");
134 1.1 haad return;
135 1.1 haad }
136 1.1 haad
137 1.1 haad if (sigprocmask(SIG_SETMASK, &set, &_oldset)) {
138 1.1 haad log_sys_error("sigprocmask", "_block_signals");
139 1.1 haad return;
140 1.1 haad }
141 1.1 haad
142 1.1 haad _signals_blocked = 1;
143 1.1 haad
144 1.1 haad return;
145 1.1 haad }
146 1.1 haad
147 1.1 haad static void _unblock_signals(void)
148 1.1 haad {
149 1.1 haad /* Don't unblock signals while any locks are held */
150 1.1 haad if (!_signals_blocked || _vg_lock_count)
151 1.1 haad return;
152 1.1 haad
153 1.1 haad if (sigprocmask(SIG_SETMASK, &_oldset, NULL)) {
154 1.1 haad log_sys_error("sigprocmask", "_block_signals");
155 1.1 haad return;
156 1.1 haad }
157 1.1 haad
158 1.1 haad _signals_blocked = 0;
159 1.1 haad
160 1.1 haad return;
161 1.1 haad }
162 1.1 haad
163 1.1 haad static void _lock_memory(uint32_t flags)
164 1.1 haad {
165 1.1 haad if (!(_locking.flags & LCK_PRE_MEMLOCK))
166 1.1 haad return;
167 1.1 haad
168 1.1 haad if ((flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_SUSPEND)
169 1.1 haad memlock_inc();
170 1.1 haad }
171 1.1 haad
172 1.1 haad static void _unlock_memory(uint32_t flags)
173 1.1 haad {
174 1.1 haad if (!(_locking.flags & LCK_PRE_MEMLOCK))
175 1.1 haad return;
176 1.1 haad
177 1.1 haad if ((flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_RESUME)
178 1.1 haad memlock_dec();
179 1.1 haad }
180 1.1 haad
181 1.1 haad void reset_locking(void)
182 1.1 haad {
183 1.1 haad int was_locked = _vg_lock_count;
184 1.1 haad
185 1.1 haad _vg_lock_count = 0;
186 1.1 haad _vg_write_lock_held = 0;
187 1.1 haad
188 1.1 haad _locking.reset_locking();
189 1.1 haad
190 1.1 haad if (was_locked)
191 1.1 haad _unblock_signals();
192 1.1 haad }
193 1.1 haad
194 1.1 haad static void _update_vg_lock_count(uint32_t flags)
195 1.1 haad {
196 1.1 haad if ((flags & LCK_SCOPE_MASK) != LCK_VG)
197 1.1 haad return;
198 1.1 haad
199 1.1 haad if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)
200 1.1 haad _vg_lock_count--;
201 1.1 haad else
202 1.1 haad _vg_lock_count++;
203 1.1 haad
204 1.1 haad /* We don't bother to reset this until all VG locks are dropped */
205 1.1 haad if ((flags & LCK_TYPE_MASK) == LCK_WRITE)
206 1.1 haad _vg_write_lock_held = 1;
207 1.1 haad else if (!_vg_lock_count)
208 1.1 haad _vg_write_lock_held = 0;
209 1.1 haad }
210 1.1 haad
211 1.1 haad /*
212 1.1 haad * Select a locking type
213 1.1 haad */
214 1.1 haad int init_locking(int type, struct cmd_context *cmd)
215 1.1 haad {
216 1.1 haad init_lockingfailed(0);
217 1.1 haad
218 1.1 haad switch (type) {
219 1.1 haad case 0:
220 1.1 haad init_no_locking(&_locking, cmd);
221 1.1 haad log_warn("WARNING: Locking disabled. Be careful! "
222 1.1 haad "This could corrupt your metadata.");
223 1.1 haad return 1;
224 1.1 haad
225 1.1 haad case 1:
226 1.1 haad log_very_verbose("File-based locking selected.");
227 1.1 haad if (!init_file_locking(&_locking, cmd))
228 1.1 haad break;
229 1.1 haad return 1;
230 1.1 haad
231 1.1 haad #ifdef HAVE_LIBDL
232 1.1 haad case 2:
233 1.1.1.2 haad if (!is_static()) {
234 1.1 haad log_very_verbose("External locking selected.");
235 1.1 haad if (init_external_locking(&_locking, cmd))
236 1.1 haad return 1;
237 1.1 haad }
238 1.1 haad if (!find_config_tree_int(cmd, "locking/fallback_to_clustered_locking",
239 1.1 haad find_config_tree_int(cmd, "global/fallback_to_clustered_locking",
240 1.1 haad DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING)))
241 1.1 haad break;
242 1.1 haad #endif
243 1.1 haad
244 1.1 haad #ifdef CLUSTER_LOCKING_INTERNAL
245 1.1 haad log_very_verbose("Falling back to internal clustered locking.");
246 1.1 haad /* Fall through */
247 1.1 haad
248 1.1 haad case 3:
249 1.1 haad log_very_verbose("Cluster locking selected.");
250 1.1 haad if (!init_cluster_locking(&_locking, cmd))
251 1.1 haad break;
252 1.1 haad return 1;
253 1.1 haad #endif
254 1.1 haad
255 1.1 haad default:
256 1.1 haad log_error("Unknown locking type requested.");
257 1.1 haad return 0;
258 1.1 haad }
259 1.1 haad
260 1.1 haad if ((type == 2 || type == 3) &&
261 1.1 haad find_config_tree_int(cmd, "locking/fallback_to_local_locking",
262 1.1 haad find_config_tree_int(cmd, "global/fallback_to_local_locking",
263 1.1 haad DEFAULT_FALLBACK_TO_LOCAL_LOCKING))) {
264 1.1 haad log_warn("WARNING: Falling back to local file-based locking.");
265 1.1 haad log_warn("Volume Groups with the clustered attribute will "
266 1.1 haad "be inaccessible.");
267 1.1 haad if (init_file_locking(&_locking, cmd))
268 1.1 haad return 1;
269 1.1 haad }
270 1.1 haad
271 1.1 haad if (!ignorelockingfailure())
272 1.1 haad return 0;
273 1.1 haad
274 1.1 haad /* FIXME Ensure only read ops are permitted */
275 1.1 haad log_verbose("Locking disabled - only read operations permitted.");
276 1.1 haad
277 1.1 haad init_no_locking(&_locking, cmd);
278 1.1 haad init_lockingfailed(1);
279 1.1 haad
280 1.1 haad return 1;
281 1.1 haad }
282 1.1 haad
283 1.1 haad void fin_locking(void)
284 1.1 haad {
285 1.1 haad _locking.fin_locking();
286 1.1 haad }
287 1.1 haad
288 1.1 haad /*
289 1.1 haad * Does the LVM1 driver know of this VG name?
290 1.1 haad */
291 1.1 haad int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname)
292 1.1 haad {
293 1.1 haad struct stat info;
294 1.1 haad char path[PATH_MAX];
295 1.1 haad
296 1.1 haad /* We'll allow operations on orphans */
297 1.1 haad if (is_orphan_vg(vgname))
298 1.1 haad return 1;
299 1.1 haad
300 1.1 haad /* LVM1 is only present in 2.4 kernels. */
301 1.1 haad if (strncmp(cmd->kernel_vsn, "2.4.", 4))
302 1.1 haad return 1;
303 1.1 haad
304 1.1 haad if (dm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", cmd->proc_dir,
305 1.1 haad vgname) < 0) {
306 1.1 haad log_error("LVM1 proc VG pathname too long for %s", vgname);
307 1.1 haad return 0;
308 1.1 haad }
309 1.1 haad
310 1.1 haad if (stat(path, &info) == 0) {
311 1.1 haad log_error("%s exists: Is the original LVM driver using "
312 1.1 haad "this volume group?", path);
313 1.1 haad return 0;
314 1.1 haad } else if (errno != ENOENT && errno != ENOTDIR) {
315 1.1 haad log_sys_error("stat", path);
316 1.1 haad return 0;
317 1.1 haad }
318 1.1 haad
319 1.1 haad return 1;
320 1.1 haad }
321 1.1 haad
322 1.1 haad /*
323 1.1 haad * VG locking is by VG name.
324 1.1 haad * FIXME This should become VG uuid.
325 1.1 haad */
326 1.1 haad static int _lock_vol(struct cmd_context *cmd, const char *resource, uint32_t flags)
327 1.1 haad {
328 1.1 haad int ret = 0;
329 1.1 haad
330 1.1 haad _block_signals(flags);
331 1.1 haad _lock_memory(flags);
332 1.1 haad
333 1.1 haad assert(resource);
334 1.1 haad
335 1.1 haad if (!*resource) {
336 1.1 haad log_error("Internal error: Use of P_orphans is deprecated.");
337 1.1 haad return 0;
338 1.1 haad }
339 1.1 haad
340 1.1 haad if (*resource == '#' && (flags & LCK_CACHE)) {
341 1.1 haad log_error("Internal error: P_%s referenced", resource);
342 1.1 haad return 0;
343 1.1 haad }
344 1.1 haad
345 1.1 haad if ((ret = _locking.lock_resource(cmd, resource, flags))) {
346 1.1 haad if ((flags & LCK_SCOPE_MASK) == LCK_VG &&
347 1.1 haad !(flags & LCK_CACHE)) {
348 1.1 haad if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)
349 1.1 haad lvmcache_unlock_vgname(resource);
350 1.1 haad else
351 1.1 haad lvmcache_lock_vgname(resource, (flags & LCK_TYPE_MASK)
352 1.1 haad == LCK_READ);
353 1.1 haad }
354 1.1 haad
355 1.1 haad _update_vg_lock_count(flags);
356 1.1 haad }
357 1.1 haad
358 1.1 haad _unlock_memory(flags);
359 1.1 haad _unblock_signals();
360 1.1 haad
361 1.1 haad return ret;
362 1.1 haad }
363 1.1 haad
364 1.1 haad int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags)
365 1.1 haad {
366 1.1 haad char resource[258] __attribute((aligned(8)));
367 1.1 haad
368 1.1 haad if (flags == LCK_NONE) {
369 1.1 haad log_debug("Internal error: %s: LCK_NONE lock requested", vol);
370 1.1 haad return 1;
371 1.1 haad }
372 1.1 haad
373 1.1 haad switch (flags & LCK_SCOPE_MASK) {
374 1.1 haad case LCK_VG:
375 1.1 haad /* Lock VG to change on-disk metadata. */
376 1.1 haad /* If LVM1 driver knows about the VG, it can't be accessed. */
377 1.1 haad if (!check_lvm1_vg_inactive(cmd, vol))
378 1.1 haad return 0;
379 1.1 haad case LCK_LV:
380 1.1 haad /* Suspend LV if it's active. */
381 1.1 haad strncpy(resource, vol, sizeof(resource));
382 1.1 haad break;
383 1.1 haad default:
384 1.1 haad log_error("Unrecognised lock scope: %d",
385 1.1 haad flags & LCK_SCOPE_MASK);
386 1.1 haad return 0;
387 1.1 haad }
388 1.1 haad
389 1.1 haad if (!_lock_vol(cmd, resource, flags))
390 1.1 haad return 0;
391 1.1 haad
392 1.1 haad /*
393 1.1 haad * If a real lock was acquired (i.e. not LCK_CACHE),
394 1.1 haad * perform an immediate unlock unless LCK_HOLD was requested.
395 1.1 haad */
396 1.1 haad if (!(flags & LCK_CACHE) && !(flags & LCK_HOLD) &&
397 1.1 haad ((flags & LCK_TYPE_MASK) != LCK_UNLOCK)) {
398 1.1 haad if (!_lock_vol(cmd, resource,
399 1.1 haad (flags & ~LCK_TYPE_MASK) | LCK_UNLOCK))
400 1.1 haad return 0;
401 1.1 haad }
402 1.1 haad
403 1.1 haad return 1;
404 1.1 haad }
405 1.1 haad
406 1.1 haad /* Unlock list of LVs */
407 1.1 haad int resume_lvs(struct cmd_context *cmd, struct dm_list *lvs)
408 1.1 haad {
409 1.1 haad struct lv_list *lvl;
410 1.1 haad
411 1.1 haad dm_list_iterate_items(lvl, lvs)
412 1.1 haad resume_lv(cmd, lvl->lv);
413 1.1 haad
414 1.1 haad return 1;
415 1.1 haad }
416 1.1 haad
417 1.1 haad /* Lock a list of LVs */
418 1.1 haad int suspend_lvs(struct cmd_context *cmd, struct dm_list *lvs)
419 1.1 haad {
420 1.1 haad struct dm_list *lvh;
421 1.1 haad struct lv_list *lvl;
422 1.1 haad
423 1.1 haad dm_list_iterate_items(lvl, lvs) {
424 1.1 haad if (!suspend_lv(cmd, lvl->lv)) {
425 1.1 haad log_error("Failed to suspend %s", lvl->lv->name);
426 1.1 haad dm_list_uniterate(lvh, lvs, &lvl->list) {
427 1.1 haad lvl = dm_list_item(lvh, struct lv_list);
428 1.1 haad resume_lv(cmd, lvl->lv);
429 1.1 haad }
430 1.1 haad
431 1.1 haad return 0;
432 1.1 haad }
433 1.1 haad }
434 1.1 haad
435 1.1 haad return 1;
436 1.1 haad }
437 1.1 haad
438 1.1 haad /* Lock a list of LVs */
439 1.1 haad int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive)
440 1.1 haad {
441 1.1 haad struct dm_list *lvh;
442 1.1 haad struct lv_list *lvl;
443 1.1 haad
444 1.1 haad dm_list_iterate_items(lvl, lvs) {
445 1.1 haad if (!exclusive) {
446 1.1 haad if (!activate_lv(cmd, lvl->lv)) {
447 1.1 haad log_error("Failed to activate %s", lvl->lv->name);
448 1.1 haad return 0;
449 1.1 haad }
450 1.1 haad } else if (!activate_lv_excl(cmd, lvl->lv)) {
451 1.1 haad log_error("Failed to activate %s", lvl->lv->name);
452 1.1 haad dm_list_uniterate(lvh, lvs, &lvl->list) {
453 1.1 haad lvl = dm_list_item(lvh, struct lv_list);
454 1.1 haad activate_lv(cmd, lvl->lv);
455 1.1 haad }
456 1.1 haad return 0;
457 1.1 haad }
458 1.1 haad }
459 1.1 haad
460 1.1 haad return 1;
461 1.1 haad }
462 1.1 haad
463 1.1 haad int vg_write_lock_held(void)
464 1.1 haad {
465 1.1 haad return _vg_write_lock_held;
466 1.1 haad }
467 1.1 haad
468 1.1 haad int locking_is_clustered(void)
469 1.1 haad {
470 1.1 haad return (_locking.flags & LCK_CLUSTERED) ? 1 : 0;
471 1.1 haad }
472 1.1 haad
473