summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile-man.am12
-rw-r--r--Makefile.am17
-rw-r--r--man/systemd-fsck@.service.xml4
-rw-r--r--man/systemd-fsckd.service.xml162
-rw-r--r--src/fsck/fsck.c254
l---------src/fsckd/Makefile1
-rw-r--r--src/fsckd/fsckd.c642
-rw-r--r--src/fsckd/fsckd.h38
-rw-r--r--units/.gitignore1
-rw-r--r--units/systemd-fsck-root.service.in2
-rw-r--r--units/systemd-fsck@.service.in3
-rw-r--r--units/systemd-fsckd.service.in17
-rw-r--r--units/systemd-fsckd.socket15
14 files changed, 167 insertions, 1002 deletions
diff --git a/.gitignore b/.gitignore
index d4edf990a4..0376e00a3d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -78,7 +78,6 @@
/systemd-export
/systemd-firstboot
/systemd-fsck
-/systemd-fsckd
/systemd-fstab-generator
/systemd-getty-generator
/systemd-gnome-ask-password-agent
diff --git a/Makefile-man.am b/Makefile-man.am
index e902e5ed43..4344ffbb4d 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -66,7 +66,6 @@ MANPAGES += \
man/systemd-efi-boot-generator.8 \
man/systemd-escape.1 \
man/systemd-fsck@.service.8 \
- man/systemd-fsckd.service.8 \
man/systemd-fstab-generator.8 \
man/systemd-getty-generator.8 \
man/systemd-gpt-auto-generator.8 \
@@ -209,8 +208,6 @@ MANPAGES_ALIAS += \
man/systemd-ask-password-wall.service.8 \
man/systemd-fsck-root.service.8 \
man/systemd-fsck.8 \
- man/systemd-fsckd.8 \
- man/systemd-fsckd.socket.8 \
man/systemd-hibernate-resume.8 \
man/systemd-hibernate.service.8 \
man/systemd-hybrid-sleep.service.8 \
@@ -321,8 +318,6 @@ man/systemd-ask-password-wall.path.8: man/systemd-ask-password-console.service.8
man/systemd-ask-password-wall.service.8: man/systemd-ask-password-console.service.8
man/systemd-fsck-root.service.8: man/systemd-fsck@.service.8
man/systemd-fsck.8: man/systemd-fsck@.service.8
-man/systemd-fsckd.8: man/systemd-fsckd.service.8
-man/systemd-fsckd.socket.8: man/systemd-fsckd.service.8
man/systemd-hibernate-resume.8: man/systemd-hibernate-resume@.service.8
man/systemd-hibernate.service.8: man/systemd-suspend.service.8
man/systemd-hybrid-sleep.service.8: man/systemd-suspend.service.8
@@ -601,12 +596,6 @@ man/systemd-fsck-root.service.html: man/systemd-fsck@.service.html
man/systemd-fsck.html: man/systemd-fsck@.service.html
$(html-alias)
-man/systemd-fsckd.html: man/systemd-fsckd.service.html
- $(html-alias)
-
-man/systemd-fsckd.socket.html: man/systemd-fsckd.service.html
- $(html-alias)
-
man/systemd-hibernate-resume.html: man/systemd-hibernate-resume@.service.html
$(html-alias)
@@ -1764,7 +1753,6 @@ EXTRA_DIST += \
man/systemd-escape.xml \
man/systemd-firstboot.xml \
man/systemd-fsck@.service.xml \
- man/systemd-fsckd.service.xml \
man/systemd-fstab-generator.xml \
man/systemd-getty-generator.xml \
man/systemd-gpt-auto-generator.xml \
diff --git a/Makefile.am b/Makefile.am
index 292cf917f6..29ffcbb8f9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -398,7 +398,6 @@ rootlibexec_PROGRAMS = \
systemd-remount-fs \
systemd-reply-password \
systemd-fsck \
- systemd-fsckd \
systemd-machine-id-commit \
systemd-ac-power \
systemd-sysctl \
@@ -501,7 +500,6 @@ dist_systemunit_DATA = \
units/slices.target \
units/system.slice \
units/x-.slice \
- units/systemd-fsckd.socket \
units/systemd-initctl.socket \
units/syslog.socket \
units/dev-hugepages.mount \
@@ -552,7 +550,6 @@ nodist_systemunit_DATA = \
units/systemd-kexec.service \
units/systemd-fsck@.service \
units/systemd-fsck-root.service \
- units/systemd-fsckd.service \
units/systemd-machine-id-commit.service \
units/systemd-udevd.service \
units/systemd-udev-trigger.service \
@@ -605,7 +602,6 @@ EXTRA_DIST += \
units/user/systemd-exit.service.in \
units/systemd-fsck@.service.in \
units/systemd-fsck-root.service.in \
- units/systemd-fsckd.service.in \
units/systemd-machine-id-commit.service.in \
units/user@.service.m4.in \
units/debug-shell.service.in \
@@ -2378,19 +2374,6 @@ systemd_fsck_LDADD = \
libsystemd-shared.la
# ------------------------------------------------------------------------------
-systemd_fsckd_SOURCES = \
- src/fsckd/fsckd.c \
- src/fsckd/fsckd.h \
- $(NULL)
-
-systemd_fsckd_LDADD = \
- libsystemd-internal.la \
- libsystemd-label.la \
- libsystemd-shared.la \
- libudev-internal.la \
- $(NULL)
-
-# ------------------------------------------------------------------------------
systemd_machine_id_commit_SOURCES = \
src/machine-id-commit/machine-id-commit.c \
src/core/machine-id-setup.c \
diff --git a/man/systemd-fsck@.service.xml b/man/systemd-fsck@.service.xml
index 69b8fdde2c..e4ffcba168 100644
--- a/man/systemd-fsck@.service.xml
+++ b/man/systemd-fsck@.service.xml
@@ -80,9 +80,7 @@
the filesystem should actually be checked based on the time since
last check, number of mounts, unclean unmount, etc.</para>
- <para><filename>systemd-fsck</filename> will forward file system
- checking progress to <filename>systemd-fsckd.service</filename>
- socket. If a file system check fails for a service without
+ <para>If a file system check fails for a service without
<option>nofail</option>, emergency mode is activated, by isolating
to <filename>emergency.target</filename>.</para>
</refsect1>
diff --git a/man/systemd-fsckd.service.xml b/man/systemd-fsckd.service.xml
deleted file mode 100644
index 2ad78448f8..0000000000
--- a/man/systemd-fsckd.service.xml
+++ /dev/null
@@ -1,162 +0,0 @@
-<?xml version="1.0"?>
-<!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-<!--
- This file is part of systemd.
-
- Copyright 2015 Canonical
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
--->
-<refentry id="systemd-fsckd.service" xmlns:xi="http://www.w3.org/2001/XInclude">
-
- <refentryinfo>
- <title>systemd-fsckd.service</title>
- <productname>systemd</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Didier</firstname>
- <surname>Roche</surname>
- <email>didrocks@ubuntu.com</email>
- </author>
- </authorgroup>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>systemd-fsckd.service</refentrytitle>
- <manvolnum>8</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>systemd-fsckd.service</refname>
- <refname>systemd-fsckd.socket</refname>
- <refname>systemd-fsckd</refname>
- <refpurpose>File system check progress reporting</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <para><filename>systemd-fsckd.service</filename></para>
- <para><filename>systemd-fsckd.socket</filename></para>
- <para><filename>/usr/lib/systemd/systemd-fsckd</filename></para>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para><filename>systemd-fsckd.service</filename> is a service responsible
- for receiving file system check progress, and communicating some
- consolidated data to console and plymouth (if running). It also handles
- possible check cancellations.</para>
-
- <para><command>systemd-fsckd</command> receives messages about file
- system check progress from <command>systemd-fsck</command> through a
- UNIX domain socket. It can display the progress of the least advanced
- fsck as well as the total number of devices being checked in parallel
- to the console. It will also send progress messages to plymouth.
- Both the raw data and translated messages are sent, so compiled
- plymouth themes can use the raw data to display custom messages, and
- scripted themes, not supporting i18n, can display the translated
- versions.</para>
-
- <para><command>systemd-fsckd</command> will instruct plymouth to grab
- Control+C keypresses. When the key is pressed, running checks will be
- terminated. It will also cancel any newly connected fsck instances for
- the lifetime of <filename>systemd-fsckd</filename>.</para>
- </refsect1>
-
- <refsect1>
- <title>Protocol for communication with plymouth</title>
-
- <para><filename>systemd-fsckd</filename> passes the
- following messages to the theme:</para>
-
- <para>Progress update, sent as a plymouth update message:
- <literal>fsckd:&lt;num_devices&gt;:&lt;progress&gt;:&lt;string&gt;</literal>
- <variablelist>
- <varlistentry>
- <term><literal>&lt;num_devices&gt;</literal></term>
- <listitem><para>the current number of devices
- being checked (int)</para></listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>&lt;progress&gt;</literal></term>
- <listitem><para>the current minimum percentage of
- all devices being checking (float, from 0 to 100)</para></listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>&lt;string&gt;</literal></term>
- <listitem><para>a translated message ready to be displayed
- by the plymouth theme displaying the data above. It can be overriden
- by themes supporting i18n.</para></listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- <para>Cancel message, sent as a traditional plymouth message:
- <literal>fsckd-cancel-msg:&lt;string&gt;</literal>
- <variablelist>
- <varlistentry>
- <term><literal>&lt;strings&gt;</literal></term>
- <listitem><para>a translated string ready to be displayed
- by the plymouth theme indicating that Control+C can be used to cancel
- current checks. It can be overriden (matching only
- <literal>fsckd-cancel-msg</literal> prefix)
- by themes supporting i18n.</para></listitem>
- </varlistentry>
- </variablelist>
- </para>
- </refsect1>
-
- <refsect1>
- <title>Options</title>
-
- <para>The following options are understood:</para>
-
- <variablelist>
- <xi:include href="standard-options.xml" xpointer="help" />
- <xi:include href="standard-options.xml" xpointer="version" />
- </variablelist>
-
- </refsect1>
-
- <refsect1>
- <title>Exit status</title>
-
- <para>On success, 0 is returned, a non-zero failure
- code otherwise. Note that the daemon stays idle for
- a while to accept new <filename>systemd-fsck</filename>
- connections before exiting.</para>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <para>
- <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-fsck</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>fsck</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-quotacheck.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>fsck.btrfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>fsck.cramfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>fsck.ext4</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>fsck.fat</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>fsck.hfsplus</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>fsck.minix</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>fsck.ntfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>fsck.xfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- </para>
- </refsect1>
-
-</refentry>
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index f030dd3d2f..56d880ac81 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -27,6 +27,7 @@
#include <fcntl.h>
#include <sys/file.h>
#include <sys/stat.h>
+#include <sys/prctl.h>
#include "sd-bus.h"
#include "sd-device.h"
@@ -40,10 +41,10 @@
#include "device-util.h"
#include "path-util.h"
#include "socket-util.h"
-#include "fsckd/fsckd.h"
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) {
@@ -135,39 +136,74 @@ static void test_files(void) {
}
#endif
+ arg_show_progress = access("/run/systemd/show-status", F_OK) >= 0;
}
-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;
- static const union sockaddr_union sa = {
- .un.sun_family = AF_UNIX,
- .un.sun_path = FSCKD_SOCKET_PATH,
+static double percent(int pass, unsigned long cur, unsigned long max) {
+ /* Values stolen from e2fsck */
+
+ static const int pass_table[] = {
+ 0, 70, 90, 92, 95, 100
};
- fsckd_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
- if (fsckd_fd < 0)
- return log_warning_errno(errno, "Cannot open fsckd socket, we won't report fsck progress: %m");
- if (connect(fsckd_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0)
- return log_warning_errno(errno, "Cannot connect to fsckd socket, we won't report fsck progress: %m");
-
- f = fdopen(fd, "r");
- if (!f)
- return log_warning_errno(errno, "Cannot connect to fsck, we won't report fsck progress: %m");
-
- while (!feof(f)) {
- int pass;
- size_t buflen;
- size_t cur, max;
- ssize_t r;
- usec_t t;
+ if (pass <= 0)
+ return 0.0;
+
+ if ((unsigned) pass >= ELEMENTSOF(pass_table) || max == 0)
+ return 100.0;
+
+ return (double) pass_table[pass-1] +
+ ((double) pass_table[pass] - (double) pass_table[pass-1]) *
+ (double) cur / (double) max;
+}
+
+static int process_progress(int fd) {
+ _cleanup_fclose_ FILE *console = NULL, *f = NULL;
+ usec_t last = 0;
+ bool locked = false;
+ int clear = 0, r;
+
+ /* No progress pipe to process? Then we are a NOP. */
+ if (fd < 0)
+ return 0;
+
+ f = fdopen(fd, "re");
+ if (!f) {
+ safe_close(fd);
+ return -errno;
+ }
+
+ console = fopen("/dev/console", "we");
+ if (!console)
+ return -ENOMEM;
+
+ for (;;) {
+ int pass, m;
+ unsigned long cur, max;
_cleanup_free_ char *device = NULL;
- FsckProgress progress;
- FsckdMessage fsckd_message;
+ double p;
+ usec_t t;
- if (fscanf(f, "%i %zu %zu %ms", &pass, &cur, &max, &device) != 4)
+ if (fscanf(f, "%i %lu %lu %ms", &pass, &cur, &max, &device) != 4) {
+
+ if (ferror(f))
+ r = log_warning_errno(errno, "Failed to read from progress pipe: %m");
+ else if (feof(f))
+ r = 0;
+ else {
+ log_warning("Failed to parse progress pipe data");
+ r = -EBADMSG;
+ }
break;
+ }
+
+ /* Only show one progress counter at max */
+ if (!locked) {
+ if (flock(fileno(console), LOCK_EX|LOCK_NB) < 0)
+ continue;
+
+ locked = true;
+ }
/* Only update once every 50ms */
t = now(CLOCK_MONOTONIC);
@@ -176,42 +212,58 @@ static int process_progress(int fd, pid_t fsck_pid, dev_t device_num) {
last = t;
- /* send progress to fsckd */
- progress.devnum = device_num;
- progress.cur = cur;
- progress.max = max;
- progress.pass = pass;
-
- 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);
- }
- }
+ p = percent(pass, cur, max);
+ fprintf(console, "\r%s: fsck %3.1f%% complete...\r%n", device, p, &m);
+ fflush(console);
+
+ if (m > clear)
+ clear = m;
}
- return 0;
+ if (clear > 0) {
+ unsigned j;
+
+ fputc('\r', console);
+ for (j = 0; j < (unsigned) clear; j++)
+ fputc(' ', console);
+ fputc('\r', console);
+ fflush(console);
+ }
+
+ return r;
+}
+
+static int fsck_progress_socket(void) {
+ static const union sockaddr_union sa = {
+ .un.sun_family = AF_UNIX,
+ .un.sun_path = "/run/systemd/fsck.progress",
+ };
+
+ int fd, r;
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0)
+ return log_warning_errno(errno, "socket(): %m");
+
+ if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
+ r = log_full_errno(errno == ECONNREFUSED || errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
+ errno, "Failed to connect to progress socket %s, ignoring: %m", sa.un.sun_path);
+ safe_close(fd);
+ return r;
+ }
+
+ return fd;
}
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_close_pair_ int progress_pipe[2] = { -1, -1 };
_cleanup_device_unref_ sd_device *dev = NULL;
const char *device, *type;
bool root_directory;
- _cleanup_close_pair_ int progress_pipe[2] = { -1, -1 };
- char dash_c[sizeof("-C")-1 + DECIMAL_STR_MAX(int) + 1];
+ siginfo_t status;
struct stat st;
+ int r;
+ pid_t pid;
if (argc > 2) {
log_error("This program expects one or no arguments.");
@@ -309,48 +361,74 @@ int main(int argc, char *argv[]) {
log_warning_errno(r, "Couldn't detect if fsck.%s may be used for %s: %m", type, device);
}
- if (pipe(progress_pipe) < 0) {
- r = log_error_errno(errno, "pipe(): %m");
- goto finish;
+ if (arg_show_progress) {
+ if (pipe(progress_pipe) < 0) {
+ r = log_error_errno(errno, "pipe(): %m");
+ goto finish;
+ }
}
- cmdline[i++] = "/sbin/fsck";
- cmdline[i++] = arg_repair;
- cmdline[i++] = "-T";
-
- /*
- * Since util-linux v2.25 fsck uses /run/fsck/<diskname>.lock files.
- * The previous versions use flock for the device and conflict with
- * udevd, see https://bugs.freedesktop.org/show_bug.cgi?id=79576#c5
- */
- cmdline[i++] = "-l";
-
- if (!root_directory)
- cmdline[i++] = "-M";
-
- if (arg_force)
- cmdline[i++] = "-f";
-
- xsprintf(dash_c, "-C%i", progress_pipe[1]);
- cmdline[i++] = dash_c;
-
- cmdline[i++] = device;
- cmdline[i++] = NULL;
-
pid = fork();
if (pid < 0) {
r = log_error_errno(errno, "fork(): %m");
goto finish;
- } else if (pid == 0) {
+ }
+ if (pid == 0) {
+ char dash_c[sizeof("-C")-1 + DECIMAL_STR_MAX(int) + 1];
+ int progress_socket = -1;
+ const char *cmdline[9];
+ int i = 0;
+
/* Child */
+
+ reset_all_signal_handlers();
+ reset_signal_mask();
+ assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
+
+ /* Close the reading side of the progress pipe */
progress_pipe[0] = safe_close(progress_pipe[0]);
+
+ /* Try to connect to a progress management daemon, if there is one */
+ progress_socket = fsck_progress_socket();
+ if (progress_socket >= 0) {
+ /* If this worked we close the progress pipe early, and just use the socket */
+ progress_pipe[1] = safe_close(progress_pipe[1]);
+ xsprintf(dash_c, "-C%i", progress_socket);
+ } else if (progress_pipe[1] >= 0) {
+ /* Otherwise if we have the progress pipe to our own local handle, we use it */
+ xsprintf(dash_c, "-C%i", progress_pipe[1]);
+ } else
+ dash_c[0] = 0;
+
+ cmdline[i++] = "/sbin/fsck";
+ cmdline[i++] = arg_repair;
+ cmdline[i++] = "-T";
+
+ /*
+ * Since util-linux v2.25 fsck uses /run/fsck/<diskname>.lock files.
+ * The previous versions use flock for the device and conflict with
+ * udevd, see https://bugs.freedesktop.org/show_bug.cgi?id=79576#c5
+ */
+ cmdline[i++] = "-l";
+
+ if (!root_directory)
+ cmdline[i++] = "-M";
+
+ if (arg_force)
+ cmdline[i++] = "-f";
+
+ if (!isempty(dash_c))
+ cmdline[i++] = dash_c;
+
+ cmdline[i++] = device;
+ cmdline[i++] = NULL;
+
execv(cmdline[0], (char**) cmdline);
_exit(8); /* Operational error */
}
progress_pipe[1] = safe_close(progress_pipe[1]);
-
- progress_rc = process_progress(progress_pipe[0], pid, st.st_rdev);
+ (void) process_progress(progress_pipe[0]);
progress_pipe[0] = -1;
r = wait_for_terminate(pid, &status);
@@ -359,14 +437,13 @@ int main(int argc, char *argv[]) {
goto finish;
}
- if (status.si_code != CLD_EXITED || (status.si_status & ~1) || progress_rc != 0) {
+ if (status.si_code != CLD_EXITED || (status.si_status & ~1)) {
- /* cancel will kill fsck (but process_progress returns 0) */
- if ((progress_rc != 0 && status.si_code == CLD_KILLED) || status.si_code == CLD_DUMPED)
+ if (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 if (progress_rc != 0)
+ else
log_error("fsck failed due to unknown reason.");
r = -EINVAL;
@@ -378,9 +455,8 @@ int main(int argc, char *argv[]) {
/* Some other problem */
start_target(SPECIAL_EMERGENCY_TARGET);
else {
+ log_warning("Ignoring error.");
r = 0;
- if (progress_rc != 0)
- log_warning("Ignoring error.");
}
} else
diff --git a/src/fsckd/Makefile b/src/fsckd/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/fsckd/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/fsckd/fsckd.c b/src/fsckd/fsckd.c
deleted file mode 100644
index 6b35fc26a2..0000000000
--- a/src/fsckd/fsckd.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2015 Canonical
-
- Author:
- Didier Roche <didrocks@ubuntu.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <getopt.h>
-#include <errno.h>
-#include <libintl.h>
-#include <math.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "sd-daemon.h"
-#include "build.h"
-#include "def.h"
-#include "event-util.h"
-#include "log.h"
-#include "list.h"
-#include "macro.h"
-#include "socket-util.h"
-#include "util.h"
-#include "fsckd.h"
-
-#define IDLE_TIME_SECONDS 30
-#define PLYMOUTH_REQUEST_KEY "K\2\2\3"
-#define CLIENTS_MAX 128
-
-struct Manager;
-
-typedef struct Client {
- struct Manager *manager;
- int fd;
- dev_t devnum;
-
- size_t cur;
- size_t max;
- int pass;
-
- double percent;
-
- size_t buflen;
- bool cancelled;
-
- sd_event_source *event_source;
-
- LIST_FIELDS(struct Client, clients);
-} Client;
-
-typedef struct Manager {
- sd_event *event;
-
- LIST_HEAD(Client, clients);
- unsigned n_clients;
-
- size_t clear;
-
- int connection_fd;
- sd_event_source *connection_event_source;
-
- bool show_status_console;
-
- double percent;
- int numdevices;
-
- int plymouth_fd;
- sd_event_source *plymouth_event_source;
- bool plymouth_cancel_sent;
-
- bool cancel_requested;
-} Manager;
-
-static void client_free(Client *c);
-static void manager_free(Manager *m);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Client*, client_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
-
-static int manager_write_console(Manager *m, const char *message) {
- _cleanup_fclose_ FILE *console = NULL;
- int l;
- size_t j;
-
- assert(m);
-
- if (!m->show_status_console)
- return 0;
-
- /* Reduce the SAK window by opening and closing console on every request */
- console = fopen("/dev/console", "we");
- if (!console)
- return -errno;
-
- if (message) {
- fprintf(console, "\r%s\r%n", message, &l);
- if (m->clear < (size_t)l)
- m->clear = (size_t)l;
- } else {
- fputc('\r', console);
- for (j = 0; j < m->clear; j++)
- fputc(' ', console);
- fputc('\r', console);
- }
- fflush(console);
-
- return 0;
-}
-
-static double compute_percent(int pass, size_t cur, size_t max) {
- /* Values stolen from e2fsck */
-
- static const double pass_table[] = {
- 0, 70, 90, 92, 95, 100
- };
-
- if (pass <= 0)
- return 0.0;
-
- if ((unsigned) pass >= ELEMENTSOF(pass_table) || max == 0)
- return 100.0;
-
- return pass_table[pass-1] +
- (pass_table[pass] - pass_table[pass-1]) *
- (double) cur / max;
-}
-
-static int client_request_cancel(Client *c) {
- FsckdMessage cancel_msg = {
- .cancel = 1,
- };
-
- ssize_t n;
-
- assert(c);
-
- if (c->cancelled)
- return 0;
-
- n = send(c->fd, &cancel_msg, sizeof(FsckdMessage), 0);
- if (n < 0)
- return log_warning_errno(errno, "Cannot send cancel to fsck on (%u:%u): %m", major(c->devnum), minor(c->devnum));
- if ((size_t) n < sizeof(FsckdMessage)) {
- log_warning("Short send when sending cancel to fsck on (%u:%u).", major(c->devnum), minor(c->devnum));
- return -EIO;
- }
-
- c->cancelled = true;
- return 1;
-}
-
-static void client_free(Client *c) {
- assert(c);
-
- if (c->manager) {
- LIST_REMOVE(clients, c->manager->clients, c);
- c->manager->n_clients--;
- }
-
- sd_event_source_unref(c->event_source);
-
- safe_close(c->fd);
- free(c);
-}
-
-static void manager_disconnect_plymouth(Manager *m) {
- assert(m);
-
- m->plymouth_event_source = sd_event_source_unref(m->plymouth_event_source);
- m->plymouth_fd = safe_close(m->plymouth_fd);
- m->plymouth_cancel_sent = false;
-}
-
-static int manager_plymouth_feedback_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- Manager *m = userdata;
- Client *current;
- char buffer[6];
- ssize_t l;
-
- assert(m);
-
- l = read(m->plymouth_fd, buffer, sizeof(buffer));
- if (l < 0) {
- log_warning_errno(errno, "Got error while reading from plymouth: %m");
- manager_disconnect_plymouth(m);
- return -errno;
- }
- if (l == 0) {
- manager_disconnect_plymouth(m);
- return 0;
- }
-
- if (l > 1 && buffer[0] == '\15')
- log_error("Message update to plymouth wasn't delivered successfully");
-
- /* the only answer support type we requested is a key interruption */
- if (l > 2 && buffer[0] == '\2' && buffer[5] == '\3') {
- m->cancel_requested = true;
-
- /* cancel all connected clients */
- LIST_FOREACH(clients, current, m->clients)
- client_request_cancel(current);
- }
-
- return 0;
-}
-
-static int manager_connect_plymouth(Manager *m) {
- union sockaddr_union sa = PLYMOUTH_SOCKET;
- int r;
-
- if (!plymouth_running())
- return 0;
-
- /* try to connect or reconnect if sending a message */
- if (m->plymouth_fd >= 0)
- return 1;
-
- m->plymouth_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
- if (m->plymouth_fd < 0)
- return log_warning_errno(errno, "Connection to plymouth socket failed: %m");
-
- if (connect(m->plymouth_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
- r = log_warning_errno(errno, "Couldn't connect to plymouth: %m");
- goto fail;
- }
-
- r = sd_event_add_io(m->event, &m->plymouth_event_source, m->plymouth_fd, EPOLLIN, manager_plymouth_feedback_handler, m);
- if (r < 0) {
- log_warning_errno(r, "Can't listen to plymouth socket: %m");
- goto fail;
- }
-
- return 1;
-
-fail:
- manager_disconnect_plymouth(m);
- return r;
-}
-
-static int plymouth_send_message(int plymouth_fd, const char *message, bool update) {
- _cleanup_free_ char *packet = NULL;
- int n;
- char mode = 'M';
-
- if (update)
- mode = 'U';
-
- if (asprintf(&packet, "%c\002%c%s%n", mode, (int) (strlen(message) + 1), message, &n) < 0)
- return log_oom();
-
- return loop_write(plymouth_fd, packet, n + 1, true);
-}
-
-static int manager_send_plymouth_message(Manager *m, const char *message) {
- const char *plymouth_cancel_message = NULL, *l10n_cancel_message = NULL;
- int r;
-
- r = manager_connect_plymouth(m);
- if (r < 0)
- return r;
- /* 0 means that plymouth isn't running, do not send any message yet */
- else if (r == 0)
- return 0;
-
- if (!m->plymouth_cancel_sent) {
-
- /* Indicate to plymouth that we listen to Ctrl+C */
- r = loop_write(m->plymouth_fd, PLYMOUTH_REQUEST_KEY, sizeof(PLYMOUTH_REQUEST_KEY), true);
- if (r < 0)
- return log_warning_errno(r, "Can't send to plymouth cancel key: %m");
-
- m->plymouth_cancel_sent = true;
-
- l10n_cancel_message = _("Press Ctrl+C to cancel all filesystem checks in progress");
- plymouth_cancel_message = strjoina("fsckd-cancel-msg:", l10n_cancel_message);
-
- r = plymouth_send_message(m->plymouth_fd, plymouth_cancel_message, false);
- if (r < 0)
- log_warning_errno(r, "Can't send filesystem cancel message to plymouth: %m");
-
- } else if (m->numdevices == 0) {
-
- m->plymouth_cancel_sent = false;
-
- r = plymouth_send_message(m->plymouth_fd, "", false);
- if (r < 0)
- log_warning_errno(r, "Can't clear plymouth filesystem cancel message: %m");
- }
-
- r = plymouth_send_message(m->plymouth_fd, message, true);
- if (r < 0)
- return log_warning_errno(r, "Couldn't send \"%s\" to plymouth: %m", message);
-
- return 0;
-}
-
-static int manager_update_global_progress(Manager *m) {
- Client *current = NULL;
- _cleanup_free_ char *console_message = NULL;
- _cleanup_free_ char *fsck_message = NULL;
- int current_numdevices = 0, r;
- double current_percent = 100;
-
- /* get the overall percentage */
- LIST_FOREACH(clients, current, m->clients) {
- current_numdevices++;
-
- /* right now, we only keep the minimum % of all fsckd processes. We could in the future trying to be
- linear, but max changes and corresponds to the pass. We have all the informations into fsckd
- already if we can treat that in a smarter way. */
- current_percent = MIN(current_percent, current->percent);
- }
-
- /* update if there is anything user-visible to update */
- if (fabs(current_percent - m->percent) > 0.001 || current_numdevices != m->numdevices) {
- m->numdevices = current_numdevices;
- m->percent = current_percent;
-
- if (asprintf(&console_message,
- ngettext("Checking in progress on %d disk (%3.1f%% complete)",
- "Checking in progress on %d disks (%3.1f%% complete)", m->numdevices),
- m->numdevices, m->percent) < 0)
- return -ENOMEM;
-
- if (asprintf(&fsck_message, "fsckd:%d:%3.1f:%s", m->numdevices, m->percent, console_message) < 0)
- return -ENOMEM;
-
- r = manager_write_console(m, console_message);
- if (r < 0)
- return r;
-
- /* try to connect to plymouth and send message */
- r = manager_send_plymouth_message(m, fsck_message);
- if (r < 0)
- return r;
- }
- return 0;
-}
-
-static int client_progress_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- Client *client = userdata;
- FsckProgress fsck_data;
- size_t buflen;
- Manager *m;
- int r;
-
- assert(client);
-
- m = client->manager;
-
- /* check first if we need to cancel this client */
- if (m->cancel_requested)
- client_request_cancel(client);
-
- /* ensure we have enough data to read */
- r = ioctl(fd, FIONREAD, &buflen);
- if (r == 0 && buflen != 0 && (size_t) buflen < sizeof(FsckProgress)) {
- if (client->buflen != buflen)
- client->buflen = buflen;
- /* we got twice the same size from a bad behaving client, kick it off the list */
- else {
- log_warning("Closing bad behaving fsck client connection at fd %d", client->fd);
- client_free(client);
- manager_update_global_progress(m);
- }
- return 0;
- }
-
- /* read actual data */
- r = recv(fd, &fsck_data, sizeof(FsckProgress), 0);
- if (r == 0) {
- log_debug("Fsck client connected to fd %d disconnected", client->fd);
- client_free(client);
- } else if (r > 0 && r != sizeof(FsckProgress))
- log_warning("Unexpected data structure sent to fsckd socket from fd: %d. Ignoring", client->fd);
- else if (r > 0 && r == sizeof(FsckProgress)) {
- client->devnum = fsck_data.devnum;
- client->cur = fsck_data.cur;
- client->max = fsck_data.max;
- client->pass = fsck_data.pass;
- client->percent = compute_percent(client->pass, client->cur, client->max);
- log_debug("Getting progress for %u:%u (%lu, %lu, %d) : %3.1f%%",
- major(client->devnum), minor(client->devnum),
- client->cur, client->max, client->pass, client->percent);
- } else
- log_error_errno(r, "Unknown error while trying to read fsck data: %m");
-
- manager_update_global_progress(m);
-
- return 0;
-}
-
-static int manager_new_connection_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_(client_freep) Client *c = NULL;
- _cleanup_close_ int new_client_fd = -1;
- Manager *m = userdata;
- int r;
-
- assert(m);
-
- /* Initialize and list new clients */
- new_client_fd = accept4(m->connection_fd, NULL, NULL, SOCK_CLOEXEC);
- if (new_client_fd < 0)
- return log_error_errno(errno, "Couldn't accept a new connection: %m");
-
- if (m->n_clients >= CLIENTS_MAX) {
- log_error("Too many clients, refusing connection.");
- return 0;
- }
-
- log_debug("New fsck client connected to fd: %d", new_client_fd);
-
- c = new0(Client, 1);
- if (!c) {
- log_oom();
- return 0;
- }
-
- c->fd = new_client_fd;
- new_client_fd = -1;
-
- r = sd_event_add_io(m->event, &c->event_source, c->fd, EPOLLIN, client_progress_handler, c);
- if (r < 0) {
- log_oom();
- return 0;
- }
-
- LIST_PREPEND(clients, m->clients, c);
- m->n_clients++;
- c->manager = m;
-
- /* only request the client to cancel now in case the request is dropped by the client (chance to recancel) */
- if (m->cancel_requested)
- client_request_cancel(c);
-
- c = NULL;
- return 0;
-}
-
-static void manager_free(Manager *m) {
- if (!m)
- return;
-
- /* clear last line */
- manager_write_console(m, NULL);
-
- sd_event_source_unref(m->connection_event_source);
- safe_close(m->connection_fd);
-
- while (m->clients)
- client_free(m->clients);
-
- manager_disconnect_plymouth(m);
-
- sd_event_unref(m->event);
-
- free(m);
-}
-
-static int manager_new(Manager **ret, int fd) {
- _cleanup_(manager_freep) Manager *m = NULL;
- int r;
-
- assert(ret);
-
- m = new0(Manager, 1);
- if (!m)
- return -ENOMEM;
-
- m->plymouth_fd = -1;
- m->connection_fd = fd;
- m->percent = 100;
-
- r = sd_event_default(&m->event);
- if (r < 0)
- return r;
-
- if (access("/run/systemd/show-status", F_OK) >= 0)
- m->show_status_console = true;
-
- r = sd_event_add_io(m->event, &m->connection_event_source, fd, EPOLLIN, manager_new_connection_handler, m);
- if (r < 0)
- return r;
-
- *ret = m;
- m = NULL;
-
- return 0;
-}
-
-static int run_event_loop_with_timeout(sd_event *e, usec_t timeout) {
- int r, code;
-
- assert(e);
-
- for (;;) {
- r = sd_event_get_state(e);
- if (r < 0)
- return r;
- if (r == SD_EVENT_FINISHED)
- break;
-
- r = sd_event_run(e, timeout);
- if (r < 0)
- return r;
-
- /* timeout reached */
- if (r == 0) {
- sd_event_exit(e, 0);
- break;
- }
- }
-
- r = sd_event_get_exit_code(e, &code);
- if (r < 0)
- return r;
-
- return code;
-}
-
-static void help(void) {
- printf("%s [OPTIONS...]\n\n"
- "Capture fsck progress and forward one stream to plymouth\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n",
- program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_ROOT,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- {}
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "hv", options, NULL)) >= 0)
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(SYSTEMD_FEATURES);
- return 0;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- if (optind < argc) {
- log_error("Extraneous arguments");
- return -EINVAL;
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- _cleanup_(manager_freep) Manager *m = NULL;
- int fd = -1;
- int r, n;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
- init_gettext();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- n = sd_listen_fds(0);
- if (n > 1) {
- log_error("Too many file descriptors received.");
- r = -EINVAL;
- goto finish;
- } else if (n == 1)
- fd = SD_LISTEN_FDS_START + 0;
- else {
- fd = make_socket_fd(LOG_DEBUG, FSCKD_SOCKET_PATH, SOCK_STREAM | SOCK_CLOEXEC);
- if (fd < 0) {
- r = log_error_errno(fd, "Couldn't create listening socket fd on %s: %m", FSCKD_SOCKET_PATH);
- goto finish;
- }
- }
-
- r = manager_new(&m, fd);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate manager: %m");
- goto finish;
- }
-
- r = run_event_loop_with_timeout(m->event, IDLE_TIME_SECONDS * USEC_PER_SEC);
- if (r < 0) {
- log_error_errno(r, "Failed to run event loop: %m");
- goto finish;
- }
-
- sd_event_get_exit_code(m->event, &r);
-
-finish:
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/fsckd/fsckd.h b/src/fsckd/fsckd.h
deleted file mode 100644
index 8239273dae..0000000000
--- a/src/fsckd/fsckd.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2015 Canonical
-
- Author:
- Didier Roche <didrocks@ubuntu.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#define FSCKD_SOCKET_PATH "/run/systemd/fsckd"
-
-#include "libudev.h"
-
-typedef struct FsckProgress {
- dev_t devnum;
- size_t cur;
- size_t max;
- int pass;
-} FsckProgress;
-
-typedef struct FsckdMessage {
- uint8_t cancel;
-} FsckdMessage;
diff --git a/units/.gitignore b/units/.gitignore
index d81d0c587a..b8f0a0b723 100644
--- a/units/.gitignore
+++ b/units/.gitignore
@@ -28,7 +28,6 @@
/systemd-firstboot.service
/systemd-fsck-root.service
/systemd-fsck@.service
-/systemd-fsckd.service
/systemd-machine-id-commit.service
/systemd-halt.service
/systemd-hibernate.service
diff --git a/units/systemd-fsck-root.service.in b/units/systemd-fsck-root.service.in
index f493445b86..3617abf04a 100644
--- a/units/systemd-fsck-root.service.in
+++ b/units/systemd-fsck-root.service.in
@@ -9,9 +9,7 @@
Description=File System Check on Root Device
Documentation=man:systemd-fsck-root.service(8)
DefaultDependencies=no
-Wants=systemd-fsckd.socket
Before=local-fs.target shutdown.target
-After=systemd-fsckd.socket
ConditionPathIsReadWrite=!/
[Service]
diff --git a/units/systemd-fsck@.service.in b/units/systemd-fsck@.service.in
index e6d98c031b..0468392dc4 100644
--- a/units/systemd-fsck@.service.in
+++ b/units/systemd-fsck@.service.in
@@ -10,8 +10,7 @@ Description=File System Check on %f
Documentation=man:systemd-fsck@.service(8)
DefaultDependencies=no
BindsTo=%i.device
-Wants=systemd-fsckd.socket
-After=%i.device systemd-fsck-root.service local-fs-pre.target systemd-fsckd.socket
+After=%i.device systemd-fsck-root.service local-fs-pre.target
Before=shutdown.target
[Service]
diff --git a/units/systemd-fsckd.service.in b/units/systemd-fsckd.service.in
deleted file mode 100644
index 9c7ed5146d..0000000000
--- a/units/systemd-fsckd.service.in
+++ /dev/null
@@ -1,17 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-[Unit]
-Description=File System Check Daemon to report status
-Documentation=man:systemd-fsckd.service(8)
-DefaultDependencies=no
-Requires=systemd-fsckd.socket
-Before=shutdown.target
-
-[Service]
-ExecStart=@rootlibexecdir@/systemd-fsckd
-StandardOutput=journal+console
diff --git a/units/systemd-fsckd.socket b/units/systemd-fsckd.socket
deleted file mode 100644
index 92e8eefea6..0000000000
--- a/units/systemd-fsckd.socket
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-[Unit]
-Description=fsck to fsckd communication Socket
-Documentation=man:systemd-fsckd.service(8) man:systemd-fsck@.service(8) man:systemd-fsck-root.service(8)
-DefaultDependencies=no
-
-[Socket]
-ListenStream=/run/systemd/fsckd
-SocketMode=0600