diff --git a/WHATS_NEW b/WHATS_NEW index 456f132bf..37225fee6 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.107 - ================================== + Separate signal handling and flock code out into lib/misc. Don't start dmeventd checking seg_monitor and monitoring is disabled. Catch CTRL-c during pvremove prompts. Show correct availability status for snapshot origin in lvscan. diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c index d0c4a4d89..3470c664a 100644 --- a/lib/cache/lvmetad.c +++ b/lib/cache/lvmetad.c @@ -21,6 +21,7 @@ #include "lvmetad-client.h" #include "format-text.h" // TODO for disk_locn, used as a DA representation #include "crc.h" +#include "lvm-signal.h" #define SCAN_TIMEOUT_SECONDS 80 #define MAX_RESCANS 10 /* Maximum number of times to scan all PVs and retry if the daemon returns a token mismatch error */ diff --git a/lib/display/display.c b/lib/display/display.c index b83bb5926..b808f25f5 100644 --- a/lib/display/display.c +++ b/lib/display/display.c @@ -20,6 +20,8 @@ #include "toolcontext.h" #include "segtype.h" #include "defaults.h" +#include "lvm-signal.h" + #include #define SIZE_BUF 128 diff --git a/lib/locking/locking.c b/lib/locking/locking.c index b5250c10b..673713a0b 100644 --- a/lib/locking/locking.c +++ b/lib/locking/locking.c @@ -22,148 +22,25 @@ #include "memlock.h" #include "defaults.h" #include "lvmcache.h" +#include "lvm-signal.h" #include -#include #include #include #include static struct locking_type _locking; -static sigset_t _oldset; static int _vg_lock_count = 0; /* Number of locks held */ static int _vg_write_lock_held = 0; /* VG write lock held? */ -static int _signals_blocked = 0; static int _blocking_supported = 0; -static volatile sig_atomic_t _sigint_caught = 0; -static volatile sig_atomic_t _handler_installed; -static struct sigaction _oldhandler; -static int _oldmasked; - typedef enum { LV_NOOP, LV_SUSPEND, LV_RESUME } lv_operation_t; -static void _catch_sigint(int unused __attribute__((unused))) -{ - _sigint_caught = 1; -} - -int sigint_caught(void) { - if (_sigint_caught) - log_error("Interrupted..."); - - return _sigint_caught; -} - -void sigint_clear(void) -{ - _sigint_caught = 0; -} - -/* - * Temporarily allow keyboard interrupts to be intercepted and noted; - * saves interrupt handler state for sigint_restore(). Users should - * use the sigint_caught() predicate to check whether interrupt was - * requested and act appropriately. Interrupt flags are never - * cleared automatically by this code, but the tools clear the flag - * before running each command in lvm_run_command(). All other places - * where the flag needs to be cleared need to call sigint_clear(). - */ - -void sigint_allow(void) -{ - struct sigaction handler; - sigset_t sigs; - - /* - * Do not overwrite the backed-up handler data - - * just increase nesting count. - */ - if (_handler_installed) { - _handler_installed++; - return; - } - - /* Grab old sigaction for SIGINT: shall not fail. */ - sigaction(SIGINT, NULL, &handler); - handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */ - handler.sa_handler = _catch_sigint; - - _handler_installed = 1; - - /* Override the signal handler: shall not fail. */ - sigaction(SIGINT, &handler, &_oldhandler); - - /* Unmask SIGINT. Remember to mask it again on restore. */ - sigprocmask(0, NULL, &sigs); - if ((_oldmasked = sigismember(&sigs, SIGINT))) { - sigdelset(&sigs, SIGINT); - sigprocmask(SIG_SETMASK, &sigs, NULL); - } -} - -void sigint_restore(void) -{ - if (!_handler_installed) - return; - - if (_handler_installed > 1) { - _handler_installed--; - return; - } - - /* Nesting count went down to 0. */ - _handler_installed = 0; - - if (_oldmasked) { - sigset_t sigs; - sigprocmask(0, NULL, &sigs); - sigaddset(&sigs, SIGINT); - sigprocmask(SIG_SETMASK, &sigs, NULL); - } - - sigaction(SIGINT, &_oldhandler, NULL); -} - -static void _block_signals(uint32_t flags __attribute__((unused))) -{ - sigset_t set; - - if (_signals_blocked) - return; - - if (sigfillset(&set)) { - log_sys_error("sigfillset", "_block_signals"); - return; - } - - if (sigprocmask(SIG_SETMASK, &set, &_oldset)) { - log_sys_error("sigprocmask", "_block_signals"); - return; - } - - _signals_blocked = 1; -} - -static void _unblock_signals(void) -{ - /* Don't unblock signals while any locks are held */ - if (!_signals_blocked || _vg_lock_count) - return; - - if (sigprocmask(SIG_SETMASK, &_oldset, NULL)) { - log_sys_error("sigprocmask", "_block_signals"); - return; - } - - _signals_blocked = 0; -} - static void _lock_memory(struct cmd_context *cmd, lv_operation_t lv_op) { if (!(_locking.flags & LCK_PRE_MEMLOCK)) @@ -182,6 +59,13 @@ static void _unlock_memory(struct cmd_context *cmd, lv_operation_t lv_op) critical_section_dec(cmd, "unlocking on resume"); } +static void _unblock_signals(void) +{ + /* Don't unblock signals while any locks are held */ + if (!_vg_lock_count) + unblock_signals(); +} + void reset_locking(void) { int was_locked = _vg_lock_count; @@ -366,7 +250,7 @@ static int _lock_vol(struct cmd_context *cmd, const char *resource, uint32_t lck_scope = flags & LCK_SCOPE_MASK; int ret = 0; - _block_signals(flags); + block_signals(flags); _lock_memory(cmd, lv_op); assert(resource); diff --git a/lib/locking/locking.h b/lib/locking/locking.h index aa4213819..0945aa04f 100644 --- a/lib/locking/locking.h +++ b/lib/locking/locking.h @@ -213,10 +213,4 @@ int resume_lvs(struct cmd_context *cmd, struct dm_list *lvs); int revert_lvs(struct cmd_context *cmd, struct dm_list *lvs); int activate_lvs(struct cmd_context *cmd, struct dm_list *lvs, unsigned exclusive); -/* Interrupt handling */ -void sigint_clear(void); -void sigint_allow(void); -void sigint_restore(void); -int sigint_caught(void); - #endif diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 85f7a39a0..681783110 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -28,6 +28,7 @@ #include "str_list.h" #include "defaults.h" #include "lvm-exec.h" +#include "lvm-signal.h" typedef enum { PREFERRED, diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index e2abba7e3..4791c1044 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -19,6 +19,7 @@ #include "toolcontext.h" #include "lvm-string.h" #include "lvm-file.h" +#include "lvm-signal.h" #include "lvmcache.h" #include "lvmetad.h" #include "memlock.h" diff --git a/lib/misc/lvm-flock.h b/lib/misc/lvm-flock.h index 5e8aefde8..3fed73e21 100644 --- a/lib/misc/lvm-flock.h +++ b/lib/misc/lvm-flock.h @@ -12,11 +12,11 @@ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _LVM_SIGNAL_H -# define _LVM_SIGNAL_H +#ifndef _LVM_FLOCK_H +#define _LVM_FLOCK_H void init_flock(struct cmd_context *cmd); int lock_file(const char *file, uint32_t flags); void release_flocks(int unlock); -#endif /* _LVM_SIGNAL_H */ +#endif /* _LVM_FLOCK_H */ diff --git a/lib/misc/lvm-signal.c b/lib/misc/lvm-signal.c index 927e839a5..f2d6d3b23 100644 --- a/lib/misc/lvm-signal.c +++ b/lib/misc/lvm-signal.c @@ -22,6 +22,13 @@ static sig_t _oldhandler; static sigset_t _fullsigset, _intsigset; static volatile sig_atomic_t _handler_installed; +static sigset_t _oldset; +static int _signals_blocked = 0; +static volatile sig_atomic_t _sigint_caught = 0; +static volatile sig_atomic_t _handler_installed2; +static struct sigaction _oldhandler2; +static int _oldmasked; + void remove_ctrl_c_handler(void) { siginterrupt(SIGINT, 0); @@ -54,3 +61,119 @@ void install_ctrl_c_handler(void) sigprocmask(SIG_SETMASK, &_intsigset, NULL); siginterrupt(SIGINT, 1); } + +static void _catch_sigint(int unused __attribute__((unused))) +{ + _sigint_caught = 1; +} + +int sigint_caught(void) { + if (_sigint_caught) + log_error("Interrupted..."); + + return _sigint_caught; +} + +void sigint_clear(void) +{ + _sigint_caught = 0; +} + +/* + * Temporarily allow keyboard interrupts to be intercepted and noted; + * saves interrupt handler state for sigint_restore(). Users should + * use the sigint_caught() predicate to check whether interrupt was + * requested and act appropriately. Interrupt flags are never + * cleared automatically by this code, but the tools clear the flag + * before running each command in lvm_run_command(). All other places + * where the flag needs to be cleared need to call sigint_clear(). + */ + +void sigint_allow(void) +{ + struct sigaction handler; + sigset_t sigs; + + /* + * Do not overwrite the backed-up handler data - + * just increase nesting count. + */ + if (_handler_installed2) { + _handler_installed2++; + return; + } + + /* Grab old sigaction for SIGINT: shall not fail. */ + sigaction(SIGINT, NULL, &handler); + handler.sa_flags &= ~SA_RESTART; /* Clear restart flag */ + handler.sa_handler = _catch_sigint; + + _handler_installed2 = 1; + + /* Override the signal handler: shall not fail. */ + sigaction(SIGINT, &handler, &_oldhandler2); + + /* Unmask SIGINT. Remember to mask it again on restore. */ + sigprocmask(0, NULL, &sigs); + if ((_oldmasked = sigismember(&sigs, SIGINT))) { + sigdelset(&sigs, SIGINT); + sigprocmask(SIG_SETMASK, &sigs, NULL); + } +} + +void sigint_restore(void) +{ + if (!_handler_installed2) + return; + + if (_handler_installed2 > 1) { + _handler_installed2--; + return; + } + + /* Nesting count went down to 0. */ + _handler_installed2 = 0; + + if (_oldmasked) { + sigset_t sigs; + sigprocmask(0, NULL, &sigs); + sigaddset(&sigs, SIGINT); + sigprocmask(SIG_SETMASK, &sigs, NULL); + } + + sigaction(SIGINT, &_oldhandler2, NULL); +} + +void block_signals(uint32_t flags __attribute__((unused))) +{ + sigset_t set; + + if (_signals_blocked) + return; + + if (sigfillset(&set)) { + log_sys_error("sigfillset", "_block_signals"); + return; + } + + if (sigprocmask(SIG_SETMASK, &set, &_oldset)) { + log_sys_error("sigprocmask", "_block_signals"); + return; + } + + _signals_blocked = 1; +} + +void unblock_signals(void) +{ + /* Don't unblock signals while any locks are held */ + if (!_signals_blocked) + return; + + if (sigprocmask(SIG_SETMASK, &_oldset, NULL)) { + log_sys_error("sigprocmask", "_block_signals"); + return; + } + + _signals_blocked = 0; +} diff --git a/lib/misc/lvm-signal.h b/lib/misc/lvm-signal.h index ce9d2e9d8..f2e6141d4 100644 --- a/lib/misc/lvm-signal.h +++ b/lib/misc/lvm-signal.h @@ -14,7 +14,17 @@ */ #ifndef _LVM_SIGNAL_H -# define _LVM_SIGNAL_H +#define _LVM_SIGNAL_H + void remove_ctrl_c_handler(void); void install_ctrl_c_handler(void); + +void sigint_allow(void); +int sigint_caught(void); +void sigint_restore(void); +void sigint_clear(void); + +void block_signals(uint32_t flags); +void unblock_signals(void); + #endif diff --git a/tools/tools.h b/tools/tools.h index a2bfe0d15..11111cb8e 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -40,6 +40,7 @@ #include "locking.h" #include "lvm-exec.h" #include "lvm-file.h" +#include "lvm-signal.h" #include "lvm-string.h" #include "segtype.h" #include "str_list.h"