Home | History | Annotate | Line # | Download | only in locking
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