summaryrefslogtreecommitdiff
path: root/src/fsck/fsck.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fsck/fsck.c')
-rw-r--r--src/fsck/fsck.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 9ecba99bb1..e7185342d7 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -132,7 +132,7 @@ static void test_files(void) {
}
-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;
@@ -153,11 +153,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;
@@ -175,9 +177,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;
@@ -187,6 +199,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;
@@ -328,7 +341,7 @@ int main(int argc, char *argv[]) {
progress_pipe[1] = safe_close(progress_pipe[1]);
if (progress_pipe[0] >= 0) {
- process_progress(progress_pipe[0], st.st_rdev);
+ progress_rc = process_progress(progress_pipe[0], pid, st.st_rdev);
progress_pipe[0] = -1;
}
@@ -338,13 +351,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)
@@ -355,7 +369,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