X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Ffsck%2Ffsck.c;h=a4a15da1bf630e8a050f422cfd948f3c9904172c;hp=6ccb2e7340edc521675ffa09a0a7b38badca548b;hb=576a13eaf6491fdbebc817ef613963ac24cfb6b8;hpb=ac6e2f0dfc2e800f01c79ecea2b811914110a7b9 diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 6ccb2e734..a4a15da1b 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -37,7 +36,6 @@ #include "bus-util.h" #include "bus-error.h" #include "bus-common-errors.h" -#include "fileio.h" #include "udev-util.h" #include "path-util.h" #include "socket-util.h" @@ -45,7 +43,6 @@ static bool arg_skip = false; static bool arg_force = false; -static bool arg_show_progress = false; static const char *arg_repair = "-a"; static void start_target(const char *target) { @@ -131,11 +128,9 @@ static void test_files(void) { } #endif - if (access("/run/systemd/show-status", F_OK) >= 0 || plymouth_running()) - arg_show_progress = true; } -static int process_progress(int fd, dev_t device_num) { +static int process_progress(int fd, pid_t fsck_pid, dev_t device_num) { _cleanup_fclose_ FILE *f = NULL; usec_t last = 0; _cleanup_close_ int fsckd_fd = -1; @@ -156,11 +151,13 @@ static int process_progress(int fd, dev_t device_num) { while (!feof(f)) { int pass; + size_t buflen; size_t cur, max; - ssize_t n; + ssize_t r; usec_t t; _cleanup_free_ char *device = NULL; FsckProgress progress; + FsckdMessage fsckd_message; if (fscanf(f, "%i %lu %lu %ms", &pass, &cur, &max, &device) != 4) break; @@ -178,9 +175,19 @@ static int process_progress(int fd, dev_t device_num) { progress.max = max; progress.pass = pass; - n = send(fsckd_fd, &progress, sizeof(FsckProgress), 0); - if (n < 0 || (size_t) n < sizeof(FsckProgress)) + r = send(fsckd_fd, &progress, sizeof(FsckProgress), 0); + if (r < 0 || (size_t) r < sizeof(FsckProgress)) log_warning_errno(errno, "Cannot communicate fsck progress to fsckd: %m"); + + /* get fsckd requests, only read when we have coherent size data */ + r = ioctl(fsckd_fd, FIONREAD, &buflen); + if (r == 0 && (size_t) buflen >= sizeof(FsckdMessage)) { + r = recv(fsckd_fd, &fsckd_message, sizeof(FsckdMessage), 0); + if (r > 0 && fsckd_message.cancel == 1) { + log_info("Request to cancel fsck from fsckd"); + kill(fsck_pid, SIGTERM); + } + } } return 0; @@ -190,6 +197,7 @@ int main(int argc, char *argv[]) { const char *cmdline[9]; int i = 0, r = EXIT_FAILURE, q; pid_t pid; + int progress_rc; siginfo_t status; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_udev_device_unref_ struct udev_device *udev_device = NULL; @@ -286,11 +294,10 @@ int main(int argc, char *argv[]) { log_warning_errno(r, "fsck.%s cannot be used for %s: %m", type, device); } - if (arg_show_progress) - if (pipe(progress_pipe) < 0) { - log_error_errno(errno, "pipe(): %m"); - return EXIT_FAILURE; - } + if (pipe(progress_pipe) < 0) { + log_error_errno(errno, "pipe(): %m"); + return EXIT_FAILURE; + } cmdline[i++] = "/sbin/fsck"; cmdline[i++] = arg_repair; @@ -309,10 +316,8 @@ int main(int argc, char *argv[]) { if (arg_force) cmdline[i++] = "-f"; - if (progress_pipe[1] >= 0) { - xsprintf(dash_c, "-C%i", progress_pipe[1]); - cmdline[i++] = dash_c; - } + xsprintf(dash_c, "-C%i", progress_pipe[1]); + cmdline[i++] = dash_c; cmdline[i++] = device; cmdline[i++] = NULL; @@ -323,18 +328,15 @@ int main(int argc, char *argv[]) { goto finish; } else if (pid == 0) { /* Child */ - if (progress_pipe[0] >= 0) - safe_close(progress_pipe[0]); + safe_close(progress_pipe[0]); execv(cmdline[0], (char**) cmdline); _exit(8); /* Operational error */ } progress_pipe[1] = safe_close(progress_pipe[1]); - if (progress_pipe[0] >= 0) { - process_progress(progress_pipe[0], st.st_rdev); - progress_pipe[0] = -1; - } + progress_rc = process_progress(progress_pipe[0], pid, st.st_rdev); + progress_pipe[0] = -1; q = wait_for_terminate(pid, &status); if (q < 0) { @@ -342,13 +344,14 @@ int main(int argc, char *argv[]) { goto finish; } - if (status.si_code != CLD_EXITED || (status.si_status & ~1)) { + if (status.si_code != CLD_EXITED || (status.si_status & ~1) || progress_rc != 0) { - if (status.si_code == CLD_KILLED || status.si_code == CLD_DUMPED) + /* cancel will kill fsck (but process_progress returns 0) */ + if ((progress_rc != 0 && 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 (progress_rc != 0) log_error("fsck failed due to unknown reason."); if (status.si_code == CLD_EXITED && (status.si_status & 2) && root_directory) @@ -359,7 +362,8 @@ int main(int argc, char *argv[]) { start_target(SPECIAL_EMERGENCY_TARGET); else { r = EXIT_SUCCESS; - log_warning("Ignoring error."); + if (progress_rc != 0) + log_warning("Ignoring error."); } } else