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