On 28 January 2015 at 14:53, Zbigniew Jędrzejewski-Szmek <zbys...@in.waw.pl> wrote: > > On Wed, Jan 28, 2015 at 02:22:54PM +0100, Didier Roche wrote: > > > > > From 104cf82ba28941e907f277a713f834ceb3d909f0 Mon Sep 17 00:00:00 2001 > > From: Didier Roche <didro...@ubuntu.com> > > Date: Mon, 26 Jan 2015 16:40:52 +0100 > > Subject: [PATCH 06/12] Support cancellation of fsck in progress > > > > Grab in fsckd plymouth watch key for C or c, and propagate this cancel > > request > > to systemd-fsck which will terminate fsck. > Could we bind to ^c or if this is not possible, "three c's in three > seconds" instead? I'm worried that before you could press anything to little > effect in plymouth, and now a single key will have significant consequences. >
Hm? an interactive message with key-binding is usually shown and then plymouth reacts to such a key prompt. This is how it has always worked on plymouth prompts since forever... thus this would not be a surprise to most plymouth users (~ 5+ years by now?!) Doing it otherwise, will, on the contrary, impede user experience. > > > Send a message to signal to user what key we are grabbing for fsck cancel. > > > > Message is: fsckd-cancel-msg:<string> > > Where string is a translated string ready to be displayed by the plymouth > > theme > > indicating that c or C can be used to cancel current checks. It can be > > overriden (matching only fsckd-cancel-msg prefix) for themes supporting > > i18n. > > --- > > src/fsck/fsck.c | 29 +++++++++++++++++++++-------- > > src/fsckd/fsckd.c | 43 +++++++++++++++++++++++++++++++++++++++++++ > > src/fsckd/fsckd.h | 5 +++++ > > 3 files changed, 69 insertions(+), 8 deletions(-) > > > > diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c > > index f5dd546..0b42e3b 100644 > > --- a/src/fsck/fsck.c > > +++ b/src/fsck/fsck.c > > @@ -47,6 +47,8 @@ > > static bool arg_skip = false; > > static bool arg_force = false; > > static const char *arg_repair = "-a"; > > +static pid_t fsck_pid; > > +static bool cancel_requested = false; > > > > static void start_target(const char *target) { > > _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; > > @@ -165,6 +167,7 @@ static int process_progress(int fd) { > > ssize_t n; > > usec_t t; > > FsckProgress progress; > > + FsckdMessage fsckd_message; > > > > if (fscanf(f, "%i %lu %lu %ms", &pass, &cur, &max, > > &device) != 4) > > break; > > @@ -185,6 +188,16 @@ static int process_progress(int fd) { > > n = send(fsckd_fd, &progress, sizeof(FsckProgress), 0); > > if (n < 0 || (size_t) n < sizeof(FsckProgress)) > > log_warning_errno(n, "Cannot communicate fsck > > progress to fsckd: %m"); > > + > > + /* get fsckd requests */ > > + n = recv(fsckd_fd, &fsckd_message, sizeof(FsckdMessage), > > 0); > > + if (n > 0) { > > + if (fsckd_message.cancel) { > > + log_warning("Request to cancel fsck from > > fsckd"); > > + cancel_requested = true; > > + kill(fsck_pid, SIGTERM); > > + } > > + } > > } > > > > return 0; > > @@ -193,7 +206,6 @@ static int process_progress(int fd) { > > int main(int argc, char *argv[]) { > > const char *cmdline[9]; > > int i = 0, r = EXIT_FAILURE, q; > > - pid_t pid; > > siginfo_t status; > > _cleanup_udev_unref_ struct udev *udev = NULL; > > _cleanup_udev_device_unref_ struct udev_device *udev_device = NULL; > > @@ -321,11 +333,11 @@ int main(int argc, char *argv[]) { > > cmdline[i++] = device; > > cmdline[i++] = NULL; > > > > - pid = fork(); > > - if (pid < 0) { > > + fsck_pid = fork(); > > + if (fsck_pid < 0) { > > log_error_errno(errno, "fork(): %m"); > > goto finish; > > - } else if (pid == 0) { > > + } else if (fsck_pid == 0) { > > /* Child */ > > if (progress_pipe[0] >= 0) > > safe_close(progress_pipe[0]); > > @@ -340,7 +352,7 @@ int main(int argc, char *argv[]) { > > progress_pipe[0] = -1; > > } > > > > - q = wait_for_terminate(pid, &status); > > + q = wait_for_terminate(fsck_pid, &status); > > if (q < 0) { > > log_error_errno(q, "waitid(): %m"); > > goto finish; > > @@ -348,11 +360,11 @@ int main(int argc, char *argv[]) { > > > > if (status.si_code != CLD_EXITED || (status.si_status & ~1)) { > > > > - if (status.si_code == CLD_KILLED || status.si_code == > > CLD_DUMPED) > > + if ((!cancel_requested && status.si_code == CLD_KILLED) || > > status.si_code == CLD_DUMPED) > > log_error("fsck terminated by signal %s.", > > signal_to_string(status.si_status)); > > else if (status.si_code == CLD_EXITED) > > log_error("fsck failed with error code %i.", > > status.si_status); > > - else > > + else if (!cancel_requested) > > log_error("fsck failed due to unknown reason."); > > > > if (status.si_code == CLD_EXITED && (status.si_status & 2) > > && root_directory) > > @@ -363,7 +375,8 @@ int main(int argc, char *argv[]) { > > start_target(SPECIAL_EMERGENCY_TARGET); > > else { > > r = EXIT_SUCCESS; > > - log_warning("Ignoring error."); > > + if (!cancel_requested) > > + log_warning("Ignoring error."); > > } > > > > } else > > diff --git a/src/fsckd/fsckd.c b/src/fsckd/fsckd.c > > index b516193..5760916 100644 > > --- a/src/fsckd/fsckd.c > > +++ b/src/fsckd/fsckd.c > > @@ -57,10 +57,15 @@ typedef struct Clients { > > unsigned long max; > > int pass; > > double percent; > > + bool cancelled; > > > > LIST_FIELDS(struct Clients, clients); > > } Clients; > > > > +#ifdef HAVE_PLYMOUTH > > +static bool cancelled = false; > > +#endif > > + > > static double compute_percent(int pass, unsigned long cur, unsigned long > > max) { > > /* Values stolen from e2fsck */ > > > > @@ -79,12 +84,25 @@ static double compute_percent(int pass, unsigned long > > cur, unsigned long max) { > > (double) cur / (double) max; > > } > > > > +#ifdef HAVE_PLYMOUTH > > +static void cancel_requested(void) { > > + log_debug("Request to cancel fsck checking received"); > > + cancelled = true; > > +} > > +#endif > > + > > static int handle_requests(int socket_fd) { > > Clients *first = NULL; > > usec_t last_activity = 0; > > int numdevices = 0, clear = 0; > > double percent = 100; > > _cleanup_fclose_ FILE *console = NULL; > > +#ifdef HAVE_PLYMOUTH > > + const char *plymouth_cancel_message; > > + bool cancel_message_plymouth_sent = false; > > + > > + plymouth_cancel_message = strappenda("fsckd-cancel-msg:", "Press C > > to cancel all checks in progress"); > > +#endif > > > > console = fopen("/dev/console", "we"); > > if (!console) { > > @@ -111,6 +129,7 @@ static int handle_requests(int socket_fd) { > > log_debug("new fsck client connected to fd: %d", > > new_client_fd); > > current = alloca0(sizeof(Clients)); > > current->fd = new_client_fd; > > + current->cancelled = false; > > if (!first) > > LIST_INIT(clients, current); > > else > > @@ -143,6 +162,20 @@ static int handle_requests(int socket_fd) { > > > > log_debug("Getting progress for %s: (%lu, > > %lu, %d) : %3.1f%%", > > current->device, current->cur, > > current->max, current->pass, current->percent); > > + > > +#ifdef HAVE_PLYMOUTH > > + /* send cancel message if cancel key was > > pressed (and the socket wasn't closed) */ > > + if (cancelled && !current->cancelled) { > > + FsckdMessage cancel_msg; > > + ssize_t n; > > + cancel_msg.cancel = true; > > + n = send(current->fd, &cancel_msg, > > sizeof(FsckdMessage), 0); > > + if (n < 0 || (size_t) n < > > sizeof(FsckdMessage)) > > + log_warning_errno(n, > > "Cannot send cancel to fsck on %s: %m", current->device); > > + else > > + current->cancelled = true; > > + } > > +#endif > > } > > > > /* update global (eventually cached) values. */ > > @@ -173,6 +206,10 @@ static int handle_requests(int socket_fd) { > > > > #ifdef HAVE_PLYMOUTH > > /* send to plymouth */ > > + if (!cancel_message_plymouth_sent) { > > + cancel_message_plymouth_sent = \ > > + plymouth_watch_key("Cc", > > plymouth_cancel_message, cancel_requested); > > + } > > plymouth_update(fsck_message); > > #endif > > > > @@ -183,6 +220,12 @@ static int handle_requests(int socket_fd) { > > /* idle out after IDLE_TIME_MINUTES minutes with no > > connected device */ > > t = now(CLOCK_MONOTONIC); > > if (numdevices == 0) { > > +#ifdef HAVE_PLYMOUTH > > + if (cancel_message_plymouth_sent) { > > + plymouth_delete_message(); > > + cancel_message_plymouth_sent = false; > > + } > > +#endif > > if (t > last_activity + IDLE_TIME_MINUTES * > > USEC_PER_MINUTE) { > > log_debug("No fsck in progress for the last %d > > minutes, shutting down.", IDLE_TIME_MINUTES); > > break; > > diff --git a/src/fsckd/fsckd.h b/src/fsckd/fsckd.h > > index e8cd014..6a029ec 100644 > > --- a/src/fsckd/fsckd.h > > +++ b/src/fsckd/fsckd.h > > @@ -23,6 +23,7 @@ > > ***/ > > > > #include <linux/limits.h> > > +#include <stdbool.h> > > > > #define FSCKD_SOCKET_PATH "/run/systemd/fsckd" > > > > @@ -32,3 +33,7 @@ typedef struct FsckProgress { > > int pass; > > char device[PATH_MAX]; > > } FsckProgress; > > + > > +typedef struct FsckdMessage { > > + bool cancel; > > +} FsckdMessage; > > Zbyszek > _______________________________________________ > systemd-devel mailing list > systemd-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/systemd-devel -- Regards, Dimitri. Intel Corporation (UK) Ltd. - Co. Reg. #1134945 - Pipers Way, Swindon SN3 1RJ. _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel