diff mbox series

[19/21] xfs_scrubbed: use the autofsck fsproperty to select mode

Message ID 173568778754.2710211.11864841620520710404.stgit@frogsfrogsfrogs (mailing list archive)
State New
Headers show
Series [01/21] xfs: create hooks for monitoring health updates | expand

Commit Message

Darrick J. Wong Dec. 31, 2024, 11:52 p.m. UTC
From: Darrick J. Wong <djwong@kernel.org>

Make the xfs_scrubbed background service query the autofsck filesystem
property to figure out which operating mode it should use.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
 scrub/xfs_scrubbed.in |   62 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 61 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/scrub/xfs_scrubbed.in b/scrub/xfs_scrubbed.in
index 90602481f64c88..2b34603cb361e2 100644
--- a/scrub/xfs_scrubbed.in
+++ b/scrub/xfs_scrubbed.in
@@ -573,6 +573,21 @@  def fgetpath(fd, fh = None, mountpoint = None):
 			break
 	return ret
 
+# Filesystem properties
+
+FSPROP_NAMESPACE = "trusted."
+FSPROP_NAME_PREFIX = "xfs:"
+FSPROP_AUTOFSCK_NAME = "autofsck"
+
+def fsprop_attrname(n):
+	'''Construct the xattr name for a filesystem property.'''
+	return f"{FSPROP_NAMESPACE}{FSPROP_NAME_PREFIX}{n}"
+
+def fsprop_getstr(fd, n):
+	'''Return the value of a filesystem property as a string.'''
+	attrname = fsprop_attrname(n)
+	return os.getxattr(fd, attrname).decode('utf-8')
+
 # main program
 
 def health_reports(mon_fp, fh):
@@ -731,6 +746,31 @@  def handle_event(e):
 	elif want_repair and event['type'] == 'sick':
 		repair_queue.submit(repair_metadata, event, fh)
 
+def want_repair_from_autofsck(fd):
+	'''Determine want_repair from the autofsck filesystem property.'''
+	global has_parent
+	global has_rmapbt
+
+	try:
+		advice = fsprop_getstr(fd, FSPROP_AUTOFSCK_NAME)
+		if advice == "repair":
+			return True
+		if advice == "check" or advice == "optimize":
+			return False
+		if advice == "none":
+			return None
+	except:
+		# Any OS error (including ENODATA) or string parsing error is
+		# treated the same as an unrecognized value.
+		pass
+
+	# For an unrecognized value, log but do not fix runtime corruption if
+	# backref metadata are enabled.  If no backref metadata are available,
+	# the fs is too old so don't run at all.
+	if has_rmapbt or has_parent:
+		return False
+	return None
+
 def monitor(mountpoint, event_queue, **kwargs):
 	'''Monitor the given mountpoint for health events.'''
 	global everything
@@ -749,6 +789,20 @@  def monitor(mountpoint, event_queue, **kwargs):
 		# Don't care if we can't detect parent pointers or rmap
 		print(f'{printf_prefix}: detecting fs features: {e}', file = sys.stderr)
 
+	# Does the sysadmin have any advice for us about whether or not to
+	# background scrub?
+	if want_repair is None:
+		want_repair = want_repair_from_autofsck(fd)
+		if want_repair is None:
+			print(f"{mountpoint}: Disabling daemon per autofsck directive.")
+			os.close(fd)
+			return 0
+		elif want_repair:
+			print(f"{mountpoint}: Automatically repairing per autofsck directive.")
+		else:
+			print(f"{mountpoint}: Only logging errors per autofsck directive.")
+
+
 	# Check for the backref metadata that makes repair effective.
 	if want_repair:
 		if not has_rmapbt:
@@ -963,7 +1017,11 @@  def main():
 			action = "store_true")
 	parser.add_argument("--everything", help = "Capture all events.", \
 			action = "store_true")
-	parser.add_argument("--repair", help = "Automatically repair corrupt metadata.", \
+	action_group = parser.add_mutually_exclusive_group()
+	action_group.add_argument("--repair", \
+			help = "Automatically repair corrupt metadata.", \
+			action = "store_true")
+	action_group.add_argument("--autofsck", help = argparse.SUPPRESS, \
 			action = "store_true")
 	parser.add_argument("-V", help = "Report version and exit.", \
 			action = "store_true")
@@ -1004,6 +1062,8 @@  def main():
 		everything = True
 	if args.debug_fast:
 		debug_fast = True
+	if args.autofsck:
+		want_repair = None
 	if args.repair:
 		want_repair = True