]> sourceware.org Git - lvm2.git/commitdiff
Allow keyboard interrupts in yes_no_prompt(). Add code to toollib.c
authorPetr Rockai <prockai@redhat.com>
Fri, 15 Jun 2007 10:11:14 +0000 (10:11 +0000)
committerPetr Rockai <prockai@redhat.com>
Fri, 15 Jun 2007 10:11:14 +0000 (10:11 +0000)
loops and to pvcreate.c, lvchange.c and lvresize.c to handle
interrupted prompts.

WHATS_NEW
lib/locking/locking.c
lib/locking/locking.h
tools/lvchange.c
tools/lvmcmdline.c
tools/lvresize.c
tools/pvcreate.c
tools/toollib.c

index 44a202595fe836e89510be0a217d0820cb0e47a4..a061df1d9772819348c38cdea130c847d67d8dbc 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 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.
index 1f188bb307f3702f878a793ff4f4f837d88ced80..0d6bd43435924ef6a68f65704f9bfb8de36df196 100644 (file)
@@ -34,6 +34,87 @@ 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 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;
index 0075b1cf9fc732577b4e0a8613f61429880ac7e4..27ebfc4b0b2005f0e25378da443494a47ba07e7c 100644 (file)
@@ -115,4 +115,11 @@ int suspend_lvs(struct cmd_context *cmd, struct list *lvs);
 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
index 4f046bc954391f0511ab30ac05230818d1327512..175200adc38275d7fe402c0a55a3ce36965945d6 100644 (file)
@@ -212,6 +212,9 @@ static int lvchange_resync(struct cmd_context *cmd,
                                return ECMD_FAILED;
                        }
 
+                       if (sigint_caught())
+                               return ECMD_FAILED;
+
                        active = 1;
                }
        }
@@ -454,6 +457,10 @@ static int lvchange_persistent(struct cmd_context *cmd,
                                  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);
@@ -626,6 +633,8 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
                        return ECMD_FAILED;
                archived = 1;
                doit += lvchange_persistent(cmd, lv);
+               if (sigint_caught())
+                       return ECMD_FAILED;
        }
 
        /* add tag */
index 390771e2bedc4b64f43c512630925000a5883e9d..6c0ccfd9b7c0f66ed2400ac5bec2a39e51ead080 100644 (file)
@@ -373,6 +373,7 @@ char yes_no_prompt(const char *prompt, ...)
        int c = 0, ret = 0;
        va_list ap;
 
+       sigint_allow();
        do {
                if (c == '\n' || !c) {
                        va_start(ap, prompt);
@@ -390,6 +391,8 @@ char yes_no_prompt(const char *prompt, ...)
                        ret = c;
        } while (!ret || c != '\n');
 
+       sigint_restore();
+
        if (c != '\n')
                printf("\n");
 
@@ -865,6 +868,9 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
        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;
 
index b77fc72195f40264d46ecf4c77e883a92d48fa80..c9fee4381a3ac0d948b5a83d8cbd9a22d7d81274 100644 (file)
@@ -485,6 +485,8 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
                                                  "reduced", lp->lv_name);
                                        return ECMD_FAILED;
                                }
+                               if (sigint_caught())
+                                       return ECMD_FAILED;
                        }
                }
        }
index 78a5d98f64b776feb05f3691d48bd1526d3892e9..ce49707a9576c771a6f165375103cfbc17f3ec58 100644 (file)
@@ -58,6 +58,9 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
                return 0;
        }
 
+       if (sigint_caught())
+               return 0;
+
        dev = dev_cache_get(name, cmd->filter);
 
        /* Is there an md superblock here? */
@@ -103,6 +106,9 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
                }
        }
 
+       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,
@@ -173,6 +179,9 @@ static int pvcreate_single(struct cmd_context *cmd, const char *pv_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;
@@ -309,6 +318,8 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv)
                r = pvcreate_single(cmd, argv[i], &pp);
                if (r > ret)
                        ret = r;
+               if (sigint_caught())
+                       return ret;
        }
 
        return ret;
index b286446b0dee94192d6330af1756c98cb1694a90..bbf3c412115049f91cfaa0d402b75a93aa3a8eb8 100644 (file)
@@ -209,6 +209,8 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
                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)) {
@@ -407,6 +409,8 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
                unlock_vg(cmd, vgname);
                if (ret > ret_max)
                        ret_max = ret;
+               if (sigint_caught())
+                       return ret_max;
        }
 
        return ret_max;
@@ -429,6 +433,8 @@ int process_each_segment_in_pv(struct cmd_context *cmd,
                ret = process_single(cmd, vg, pvseg, handle);
                if (ret > ret_max)
                        ret_max = ret;
+               if (sigint_caught())
+                       return ret_max;
        }
 
        return ret_max;
@@ -449,6 +455,8 @@ int process_each_segment_in_lv(struct cmd_context *cmd,
                ret = process_single(cmd, seg, handle);
                if (ret > ret_max)
                        ret_max = ret;
+               if (sigint_caught())
+                       return ret_max;
        }
 
        return ret_max;
@@ -498,6 +506,9 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
                ret_max = ret;
        }
 
+       if (sigint_caught())
+               return ret_max;
+
        unlock_vg(cmd, vg_name);
 
        return ret_max;
@@ -573,6 +584,8 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
                                                  &arg_vgnames,
                                                  lock_type, consistent, handle,
                                                  ret_max, process_single);
+                       if (sigint_caught())
+                               return ret_max;
                }
        } else {
                list_iterate_items(sl, vgnames) {
@@ -583,6 +596,8 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
                                                  &arg_vgnames,
                                                  lock_type, consistent, handle,
                                                  ret_max, process_single);
+                       if (sigint_caught())
+                               return ret_max;
                }
        }
 
@@ -607,6 +622,8 @@ int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
                }
                if ((ret = process_single(cmd, vg, pvl->pv, handle)) > ret_max)
                        ret_max = ret;
+               if (sigint_caught())
+                       return ret_max;
        }
 
        return ret_max;
@@ -643,6 +660,8 @@ static int _process_all_devs(struct cmd_context *cmd, void *handle,
                ret = process_single(cmd, NULL, pv, handle);
                if (ret > ret_max)
                        ret_max = ret;
+               if (sigint_caught())
+                       return ret_max;
        }
 
        dev_iter_destroy(iter);
@@ -715,6 +734,8 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
                        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)) {
@@ -735,6 +756,8 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
                                                            process_single);
                                if (ret > ret_max)
                                        ret_max = ret;
+                               if (sigint_caught())
+                                       return ret_max;
                        }
                }
        } else {
@@ -745,10 +768,14 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
                                                    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)))
@@ -759,6 +786,8 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
                                                     handle);
                                if (ret > ret_max)
                                        ret_max = ret;
+                               if (sigint_caught())
+                                       return ret_max;
                        }
                }
        }
This page took 0.050528 seconds and 5 git commands to generate.