diff options
-rwxr-xr-x | debian/rules | 1 | ||||
-rw-r--r-- | include/builddefs.in | 2 | ||||
-rw-r--r-- | scrub/Makefile | 26 | ||||
-rw-r--r-- | scrub/xfs_scrub@.service.in | 6 | ||||
-rw-r--r-- | scrub/xfs_scrub_all.in | 53 | ||||
-rwxr-xr-x | scrub/xfs_scrub_fail.in (renamed from scrub/xfs_scrub_fail) | 12 | ||||
-rw-r--r-- | scrub/xfs_scrub_fail@.service.in | 4 |
7 files changed, 57 insertions, 47 deletions
diff --git a/debian/rules b/debian/rules index 95df4835b2..57baad625c 100755 --- a/debian/rules +++ b/debian/rules @@ -108,6 +108,7 @@ binary-arch: checkroot built dh_compress dh_fixperms dh_makeshlibs + dh_installsystemd -p xfsprogs --no-enable --no-start --no-restart-after-upgrade --no-stop-on-upgrade dh_installdeb dh_shlibdeps dh_gencontrol diff --git a/include/builddefs.in b/include/builddefs.in index 43025ba4fc..a3745efbe2 100644 --- a/include/builddefs.in +++ b/include/builddefs.in @@ -51,7 +51,7 @@ PKG_SBIN_DIR = @sbindir@ PKG_ROOT_SBIN_DIR = @root_sbindir@ PKG_ROOT_LIB_DIR= @root_libdir@@libdirsuffix@ PKG_LIB_DIR = @libdir@@libdirsuffix@ -PKG_LIB_SCRIPT_DIR = @libdir@ +PKG_LIBEXEC_DIR = @libexecdir@/@pkg_name@ PKG_INC_DIR = @includedir@/xfs DK_INC_DIR = @includedir@/disk PKG_MAN_DIR = @mandir@ diff --git a/scrub/Makefile b/scrub/Makefile index 24af971612..4368897f2c 100644 --- a/scrub/Makefile +++ b/scrub/Makefile @@ -8,14 +8,17 @@ include $(builddefs) SCRUB_PREREQS=$(HAVE_OPENAT)$(HAVE_FSTATAT)$(HAVE_GETFSMAP) +scrub_svcname=xfs_scrub@.service + ifeq ($(SCRUB_PREREQS),yesyesyes) LTCOMMAND = xfs_scrub INSTALL_SCRUB = install-scrub XFS_SCRUB_ALL_PROG = xfs_scrub_all +XFS_SCRUB_FAIL_PROG = xfs_scrub_fail XFS_SCRUB_ARGS = -b -n ifeq ($(HAVE_SYSTEMD),yes) INSTALL_SCRUB += install-systemd -SYSTEMD_SERVICES = xfs_scrub@.service xfs_scrub_all.service xfs_scrub_all.timer xfs_scrub_fail@.service +SYSTEMD_SERVICES = $(scrub_svcname) xfs_scrub_all.service xfs_scrub_all.timer xfs_scrub_fail@.service OPTIONAL_TARGETS += $(SYSTEMD_SERVICES) endif ifeq ($(HAVE_CROND),yes) @@ -23,7 +26,7 @@ INSTALL_SCRUB += install-crond CRONTABS = xfs_scrub_all.cron OPTIONAL_TARGETS += $(CRONTABS) # Don't enable the crontab by default for now -CROND_DIR = $(PKG_LIB_SCRIPT_DIR)/$(PKG_NAME) +CROND_DIR = $(PKG_DATA_DIR) endif endif # scrub_prereqs @@ -107,17 +110,25 @@ ifeq ($(HAVE_HDIO_GETGEO),yes) LCFLAGS += -DHAVE_HDIO_GETGEO endif -LDIRT = $(XFS_SCRUB_ALL_PROG) *.service *.cron +LDIRT = $(XFS_SCRUB_ALL_PROG) $(XFS_SCRUB_FAIL_PROG) *.service *.cron -default: depend $(LTCOMMAND) $(XFS_SCRUB_ALL_PROG) $(OPTIONAL_TARGETS) +default: depend $(LTCOMMAND) $(XFS_SCRUB_ALL_PROG) $(XFS_SCRUB_FAIL_PROG) $(OPTIONAL_TARGETS) xfs_scrub_all: xfs_scrub_all.in $(builddefs) @echo " [SED] $@" $(Q)$(SED) -e "s|@sbindir@|$(PKG_SBIN_DIR)|g" \ + -e "s|@scrub_svcname@|$(scrub_svcname)|g" \ -e "s|@pkg_version@|$(PKG_VERSION)|g" \ -e "s|@scrub_args@|$(XFS_SCRUB_ARGS)|g" < $< > $@ $(Q)chmod a+x $@ +xfs_scrub_fail: xfs_scrub_fail.in $(builddefs) + @echo " [SED] $@" + $(Q)$(SED) -e "s|@sbindir@|$(PKG_SBIN_DIR)|g" \ + -e "s|@scrub_svcname@|$(scrub_svcname)|g" \ + -e "s|@pkg_version@|$(PKG_VERSION)|g" < $< > $@ + $(Q)chmod a+x $@ + phase5.o unicrash.o xfs.o: $(builddefs) include $(BUILDRULES) @@ -128,8 +139,7 @@ install: $(INSTALL_SCRUB) @echo " [SED] $@" $(Q)$(SED) -e "s|@sbindir@|$(PKG_SBIN_DIR)|g" \ -e "s|@scrub_args@|$(XFS_SCRUB_ARGS)|g" \ - -e "s|@pkg_lib_dir@|$(PKG_LIB_SCRIPT_DIR)|g" \ - -e "s|@pkg_name@|$(PKG_NAME)|g" \ + -e "s|@pkg_libexec_dir@|$(PKG_LIBEXEC_DIR)|g" \ < $< > $@ %.cron: %.cron.in $(builddefs) @@ -139,8 +149,8 @@ install: $(INSTALL_SCRUB) install-systemd: default $(SYSTEMD_SERVICES) $(INSTALL) -m 755 -d $(SYSTEMD_SYSTEM_UNIT_DIR) $(INSTALL) -m 644 $(SYSTEMD_SERVICES) $(SYSTEMD_SYSTEM_UNIT_DIR) - $(INSTALL) -m 755 -d $(PKG_LIB_SCRIPT_DIR)/$(PKG_NAME) - $(INSTALL) -m 755 xfs_scrub_fail $(PKG_LIB_SCRIPT_DIR)/$(PKG_NAME) + $(INSTALL) -m 755 -d $(PKG_LIBEXEC_DIR) + $(INSTALL) -m 755 $(XFS_SCRUB_FAIL_PROG) $(PKG_LIBEXEC_DIR) install-crond: default $(CRONTABS) $(INSTALL) -m 755 -d $(CROND_DIR) diff --git a/scrub/xfs_scrub@.service.in b/scrub/xfs_scrub@.service.in index b90107bdcb..05e5293ee1 100644 --- a/scrub/xfs_scrub@.service.in +++ b/scrub/xfs_scrub@.service.in @@ -4,7 +4,7 @@ # Author: Darrick J. Wong <djwong@kernel.org> [Unit] -Description=Online XFS Metadata Check for %I +Description=Online XFS Metadata Check for %f OnFailure=xfs_scrub_fail@%i.service Documentation=man:xfs_scrub(8) @@ -13,7 +13,7 @@ Type=oneshot PrivateNetwork=true ProtectSystem=full ProtectHome=read-only -# Disable private /tmp just in case %i is a path under /tmp. +# Disable private /tmp just in case %f is a path under /tmp. PrivateTmp=no AmbientCapabilities=CAP_SYS_ADMIN CAP_FOWNER CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_SYS_RAWIO NoNewPrivileges=yes @@ -21,5 +21,5 @@ User=nobody IOSchedulingClass=idle CPUSchedulingPolicy=idle Environment=SERVICE_MODE=1 -ExecStart=@sbindir@/xfs_scrub @scrub_args@ %I +ExecStart=@sbindir@/xfs_scrub @scrub_args@ %f SyslogIdentifier=%N diff --git a/scrub/xfs_scrub_all.in b/scrub/xfs_scrub_all.in index 5042321a73..d7d36e1bdb 100644 --- a/scrub/xfs_scrub_all.in +++ b/scrub/xfs_scrub_all.in @@ -81,31 +81,20 @@ def run_killable(cmd, stdout, killfuncs, kill_fn): return -1 # systemd doesn't like unit instance names with slashes in them, so it -# replaces them with dashes when it invokes the service. However, it's not -# smart enough to convert the dashes to something else, so when it unescapes -# the instance name to feed to xfs_scrub, it turns all dashes into slashes. -# "/moo-cow" becomes "-moo-cow" becomes "/moo/cow", which is wrong. systemd -# actually /can/ escape the dashes correctly if it is told that this is a path -# (and not a unit name), but it didn't do this prior to January 2017, so fix -# this for them. -# -# systemd path escaping also drops the initial slash so we add that back in so -# that log messages from the service units preserve the full path and users can -# look up log messages using full paths. However, for "/" the escaping rules -# do /not/ drop the initial slash, so we have to special-case that here. -def systemd_escape(path): - '''Escape a path to avoid mangled systemd mangling.''' - - if path == '/': - return '-' - cmd = ['systemd-escape', '--path', path] +# replaces them with dashes when it invokes the service. Filesystem paths +# need a special --path argument so that dashes do not get mangled. +def path_to_serviceunit(path): + '''Convert a pathname into a systemd service unit name.''' + + cmd = ['systemd-escape', '--template', '@scrub_svcname@', + '--path', path] try: proc = subprocess.Popen(cmd, stdout = subprocess.PIPE) proc.wait() for line in proc.stdout: - return '-' + line.decode(sys.stdout.encoding).strip() + return line.decode(sys.stdout.encoding).strip() except: - return path + return None def run_scrub(mnt, cond, running_devs, mntdevs, killfuncs): '''Run a scrub process.''' @@ -119,17 +108,19 @@ def run_scrub(mnt, cond, running_devs, mntdevs, killfuncs): return # Try it the systemd way - cmd=['systemctl', 'start', 'xfs_scrub@%s' % systemd_escape(mnt)] - ret = run_killable(cmd, DEVNULL(), killfuncs, \ - lambda proc: kill_systemd('xfs_scrub@%s' % mnt, proc)) - if ret == 0 or ret == 1: - print("Scrubbing %s done, (err=%d)" % (mnt, ret)) - sys.stdout.flush() - retcode |= ret - return - - if terminate: - return + unitname = path_to_serviceunit(path) + if unitname is not None: + cmd=['systemctl', 'start', unitname] + ret = run_killable(cmd, DEVNULL(), killfuncs, \ + lambda proc: kill_systemd(unitname, proc)) + if ret == 0 or ret == 1: + print("Scrubbing %s done, (err=%d)" % (mnt, ret)) + sys.stdout.flush() + retcode |= ret + return + + if terminate: + return # Invoke xfs_scrub manually cmd=['@sbindir@/xfs_scrub', '@scrub_args@', mnt] diff --git a/scrub/xfs_scrub_fail b/scrub/xfs_scrub_fail.in index 4f3f11d43f..9437b0327e 100755 --- a/scrub/xfs_scrub_fail +++ b/scrub/xfs_scrub_fail.in @@ -7,25 +7,33 @@ # Email logs of failed xfs_scrub 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}" + +mailer="$(command -v sendmail)" if [ ! -x "${mailer}" ]; then echo "${mailer}: Mailer program not found." exit 1 fi +# Turn the mountpoint into a properly escaped systemd instance name +scrub_svc="$(systemd-escape --template "@scrub_svcname@" --path "${mntpoint}")" + (cat << ENDL To: $1 From: <xfs_scrub@${hostname}> Subject: xfs_scrub failure on ${mntpoint} +Content-Transfer-Encoding: 8bit +Content-Type: text/plain; charset=UTF-8 So sorry, the automatic xfs_scrub of ${mntpoint} on ${hostname} failed. +Please do not reply to this mesage. A log of what happened follows: ENDL -systemctl status --full --lines 4294967295 "xfs_scrub@${mntpoint}") | "${mailer}" -t -i +systemctl status --full --lines 4294967295 "${scrub_svc}") | "${mailer}" -t -i +exit "${PIPESTATUS[1]}" diff --git a/scrub/xfs_scrub_fail@.service.in b/scrub/xfs_scrub_fail@.service.in index 489a946732..96a2ed5da3 100644 --- a/scrub/xfs_scrub_fail@.service.in +++ b/scrub/xfs_scrub_fail@.service.in @@ -4,13 +4,13 @@ # Author: Darrick J. Wong <djwong@kernel.org> [Unit] -Description=Online XFS Metadata Check Failure Reporting for %I +Description=Online XFS Metadata Check Failure Reporting for %f Documentation=man:xfs_scrub(8) [Service] Type=oneshot Environment=EMAIL_ADDR=root -ExecStart=@pkg_lib_dir@/@pkg_name@/xfs_scrub_fail "${EMAIL_ADDR}" %I +ExecStart=@pkg_libexec_dir@/xfs_scrub_fail "${EMAIL_ADDR}" %f User=mail Group=mail SupplementaryGroups=systemd-journal |