On Tue, Mar 13, 2018 at 07:29:53AM +0100, Lukas Czerner wrote: > On Mon, Mar 12, 2018 at 09:14:59AM -0700, Darrick J. Wong wrote: > > From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > > > Add the ability to run the e2scrub utilities as a periodically scheduled > > system service. > > comment bellow > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > --- > > MCONFIG.in | 5 + > > configure | 179 ++++++++++++++++++++++++++++++++++++++++ > > configure.ac | 74 ++++++++++++++++- > > debian/e2fsprogs.files | 3 + > > debian/e2fsprogs.postinst | 19 ++++ > > debian/e2fsprogs.postrm | 35 ++++++++ > > scrub/Makefile.in | 90 ++++++++++++++++++++ > > scrub/e2scrub.in | 38 +++++++- > > scrub/e2scrub@xxxxxxxxxxx | 20 ++++ > > scrub/e2scrub_all.cron.in | 2 > > scrub/e2scrub_all.in | 38 ++++++++ > > scrub/e2scrub_all.service.in | 10 ++ > > scrub/e2scrub_all.timer.in | 11 ++ > > scrub/e2scrub_all_cron.in | 68 +++++++++++++++ > > scrub/e2scrub_fail.in | 25 ++++++ > > scrub/e2scrub_fail@xxxxxxxxxxx | 10 ++ > > scrub/e2scrub_reap.in | 48 +++++++++++ > > scrub/e2scrub_reap.service.in | 21 +++++ > > util/subst.conf.in | 3 + > > 19 files changed, 684 insertions(+), 15 deletions(-) > > create mode 100644 debian/e2fsprogs.postrm > > create mode 100644 scrub/e2scrub@xxxxxxxxxxx > > create mode 100644 scrub/e2scrub_all.cron.in > > create mode 100644 scrub/e2scrub_all.service.in > > create mode 100644 scrub/e2scrub_all.timer.in > > create mode 100644 scrub/e2scrub_all_cron.in > > create mode 100644 scrub/e2scrub_fail.in > > create mode 100644 scrub/e2scrub_fail@xxxxxxxxxxx > > create mode 100644 scrub/e2scrub_reap.in > > create mode 100644 scrub/e2scrub_reap.service.in > > > > > > diff --git a/MCONFIG.in b/MCONFIG.in > > index adeb5bd..ee83554 100644 > > --- a/MCONFIG.in > > +++ b/MCONFIG.in > > @@ -32,9 +32,14 @@ man8dir = $(mandir)/man8 > > infodir = @infodir@ > > datadir = @datadir@ > > pkgconfigdir = $(libdir)/pkgconfig > > +pkglibdir = $(libdir)/e2fsprogs > > > > HAVE_UDEV = @have_udev@ > > UDEV_RULES_DIR = @pkg_udev_rules_dir@ > > +HAVE_CROND = @have_crond@ > > +CROND_DIR = @crond_dir@ > > +HAVE_SYSTEMD = @have_systemd@ > > +SYSTEMD_SYSTEM_UNIT_DIR = @systemd_system_unit_dir@ > > > > @SET_MAKE@ > > > > diff --git a/configure b/configure > > index 986e057..f6a0dea 100755 > > --- a/configure > > +++ b/configure > > @@ -625,6 +625,12 @@ gl_use_threads_default= > > ac_func_list= > > ac_subst_vars='LTLIBOBJS > > LIBOBJS > > +systemd_system_unit_dir > > +have_systemd > > +systemd_LIBS > > +systemd_CFLAGS > > +crond_dir > > +have_crond > > pkg_udev_rules_dir > > have_udev > > udev_LIBS > > @@ -899,6 +905,8 @@ with_libintl_prefix > > enable_fuse2fs > > with_multiarch > > with_udev_rules_dir > > +with_crond_dir > > +with_systemd_unit_dir > > ' > > ac_precious_vars='build_alias > > host_alias > > @@ -913,7 +921,9 @@ PKG_CONFIG > > PKG_CONFIG_PATH > > PKG_CONFIG_LIBDIR > > udev_CFLAGS > > -udev_LIBS' > > +udev_LIBS > > +systemd_CFLAGS > > +systemd_LIBS' > > > > > > # Initialize some variables set by options. > > @@ -1591,6 +1601,9 @@ Optional Packages: > > --with-multiarch=ARCH specify the multiarch triplet > > --with-udev-rules-dir[=DIR] > > Install udev rules into DIR. > > + --with-crond-dir[=DIR] Install system crontabs into DIR. > > + --with-systemd-unit-dir[=DIR] > > + Install systemd system units into DIR. > > > > Some influential environment variables: > > CC C compiler command > > @@ -1608,6 +1621,10 @@ Some influential environment variables: > > path overriding pkg-config's built-in search path > > udev_CFLAGS C compiler flags for udev, overriding pkg-config > > udev_LIBS linker flags for udev, overriding pkg-config > > + systemd_CFLAGS > > + C compiler flags for systemd, overriding pkg-config > > + systemd_LIBS > > + linker flags for systemd, overriding pkg-config > > > > Use these variables to override the choices made by `configure' or to help > > it to find libraries and programs with nonstandard names/locations. > > @@ -13803,6 +13820,7 @@ else > > fi > > > > fi > > + > > { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can link with -static" >&5 > > $as_echo_n "checking whether we can link with -static... " >&6; } > > if ${ac_cv_e2fsprogs_use_static+:} false; then : > > @@ -14009,6 +14027,165 @@ fi > > > > > > > > + > > +# Check whether --with-crond_dir was given. > > +if test "${with_crond_dir+set}" = set; then : > > + withval=$with_crond_dir; > > +else > > + with_crond_dir=yes > > +fi > > + > > +if test "x${with_crond_dir}" != "xno"; then : > > + > > + if test "x${with_crond_dir}" = "xyes"; then : > > + > > + if test -d "/etc/cron.d"; then : > > + with_crond_dir="/etc/cron.d" > > +fi > > + > > +fi > > + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for system crontab dir" >&5 > > +$as_echo_n "checking for system crontab dir... " >&6; } > > + crond_dir="${with_crond_dir}" > > + if test -n "${crond_dir}"; then : > > + > > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${crond_dir}" >&5 > > +$as_echo "${crond_dir}" >&6; } > > + have_crond="yes" > > + > > +else > > + > > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 > > +$as_echo "no" >&6; } > > + have_crond="no" > > + > > +fi > > + > > +else > > + > > + have_crond="disabled" > > + > > +fi > > + > > + > > + > > + > > +# Check whether --with-systemd_unit_dir was given. > > +if test "${with_systemd_unit_dir+set}" = set; then : > > + withval=$with_systemd_unit_dir; > > +else > > + with_systemd_unit_dir=yes > > +fi > > + > > +if test "x${with_systemd_unit_dir}" != "xno"; then : > > + > > + if test "x${with_systemd_unit_dir}" = "xyes"; then : > > + > > + > > +pkg_failed=no > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for systemd" >&5 > > +$as_echo_n "checking for systemd... " >&6; } > > + > > +if test -n "$systemd_CFLAGS"; then > > + pkg_cv_systemd_CFLAGS="$systemd_CFLAGS" > > + elif test -n "$PKG_CONFIG"; then > > + if test -n "$PKG_CONFIG" && \ > > + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd\""; } >&5 > > + ($PKG_CONFIG --exists --print-errors "systemd") 2>&5 > > + ac_status=$? > > + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 > > + test $ac_status = 0; }; then > > + pkg_cv_systemd_CFLAGS=`$PKG_CONFIG --cflags "systemd" 2>/dev/null` > > + test "x$?" != "x0" && pkg_failed=yes > > +else > > + pkg_failed=yes > > +fi > > + else > > + pkg_failed=untried > > +fi > > +if test -n "$systemd_LIBS"; then > > + pkg_cv_systemd_LIBS="$systemd_LIBS" > > + elif test -n "$PKG_CONFIG"; then > > + if test -n "$PKG_CONFIG" && \ > > + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd\""; } >&5 > > + ($PKG_CONFIG --exists --print-errors "systemd") 2>&5 > > + ac_status=$? > > + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 > > + test $ac_status = 0; }; then > > + pkg_cv_systemd_LIBS=`$PKG_CONFIG --libs "systemd" 2>/dev/null` > > + test "x$?" != "x0" && pkg_failed=yes > > +else > > + pkg_failed=yes > > +fi > > + else > > + pkg_failed=untried > > +fi > > + > > + > > + > > +if test $pkg_failed = yes; then > > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 > > +$as_echo "no" >&6; } > > + > > +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then > > + _pkg_short_errors_supported=yes > > +else > > + _pkg_short_errors_supported=no > > +fi > > + if test $_pkg_short_errors_supported = yes; then > > + systemd_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "systemd" 2>&1` > > + else > > + systemd_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "systemd" 2>&1` > > + fi > > + # Put the nasty error message in config.log where it belongs > > + echo "$systemd_PKG_ERRORS" >&5 > > + > > + > > + with_systemd_unit_dir="" > > + > > +elif test $pkg_failed = untried; then > > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 > > +$as_echo "no" >&6; } > > + > > + with_systemd_unit_dir="" > > + > > +else > > + systemd_CFLAGS=$pkg_cv_systemd_CFLAGS > > + systemd_LIBS=$pkg_cv_systemd_LIBS > > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 > > +$as_echo "yes" >&6; } > > + > > + with_systemd_unit_dir="$($PKG_CONFIG --variable=systemdsystemunitdir systemd)" > > + > > +fi > > + > > + > > +fi > > + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for systemd system unit dir" >&5 > > +$as_echo_n "checking for systemd system unit dir... " >&6; } > > + systemd_system_unit_dir="${with_systemd_unit_dir}" > > + if test -n "${systemd_system_unit_dir}"; then : > > + > > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${systemd_system_unit_dir}" >&5 > > +$as_echo "${systemd_system_unit_dir}" >&6; } > > + have_systemd="yes" > > + > > +else > > + > > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 > > +$as_echo "no" >&6; } > > + have_systemd="no" > > + > > +fi > > + > > +else > > + > > + have_systemd="disabled" > > + > > +fi > > + > > + > > + > > test -d lib || mkdir lib > > test -d include || mkdir include > > test -d include/linux || mkdir include/linux > > diff --git a/configure.ac b/configure.ac > > index 6e549c5..5a2c8be 100644 > > --- a/configure.ac > > +++ b/configure.ac > > @@ -1392,7 +1392,8 @@ else > > libdir=$libdir/$withval > > root_libdir=$root_libdir/$withval > > fi > > -)dnl > > +) > > +dnl > > dnl > > dnl See if -static works. This could fail if the linker does not > > dnl support -static, or if required external libraries are not available > > @@ -1514,6 +1515,77 @@ AC_SUBST(have_udev) > > AC_SUBST(pkg_udev_rules_dir) > > > > dnl > > +dnl Where do cron jobs go? > > +dnl > > +AC_ARG_WITH([crond_dir], > > + [AS_HELP_STRING([--with-crond-dir@<:@=DIR@:>@], > > + [Install system crontabs into DIR.])], > > + [], > > + [with_crond_dir=yes]) > > +AS_IF([test "x${with_crond_dir}" != "xno"], > > + [ > > + AS_IF([test "x${with_crond_dir}" = "xyes"], > > + [ > > + AS_IF([test -d "/etc/cron.d"], > > + [with_crond_dir="/etc/cron.d"]) > > + ]) > > + AC_MSG_CHECKING([for system crontab dir]) > > + crond_dir="${with_crond_dir}" > > + AS_IF([test -n "${crond_dir}"], > > + [ > > + AC_MSG_RESULT(${crond_dir}) > > + have_crond="yes" > > + ], > > + [ > > + AC_MSG_RESULT(no) > > + have_crond="no" > > + ]) > > + ], > > + [ > > + have_crond="disabled" > > + ]) > > +AC_SUBST(have_crond) > > +AC_SUBST(crond_dir) > > + > > +dnl > > +dnl Where do systemd services go? > > +dnl > > +AC_ARG_WITH([systemd_unit_dir], > > + [AS_HELP_STRING([--with-systemd-unit-dir@<:@=DIR@:>@], > > + [Install systemd system units into DIR.])], > > + [], > > + [with_systemd_unit_dir=yes]) > > +AS_IF([test "x${with_systemd_unit_dir}" != "xno"], > > + [ > > + AS_IF([test "x${with_systemd_unit_dir}" = "xyes"], > > + [ > > + PKG_CHECK_MODULES([systemd], [systemd], > > + [ > > + with_systemd_unit_dir="$($PKG_CONFIG --variable=systemdsystemunitdir systemd)" > > + ], [ > > + with_systemd_unit_dir="" > > + ]) > > + m4_pattern_allow([^PKG_(MAJOR|MINOR|BUILD|REVISION)$]) > > + ]) > > + AC_MSG_CHECKING([for systemd system unit dir]) > > + systemd_system_unit_dir="${with_systemd_unit_dir}" > > + AS_IF([test -n "${systemd_system_unit_dir}"], > > + [ > > + AC_MSG_RESULT(${systemd_system_unit_dir}) > > + have_systemd="yes" > > + ], > > + [ > > + AC_MSG_RESULT(no) > > + have_systemd="no" > > + ]) > > + ], > > + [ > > + have_systemd="disabled" > > + ]) > > +AC_SUBST(have_systemd) > > +AC_SUBST(systemd_system_unit_dir) > > + > > +dnl > > dnl Make our output files, being sure that we create the some miscellaneous > > dnl directories > > dnl > > diff --git a/debian/e2fsprogs.files b/debian/e2fsprogs.files > > index 78720fe..e0e49ce 100644 > > --- a/debian/e2fsprogs.files > > +++ b/debian/e2fsprogs.files > > @@ -1,6 +1,9 @@ > > sbin > > usr/bin > > +usr/lib > > usr/sbin > > usr/share/man > > etc > > lib/udev/rules.d > > +lib/systemd/system > > +usr/lib > > diff --git a/debian/e2fsprogs.postinst b/debian/e2fsprogs.postinst > > index 00ac363..e7acb0e 100644 > > --- a/debian/e2fsprogs.postinst > > +++ b/debian/e2fsprogs.postinst > > @@ -10,4 +10,23 @@ fi > > > > #DEBHELPER# > > > > +# debhelper doesn't know what timers are... > > +update_svc() { > > + deb-systemd-helper unmask "$1" >/dev/null || true > > + > > + if deb-systemd-helper --quiet was-enabled "$1"; then > > + deb-systemd-helper enable "$1" >/dev/null || true > > + else > > + deb-systemd-helper update-state "$1" >/dev/null || true > > + fi > > +} > > +update_svc e2scrub_all.timer > > +update_svc e2scrub_reap.service > > + > > +# Start our new services > > +if [ -d /run/systemd/system ]; then > > + systemctl --system daemon-reload >/dev/null || true > > + deb-systemd-invoke start e2scrub_all.timer >/dev/null || true > > +fi > > + > > exit 0 > > diff --git a/debian/e2fsprogs.postrm b/debian/e2fsprogs.postrm > > new file mode 100644 > > index 0000000..32cb642 > > --- /dev/null > > +++ b/debian/e2fsprogs.postrm > > @@ -0,0 +1,35 @@ > > +#!/bin/sh > > + > > +update_svc() { > > + deb-systemd-helper mask "$1" >/dev/null || true > > + > > + if deb-systemd-helper --quiet was-enabled "$1"; then > > + # Enables the unit on first installation, creates new > > + # symlinks on upgrades if the unit file has changed. > > + deb-systemd-helper disable "$1" >/dev/null || true > > + fi > > +} > > + > > +if [ "$1" != "upgrade" ]; then > > + # Abort on error. > > + set -e > > + > > + if [ -x /usr/sbin/update-initramfs -a \ > > + -e /etc/initramfs-tools/initramfs.conf ]; then > > + update-initramfs -u > > + fi > > + > > + #DEBHELPER# > > + > > + # debhelper doesn't know what timers are... > > + update_svc e2scrub_all.timer > > + update_svc e2scrub_reap.service > > + > > + # Start our new services > > + if [ -d /run/systemd/system ]; then > > + deb-systemd-invoke stop e2scrub_all.timer >/dev/null || true > > + fi > > +fi > > + > > +exit 0 > > + > > diff --git a/scrub/Makefile.in b/scrub/Makefile.in > > index 1744941..cc2e9ce 100644 > > --- a/scrub/Makefile.in > > +++ b/scrub/Makefile.in > > @@ -22,7 +22,23 @@ INSTALL_TGT += install-udev > > UNINSTALL_TGT += uninstall-udev > > endif > > > > -all:: $(PROGS) $(MANPAGES) $(CONFFILES) $(UDEV_RULES) > > +ifeq ($(HAVE_CROND),yes) > > +CRONTABS = e2scrub_all.cron > > +LIBPROGS += e2scrub_reap e2scrub_all_cron > > +INSTALLDIRS_TGT += installdirs-crond installdirs-libprogs > > +INSTALL_TGT += install-crond install-libprogs > > +UNINSTALL_TGT += uninstall-crond uninstall-libprogs > > +endif > > + > > +ifeq ($(HAVE_SYSTEMD),yes) > > +SERVICE_FILES = e2scrub@.service e2scrub_all.service e2scrub_all.timer e2scrub_fail@.service e2scrub_reap.service > > +LIBPROGS += e2scrub_fail e2scrub_reap > > +INSTALLDIRS_TGT += installdirs-systemd installdirs-libprogs > > +INSTALL_TGT += install-systemd install-libprogs > > +UNINSTALL_TGT += uninstall-systemd uninstall-libprogs > > +endif > > + > > +all:: $(PROGS) $(MANPAGES) $(CONFFILES) $(UDEV_RULES) $(SERVICE_FILES) $(CRONTABS) $(LIBPROGS) > > > > e2scrub: $(DEP_SUBSTITUTE) e2scrub.in > > $(E) " SUBST $@" > > @@ -34,6 +50,21 @@ e2scrub_all: e2scrub_all.in > > $(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2scrub_all.in $@ > > $(Q) chmod a+x $@ > > > > +e2scrub_fail: e2scrub_fail.in > > + $(E) " SUBST $@" > > + $(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2scrub_fail.in $@ > > + $(Q) chmod a+x $@ > > + > > +e2scrub_reap: e2scrub_reap.in > > + $(E) " SUBST $@" > > + $(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2scrub_reap.in $@ > > + $(Q) chmod a+x $@ > > + > > +e2scrub_all_cron: e2scrub_all_cron.in > > + $(E) " SUBST $@" > > + $(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2scrub_all_cron.in $@ > > + $(Q) chmod a+x $@ > > + > > %.8: %.8.in $(DEP_SUBSTITUTE) > > $(E) " SUBST $@" > > $(Q) $(SUBSTITUTE_UPTIME) $< $@ > > @@ -46,10 +77,34 @@ e2scrub_all: e2scrub_all.in > > $(E) " SUBST $@" > > $(Q) $(SUBSTITUTE_UPTIME) $< $@ > > > > +%.service: %.service.in $(DEP_SUBSTITUTE) > > + $(E) " SUBST $@" > > + $(Q) $(SUBSTITUTE_UPTIME) $< $@ > > + > > +%.cron: %.cron.in $(DEP_SUBSTITUTE) > > + $(E) " SUBST $@" > > + $(Q) $(SUBSTITUTE_UPTIME) $< $@ > > + > > +%.timer: %.timer.in $(DEP_SUBSTITUTE) > > + $(E) " SUBST $@" > > + $(Q) $(SUBSTITUTE_UPTIME) $< $@ > > + > > installdirs-udev: > > $(E) " MKINSTALLDIRS $(UDEV_RULES_DIR)" > > $(Q) $(MKINSTALLDIRS) $(DESTDIR)$(UDEV_RULES_DIR) > > > > +installdirs-crond: > > + $(E) " MKINSTALLDIRS $(CROND_DIR)" > > + $(Q) $(MKINSTALLDIRS) $(DESTDIR)$(CROND_DIR) > > + > > +installdirs-libprogs: > > + $(E) " MKINSTALLDIRS $(pkglibdir)" > > + $(Q) $(MKINSTALLDIRS) $(DESTDIR)$(pkglibdir) > > + > > +installdirs-systemd: > > + $(E) " MKINSTALLDIRS $(SYSTEMD_SYSTEM_UNIT_DIR)" > > + $(Q) $(MKINSTALLDIRS) $(DESTDIR)$(SYSTEMD_SYSTEM_UNIT_DIR) > > + > > installdirs: $(INSTALLDIRS_TGT) > > $(E) " MKINSTALLDIRS $(root_sbindir) $(man8dir) $(root_sysconfdir)" > > $(Q) $(MKINSTALLDIRS) $(DESTDIR)$(root_sbindir) \ > > @@ -61,6 +116,24 @@ install-udev: > > $(INSTALL_PROGRAM) $$i $(DESTDIR)$(UDEV_RULES_DIR)/96-$$i; \ > > done > > > > +install-crond: > > + $(Q) for i in $(CRONTABS); do \ > > + $(ES) " INSTALL $(CROND_DIR)/$$i"; \ > > + $(INSTALL_PROGRAM) $$i $(DESTDIR)$(CROND_DIR)/$$i; \ > > + done > > + > > +install-libprogs: $(LIBPROGS) > > + $(Q) for i in $(LIBPROGS); do \ > > + $(ES) " INSTALL $(pkglibdir)/$$i"; \ > > + $(INSTALL_PROGRAM) $$i $(DESTDIR)$(pkglibdir)/$$i; \ > > + done > > + > > +install-systemd: $(SERVICE_FILES) > > + $(Q) for i in $(SERVICE_FILES); do \ > > + $(ES) " INSTALL_DATA $(SYSTEMD_SYSTEM_UNIT_DIR)/$$i"; \ > > + $(INSTALL_DATA) $$i $(DESTDIR)$(SYSTEMD_SYSTEM_UNIT_DIR)/$$i; \ > > + done > > + > > install: $(PROGS) $(MANPAGES) $(FMANPAGES) installdirs $(INSTALL_TGT) > > $(Q) for i in $(PROGS); do \ > > $(ES) " INSTALL $(root_sbindir)/$$i"; \ > > @@ -83,6 +156,21 @@ uninstall-udev: > > $(RM) -f $(DESTDIR)$(UDEV_RULES_DIR)/96-$$i; \ > > done > > > > +uninstall-crond: > > + for i in $(CRONTABS); do \ > > + $(RM) -f $(DESTDIR)$(CROND_DIR)/$$i; \ > > + done > > + > > +uninstall-libprogs: > > + for i in $(LIBPROGS); do \ > > + $(RM) -f $(DESTDIR)$(pkglibdir)/$$i; \ > > + done > > + > > +uninstall-systemd: > > + for i in $(SERVICE_FILES); do \ > > + $(RM) -f $(DESTDIR)$(SYSTEMD_SYSTEM_UNIT_DIR)/$$i; \ > > + done > > + > > uninstall: $(UNINSTALL_TGT) > > for i in $(PROGS); do \ > > $(RM) -f $(DESTDIR)$(root_sbindir)/$$i; \ > > diff --git a/scrub/e2scrub.in b/scrub/e2scrub.in > > index f77ec6f..a19b6bb 100644 > > --- a/scrub/e2scrub.in > > +++ b/scrub/e2scrub.in > > @@ -44,12 +44,34 @@ print_version() { > > echo "e2scrub @E2FSPROGS_VERSION@ (@E2FSPROGS_DATE@)" > > } > > > > +exitcode() { > > + ret="$1" > > + > > + # If we're being run as a service, the return code must fit the LSB > > + # init script action error guidelines, which is to say that we > > + # compress all errors to 1 ("generic or unspecified error", LSB 5.0 > > + # section 22.2) and hope the admin will scan the log for what > > + # actually happened. > > + > > + # We have to sleep 2 seconds here because journald uses the pid to > > + # connect our log messages to the systemd service. This is critical > > + # for capturing all the log messages if the scrub fails, because the > > + # fail service uses the service name to gather log messages for the > > + # error report. > > + if [ -n "${SERVICE_MODE}" ]; then > > + test "${ret}" -ne 0 && ret=1 > > + sleep 2 > > + fi > > + > > + exit "${ret}" > > +} > > + > > while getopts "rtV" opt; do > > case "${opt}" in > > "r") reap=1;; > > "t") fstrim=1;; > > - "V") print_version; exit 0;; > > - *) print_help; exit 2;; > > + "V") print_version; exitcode 0;; > > + *) print_help; exitcode 2;; > > esac > > done > > shift "$((OPTIND - 1))" > > @@ -57,18 +79,18 @@ shift "$((OPTIND - 1))" > > dev="$1" > > if [ -z "${dev}" ]; then > > print_help > > - exit 1 > > + exitcode 1 > > elif [ ! -b "${dev}" ]; then > > echo "${dev}: Not a block device?" > > print_help > > - exit 16 > > + exitcode 16 > > fi > > > > # Make sure this is an LVM device we can snapshot > > eval $(lvs --nameprefixes -o name,vgname --noheadings "${dev}") > > if [ -z "${LVM2_VG_NAME}" ] || [ -z "${LVM2_LV_NAME}" ]; then > > echo "${dev}: Not a LVM device." > > - exit 16 > > + exitcode 16 > > fi > > start_time="$(date +'%Y%m%d%H%M%S')" > > snap="${LVM2_LV_NAME}.e2scrub" > > @@ -80,7 +102,7 @@ ext[234]) > > ;; > > *) > > echo "${dev}: Filesystem of type ${fstype} not supported." > > - exit 16 > > + exitcode 16 > > ;; > > esac > > > > @@ -128,7 +150,7 @@ if [ "${reap}" -gt 0 ]; then > > fi > > if ! setup; then > > echo "Snapshot of ${dev} FAILED, will not check!" > > - exit 1 > > + exitcode 1 > > fi > > > > # Check and react > > @@ -167,4 +189,4 @@ else > > fi > > fi > > > > -exit "${ret}" > > +exitcode "${ret}" > > diff --git a/scrub/e2scrub@xxxxxxxxxxx b/scrub/e2scrub@xxxxxxxxxxx > > new file mode 100644 > > index 0000000..496f894 > > --- /dev/null > > +++ b/scrub/e2scrub@xxxxxxxxxxx > > @@ -0,0 +1,20 @@ > > +[Unit] > > +Description=Online ext4 Metadata Check for %I > > +OnFailure=e2scrub_fail@%i.service > > +Documentation=man:e2scrub(8) > > + > > +[Service] > > +Type=oneshot > > +WorkingDirectory=/ > > +PrivateNetwork=true > > +ProtectSystem=true > > +ProtectHome=read-only > > +PrivateTmp=yes > > +AmbientCapabilities=CAP_SYS_ADMIN CAP_SYS_RAWIO > > +NoNewPrivileges=yes > > +User=root > > +IOSchedulingClass=idle > > +CPUSchedulingPolicy=idle > > +Environment=SERVICE_MODE=1 > > +ExecStart=@root_sbindir@/e2scrub -t %I > > +SyslogIdentifier=%N > > diff --git a/scrub/e2scrub_all.cron.in b/scrub/e2scrub_all.cron.in > > new file mode 100644 > > index 0000000..0cb5f1f > > --- /dev/null > > +++ b/scrub/e2scrub_all.cron.in > > @@ -0,0 +1,2 @@ > > +30 3 * * 0 root test -e /run/systemd/system || @pkglibdir@/e2scrub_all_cron > > +10 3 * * * root test -e /run/systemd/system || @pkglibdir@/e2scrub_reap > > diff --git a/scrub/e2scrub_all.in b/scrub/e2scrub_all.in > > index 453981b..fbf2e95 100644 > > --- a/scrub/e2scrub_all.in > > +++ b/scrub/e2scrub_all.in > > @@ -30,10 +30,32 @@ print_version() { > > echo "e2scrub_all @E2FSPROGS_VERSION@ (@E2FSPROGS_DATE@)" > > } > > > > +exitcode() { > > + ret="$1" > > + > > + # If we're being run as a service, the return code must fit the LSB > > + # init script action error guidelines, which is to say that we > > + # compress all errors to 1 ("generic or unspecified error", LSB 5.0 > > + # section 22.2) and hope the admin will scan the log for what > > + # actually happened. > > + > > + # We have to sleep 2 seconds here because journald uses the pid to > > + # connect our log messages to the systemd service. This is critical > > + # for capturing all the log messages if the scrub fails, because the > > + # fail service uses the service name to gather log messages for the > > + # error report. > > + if [ -n "${SERVICE_MODE}" ]; then > > + test "${ret}" -ne 0 && ret=1 > > + sleep 2 > > + fi > > + > > + exit "${ret}" > > +} > > + > > while getopts "V" opt; do > > case "${opt}" in > > - "V") print_version; exit 0;; > > - *) print_help; exit 2;; > > + "V") print_version; exitcode 0;; > > + *) print_help; exitcode 2;; > > esac > > done > > shift "$((OPTIND - 1))" > > @@ -49,7 +71,15 @@ lvs -o vg_name,lv_name,lv_role --noheadings 2> /dev/null | while read vg lv role > > # Skip non-ext[234] > > blkid -p -n "${types}" "${dev}" > /dev/null 2>&1 || continue > > > > - ${DBG} "@root_sbindir@/e2scrub" "${dev}" > > + if type systemctl > /dev/null 2>&1; then > > + ${DBG} systemctl start "e2scrub@${dev}" 2> /dev/null > > + res=$? > > + if [ "${res}" -ne 0 ] && [ "${res}" -ne 1 ]; then > > + ${DBG} "@root_sbindir@/e2scrub" "${dev}" > > + fi > > + else > > + ${DBG} "@root_sbindir@/e2scrub" "${dev}" > > + fi > > done > > > > -exit 0 > > +exitcode 0 > > diff --git a/scrub/e2scrub_all.service.in b/scrub/e2scrub_all.service.in > > new file mode 100644 > > index 0000000..bc05184 > > --- /dev/null > > +++ b/scrub/e2scrub_all.service.in > > @@ -0,0 +1,10 @@ > > +[Unit] > > +Description=Online ext4 Metadata Check for All Filesystems > > +ConditionACPower=true > > +Documentation=man:e2scrub_all(8) > > + > > +[Service] > > +Type=oneshot > > +Environment=SERVICE_MODE=1 > > +ExecStart=@root_sbindir@/e2scrub_all > > +SyslogIdentifier=e2scrub_all > > diff --git a/scrub/e2scrub_all.timer.in b/scrub/e2scrub_all.timer.in > > new file mode 100644 > > index 0000000..3d558bb > > --- /dev/null > > +++ b/scrub/e2scrub_all.timer.in > > @@ -0,0 +1,11 @@ > > +[Unit] > > +Description=Periodic ext4 Online Metadata Check for All Filesystems > > + > > +[Timer] > > +# Run on Sunday at 3:10am, to avoid running afoul of DST changes > > +OnCalendar=Sun *-*-* 03:10:00 > > +RandomizedDelaySec=60 > > +Persistent=true > > + > > +[Install] > > +WantedBy=timers.target > > diff --git a/scrub/e2scrub_all_cron.in b/scrub/e2scrub_all_cron.in > > new file mode 100644 > > index 0000000..f9cff87 > > --- /dev/null > > +++ b/scrub/e2scrub_all_cron.in > > @@ -0,0 +1,68 @@ > > +#!/bin/bash > > + > > +# Copyright (C) 2018 Oracle. All Rights Reserved. > > +# > > +# Author: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > +# > > +# This program is free software; you can redistribute it and/or > > +# modify it under the terms of the GNU General Public License > > +# as published by the Free Software Foundation; either version 2 > > +# of the License, or (at your option) any later version. > > +# > > +# This program is distributed in the hope that it would be useful, > > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > +# GNU General Public License for more details. > > +# > > +# You should have received a copy of the GNU General Public License > > +# along with this program; if not, write the Free Software Foundation, > > +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > > + > > +# Run e2scrub_all from a cronjob if we don't have systemd and we're not > > +# running on AC power. > > + > > +on_ac_power() { > > + local any_known=no > > + > > + # try sysfs power class first > > + if [ -d /sys/class/power_supply ]; then > > + for psu in /sys/class/power_supply/*; do > > + if [ -r "$psu/type" ]; then > > + type=$(cat "$psu/type") > > + > > + # ignore batteries > > + [ "$type" = "Battery" ] && continue > > + > > + online=$(cat "$psu/online") > > + > > + [ "$online" = 1 ] && return 0 > > + [ "$online" = 0 ] && any_known=yes > > + fi > > + done > > + > > + [ "$any_known" = "yes" ] && return 1 > > + fi > > + > > + # else fall back to AC adapters in /proc > > + if [ -d /proc/acpi/ac_adapter ]; then > > + for ac in /proc/acpi/ac_adapter/*; do > > + if [ -r "$ac/state" ]; then > > + grep -q on-line "$ac/state" && return 0 > > + grep -q off-line "$ac/state" && any_known=yes > > + elif [ -r "$ac/status" ]; then > > + grep -q on-line "$ac/status" && return 0 > > + grep -q off-line "$ac/status" && any_known=yes > > + fi > > + done > > + > > + [ "$any_known" = "yes" ] && return 1 > > + fi > > + > > + # Can't tell, just assume we're on AC. > > + return 0 > > +} > > + > > +test -e /run/systemd/system && exit 0 > > +on_ac_power || exit 0 > > + > > +exec @root_sbindir@/e2scrub_all > > diff --git a/scrub/e2scrub_fail.in b/scrub/e2scrub_fail.in > > new file mode 100644 > > index 0000000..f27197a > > --- /dev/null > > +++ b/scrub/e2scrub_fail.in > > @@ -0,0 +1,25 @@ > > +#!/bin/bash > > + > > +# Email logs of failed e2scrub unit runs when the systemd service fails. > > + > > +recipient="$1" > > +test -z "${recipient}" && exit 0 > > +device="$2" > > +test -z "${device}" && exit 0 > > +hostname="$(hostname -f 2>/dev/null)" > > +test -z "${hostname}" && hostname="${HOSTNAME}" > > +if ! type sendmail > /dev/null 2>&1; then > > + echo "$0: sendmail program not found." > > + exit 1 > > +fi > > + > > +(cat << ENDL > > +To: $1 > > +From: <e2scrub@${hostname}> > > +Subject: e2scrub failure on ${device} > > + > > +So sorry, the automatic e2scrub of ${device} on ${hostname} failed. > > + > > +A log of what happened follows: > > +ENDL > > +systemctl status --full --lines 4294967295 "e2scrub@${device}") | sendmail -t -i > > diff --git a/scrub/e2scrub_fail@xxxxxxxxxxx b/scrub/e2scrub_fail@xxxxxxxxxxx > > new file mode 100644 > > index 0000000..df87949 > > --- /dev/null > > +++ b/scrub/e2scrub_fail@xxxxxxxxxxx > > @@ -0,0 +1,10 @@ > > +[Unit] > > +Description=Online ext4 Metadata Check Failure Reporting for %I > > + > > +[Service] > > +Type=oneshot > > +Environment=EMAIL_ADDR=root > > +ExecStart=@pkglibdir@/e2scrub_fail "${EMAIL_ADDR}" %I > > +User=mail > > +Group=mail > > +SupplementaryGroups=systemd-journal > > diff --git a/scrub/e2scrub_reap.in b/scrub/e2scrub_reap.in > > new file mode 100644 > > index 0000000..0fde0e6 > > --- /dev/null > > +++ b/scrub/e2scrub_reap.in > > @@ -0,0 +1,48 @@ > > +#!/bin/bash > > + > > +# Copyright (C) 2018 Oracle. All Rights Reserved. > > +# > > +# Author: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > +# > > +# This program is free software; you can redistribute it and/or > > +# modify it under the terms of the GNU General Public License > > +# as published by the Free Software Foundation; either version 2 > > +# of the License, or (at your option) any later version. > > +# > > +# This program is distributed in the hope that it would be useful, > > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > +# GNU General Public License for more details. > > +# > > +# You should have received a copy of the GNU General Public License > > +# along with this program; if not, write the Free Software Foundation, > > +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > > + > > +# Clean up leftover e2scrub snapshots > > + > > +# Find any ${lvname}.e2scrub snapshot and delete it > > +lvs -o vg_name,lv_name,lv_role --noheadings 2> /dev/null | while read vg lv role extra; do > > + # Parse error? > > + test -n "${extra}" || continue > > + # Is this really a snapshot? > > + echo "${role}" | grep -q "snapshot" || continue > > + # An e2scrub snapshot? > > + echo "${lv}" | grep -q ".e2scrub$" || continue > > + > > + # Check that the e2scrub snap still exists after waiting a brief period. > > + # This is how try to avoid deleting a snap from underneath a running > > + # scrub. > > + dev="/dev/${vg}/${lv}" > > + test -e "${dev}" || continue > > + sleep 2 > > + test -e "${dev}" || continue > > + > > + # Remove and wait for removal to succeed. > > + lvremove -f "${vg}/${lv}" 3>&- > > + while [ -e "${dev}" ] && [ "$?" -eq "5" ]; do > > + sleep 0.5 > > + lvremove -f "${vg}/${lv}" 3>&- > > + done > > +done > > + > > +exitcode 0 > > diff --git a/scrub/e2scrub_reap.service.in b/scrub/e2scrub_reap.service.in > > new file mode 100644 > > index 0000000..38eefc4 > > --- /dev/null > > +++ b/scrub/e2scrub_reap.service.in > > @@ -0,0 +1,21 @@ > > +[Unit] > > +Description=Remove Stale Online ext4 Metadata Check Snapshots > > + > > +[Service] > > +Type=oneshot > > +WorkingDirectory=/ > > +PrivateNetwork=true > > +ProtectSystem=true > > +ProtectHome=read-only > > +PrivateTmp=yes > > +AmbientCapabilities=CAP_SYS_ADMIN CAP_SYS_RAWIO > > +NoNewPrivileges=yes > > +User=root > > +IOSchedulingClass=idle > > +CPUSchedulingPolicy=idle > > +ExecStart=@pkglibdir@/e2scrub_reap > > I thought that the idea was to use e2scrub -r and get rid of the > e2scrub_reap. e2scrub -r only gets rid of one lvm volume's e2scrub snapshot, so you need a utility to find them all and nuke them. That used to be e2scrub_reap, but I've folded that into "e2scrub_all -r". --D > -Lukas > > > +SyslogIdentifier=%N > > +RemainAfterExit=no > > + > > +[Install] > > +WantedBy=default.target > > diff --git a/util/subst.conf.in b/util/subst.conf.in > > index 6bf658d..0da4554 100644 > > --- a/util/subst.conf.in > > +++ b/util/subst.conf.in > > @@ -21,3 +21,6 @@ JDEV > > TDB_MAN_COMMENT @TDB_MAN_COMMENT@ > > root_sbindir @root_sbindir@ > > root_bindir @root_bindir@ > > +libdir @libdir@ > > +$exec_prefix @exec_prefix@ > > +pkglibdir @libdir@/e2fsprogs > >