Home | History | Annotate | Line # | Download | only in locking
locking.c revision 1.1
      1  1.1  haad /*	$NetBSD: locking.c,v 1.1 2008/12/22 00:18:04 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  haad 		if (!cmd->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