Version 2.02.26 -
=================================
+ Allow keyboard interrupt in user prompts where appropriate.
Remove system-lv code from clvmd. It's highly dodgy and never used.
Convert a lot of code pv dereferences to use get_pv_* functions.
Suppress a couple benign warnings by adding variable initializations.
static int _vg_write_lock_held = 0; /* VG write lock held? */
static int _signals_blocked = 0;
+static volatile sig_atomic_t _sigint_caught = 0;
+static volatile sig_atomic_t _handler_installed;
+static struct sigaction _oldhandler;
+static int _oldmasked;
+
+static void _catch_sigint(int unused __attribute__((unused)))
+{
+ _sigint_caught = 1;
+}
+
+int sigint_caught() {
+ return _sigint_caught;
+}
+
+void sigint_clear()
+{
+ _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
+ automatically cleared by this code, but lvm_run_command() clears
+ the flag before running any command. All other places where the
+ flag needs to be cleared need to call sigint_clear(). */
+
+void sigint_allow()
+{
+ struct sigaction handler;
+ sigset_t sigs;
+
+ /* do not overwrite the backed up handler data with our
+ override ones; we 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()
+{
+ /* extra call, ignore */
+ 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(int flags __attribute((unused)))
{
sigset_t set;
int resume_lvs(struct cmd_context *cmd, struct list *lvs);
int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs);
+/* interrupt handling */
+
+void sigint_clear();
+void sigint_allow();
+void sigint_restore();
+int sigint_caught();
+
#endif
return ECMD_FAILED;
}
+ if (sigint_caught())
+ return ECMD_FAILED;
+
active = 1;
}
}
lv->name);
return 0;
}
+
+ if (sigint_caught())
+ return 0;
+
log_verbose("Ensuring %s is inactive.", lv->name);
if (!deactivate_lv(cmd, lv)) {
log_error("%s: deactivation failed", lv->name);
return ECMD_FAILED;
archived = 1;
doit += lvchange_persistent(cmd, lv);
+ if (sigint_caught())
+ return ECMD_FAILED;
}
/* add tag */
int c = 0, ret = 0;
va_list ap;
+ sigint_allow();
do {
if (c == '\n' || !c) {
va_start(ap, prompt);
ret = c;
} while (!ret || c != '\n');
+ sigint_restore();
+
if (c != '\n')
printf("\n");
int ret = 0;
int locking_type;
+ /* each command should start out with sigint flag cleared */
+ sigint_clear();
+
if (!(cmd->cmd_line = _copy_command_line(cmd, argc, argv)))
return ECMD_FAILED;
"reduced", lp->lv_name);
return ECMD_FAILED;
}
+ if (sigint_caught())
+ return ECMD_FAILED;
}
}
}
return 0;
}
+ if (sigint_caught())
+ return 0;
+
dev = dev_cache_get(name, cmd->filter);
/* Is there an md superblock here? */
}
}
+ if (sigint_caught())
+ return 0;
+
if (pv && !is_orphan(pv) && arg_count(cmd, force_ARG)) {
log_print("WARNING: Forcing physical volume creation on "
"%s%s%s%s", name,
if (!pvcreate_check(cmd, pv_name))
goto error;
+ if (sigint_caught())
+ goto error;
+
if (arg_sign_value(cmd, physicalvolumesize_ARG, 0) == SIGN_MINUS) {
log_error("Physical volume size may not be negative");
goto error;
r = pvcreate_single(cmd, argv[i], &pp);
if (r > ret)
ret = r;
+ if (sigint_caught())
+ return ret;
}
return ret;
ret = process_single(cmd, lvl->lv, handle);
if (ret > ret_max)
ret_max = ret;
+ if (sigint_caught())
+ return ret_max;
}
if (lvargs_supplied && lvargs_matched != list_size(arg_lvnames)) {
unlock_vg(cmd, vgname);
if (ret > ret_max)
ret_max = ret;
+ if (sigint_caught())
+ return ret_max;
}
return ret_max;
ret = process_single(cmd, vg, pvseg, handle);
if (ret > ret_max)
ret_max = ret;
+ if (sigint_caught())
+ return ret_max;
}
return ret_max;
ret = process_single(cmd, seg, handle);
if (ret > ret_max)
ret_max = ret;
+ if (sigint_caught())
+ return ret_max;
}
return ret_max;
ret_max = ret;
}
+ if (sigint_caught())
+ return ret_max;
+
unlock_vg(cmd, vg_name);
return ret_max;
&arg_vgnames,
lock_type, consistent, handle,
ret_max, process_single);
+ if (sigint_caught())
+ return ret_max;
}
} else {
list_iterate_items(sl, vgnames) {
&arg_vgnames,
lock_type, consistent, handle,
ret_max, process_single);
+ if (sigint_caught())
+ return ret_max;
}
}
}
if ((ret = process_single(cmd, vg, pvl->pv, handle)) > ret_max)
ret_max = ret;
+ if (sigint_caught())
+ return ret_max;
}
return ret_max;
ret = process_single(cmd, NULL, pv, handle);
if (ret > ret_max)
ret_max = ret;
+ if (sigint_caught())
+ return ret_max;
}
dev_iter_destroy(iter);
ret = process_single(cmd, vg, pv, handle);
if (ret > ret_max)
ret_max = ret;
+ if (sigint_caught())
+ return ret_max;
}
if (!list_empty(&tags) && (vgnames = get_vgs(cmd, 0)) &&
!list_empty(vgnames)) {
process_single);
if (ret > ret_max)
ret_max = ret;
+ if (sigint_caught())
+ return ret_max;
}
}
} else {
process_single);
if (ret > ret_max)
ret_max = ret;
+ if (sigint_caught())
+ return ret_max;
} else if (arg_count(cmd, all_ARG)) {
ret = _process_all_devs(cmd, handle, process_single);
if (ret > ret_max)
ret_max = ret;
+ if (sigint_caught())
+ return ret_max;
} else {
log_verbose("Scanning for physical volume names");
if (!(pvslist = get_pvs(cmd)))
handle);
if (ret > ret_max)
ret_max = ret;
+ if (sigint_caught())
+ return ret_max;
}
}
}