[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <151267252240.1350.14080940928827658377.stgit@magnolia>
Date: Thu, 07 Dec 2017 10:48:42 -0800
From: "Darrick J. Wong" <darrick.wong@...cle.com>
To: tytso@....edu, darrick.wong@...cle.com
Cc: adilger@...ger.ca, linux-ext4@...r.kernel.org
Subject: [PATCH 3/4] e2scrub: add service (cron, systemd) support
From: Darrick J. Wong <darrick.wong@...cle.com>
Add the ability to run the e2scrub utilities as a periodically scheduled
system service.
Signed-off-by: Darrick J. Wong <darrick.wong@...cle.com>
---
MCONFIG.in | 4 ++
configure | 24 +++++++++++++++
configure.ac | 28 ++++++++++++++++-
debian/e2fsprogs.files | 2 +
debian/e2fsprogs.postinst | 19 ++++++++++++
scrub/Makefile.in | 66 ++++++++++++++++++++++++++++++++++++++--
scrub/e2scrub.in | 12 +++++++
scrub/e2scrub@...rvice.in | 18 +++++++++++
scrub/e2scrub_all.cron.in | 2 +
scrub/e2scrub_all.in | 24 ++++++++++++++-
scrub/e2scrub_all.service.in | 8 +++++
scrub/e2scrub_all.timer.in | 11 +++++++
scrub/e2scrub_fail.in | 26 ++++++++++++++++
scrub/e2scrub_fail@...rvice.in | 10 ++++++
util/subst.conf.in | 2 +
15 files changed, 250 insertions(+), 6 deletions(-)
create mode 100644 scrub/e2scrub@...rvice.in
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_fail.in
create mode 100644 scrub/e2scrub_fail@...rvice.in
diff --git a/MCONFIG.in b/MCONFIG.in
index a244728..aa7d0d1 100644
--- a/MCONFIG.in
+++ b/MCONFIG.in
@@ -23,6 +23,7 @@ libdir = @libdir@
datadir= @datadir@
localedir = $(datadir)/locale
root_sysconfdir= @root_sysconfdir@
+root_crondir= @root_crondir@
includedir = @includedir@
mandir = @mandir@
man1dir = $(mandir)/man1
@@ -32,6 +33,9 @@ man8dir = $(mandir)/man8
infodir = @infodir@
datadir = @datadir@
pkgconfigdir = $(libdir)/pkgconfig
+pkglibdir = @pkglibdir@
+HAVE_SYSTEMD= @have_systemd@
+SYSTEMDSYSTEMUNITDIR= @systemdsystemunitdir@
HAVE_UDEV = @have_udev@
UDEVRULESDIR = @udevrulesdir@
diff --git a/configure b/configure
index c911469..cca0c23 100755
--- a/configure
+++ b/configure
@@ -625,6 +625,8 @@ gl_use_threads_default=
ac_func_list=
ac_subst_vars='LTLIBOBJS
LIBOBJS
+systemdsystemunitdir
+have_systemd
udevrulesdir
have_udev
LDFLAGS_SHLIB
@@ -636,6 +638,8 @@ MKINSTALLDIRS
INCLUDES
DO_TEST_SUITE
LDFLAGS_STATIC
+pkglibdir
+root_crondir
root_sysconfdir
root_libdir
root_sbindir
@@ -13749,11 +13753,13 @@ if test "$root_prefix" = NONE ; then
root_sbindir=$sbindir
root_libdir=$libdir
root_sysconfdir=$sysconfdir
+ root_crondir=$sysconfdir/cron.d
else
root_bindir='${root_prefix}/bin'
root_sbindir='${root_prefix}/sbin'
root_libdir='${root_prefix}/lib'
root_sysconfdir='${root_prefix}/etc'
+ root_crondir='${root_sysconfdir}/cron.d'
fi
if test "$bindir" != '${exec_prefix}/bin'; then
root_bindir=$bindir
@@ -13781,6 +13787,7 @@ fi
+
# Check whether --with-multiarch was given.
if test "${with_multiarch+set}" = set; then :
withval=$with_multiarch; if test "$withval" = "lib64"; then
@@ -13792,6 +13799,9 @@ else
fi
fi
+
+pkglibdir=$libdir/e2fsprogs
+
{ $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 :
@@ -13895,6 +13905,20 @@ case "${pkg_udevrulesdir}" in
esac
+pkg_systemdsystemunitdir="$(pkg-config --variable=systemdsystemunitdir systemd 2>/dev/null)"
+case "${pkg_systemdsystemunitdir}" in
+"")
+ systemdsystemunitdir=""
+ have_systemd=no
+ ;;
+*)
+ systemdsystemunitdir="${pkg_systemdsystemunitdir}"
+ have_systemd=yes
+ ;;
+esac
+
+
+
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 ad2884d..28172bd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1351,11 +1351,13 @@ if test "$root_prefix" = NONE ; then
root_sbindir=$sbindir
root_libdir=$libdir
root_sysconfdir=$sysconfdir
+ root_crondir=$sysconfdir/cron.d
else
root_bindir='${root_prefix}/bin'
root_sbindir='${root_prefix}/sbin'
root_libdir='${root_prefix}/lib'
root_sysconfdir='${root_prefix}/etc'
+ root_crondir='${root_sysconfdir}/cron.d'
fi
if test "$bindir" != '${exec_prefix}/bin'; then
root_bindir=$bindir
@@ -1378,6 +1380,7 @@ AC_SUBST(root_bindir)
AC_SUBST(root_sbindir)
AC_SUBST(root_libdir)
AC_SUBST(root_sysconfdir)
+AC_SUBST(root_crondir)
dnl
dnl Allow specification of the multiarch arch
dnl
@@ -1390,7 +1393,13 @@ else
libdir=$libdir/$withval
root_libdir=$root_libdir/$withval
fi
-)dnl
+)
+dnl
+dnl define pkglibdir for /usr/lib/e2fsprogs
+dnl
+pkglibdir=$libdir/e2fsprogs
+AC_SUBST(pkglibdir)
+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
@@ -1491,6 +1500,23 @@ esac
AC_SUBST([have_udev])
AC_SUBST([udevrulesdir])
dnl
+dnl Where do systemd services go?
+dnl
+pkg_systemdsystemunitdir="$(pkg-config --variable=systemdsystemunitdir systemd 2>/dev/null)"
+case "${pkg_systemdsystemunitdir}" in
+"")
+ systemdsystemunitdir=""
+ have_systemd=no
+ ;;
+*)
+ systemdsystemunitdir="${pkg_systemdsystemunitdir}"
+ have_systemd=yes
+ ;;
+esac
+AC_SUBST([have_systemd])
+AC_SUBST([systemdsystemunitdir])
+
+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 7dd64ac..677367c 100644
--- a/debian/e2fsprogs.files
+++ b/debian/e2fsprogs.files
@@ -1,7 +1,9 @@
sbin
usr/bin
+usr/lib
usr/sbin
usr/share/man
usr/share/locale
etc
+lib/systemd/system
lib/udev/rules
diff --git a/debian/e2fsprogs.postinst b/debian/e2fsprogs.postinst
index 00ac363..fceda61 100644
--- a/debian/e2fsprogs.postinst
+++ b/debian/e2fsprogs.postinst
@@ -10,4 +10,23 @@ fi
#DEBHELPER#
+# debhelper doesn't know what timers are...
+deb-systemd-helper unmask e2scrub_all.timer >/dev/null || true
+
+if deb-systemd-helper --quiet was-enabled e2scrub_all.timer; then
+ # Enables the unit on first installation, creates new
+ # symlinks on upgrades if the unit file has changed.
+ deb-systemd-helper enable e2scrub_all.timer >/dev/null || true
+else
+ # Update the statefile to add new symlinks (if any), which need to be
+ # cleaned up on purge. Also remove old symlinks.
+ deb-systemd-helper update-state e2scrub_all.timer >/dev/null || true
+fi
+
+# 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/scrub/Makefile.in b/scrub/Makefile.in
index ce8c85f..65ecc8c 100644
--- a/scrub/Makefile.in
+++ b/scrub/Makefile.in
@@ -22,7 +22,18 @@ INSTALL_TGT += install-udev
UNINSTALL_TGT += uninstall-udev
endif
-all:: $(PROGS) $(MANPAGES) $(CONFFILES) $(UDEVRULES)
+CRONTABS= e2scrub_all.cron
+
+ifeq ($(HAVE_SYSTEMD),yes)
+INSTALLDIRS_TGT += installdirs-systemd
+INSTALL_TGT += install-systemd
+UNINSTALL_TGT += uninstall-systemd
+LIBPROGS += e2scrub_fail
+SERVICE_FILES = e2scrub@...rvice e2scrub_all.service e2scrub_all.timer e2scrub_fail@...rvice
+SYSTEMD_DIRS = $(DESTDIR)/$(pkglibdir) $(DESTDIR)$(SYSTEMDSYSTEMUNITDIR)
+endif
+
+all:: $(PROGS) $(MANPAGES) $(CONFFILES) $(UDEVRULES) $(SERVICE_FILES) $(CRONTABS) $(LIBPROGS)
e2scrub: $(DEP_SUBSTITUTE) e2scrub.in
$(E) " SUBST $@"
@@ -34,6 +45,11 @@ 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 $@
+
%.8: %.8.in $(DEP_SUBSTITUTE)
$(E) " SUBST $@"
$(Q) $(SUBSTITUTE_UPTIME) $< $@
@@ -46,14 +62,31 @@ 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 $(udevdir)"
$(Q) $(MKINSTALLDIRS) $(DESTDIR)$(UDEVRULESDIR)
+installdirs-systemd:
+ $(E) " MKINSTALLDIRS $(SYSTEMD_DIRS) $(pkglibdir)"
+ $(Q) $(MKINSTALLDIRS) $(DESTDIR)$(SYSTEMD_DIRS) $(DESTDIR)$(pkglibdir)
+
installdirs: $(INSTALLDIRS_TGT)
- $(E) " MKINSTALLDIRS $(root_sbindir) $(man8dir) $(root_sysconfdir)"
+ $(E) " MKINSTALLDIRS $(root_sbindir) $(man8dir) $(root_sysconfdir) $(root_crondir)"
$(Q) $(MKINSTALLDIRS) $(DESTDIR)$(root_sbindir) \
- $(DESTDIR)$(man8dir) $(DESTDIR)$(root_sysconfdir)
+ $(DESTDIR)$(man8dir) $(DESTDIR)$(root_sysconfdir) \
+ $(DESTDIR)$(root_crondir)
install-udev:
$(Q) for i in $(UDEVRULES); do \
@@ -61,7 +94,17 @@ install-udev:
$(INSTALL_PROGRAM) $$i $(DESTDIR)$(UDEVRULESDIR)/96-$$i; \
done
-install: $(PROGS) $(MANPAGES) $(FMANPAGES) installdirs $(INSTALL_TGT)
+install-systemd: $(SERVICE_FILES)
+ $(Q) for i in $(SERVICE_FILES); do \
+ $(ES) " INSTALL_DATA $(SYSTEMDSYSTEMUNITDIR)/$$i"; \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(SYSTEMDSYSTEMUNITDIR)/$$i; \
+ done
+ $(Q) for i in $(LIBPROGS); do \
+ $(ES) " INSTALL $(pkglibdir)/$$i"; \
+ $(INSTALL_PROGRAM) $$i $(DESTDIR)$(pkglibdir)/$$i; \
+ done
+
+install: $(PROGS) $(MANPAGES) $(FMANPAGES) installdirs $(INSTALL_TGT) $(CRONTABS)
$(Q) for i in $(PROGS); do \
$(ES) " INSTALL $(root_sbindir)/$$i"; \
$(INSTALL_PROGRAM) $$i $(DESTDIR)$(root_sbindir)/$$i; \
@@ -77,12 +120,24 @@ install: $(PROGS) $(MANPAGES) $(FMANPAGES) installdirs $(INSTALL_TGT)
$(ES) " INSTALL_DATA $(root_sysconfdir)/$$i"; \
$(INSTALL_DATA) $$i $(DESTDIR)$(root_sysconfdir)/$$i; \
done
+ $(Q) for i in $(CRONTABS); do \
+ $(ES) " INSTALL_DATA $(root_crondir)/$$i"; \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(root_crondir)/$$i; \
+ done
uninstall-udev:
for i in $(UDEVRULES); do \
$(RM) -f $(DESTDIR)$(UDEVRULESDIR)/$$i; \
done
+uninstall-systemd:
+ for i in $(SERVICE_FILES); do \
+ $(RM) -f $(DESTDIR)$(SYSTEMDSYSTEMUNITDIR)/$$i; \
+ done
+ for i in $(LIBPROGS); do \
+ $(RM) -f $(DESTDIR)$(pkglibdir)/$(package)/$$i; \
+ done
+
uninstall: $(UNINSTALL_TGT)
for i in $(PROGS); do \
$(RM) -f $(DESTDIR)$(root_sbindir)/$$i; \
@@ -93,6 +148,9 @@ uninstall: $(UNINSTALL_TGT)
for i in $(CONFFILES); do \
$(RM) -f $(DESTDIR)$(root_sysconfdir)/$$i; \
done
+ for i in $(CRONTABS); do \
+ $(RM) -f $(DESTDIR)$(root_crondir)/$$i; \
+ done
clean::
$(RM) -f $(PROGS)
diff --git a/scrub/e2scrub.in b/scrub/e2scrub.in
index 75e0639..9ea9b19 100644
--- a/scrub/e2scrub.in
+++ b/scrub/e2scrub.in
@@ -40,6 +40,18 @@ print_help() {
exitcode() {
ret="$1"
+ # If we're in service mode, add 150 to the error code to
+ # avoid conflicting with sysvinit error codes
+ if [ -n "${SERVICE_MODE}" ] && [ "${ret}" -ne 0 ]; then
+ ret="$((ret + 150))"
+ fi
+
+ # Stupid journald bug where the process still has to exist for
+ # the last few messages to get tagged to the service...
+ if [ -n "${SERVICE_MODE}" ] && [ -x "${SLEEP_PROG}" ]; then
+ "${SLEEP_PROG}" 2
+ fi
+
exit "${ret}"
}
diff --git a/scrub/e2scrub@...rvice.in b/scrub/e2scrub@...rvice.in
new file mode 100644
index 0000000..213cffc
--- /dev/null
+++ b/scrub/e2scrub@...rvice.in
@@ -0,0 +1,18 @@
+[Unit]
+Description=Online ext4 Metadata Check for %I
+OnFailure=e2scrub_fail@...service
+
+[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=@...t_sbindir@...scrub -t %I
diff --git a/scrub/e2scrub_all.cron.in b/scrub/e2scrub_all.cron.in
new file mode 100644
index 0000000..6551a77
--- /dev/null
+++ b/scrub/e2scrub_all.cron.in
@@ -0,0 +1,2 @@
+SERVICE_MODE=1
+10 3 * * 0 root test -e /run/systemd/system || @root_sbindir@...scrub_all
diff --git a/scrub/e2scrub_all.in b/scrub/e2scrub_all.in
index a9ba670..71fb343 100644
--- a/scrub/e2scrub_all.in
+++ b/scrub/e2scrub_all.in
@@ -24,6 +24,18 @@ types="ext2,ext3,ext4"
exitcode() {
ret="$1"
+ # If we're in service mode, add 150 to the error code to
+ # avoid conflicting with sysvinit error codes
+ if [ -n "${SERVICE_MODE}" ] && [ "${ret}" -ne 0 ]; then
+ ret="$((ret + 150))"
+ fi
+
+ # Stupid journald bug where the process still has to exist for
+ # the last few messages to get tagged to the service...
+ if [ -n "${SERVICE_MODE}" ]; then
+ "${SLEEP_PROG}" 2
+ fi
+
exit "${ret}"
}
@@ -39,13 +51,23 @@ prog_path() {
LVS_PROG="$(prog_path "@root_sbindir@...s" "lvs")"
BLKID_PROG="$(prog_path "@root_sbindir@...kid" "blkid")"
+SYSTEMCTL_PROG="$(prog_path "@root_bindir@...stemctl")"
+SLEEP_PROG="$(prog_path "@root_bindir@...eep")"
# Scrub any fs on lvm by creating a snapshot and fscking that.
"${LVS_PROG}" -o vg_name,lv_name --noheadings 2> /dev/null | while read vg lv; do
dev="/dev/${vg}/${lv}"
"${BLKID_PROG}" -p -n "${types}" "${dev}" > /dev/null 2>&1 || continue
- ${DBG} "@root_sbindir@...scrub" "${dev}"
+ if [ ! -x "${SYSTEMCTL_PROG}" ]; then
+ ${DBG} "@root_sbindir@...scrub" "${dev}"
+ else
+ ${DBG} "${SYSTEMCTL_PROG}" start "e2scrub@...ev}" 2> /dev/null
+ res=$?
+ if [ "${res}" -ne 0 ] && [ "${res}" -ne 1 ]; then
+ ${DBG} "@root_sbindir@...scrub" "${dev}"
+ fi
+ fi
done
exitcode 0
diff --git a/scrub/e2scrub_all.service.in b/scrub/e2scrub_all.service.in
new file mode 100644
index 0000000..89a76e2
--- /dev/null
+++ b/scrub/e2scrub_all.service.in
@@ -0,0 +1,8 @@
+[Unit]
+Description=Online ext4 Metadata Check for All Filesystems
+ConditionACPower=true
+
+[Service]
+Type=oneshot
+Environment=SERVICE_MODE=1
+ExecStart=@...t_sbindir@...scrub_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_fail.in b/scrub/e2scrub_fail.in
new file mode 100644
index 0000000..b95db1b
--- /dev/null
+++ b/scrub/e2scrub_fail.in
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Email logs of failed e2scrub unit runs
+
+mailer=/usr/sbin/sendmail
+recipient="$1"
+test -z "${recipient}" && exit 0
+mntpoint="$2"
+test -z "${mntpoint}" && exit 0
+hostname="$(hostname -f 2>/dev/null)"
+test -z "${hostname}" && hostname="${HOSTNAME}"
+if [ ! -x "${mailer}" ]; then
+ echo "${mailer}: Mailer program not found."
+ exit 1
+fi
+
+(cat << ENDL
+To: $1
+From: <e2scrub@...ostname}>
+Subject: e2scrub failure on ${mntpoint}
+
+So sorry, the automatic e2scrub of ${mntpoint} on ${hostname} failed.
+
+A log of what happened follows:
+ENDL
+systemctl status --full --lines 4294967295 "e2scrub@...ntpoint}") | "${mailer}" -t -i
diff --git a/scrub/e2scrub_fail@...rvice.in b/scrub/e2scrub_fail@...rvice.in
new file mode 100644
index 0000000..df87949
--- /dev/null
+++ b/scrub/e2scrub_fail@...rvice.in
@@ -0,0 +1,10 @@
+[Unit]
+Description=Online ext4 Metadata Check Failure Reporting for %I
+
+[Service]
+Type=oneshot
+Environment=EMAIL_ADDR=root
+ExecStart=@...libdir@...scrub_fail "${EMAIL_ADDR}" %I
+User=mail
+Group=mail
+SupplementaryGroups=systemd-journal
diff --git a/util/subst.conf.in b/util/subst.conf.in
index effac78..f534f67 100644
--- a/util/subst.conf.in
+++ b/util/subst.conf.in
@@ -20,3 +20,5 @@ JDEV
TDB_MAN_COMMENT @TDB_MAN_COMMENT@
root_sbindir @root_sbindir@
root_bindir @root_bindir@
+pkglibdir @pkglibdir@
+$exec_prefix @exec_prefix@
Powered by blists - more mailing lists