[PATCH 1/5] xfs_scrub_all: encapsulate all the subprocess code in an object

Darrick J. Wong
2023-12-31T22:59:07Z

Move all the xfs_scrub subprocess handling code to an object so that we
can contain all the details in a single place. This also simplifies the
background state management.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
scrub/xfs_scrub_all.in | 68 ++++++++++++++++++++++++++++++++++++++----------
1 file changed, 54 insertions(+), 14 deletions(-)

diff --git a/scrub/xfs_scrub_all.in b/scrub/xfs_scrub_all.in
index 9d5cbd2a648..001c49a7012 100644
--- a/scrub/xfs_scrub_all.in
+++ b/scrub/xfs_scrub_all.in
@@ -78,15 +78,62 @@ def remove_killfunc(killfuncs, fn):
except:
pass

-def run_killable(cmd, stdout, killfuncs):
+class scrub_control(object):
+ '''Control object for xfs_scrub.'''
+ def __init__(self):
+ pass
+
+ def start(self):
+ '''Start scrub and wait for it to complete. Returns -1 if the
+ service was not started, 0 if it succeeded, or 1 if it
+ failed.'''
+ assert False
+
+ def stop(self):
+ '''Stop scrub.'''
+ assert False
+
+class scrub_subprocess(scrub_control):
+ '''Control object for xfs_scrub subprocesses.'''
+ def __init__(self, mnt, scrub_media):
+ cmd = ['@sbindir@/xfs_scrub']
+ if 'SERVICE_MODE' in os.environ:
+ cmd += '@scrub_service_args@'.split()
+ cmd += '@scrub_args@'.split()
+ if scrub_media:
+ cmd += '-x'
+ cmd += [mnt]
+ self.cmdline = cmd
+ self.proc = None
+
+ def start(self):
+ '''Start xfs_scrub and wait for it to complete. Returns -1 if
+ the service was not started, 0 if it succeeded, or 1 if it
+ failed.'''
+ try:
+ self.proc = subprocess.Popen(self.cmdline)
+ self.proc.wait()
+ except:
+ return -1
+
+ proc = self.proc
+ self.proc = None
+ return proc.returncode
+
+ def stop(self):
+ '''Stop xfs_scrub.'''
+ if self.proc is not None:
+ self.proc.terminate()
+
+def run_subprocess(mnt, scrub_media, killfuncs):
'''Run a killable program. Returns program retcode or -1 if we can't
start it.'''
try:
- proc = subprocess.Popen(cmd, stdout = stdout)
- killfuncs.add(proc.terminate)
- proc.wait()
- remove_killfunc(killfuncs, proc.terminate)
- return proc.returncode
+ p = scrub_subprocess(mnt, scrub_media)
+ killfuncs.add(p.stop)
+ ret = p.start()
+ remove_killfunc(killfuncs, p.stop)
+ return ret
except:
return -1

@@ -188,14 +235,7 @@ def run_scrub(mnt, cond, running_devs, mntdevs, killfuncs):
# Invoke xfs_scrub manually if we're running in the foreground.
# We also permit this if we're running as a cronjob where
# systemd services are unavailable.
- cmd = ['@sbindir@/xfs_scrub']
- if 'SERVICE_MODE' in os.environ:
- cmd += '@scrub_service_args@'.split()
- cmd += '@scrub_args@'.split()
- if scrub_media:
- cmd += '-x'
- cmd += [mnt]
- ret = run_killable(cmd, None, killfuncs)
+ ret = run_subprocess(mnt, scrub_media, killfuncs)
if ret >= 0:
print("Scrubbing %s done, (err=%d)" % (mnt, ret))
sys.stdout.flush()