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